Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16c0b295 authored by Wink Saville's avatar Wink Saville Committed by Android Git Automerger
Browse files

am bba3a694: Merge "Telephony API extension v2"

* commit 'bba3a694':
  Telephony API extension v2
parents 93994e9d bba3a694
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -1088,6 +1088,14 @@
        android:label="@string/permlab_readPhoneState"
        android:description="@string/permdesc_readPhoneState" />

    <!-- Allows read only access to precise phone state.
         @hide Pending API council approval -->
    <permission android:name="android.permission.READ_PRECISE_PHONE_STATE"
        android:permissionGroup="android.permission-group.PHONE_CALLS"
        android:protectionLevel="dangerous"
        android:label="@string/permlab_readPrecisePhoneState"
        android:description="@string/permdesc_readPrecisePhoneState" />

    <!-- Allows read access to privileged phone state.
         @hide Used internally. -->
    <permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"
+8 −0
Original line number Diff line number Diff line
@@ -1638,6 +1638,14 @@
      phone number and device IDs, whether a call is active, and the remote number
      connected by a call.</string>

    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permlab_readPrecisePhoneState">read precise phone states</string>
    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permdesc_readPrecisePhoneState">Allows the app to access the precise
      phone states.  This permission allows the app to determine the real
      call status, whether a call is active or in the background, call fails,
      precise data connection status and data connection fails.</string>

    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
    <string name="permlab_wakeLock" product="tablet">prevent tablet from sleeping</string>
    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+169 −10
Original line number Diff line number Diff line
@@ -37,6 +37,10 @@ import android.telephony.ServiceState;
import android.telephony.SignalStrength;
import android.telephony.CellInfo;
import android.telephony.TelephonyManager;
import android.telephony.DisconnectCause;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.PreciseDisconnectCause;
import android.text.TextUtils;
import android.util.Slog;

