diff options
Diffstat (limited to 'services/java/com/android/server/TelephonyRegistry.java')
-rw-r--r-- | services/java/com/android/server/TelephonyRegistry.java | 246 |
1 files changed, 153 insertions, 93 deletions
diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java index 3370279..eb14180 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/java/com/android/server/TelephonyRegistry.java @@ -19,7 +19,8 @@ package com.android.server; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.net.NetworkUtils; +import android.net.LinkCapabilities; +import android.net.LinkProperties; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -35,12 +36,14 @@ import android.util.Slog; import java.util.ArrayList; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.net.NetworkInterface; import com.android.internal.app.IBatteryStats; import com.android.internal.telephony.ITelephonyRegistry; import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.telephony.DefaultPhoneNotifier; import com.android.internal.telephony.Phone; +import com.android.internal.telephony.ServiceStateTracker; import com.android.internal.telephony.TelephonyIntents; import com.android.server.am.BatteryStatsService; @@ -63,7 +66,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private final Context mContext; - private final ArrayList<Record> mRecords = new ArrayList(); + // access should be inside synchronized (mRecords) for these two fields + private final ArrayList<IBinder> mRemoveList = new ArrayList<IBinder>(); + private final ArrayList<Record> mRecords = new ArrayList<Record>(); private final IBatteryStats mBatteryStats; @@ -81,7 +86,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private int mDataActivity = TelephonyManager.DATA_ACTIVITY_NONE; - private int mDataConnectionState = TelephonyManager.DATA_CONNECTED; + private int mDataConnectionState = TelephonyManager.DATA_UNKNOWN; private boolean mDataConnectionPossible = false; @@ -89,14 +94,18 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private String mDataConnectionApn = ""; - private String[] mDataConnectionApnTypes = null; + private ArrayList<String> mConnectedApns; - private String mDataConnectionInterfaceName = ""; + private LinkProperties mDataConnectionLinkProperties; + + private LinkCapabilities mDataConnectionLinkCapabilities; private Bundle mCellLocation = new Bundle(); private int mDataConnectionNetworkType; + private int mOtaspMode = ServiceStateTracker.OTASP_UNKNOWN; + static final int PHONE_STATE_PERMISSION_MASK = PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR | PhoneStateListener.LISTEN_CALL_STATE | @@ -121,6 +130,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } mContext = context; mBatteryStats = BatteryStatsService.getService(); + mConnectedApns = new ArrayList<String>(); } public void listen(String pkgForDebug, IPhoneStateListener callback, int events, @@ -153,7 +163,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { r.events = events; if (notifyNow) { if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { - sendServiceState(r, mServiceState); + try { + r.callback.onServiceStateChanged(new ServiceState(mServiceState)); + } catch (RemoteException ex) { + remove(r.binder); + } } if ((events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { try { @@ -179,7 +193,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } if ((events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { - sendCellLocation(r, mCellLocation); + try { + r.callback.onCellLocationChanged(new Bundle(mCellLocation)); + } catch (RemoteException ex) { + remove(r.binder); + } } if ((events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { try { @@ -210,6 +228,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if ((events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { + try { + r.callback.onOtaspChanged(mOtaspMode); + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } else { @@ -236,16 +261,16 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { synchronized (mRecords) { mCallState = state; mCallIncomingNumber = incomingNumber; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { try { r.callback.onCallStateChanged(state, incomingNumber); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } } + handleRemoveListLocked(); } broadcastCallStateChanged(state, incomingNumber); } @@ -257,12 +282,16 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { Slog.i(TAG, "notifyServiceState: " + state); synchronized (mRecords) { mServiceState = state; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { - sendServiceState(r, state); + try { + r.callback.onServiceStateChanged(new ServiceState(state)); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } } } + handleRemoveListLocked(); } broadcastServiceStateChanged(state); } @@ -273,10 +302,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } synchronized (mRecords) { mSignalStrength = signalStrength; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) { - sendSignalStrength(r, signalStrength); + try { + r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength)); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } } if ((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTH) != 0) { try { @@ -284,10 +316,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { r.callback.onSignalStrengthChanged((gsmSignalStrength == 99 ? -1 : gsmSignalStrength)); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } } + handleRemoveListLocked(); } broadcastSignalStrengthChanged(signalStrength); } @@ -296,19 +329,18 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { return; } - Slog.i(TAG, "notifyMessageWaitingChanged: " + mwi); synchronized (mRecords) { mMessageWaiting = mwi; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_MESSAGE_WAITING_INDICATOR) != 0) { try { r.callback.onMessageWaitingIndicatorChanged(mwi); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } } + handleRemoveListLocked(); } } @@ -316,19 +348,18 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyCallForwardingChanged()")) { return; } - Slog.i(TAG, "notifyCallForwardingChanged: " + cfi); synchronized (mRecords) { mCallForwarding = cfi; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_CALL_FORWARDING_INDICATOR) != 0) { try { r.callback.onCallForwardingIndicatorChanged(cfi); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } } + handleRemoveListLocked(); } } @@ -338,58 +369,83 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } synchronized (mRecords) { mDataActivity = state; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_DATA_ACTIVITY) != 0) { try { r.callback.onDataActivity(state); } catch (RemoteException ex) { - remove(r.binder); + mRemoveList.add(r.binder); } } } + handleRemoveListLocked(); } } public void notifyDataConnection(int state, boolean isDataConnectivityPossible, - String reason, String apn, String[] apnTypes, String interfaceName, int networkType, - String gateway) { + String reason, String apn, String apnType, LinkProperties linkProperties, + LinkCapabilities linkCapabilities, int networkType) { if (!checkNotifyPermission("notifyDataConnection()" )) { return; } Slog.i(TAG, "notifyDataConnection: state=" + state + " isDataConnectivityPossible=" - + isDataConnectivityPossible + " reason=" + reason - + " interfaceName=" + interfaceName + " networkType=" + networkType); + + isDataConnectivityPossible + " reason='" + reason + + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType); synchronized (mRecords) { - mDataConnectionState = state; + boolean modified = false; + if (state == TelephonyManager.DATA_CONNECTED) { + if (!mConnectedApns.contains(apnType)) { + mConnectedApns.add(apnType); + if (mDataConnectionState != state) { + mDataConnectionState = state; + modified = true; + } + } + } else { + if (mConnectedApns.remove(apnType)) { + if (mConnectedApns.isEmpty()) { + mDataConnectionState = state; + modified = true; + } else { + // leave mDataConnectionState as is and + // send out the new status for the APN in question. + } + } + } mDataConnectionPossible = isDataConnectivityPossible; mDataConnectionReason = reason; - mDataConnectionApn = apn; - mDataConnectionApnTypes = apnTypes; - mDataConnectionInterfaceName = interfaceName; - mDataConnectionNetworkType = networkType; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); - if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { - try { - r.callback.onDataConnectionStateChanged(state, networkType); - } catch (RemoteException ex) { - remove(r.binder); + mDataConnectionLinkProperties = linkProperties; + mDataConnectionLinkCapabilities = linkCapabilities; + if (mDataConnectionNetworkType != networkType) { + mDataConnectionNetworkType = networkType; + // need to tell registered listeners about the new network type + modified = true; + } + if (modified) { + Slog.d(TAG, "onDataConnectionStateChanged(" + state + ", " + networkType + ")"); + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { + try { + r.callback.onDataConnectionStateChanged(state, networkType); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } } } + handleRemoveListLocked(); } } broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn, - apnTypes, interfaceName, gateway); + apnType, linkProperties, linkCapabilities); } - public void notifyDataConnectionFailed(String reason) { + public void notifyDataConnectionFailed(String reason, String apnType) { if (!checkNotifyPermission("notifyDataConnectionFailed()")) { return; } /* - * This is commented out because there is on onDataConnectionFailed callback - * on PhoneStateListener. There should be + * This is commented out because there is no onDataConnectionFailed callback + * in PhoneStateListener. There should be. synchronized (mRecords) { mDataConnectionFailedReason = reason; final int N = mRecords.size(); @@ -401,7 +457,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } */ - broadcastDataConnectionFailed(reason); + broadcastDataConnectionFailed(reason, apnType); } public void notifyCellLocation(Bundle cellLocation) { @@ -410,39 +466,36 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } synchronized (mRecords) { mCellLocation = cellLocation; - for (int i = mRecords.size() - 1; i >= 0; i--) { - Record r = mRecords.get(i); + for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_CELL_LOCATION) != 0) { - sendCellLocation(r, cellLocation); + try { + r.callback.onCellLocationChanged(new Bundle(cellLocation)); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } } + handleRemoveListLocked(); } } - /** - * Copy the service state object so they can't mess it up in the local calls - */ - public void sendServiceState(Record r, ServiceState state) { - try { - r.callback.onServiceStateChanged(new ServiceState(state)); - } catch (RemoteException ex) { - remove(r.binder); - } - } - - private void sendCellLocation(Record r, Bundle cellLocation) { - try { - r.callback.onCellLocationChanged(new Bundle(cellLocation)); - } catch (RemoteException ex) { - remove(r.binder); + public void notifyOtaspChanged(int otaspMode) { + if (!checkNotifyPermission("notifyOtaspChanged()" )) { + return; } - } - - private void sendSignalStrength(Record r, SignalStrength signalStrength) { - try { - r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength)); - } catch (RemoteException ex) { - remove(r.binder); + synchronized (mRecords) { + mOtaspMode = otaspMode; + for (Record r : mRecords) { + if ((r.events & PhoneStateListener.LISTEN_OTASP_CHANGED) != 0) { + try { + r.callback.onOtaspChanged(otaspMode); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); } } @@ -468,11 +521,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println(" mDataConnectionPossible=" + mDataConnectionPossible); pw.println(" mDataConnectionReason=" + mDataConnectionReason); pw.println(" mDataConnectionApn=" + mDataConnectionApn); - pw.println(" mDataConnectionInterfaceName=" + mDataConnectionInterfaceName); + pw.println(" mDataConnectionLinkProperties=" + mDataConnectionLinkProperties); + pw.println(" mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities); pw.println(" mCellLocation=" + mCellLocation); pw.println("registrations: count=" + recordCount); - for (int i = 0; i < recordCount; i++) { - Record r = mRecords.get(i); + for (Record r : mRecords) { pw.println(" " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events)); } } @@ -543,7 +596,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private void broadcastDataConnectionStateChanged(int state, boolean isDataConnectivityPossible, - String reason, String apn, String[] apnTypes, String interfaceName, String gateway) { + String reason, String apn, String apnType, LinkProperties linkProperties, + LinkCapabilities linkCapabilities) { // Note: not reporting to the battery stats service here, because the // status bar takes care of that after taking into account all of the // required info. @@ -556,29 +610,26 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (reason != null) { intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason); } - intent.putExtra(Phone.DATA_APN_KEY, apn); - String types = new String(""); - if (apnTypes.length > 0) { - types = apnTypes[0]; - for (int i = 1; i < apnTypes.length; i++) { - types = types+","+apnTypes[i]; + if (linkProperties != null) { + intent.putExtra(Phone.DATA_LINK_PROPERTIES_KEY, linkProperties); + String iface = linkProperties.getInterfaceName(); + if (iface != null) { + intent.putExtra(Phone.DATA_IFACE_NAME_KEY, iface); } } - intent.putExtra(Phone.DATA_APN_TYPES_KEY, types); - intent.putExtra(Phone.DATA_IFACE_NAME_KEY, interfaceName); - int gatewayAddr = 0; - if (gateway != null) { - gatewayAddr = NetworkUtils.v4StringToInt(gateway); + if (linkCapabilities != null) { + intent.putExtra(Phone.DATA_LINK_CAPABILITIES_KEY, linkCapabilities); } - intent.putExtra(Phone.DATA_GATEWAY_KEY, gatewayAddr); - + intent.putExtra(Phone.DATA_APN_KEY, apn); + intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType); mContext.sendStickyBroadcast(intent); } - private void broadcastDataConnectionFailed(String reason) { + private void broadcastDataConnectionFailed(String reason, String apnType) { Intent intent = new Intent(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(Phone.FAILURE_REASON_KEY, reason); + intent.putExtra(Phone.DATA_APN_TYPE_KEY, apnType); mContext.sendStickyBroadcast(intent); } @@ -605,4 +656,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { android.Manifest.permission.READ_PHONE_STATE, null); } } + + private void handleRemoveListLocked() { + if (mRemoveList.size() > 0) { + for (IBinder b: mRemoveList) { + remove(b); + } + mRemoveList.clear(); + } + } } |