Loading core/res/AndroidManifest.xml +8 −0 Original line number Diff line number Diff line Loading @@ -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" Loading core/res/res/values/strings.xml +8 −0 Original line number Diff line number Diff line Loading @@ -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. --> Loading services/java/com/android/server/TelephonyRegistry.java +169 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 | Loading @@ -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() { Loading Loading @@ -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 { Loading Loading @@ -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) { Loading Loading @@ -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) Loading Loading @@ -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) { Loading Loading @@ -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() { Loading telephony/java/android/telephony/DisconnectCause.java 0 → 100644 +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. } } telephony/java/android/telephony/PhoneStateListener.java +58 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { } Loading Loading @@ -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. Loading Loading @@ -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() { Loading Loading @@ -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 Loading
core/res/AndroidManifest.xml +8 −0 Original line number Diff line number Diff line Loading @@ -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" Loading
core/res/res/values/strings.xml +8 −0 Original line number Diff line number Diff line Loading @@ -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. --> Loading
services/java/com/android/server/TelephonyRegistry.java +169 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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 | Loading @@ -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() { Loading Loading @@ -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 { Loading Loading @@ -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) { Loading Loading @@ -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) Loading Loading @@ -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) { Loading Loading @@ -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() { Loading
telephony/java/android/telephony/DisconnectCause.java 0 → 100644 +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. } }
telephony/java/android/telephony/PhoneStateListener.java +58 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { } Loading Loading @@ -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. Loading Loading @@ -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() { Loading Loading @@ -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