@@ -125,6 +129,17 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {

    private List<CellInfo> mCellInfo = null;

    private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;

    private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;

    private int mBackgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;

    private PreciseCallState mPreciseCallState = new PreciseCallState();

    private PreciseDataConnectionState mPreciseDataConnectionState =
                new PreciseDataConnectionState();

    static final int PHONE_STATE_PERMISSION_MASK =
                PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR |
                PhoneStateListener.LISTEN_CALL_STATE |
@@ -132,6 +147,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
                PhoneStateListener.LISTEN_DATA_CONNECTION_STATE |
                PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR;

    static final int PRECISE_PHONE_STATE_PERMISSION_MASK =
                PhoneStateListener.LISTEN_PRECISE_CALL_STATE |
                PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE;

    private static final int MSG_USER_SWITCHED = 1;

    private final Handler mHandler = new Handler() {
@@ -305,6 +324,21 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
                            remove(r.binder);
                        }
                    }
                    if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
                        try {
                            r.callback.onPreciseCallStateChanged(mPreciseCallState);
                        } catch (RemoteException ex) {
                            remove(r.binder);
                        }
                    }
                    if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
                        try {
                            r.callback.onPreciseDataConnectionStateChanged(
                                    mPreciseDataConnectionState);
                        } catch (RemoteException ex) {
                            remove(r.binder);
                        }
                    }
                }
            }
        } else {
@@ -533,30 +567,47 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
                }
                handleRemoveListLocked();
            }
            mPreciseDataConnectionState = new PreciseDataConnectionState(state, networkType,
                    apnType, apn, reason, linkProperties, "");
            for (Record r : mRecords) {
                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
                    try {
                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
                    } catch (RemoteException ex) {
                        mRemoveList.add(r.binder);
                    }
                }
            }
            handleRemoveListLocked();
        }
        broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
                apnType, linkProperties, linkCapabilities, roaming);
        broadcastPreciseDataConnectionStateChanged(state, networkType, apnType, apn, reason,
                linkProperties, "");
    }

    public void notifyDataConnectionFailed(String reason, String apnType) {
        if (!checkNotifyPermission("notifyDataConnectionFailed()")) {
            return;
        }
        /*
         * This is commented out because there is no onDataConnectionFailed callback
         * in PhoneStateListener. There should be.
        synchronized (mRecords) {
            mDataConnectionFailedReason = reason;
            final int N = mRecords.size();
            for (int i=N-1; i>=0; i--) {
                Record r = mRecords.get(i);
                if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_FAILED) != 0) {
                    // XXX
            mPreciseDataConnectionState = new PreciseDataConnectionState(
                    TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN,
                    apnType, "", reason, null, "");
            for (Record r : mRecords) {
                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
                    try {
                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
                    } catch (RemoteException ex) {
                        mRemoveList.add(r.binder);
                    }
                }
            }
        */
            handleRemoveListLocked();
        }
        broadcastDataConnectionFailed(reason, apnType);
        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, "", reason, null, "");
    }

    public void notifyCellLocation(Bundle cellLocation) {
@@ -602,6 +653,81 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
        }
    }

    public void notifyPreciseCallState(int ringingCallState, int foregroundCallState,
            int backgroundCallState) {
        if (!checkNotifyPermission("notifyPreciseCallState()")) {
            return;
        }
        synchronized (mRecords) {
            mRingingCallState = ringingCallState;
            mForegroundCallState = foregroundCallState;
            mBackgroundCallState = backgroundCallState;
            mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState,
                    backgroundCallState,
                    DisconnectCause.NOT_VALID,
                    PreciseDisconnectCause.NOT_VALID);
            for (Record r : mRecords) {
                if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
                    try {
                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
                    } catch (RemoteException ex) {
                        mRemoveList.add(r.binder);
                    }
                }
            }
            handleRemoveListLocked();
        }
        broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState,
                DisconnectCause.NOT_VALID,
                PreciseDisconnectCause.NOT_VALID);
    }

    public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) {
        if (!checkNotifyPermission("notifyDisconnectCause()")) {
            return;
        }
        synchronized (mRecords) {
            mPreciseCallState = new PreciseCallState(mRingingCallState, mForegroundCallState,
                    mBackgroundCallState, disconnectCause, preciseDisconnectCause);
            for (Record r : mRecords) {
                if ((r.events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
                    try {
                        r.callback.onPreciseCallStateChanged(mPreciseCallState);
                    } catch (RemoteException ex) {
                        mRemoveList.add(r.binder);
                    }
                }
            }
            handleRemoveListLocked();
        }
        broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState,
                mBackgroundCallState, disconnectCause, preciseDisconnectCause);
    }

    public void notifyPreciseDataConnectionFailed(String reason, String apnType,
            String apn, String failCause) {
        if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) {
            return;
        }
        synchronized (mRecords) {
            mPreciseDataConnectionState = new PreciseDataConnectionState(
                    TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN,
                    apnType, apn, reason, null, failCause);
            for (Record r : mRecords) {
                if ((r.events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) {
                    try {
                        r.callback.onPreciseDataConnectionStateChanged(mPreciseDataConnectionState);
                    } catch (RemoteException ex) {
                        mRemoveList.add(r.binder);
                    }
                }
            }
            handleRemoveListLocked();
        }
        broadcastPreciseDataConnectionStateChanged(TelephonyManager.DATA_UNKNOWN,
                TelephonyManager.NETWORK_TYPE_UNKNOWN, apnType, apn, reason, null, failCause);
    }

    @Override
    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -738,6 +864,33 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
    }

    private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState,
            int backgroundCallState, int disconnectCause, int preciseDisconnectCause) {
        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED);
        intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState);
        intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState);
        intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState);
        intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause);
        intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause);
        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
    }

    private void broadcastPreciseDataConnectionStateChanged(int state, int networkType,
            String apnType, String apn, String reason, LinkProperties linkProperties, String failCause) {
        Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED);
        intent.putExtra(PhoneConstants.STATE_KEY, state);
        intent.putExtra(PhoneConstants.DATA_NETWORK_TYPE_KEY, networkType);
        if (reason != null) intent.putExtra(PhoneConstants.STATE_CHANGE_REASON_KEY, reason);
        if (apnType != null) intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType);
        if (apn != null) intent.putExtra(PhoneConstants.DATA_APN_KEY, apn);
        if (linkProperties != null) intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties);
        if (failCause != null) intent.putExtra(PhoneConstants.DATA_FAILURE_CAUSE_KEY, failCause);

        mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                android.Manifest.permission.READ_PRECISE_PHONE_STATE);
    }

    private boolean checkNotifyPermission(String method) {
        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
                == PackageManager.PERMISSION_GRANTED) {
@@ -766,6 +919,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.READ_PHONE_STATE, null);
        }

        if ((events & PRECISE_PHONE_STATE_PERMISSION_MASK) != 0) {
            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.READ_PRECISE_PHONE_STATE, null);

        }
    }

    private void handleRemoveListLocked() {
+108 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.telephony;

/**
 * Contains disconnect call causes generated by the
 * framework and the RIL.
 *
 * @hide
 */
public class DisconnectCause {

    /** The disconnect cause is not valid (Not received a disconnect cause) */
    public static final int NOT_VALID                      = -1;
    /** Has not yet disconnected */
    public static final int NOT_DISCONNECTED               = 0;
    /** An incoming call that was missed and never answered */
    public static final int INCOMING_MISSED                = 1;
    /** Normal; Remote hangup*/
    public static final int NORMAL                         = 2;
    /** Normal; Local hangup */
    public static final int LOCAL                          = 3;
    /** Outgoing call to busy line */
    public static final int BUSY                           = 4;
    /** Outgoing call to congested network */
    public static final int CONGESTION                     = 5;
    /** Not presently used */
    public static final int MMI                            = 6;
    /** Invalid dial string */
    public static final int INVALID_NUMBER                 = 7;
    /** Cannot reach the peer */
    public static final int NUMBER_UNREACHABLE             = 8;
    /** Cannot reach the server */
    public static final int SERVER_UNREACHABLE             = 9;
    /** Invalid credentials */
    public static final int INVALID_CREDENTIALS            = 10;
    /** Calling from out of network is not allowed */
    public static final int OUT_OF_NETWORK                 = 11;
    /** Server error */
    public static final int SERVER_ERROR                   = 12;
    /** Client timed out */
    public static final int TIMED_OUT                      = 13;
    /** Client went out of network range */
    public static final int LOST_SIGNAL                    = 14;
    /** GSM or CDMA ACM limit exceeded */
    public static final int LIMIT_EXCEEDED                 = 15;
    /** An incoming call that was rejected */
    public static final int INCOMING_REJECTED              = 16;
    /** Radio is turned off explicitly */
    public static final int POWER_OFF                      = 17;
    /** Out of service */
    public static final int OUT_OF_SERVICE                 = 18;
    /** No ICC, ICC locked, or other ICC error */
    public static final int ICC_ERROR                      = 19;
    /** Call was blocked by call barring */
    public static final int CALL_BARRED                    = 20;
    /** Call was blocked by fixed dial number */
    public static final int FDN_BLOCKED                    = 21;
    /** Call was blocked by restricted all voice access */
    public static final int CS_RESTRICTED                  = 22;
    /** Call was blocked by restricted normal voice access */
    public static final int CS_RESTRICTED_NORMAL           = 23;
    /** Call was blocked by restricted emergency voice access */
    public static final int CS_RESTRICTED_EMERGENCY        = 24;
    /** Unassigned number */
    public static final int UNOBTAINABLE_NUMBER            = 25;
    /** MS is locked until next power cycle */
    public static final int CDMA_LOCKED_UNTIL_POWER_CYCLE  = 26;
    /** Drop call*/
    public static final int CDMA_DROP                      = 27;
    /** INTERCEPT order received, MS state idle entered */
    public static final int CDMA_INTERCEPT                 = 28;
    /** MS has been redirected, call is cancelled */
    public static final int CDMA_REORDER                   = 29;
    /** Service option rejection */
    public static final int CDMA_SO_REJECT                 = 30;
    /** Requested service is rejected, retry delay is set */
    public static final int CDMA_RETRY_ORDER               = 31;
    /** Unable to obtain access to the CDMA system */
    public static final int CDMA_ACCESS_FAILURE            = 32;
    /** Not a preempted call */
    public static final int CDMA_PREEMPTED                 = 33;
    /** Not an emergency call */
    public static final int CDMA_NOT_EMERGENCY             = 34;
    /** Access Blocked by CDMA network */
    public static final int CDMA_ACCESS_BLOCKED            = 35;
    /** Unknown error or not specified */
    public static final int ERROR_UNSPECIFIED              = 36;

    /** Private constructor to avoid class instantiation. */
    private DisconnectCause() {
        // Do nothing.
    }
}
+58 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.telephony.SignalStrength;
import android.telephony.CellLocation;
import android.telephony.CellInfo;
import android.telephony.Rlog;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;

import com.android.internal.telephony.IPhoneStateListener;

@@ -165,6 +167,27 @@ public class PhoneStateListener {
     */
    public static final int LISTEN_CELL_INFO = 0x00000400;

    /**
     * Listen for precise changes and fails to the device calls (cellular).
     * {@more}
     * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
     * READ_PRECISE_PHONE_STATE}
     *
     * @hide
     */
    public static final int LISTEN_PRECISE_CALL_STATE                       = 0x00000800;

    /**
     * Listen for precise changes and fails on the data connection (cellular).
     * {@more}
     * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
     * READ_PRECISE_PHONE_STATE}
     *
     * @see #onPreciseDataConnectionStateChanged
     * @hide
     */
    public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE            = 0x00001000;

    public PhoneStateListener() {
    }

@@ -292,6 +315,25 @@ public class PhoneStateListener {
    public void onCellInfoChanged(List<CellInfo> cellInfo) {
    }

    /**
     * Callback invoked when precise device call state changes.
     *
     * @hide
     */
    public void onPreciseCallStateChanged(PreciseCallState callState) {
        // default implementation empty
    }

    /**
     * Callback invoked when data connection state changes with precise information.
     *
     * @hide
     */
    public void onPreciseDataConnectionStateChanged(
            PreciseDataConnectionState dataConnectionState) {
        // default implementation empty
    }

    /**
     * The callback methods need to be called on the handler thread where
     * this object was created.  If the binder did that for us it'd be nice.
@@ -344,6 +386,16 @@ public class PhoneStateListener {
        public void onCellInfoChanged(List<CellInfo> cellInfo) {
            Message.obtain(mHandler, LISTEN_CELL_INFO, 0, 0, cellInfo).sendToTarget();
        }

        public void onPreciseCallStateChanged(PreciseCallState callState) {
            Message.obtain(mHandler, LISTEN_PRECISE_CALL_STATE, 0, 0, callState).sendToTarget();
        }

        public void onPreciseDataConnectionStateChanged(
                PreciseDataConnectionState dataConnectionState) {
            Message.obtain(mHandler, LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0,
                    dataConnectionState).sendToTarget();
        }
    };

    Handler mHandler = new Handler() {
@@ -383,6 +435,12 @@ public class PhoneStateListener {
                    break;
                case LISTEN_CELL_INFO:
                    PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
                    break;
                case LISTEN_PRECISE_CALL_STATE:
                    PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
                    break;
                case LISTEN_PRECISE_DATA_CONNECTION_STATE:
                    PhoneStateListener.this.onPreciseDataConnectionStateChanged((PreciseDataConnectionState)msg.obj);
            }
        }
    };
Loading