diff options
| -rw-r--r-- | api/current.txt | 13 | ||||
| -rwxr-xr-x | api/system-current.txt | 15 | ||||
| -rw-r--r-- | api/test-current.txt | 4 | ||||
| -rw-r--r-- | core/java/android/telephony/PhoneStateListener.java | 45 | ||||
| -rw-r--r-- | core/java/android/telephony/TelephonyRegistryManager.java | 48 | ||||
| -rw-r--r-- | core/java/com/android/internal/telephony/ITelephonyRegistry.aidl | 11 | ||||
| -rw-r--r-- | services/core/java/com/android/server/TelephonyRegistry.java | 167 | ||||
| -rw-r--r-- | telephony/java/android/telephony/PreciseDataConnectionState.java | 179 | ||||
| -rw-r--r-- | telephony/java/android/telephony/TelephonyManager.java | 29 | ||||
| -rw-r--r-- | telephony/java/com/android/internal/telephony/PhoneConstantConversions.java | 8 | ||||
| -rw-r--r-- | telephony/java/com/android/internal/telephony/PhoneConstants.java | 12 |
11 files changed, 327 insertions, 204 deletions
diff --git a/api/current.txt b/api/current.txt index 5fbd96711b51..08f63c319c7f 100644 --- a/api/current.txt +++ b/api/current.txt @@ -44752,6 +44752,7 @@ package android.telephony { method public void onDataConnectionStateChanged(int); method public void onDataConnectionStateChanged(int, int); method public void onMessageWaitingIndicatorChanged(boolean); + method @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); method public void onServiceStateChanged(android.telephony.ServiceState); method @Deprecated public void onSignalStrengthChanged(int); method public void onSignalStrengthsChanged(android.telephony.SignalStrength); @@ -44766,12 +44767,23 @@ package android.telephony { field public static final int LISTEN_EMERGENCY_NUMBER_LIST = 16777216; // 0x1000000 field public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 4; // 0x4 field public static final int LISTEN_NONE = 0; // 0x0 + field @RequiresPermission("android.permission.MODIFY_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000 field public static final int LISTEN_SERVICE_STATE = 1; // 0x1 field @Deprecated public static final int LISTEN_SIGNAL_STRENGTH = 2; // 0x2 field public static final int LISTEN_SIGNAL_STRENGTHS = 256; // 0x100 field public static final int LISTEN_USER_MOBILE_DATA_STATE = 524288; // 0x80000 } + public final class PreciseDataConnectionState implements android.os.Parcelable { + method public int describeContents(); + method public int getLastCauseCode(); + method @Nullable public android.net.LinkProperties getLinkProperties(); + method public int getNetworkType(); + method public int getState(); + method public void writeToParcel(@NonNull android.os.Parcel, int); + field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR; + } + public final class RadioAccessSpecifier implements android.os.Parcelable { ctor public RadioAccessSpecifier(int, int[], int[]); method public int describeContents(); @@ -45274,6 +45286,7 @@ package android.telephony { field public static final int DATA_CONNECTED = 2; // 0x2 field public static final int DATA_CONNECTING = 1; // 0x1 field public static final int DATA_DISCONNECTED = 0; // 0x0 + field public static final int DATA_DISCONNECTING = 4; // 0x4 field public static final int DATA_SUSPENDED = 3; // 0x3 field public static final int DATA_UNKNOWN = -1; // 0xffffffff field public static final String EXTRA_CALL_VOICEMAIL_INTENT = "android.telephony.extra.CALL_VOICEMAIL_INTENT"; diff --git a/api/system-current.txt b/api/system-current.txt index b0c359151c0d..0012e35cb299 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -8505,7 +8505,6 @@ package android.telephony { method public void onOutgoingEmergencyCall(@NonNull android.telephony.emergency.EmergencyNumber); method public void onOutgoingEmergencySms(@NonNull android.telephony.emergency.EmergencyNumber); method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState); - method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseDataConnectionStateChanged(@NonNull android.telephony.PreciseDataConnectionState); method public void onRadioPowerStateChanged(int); method public void onSrvccStateChanged(int); method public void onVoiceActivationStateChanged(int); @@ -8515,7 +8514,6 @@ package android.telephony { field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_CALL = 268435456; // 0x10000000 field @RequiresPermission(android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION) public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000 field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800 - field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000 field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000 field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000 field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000 @@ -8541,13 +8539,12 @@ package android.telephony { } public final class PreciseDataConnectionState implements android.os.Parcelable { - method public int describeContents(); - method @Nullable public String getDataConnectionApn(); - method public int getDataConnectionApnTypeBitMask(); - method public int getDataConnectionFailCause(); - method public int getDataConnectionState(); - method public void writeToParcel(android.os.Parcel, int); - field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR; + method @Deprecated @NonNull public String getDataConnectionApn(); + method @Deprecated public int getDataConnectionApnTypeBitMask(); + method @Deprecated public int getDataConnectionFailCause(); + method @Deprecated @Nullable public android.net.LinkProperties getDataConnectionLinkProperties(); + method @Deprecated public int getDataConnectionNetworkType(); + method @Deprecated public int getDataConnectionState(); } public final class PreciseDisconnectCause { diff --git a/api/test-current.txt b/api/test-current.txt index 44498dd16b87..22ac3abcefd9 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -3004,6 +3004,10 @@ package android.telephony { field @RequiresPermission("android.permission.READ_ACTIVE_EMERGENCY_SESSION") public static final int LISTEN_OUTGOING_EMERGENCY_SMS = 536870912; // 0x20000000 } + public final class PreciseDataConnectionState implements android.os.Parcelable { + ctor @Deprecated public PreciseDataConnectionState(int, int, int, @NonNull String, @Nullable android.net.LinkProperties, int); + } + public class ServiceState implements android.os.Parcelable { method public void addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo); method public void setCdmaSystemAndNetworkId(int, int); diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java index 716a5225ea91..e3f11a19f483 100644 --- a/core/java/android/telephony/PhoneStateListener.java +++ b/core/java/android/telephony/PhoneStateListener.java @@ -35,8 +35,8 @@ import android.telephony.Annotation.SrvccState; import android.telephony.emergency.EmergencyNumber; import android.telephony.ims.ImsReasonInfo; -import com.android.internal.telephony.IPhoneStateListener; import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.telephony.IPhoneStateListener; import dalvik.system.VMRuntime; @@ -196,12 +196,13 @@ public class PhoneStateListener { /** * Listen for {@link PreciseDataConnectionState} on the data connection (cellular). * - * @see #onPreciseDataConnectionStateChanged + * <p>Requires permission {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). * - * @hide + * @see #onPreciseDataConnectionStateChanged */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) - @SystemApi + @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE)) public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 0x00001000; /** @@ -719,8 +720,9 @@ public class PhoneStateListener { } /** - * Callback invoked when data connection state changes with precise information - * on the registered subscription. + * Callback providing update about the default/internet data connection on the registered + * subscription. + * * Note, the registration subId comes from {@link TelephonyManager} object which registers * PhoneStateListener by {@link TelephonyManager#listen(PhoneStateListener, int)}. * If this TelephonyManager object was created with @@ -728,12 +730,13 @@ public class PhoneStateListener { * subId. Otherwise, this callback applies to * {@link SubscriptionManager#getDefaultSubscriptionId()}. * - * @param dataConnectionState {@link PreciseDataConnectionState} + * <p>Requires permission {@link android.Manifest.permission#MODIFY_PHONE_STATE} + * or the calling app has carrier privileges + * (see {@link TelephonyManager#hasCarrierPrivileges}). * - * @hide + * @param dataConnectionState {@link PreciseDataConnectionState} */ - @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE)) - @SystemApi + @RequiresPermission((android.Manifest.permission.MODIFY_PHONE_STATE)) public void onPreciseDataConnectionStateChanged( @NonNull PreciseDataConnectionState dataConnectionState) { // default implementation empty @@ -1042,11 +1045,21 @@ public class PhoneStateListener { PhoneStateListener psl = mPhoneStateListenerWeakRef.get(); if (psl == null) return; - Binder.withCleanCallingIdentity(() -> mExecutor.execute( - () -> { - psl.onDataConnectionStateChanged(state, networkType); - psl.onDataConnectionStateChanged(state); - })); + if (state == TelephonyManager.DATA_DISCONNECTING + && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) { + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> { + psl.onDataConnectionStateChanged( + TelephonyManager.DATA_CONNECTED, networkType); + psl.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED); + })); + } else { + Binder.withCleanCallingIdentity(() -> mExecutor.execute( + () -> { + psl.onDataConnectionStateChanged(state, networkType); + psl.onDataConnectionStateChanged(state); + })); + } } public void onDataActivity(int direction) { diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index f87a7c57fda4..1a12eaf853eb 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -21,17 +21,13 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.TestApi; import android.content.Context; -import android.net.LinkProperties; -import android.net.NetworkCapabilities; import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; import android.os.ServiceManager; -import android.telephony.Annotation.ApnType; import android.telephony.Annotation.CallState; import android.telephony.Annotation.DataActivityType; import android.telephony.Annotation.DataFailureCause; -import android.telephony.Annotation.DataState; import android.telephony.Annotation.NetworkType; import android.telephony.Annotation.PreciseCallStates; import android.telephony.Annotation.RadioPowerState; @@ -363,27 +359,18 @@ public class TelephonyRegistryManager { * @param subId for which data connection state changed. * @param slotIndex for which data connections state changed. Can be derived from subId except * when subId is invalid. - * @param state latest data connection state, e.g, - * @param isDataConnectivityPossible indicates if data is allowed - * @param apn the APN {@link ApnSetting#getApnName()} of this data connection. - * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN. - * @param linkProperties {@link LinkProperties} associated with this data connection. - * @param networkCapabilities {@link NetworkCapabilities} associated with this data connection. - * @param networkType associated with this data connection. - * @param roaming {@code true} indicates in roaming, {@false} otherwise. - * @see TelephonyManager#DATA_DISCONNECTED - * @see TelephonyManager#isDataConnectivityPossible() + * @param apnType the APN type that triggered this update + * @param preciseState the PreciseDataConnectionState * + * @see android.telephony.PreciseDataConnection + * @see TelephonyManager#DATA_DISCONNECTED * @hide */ - public void notifyDataConnectionForSubscriber(int slotIndex, int subId, @DataState int state, - boolean isDataConnectivityPossible, - @ApnType String apn, String apnType, LinkProperties linkProperties, - NetworkCapabilities networkCapabilities, int networkType, boolean roaming) { + public void notifyDataConnectionForSubscriber(int slotIndex, int subId, + String apnType, PreciseDataConnectionState preciseState) { try { - sRegistry.notifyDataConnectionForSubscriber(slotIndex, subId, state, - isDataConnectivityPossible, - apn, apnType, linkProperties, networkCapabilities, networkType, roaming); + sRegistry.notifyDataConnectionForSubscriber( + slotIndex, subId, apnType, preciseState); } catch (RemoteException ex) { // system process is dead } @@ -668,25 +655,6 @@ public class TelephonyRegistryManager { } /** - * Notify data connection failed on certain subscription. - * - * @param subId for which data connection failed. - * @param slotIndex for which data conenction faled. Can be derived from subId except when subId - * is invalid. - * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN. Note each data - * connection can support multiple anyTypes. - * - * @hide - */ - public void notifyDataConnectionFailed(int subId, int slotIndex, String apnType) { - try { - sRegistry.notifyDataConnectionFailedForSubscriber(slotIndex, subId, apnType); - } catch (RemoteException ex) { - // system process is dead - } - } - - /** * TODO change from bundle to CellLocation? * @hide */ diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index f4e63183957e..1f80cdd53377 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -24,6 +24,8 @@ import android.telephony.CallQuality; import android.telephony.CellInfo; import android.telephony.ims.ImsReasonInfo; import android.telephony.PhoneCapability; +import android.telephony.PhysicalChannelConfig; +import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.emergency.EmergencyNumber; @@ -54,13 +56,8 @@ interface ITelephonyRegistry { @UnsupportedAppUsage(maxTargetSdk = 28) void notifyDataActivity(int state); void notifyDataActivityForSubscriber(in int subId, int state); - void notifyDataConnection(int state, boolean isDataConnectivityPossible, - String apn, String apnType, in LinkProperties linkProperties, - in NetworkCapabilities networkCapabilities, int networkType, boolean roaming); - void notifyDataConnectionForSubscriber(int phoneId, int subId, int state, - boolean isDataConnectivityPossible, - String apn, String apnType, in LinkProperties linkProperties, - in NetworkCapabilities networkCapabilities, int networkType, boolean roaming); + void notifyDataConnectionForSubscriber( + int phoneId, int subId, String apnType, in PreciseDataConnectionState preciseState); @UnsupportedAppUsage void notifyDataConnectionFailed(String apnType); void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 92f6241a79a3..fe306f88d76e 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -30,7 +30,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.net.LinkProperties; -import android.net.NetworkCapabilities; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -258,7 +257,9 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private final LocalLog mListenLog = new LocalLog(100); - private PreciseDataConnectionState[] mPreciseDataConnectionState; + // Per-phoneMap of APN Type to DataConnectionState + private List<Map<String, PreciseDataConnectionState>> mPreciseDataConnectionStates = + new ArrayList<Map<String, PreciseDataConnectionState>>(); // Nothing here yet, but putting it here in case we want to add more in the future. static final int ENFORCE_COARSE_LOCATION_PERMISSION_MASK = 0; @@ -413,7 +414,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mCallQuality = copyOf(mCallQuality, mNumPhones); mCallNetworkType = copyOf(mCallNetworkType, mNumPhones); mCallAttributes = copyOf(mCallAttributes, mNumPhones); - mPreciseDataConnectionState = copyOf(mPreciseDataConnectionState, mNumPhones); mOutgoingCallEmergencyNumber = copyOf(mOutgoingCallEmergencyNumber, mNumPhones); mOutgoingSmsEmergencyNumber = copyOf(mOutgoingSmsEmergencyNumber, mNumPhones); @@ -421,6 +421,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (mNumPhones < oldNumPhones) { cutListToSize(mCellInfo, mNumPhones); cutListToSize(mImsReasonInfo, mNumPhones); + cutListToSize(mPreciseDataConnectionStates, mNumPhones); return; } @@ -452,7 +453,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; - mPreciseDataConnectionState[i] = new PreciseDataConnectionState(); + mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>()); } // Note that location can be null for non-phone builds like @@ -514,7 +515,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mCallQuality = new CallQuality[numPhones]; mCallNetworkType = new int[numPhones]; mCallAttributes = new CallAttributes[numPhones]; - mPreciseDataConnectionState = new PreciseDataConnectionState[numPhones]; + mPreciseDataConnectionStates = new ArrayList<>(); mCellInfo = new ArrayList<>(); mImsReasonInfo = new ArrayList<>(); mEmergencyNumberList = new HashMap<>(); @@ -547,7 +548,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mForegroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; - mPreciseDataConnectionState[i] = new PreciseDataConnectionState(); + mPreciseDataConnectionStates.add(new HashMap<String, PreciseDataConnectionState>()); } // Note that location can be null for non-phone builds like @@ -909,8 +910,10 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } if ((events & PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) != 0) { try { - r.callback.onPreciseDataConnectionStateChanged( - mPreciseDataConnectionState[phoneId]); + for (PreciseDataConnectionState pdcs + : mPreciseDataConnectionStates.get(phoneId).values()) { + r.callback.onPreciseDataConnectionStateChanged(pdcs); + } } catch (RemoteException ex) { remove(r.binder); } @@ -924,7 +927,8 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } if ((events & PhoneStateListener.LISTEN_VOICE_ACTIVATION_STATE) !=0) { try { - r.callback.onVoiceActivationStateChanged(mVoiceActivationState[phoneId]); + r.callback.onVoiceActivationStateChanged( + mVoiceActivationState[phoneId]); } catch (RemoteException ex) { remove(r.binder); } @@ -1482,30 +1486,38 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - public void notifyDataConnection(int state, boolean isDataAllowed, String apn, String apnType, - LinkProperties linkProperties, - NetworkCapabilities networkCapabilities, int networkType, - boolean roaming) { - notifyDataConnectionForSubscriber(SubscriptionManager.DEFAULT_PHONE_INDEX, - SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, state, - isDataAllowed, apn, apnType, linkProperties, - networkCapabilities, networkType, roaming); - } - - public void notifyDataConnectionForSubscriber(int phoneId, int subId, int state, - boolean isDataAllowed, - String apn, String apnType, - LinkProperties linkProperties, NetworkCapabilities networkCapabilities, - int networkType, boolean roaming) { + /** + * Send a notification to registrants that the data connection state has changed. + * + * @param phoneId the phoneId carrying the data connection + * @param subId the subscriptionId for the data connection + * @param apnType the APN type that triggered a change in the data connection + * @param preciseState a PreciseDataConnectionState that has info about the data connection + */ + public void notifyDataConnectionForSubscriber( + int phoneId, int subId, String apnType, PreciseDataConnectionState preciseState) { if (!checkNotifyPermission("notifyDataConnection()" )) { return; } + + String apn = ""; + int state = TelephonyManager.DATA_UNKNOWN; + int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; + LinkProperties linkProps = null; + + if (preciseState != null) { + apn = preciseState.getDataConnectionApn(); + state = preciseState.getState(); + networkType = preciseState.getNetworkType(); + linkProps = preciseState.getDataConnectionLinkProperties(); + } if (VDBG) { log("notifyDataConnectionForSubscriber: subId=" + subId - + " state=" + state + " isDataAllowed=" + isDataAllowed - + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType - + " mRecords.size()=" + mRecords.size()); + + " state=" + state + "' apn='" + apn + + "' apnType=" + apnType + " networkType=" + networkType + + "' preciseState=" + preciseState); } + synchronized (mRecords) { if (validatePhoneId(phoneId)) { // We only call the callback when the change is for default APN type. @@ -1537,33 +1549,45 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mDataConnectionState[phoneId] = state; mDataConnectionNetworkType[phoneId] = networkType; } - mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState( - state, networkType, - ApnSetting.getApnTypesBitmaskFromString(apnType), apn, - linkProperties, DataFailCause.NONE); - for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent( - PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) - && idMatch(r.subId, subId, phoneId)) { - try { - r.callback.onPreciseDataConnectionStateChanged( - mPreciseDataConnectionState[phoneId]); - } catch (RemoteException ex) { - mRemoveList.add(r.binder); + + boolean needsNotify = false; + // State has been cleared for this APN Type + if (preciseState == null) { + // We try clear the state and check if the state was previously not cleared + needsNotify = mPreciseDataConnectionStates.get(phoneId).remove(apnType) != null; + } else { + // We need to check to see if the state actually changed + PreciseDataConnectionState oldPreciseState = + mPreciseDataConnectionStates.get(phoneId).put(apnType, preciseState); + needsNotify = !preciseState.equals(oldPreciseState); + } + + if (needsNotify) { + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) + && idMatch(r.subId, subId, phoneId)) { + try { + r.callback.onPreciseDataConnectionStateChanged(preciseState); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } } } } } handleRemoveListLocked(); } - broadcastDataConnectionStateChanged(state, isDataAllowed, apn, apnType, linkProperties, - networkCapabilities, roaming, subId); + + broadcastDataConnectionStateChanged(state, apn, apnType, subId); } + /** + * Stub to satisfy the ITelephonyRegistry aidl interface; do not use this function. + * @see #notifyDataConnectionFailedForSubscriber + */ public void notifyDataConnectionFailed(String apnType) { - notifyDataConnectionFailedForSubscriber(SubscriptionManager.DEFAULT_PHONE_INDEX, - SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, - apnType); + loge("This function should not be invoked"); } public void notifyDataConnectionFailedForSubscriber(int phoneId, int subId, String apnType) { @@ -1576,17 +1600,20 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } synchronized (mRecords) { if (validatePhoneId(phoneId)) { - mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState( - TelephonyManager.DATA_UNKNOWN,TelephonyManager.NETWORK_TYPE_UNKNOWN, - ApnSetting.getApnTypesBitmaskFromString(apnType), null, null, - DataFailCause.NONE); + mPreciseDataConnectionStates.get(phoneId).put( + apnType, + new PreciseDataConnectionState( + TelephonyManager.DATA_UNKNOWN, + TelephonyManager.NETWORK_TYPE_UNKNOWN, + ApnSetting.getApnTypesBitmaskFromString(apnType), null, null, + DataFailCause.NONE)); for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onPreciseDataConnectionStateChanged( - mPreciseDataConnectionState[phoneId]); + mPreciseDataConnectionStates.get(phoneId).get(apnType)); } catch (RemoteException ex) { mRemoveList.add(r.binder); } @@ -1774,25 +1801,32 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { if (!checkNotifyPermission("notifyPreciseDataConnectionFailed()")) { return; } + + // precise notify invokes imprecise notify + notifyDataConnectionFailedForSubscriber(phoneId, subId, apnType); + synchronized (mRecords) { if (validatePhoneId(phoneId)) { - mPreciseDataConnectionState[phoneId] = new PreciseDataConnectionState( - TelephonyManager.DATA_UNKNOWN, TelephonyManager.NETWORK_TYPE_UNKNOWN, - ApnSetting.getApnTypesBitmaskFromString(apnType), apn, null, failCause); + mPreciseDataConnectionStates.get(phoneId).put( + apnType, + new PreciseDataConnectionState( + TelephonyManager.DATA_UNKNOWN, + TelephonyManager.NETWORK_TYPE_UNKNOWN, + ApnSetting.getApnTypesBitmaskFromString(apnType), null, null, + failCause)); for (Record r : mRecords) { if (r.matchPhoneStateListenerEvent( PhoneStateListener.LISTEN_PRECISE_DATA_CONNECTION_STATE) && idMatch(r.subId, subId, phoneId)) { try { r.callback.onPreciseDataConnectionStateChanged( - mPreciseDataConnectionState[phoneId]); + mPreciseDataConnectionStates.get(phoneId).get(apnType)); } catch (RemoteException ex) { mRemoveList.add(r.binder); } } } } - handleRemoveListLocked(); } } @@ -2050,7 +2084,6 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); @@ -2089,7 +2122,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mCallQuality=" + mCallQuality[i]); pw.println("mCallAttributes=" + mCallAttributes[i]); pw.println("mCallNetworkType=" + mCallNetworkType[i]); - pw.println("mPreciseDataConnectionState=" + mPreciseDataConnectionState[i]); + pw.println("mPreciseDataConnectionStates=" + mPreciseDataConnectionStates.get(i)); pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]); pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]); pw.decreaseIndent(); @@ -2249,29 +2282,13 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } } - private void broadcastDataConnectionStateChanged(int state, boolean isDataAllowed, String apn, - String apnType, LinkProperties linkProperties, - NetworkCapabilities networkCapabilities, - boolean roaming, int subId) { + private void broadcastDataConnectionStateChanged(int state, String apn, + String apnType, int subId) { // 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. Intent intent = new Intent(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); intent.putExtra(TelephonyManager.EXTRA_STATE, dataStateToString(state)); - if (!isDataAllowed) { - intent.putExtra(PhoneConstants.NETWORK_UNAVAILABLE_KEY, true); - } - if (linkProperties != null) { - intent.putExtra(PhoneConstants.DATA_LINK_PROPERTIES_KEY, linkProperties); - String iface = linkProperties.getInterfaceName(); - if (iface != null) { - intent.putExtra(PhoneConstants.DATA_IFACE_NAME_KEY, iface); - } - } - if (networkCapabilities != null) { - intent.putExtra(PhoneConstants.DATA_NETWORK_CAPABILITIES_KEY, networkCapabilities); - } - if (roaming) intent.putExtra(PhoneConstants.DATA_NETWORK_ROAMING_KEY, true); intent.putExtra(PhoneConstants.DATA_APN_KEY, apn); intent.putExtra(PhoneConstants.DATA_APN_TYPE_KEY, apnType); diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java index 257d634f1577..78ad5c58423c 100644 --- a/telephony/java/android/telephony/PreciseDataConnectionState.java +++ b/telephony/java/android/telephony/PreciseDataConnectionState.java @@ -19,8 +19,10 @@ package android.telephony; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.annotation.UnsupportedAppUsage; import android.net.LinkProperties; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; import android.telephony.Annotation.ApnType; @@ -29,6 +31,8 @@ import android.telephony.Annotation.DataState; import android.telephony.Annotation.NetworkType; import android.telephony.data.ApnSetting; +import dalvik.system.VMRuntime; + import java.util.Objects; @@ -46,35 +50,62 @@ import java.util.Objects; * <li>Data connection fail cause. * </ul> * - * @hide */ -@SystemApi public final class PreciseDataConnectionState implements Parcelable { private @DataState int mState = TelephonyManager.DATA_UNKNOWN; private @NetworkType int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; private @DataFailureCause int mFailCause = DataFailCause.NONE; - private @ApnType int mAPNTypes = ApnSetting.TYPE_NONE; - private String mAPN = ""; + private @ApnType int mApnTypes = ApnSetting.TYPE_NONE; + private String mApn = ""; private LinkProperties mLinkProperties = null; + private ApnSetting mApnSetting = null; /** * Constructor * + * @deprecated this constructor has been superseded and should not be used. * @hide */ - @UnsupportedAppUsage + @TestApi + @Deprecated + @UnsupportedAppUsage // (maxTargetSdk = Build.VERSION_CODES.Q) + // FIXME: figure out how to remove the UnsupportedAppUsage and delete this constructor public PreciseDataConnectionState(@DataState int state, @NetworkType int networkType, - @ApnType int apnTypes, String apn, - LinkProperties linkProperties, + @ApnType int apnTypes, @NonNull String apn, + @Nullable LinkProperties linkProperties, @DataFailureCause int failCause) { + this(state, networkType, apnTypes, apn, linkProperties, failCause, null); + } + + + /** + * Constructor + * + * @param state the state of the data connection + * @param networkType the access network that is/would carry this data connection + * @param apnTypes the APN types that this data connection carries + * @param apnSetting if there is a valid APN for this Data Connection, then the APN Settings; + * if there is no valid APN setting for the specific type, then this will be null + * @param linkProperties if the data connection is connected, the properties of the connection + * @param failCause in case a procedure related to this data connection fails, a non-zero error + * code indicating the cause of the failure. + * @hide + */ + public PreciseDataConnectionState(@DataState int state, + @NetworkType int networkType, + @ApnType int apnTypes, @NonNull String apn, + @Nullable LinkProperties linkProperties, + @DataFailureCause int failCause, + @Nullable ApnSetting apnSetting) { mState = state; mNetworkType = networkType; - mAPNTypes = apnTypes; - mAPN = apn; + mApnTypes = apnTypes; + mApn = apn; mLinkProperties = linkProperties; mFailCause = failCause; + mApnSetting = apnSetting; } /** @@ -93,76 +124,160 @@ public final class PreciseDataConnectionState implements Parcelable { private PreciseDataConnectionState(Parcel in) { mState = in.readInt(); mNetworkType = in.readInt(); - mAPNTypes = in.readInt(); - mAPN = in.readString(); - mLinkProperties = (LinkProperties)in.readParcelable(null); + mApnTypes = in.readInt(); + mApn = in.readString(); + mLinkProperties = (LinkProperties) in.readParcelable(null); mFailCause = in.readInt(); + mApnSetting = (ApnSetting) in.readParcelable(null); } /** * Returns the state of data connection that supported the apn types returned by * {@link #getDataConnectionApnTypeBitMask()} + * + * @deprecated use {@link #getState()} + * @hide */ + @Deprecated + @SystemApi public @DataState int getDataConnectionState() { + if (mState == TelephonyManager.DATA_DISCONNECTING + && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) { + return TelephonyManager.DATA_CONNECTED; + } + + return mState; + } + + /** + * Returns the high-level state of this data connection. + */ + public @DataState int getState() { return mState; } /** * Returns the network type associated with this data connection. + * + * @deprecated use {@link getNetworkType()} * @hide */ + @Deprecated + @SystemApi public @NetworkType int getDataConnectionNetworkType() { return mNetworkType; } /** - * Returns the data connection APN types supported by this connection and triggers - * {@link PreciseDataConnectionState} change. + * Returns the network type associated with this data connection. + * + * Return the current/latest (radio) bearer technology that carries this data connection. + * For a variety of reasons, the network type can change during the life of the data + * connection, and this information is not reliable unless the physical link is currently + * active; (there is currently no mechanism to know whether the physical link is active at + * any given moment). Thus, this value is generally correct but may not be relied-upon to + * represent the status of the radio bearer at any given moment. + */ + public @NetworkType int getNetworkType() { + return mNetworkType; + } + + /** + * Returns the APN types mapped to this data connection. + * + * @deprecated use {@link #getApnSetting()} + * @hide */ + @Deprecated + @SystemApi public @ApnType int getDataConnectionApnTypeBitMask() { - return mAPNTypes; + return mApnTypes; } /** - * Returns APN {@link ApnSetting} of this data connection. + * Returns APN of this data connection. + * + * @deprecated use {@link #getApnSetting()} + * @hide */ - @Nullable + @NonNull + @SystemApi + @Deprecated public String getDataConnectionApn() { - return mAPN; + return mApn; } /** * Get the properties of the network link {@link LinkProperties}. + * + * @deprecated use {@link #getLinkProperties()} * @hide */ - @UnsupportedAppUsage + @Deprecated + @SystemApi + @Nullable public LinkProperties getDataConnectionLinkProperties() { return mLinkProperties; } /** - * Returns data connection fail cause, in case there was a failure. + * Get the properties of the network link {@link LinkProperties}. + */ + @Nullable + public LinkProperties getLinkProperties() { + return mLinkProperties; + } + + /** + * Returns the cause code generated by the most recent state change. + * + * @deprecated use {@link #getLastCauseCode()} + * @hide + */ + @Deprecated + @SystemApi + public int getDataConnectionFailCause() { + return mFailCause; + } + + /** + * Returns the cause code generated by the most recent state change. + * + * Return the cause code for the most recent change in {@link #getState}. In the event of an + * error, this cause code will be non-zero. */ - public @Annotation.DataFailureCause int getDataConnectionFailCause() { + // FIXME(b144774287): some of these cause codes should have a prescribed meaning. + public int getLastCauseCode() { return mFailCause; } + /** + * Return the APN Settings for this data connection. + * + * Returns the ApnSetting that was used to configure this data connection. + */ + // FIXME: This shouldn't be nullable; update once the ApnSetting is supplied correctly + @Nullable ApnSetting getApnSetting() { + return mApnSetting; + } + @Override public int describeContents() { return 0; } @Override - public void writeToParcel(Parcel out, int flags) { + public void writeToParcel(@NonNull Parcel out, int flags) { out.writeInt(mState); out.writeInt(mNetworkType); - out.writeInt(mAPNTypes); - out.writeString(mAPN); + out.writeInt(mApnTypes); + out.writeString(mApn); out.writeParcelable(mLinkProperties, flags); out.writeInt(mFailCause); + out.writeParcelable(mApnSetting, flags); } - public static final @android.annotation.NonNull Parcelable.Creator<PreciseDataConnectionState> CREATOR + public static final @NonNull Parcelable.Creator<PreciseDataConnectionState> CREATOR = new Parcelable.Creator<PreciseDataConnectionState>() { public PreciseDataConnectionState createFromParcel(Parcel in) { @@ -176,8 +291,8 @@ public final class PreciseDataConnectionState implements Parcelable { @Override public int hashCode() { - return Objects.hash(mState, mNetworkType, mAPNTypes, mAPN, mLinkProperties, - mFailCause); + return Objects.hash(mState, mNetworkType, mApnTypes, mApn, mLinkProperties, + mFailCause, mApnSetting); } @Override @@ -188,11 +303,12 @@ public final class PreciseDataConnectionState implements Parcelable { } PreciseDataConnectionState other = (PreciseDataConnectionState) obj; - return Objects.equals(mAPN, other.mAPN) && mAPNTypes == other.mAPNTypes + return Objects.equals(mApn, other.mApn) && mApnTypes == other.mApnTypes && mFailCause == other.mFailCause && Objects.equals(mLinkProperties, other.mLinkProperties) && mNetworkType == other.mNetworkType - && mState == other.mState; + && mState == other.mState + && Objects.equals(mApnSetting, other.mApnSetting); } @NonNull @@ -202,10 +318,11 @@ public final class PreciseDataConnectionState implements Parcelable { sb.append("Data Connection state: " + mState); sb.append(", Network type: " + mNetworkType); - sb.append(", APN types: " + ApnSetting.getApnTypesStringFromBitmask(mAPNTypes)); - sb.append(", APN: " + mAPN); + sb.append(", APN types: " + ApnSetting.getApnTypesStringFromBitmask(mApnTypes)); + sb.append(", APN: " + mApn); sb.append(", Link properties: " + mLinkProperties); sb.append(", Fail cause: " + DataFailCause.toString(mFailCause)); + sb.append(", Apn Setting: " + mApnSetting); return sb.toString(); } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 642030b32fec..a11bbf525ebe 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -777,18 +777,6 @@ public class TelephonyManager { public static final String EXTRA_DATA_APN = PhoneConstants.DATA_APN_KEY; /** - * The lookup key used with the {@link #ACTION_PRECISE_DATA_CONNECTION_STATE_CHANGED} broadcast - * for an String representation of the data interface. - * - * <p class="note"> - * Retrieve with - * {@link android.content.Intent#getParcelableExtra(String name)}. - * - * @hide - */ - public static final String EXTRA_DATA_LINK_PROPERTIES_KEY = PhoneConstants.DATA_LINK_PROPERTIES_KEY; - - /** * Broadcast intent action for letting the default dialer to know to show voicemail * notification. * @@ -4982,6 +4970,7 @@ public class TelephonyManager { DATA_CONNECTING, DATA_CONNECTED, DATA_SUSPENDED, + DATA_DISCONNECTING, }) @Retention(RetentionPolicy.SOURCE) public @interface DataState{} @@ -4998,6 +4987,12 @@ public class TelephonyManager { * traffic is temporarily unavailable. For example, in a 2G network, * data activity may be suspended when a voice call arrives. */ public static final int DATA_SUSPENDED = 3; + /** + * Data connection state: Disconnecting. + * + * IP traffic may be available but will cease working imminently. + */ + public static final int DATA_DISCONNECTING = 4; /** * Returns a constant indicating the current data connection state @@ -5007,14 +5002,21 @@ public class TelephonyManager { * @see #DATA_CONNECTING * @see #DATA_CONNECTED * @see #DATA_SUSPENDED + * @see #DATA_DISCONNECTING */ public int getDataState() { try { ITelephony telephony = getITelephony(); if (telephony == null) return DATA_DISCONNECTED; - return telephony.getDataStateForSubId( + int state = telephony.getDataStateForSubId( getSubId(SubscriptionManager.getActiveDataSubscriptionId())); + if (state == TelephonyManager.DATA_DISCONNECTING + && VMRuntime.getRuntime().getTargetSdkVersion() < Build.VERSION_CODES.R) { + return TelephonyManager.DATA_CONNECTED; + } + + return state; } catch (RemoteException ex) { // the phone process is restarting. return DATA_DISCONNECTED; @@ -5035,6 +5037,7 @@ public class TelephonyManager { case DATA_CONNECTING: return "CONNECTING"; case DATA_CONNECTED: return "CONNECTED"; case DATA_SUSPENDED: return "SUSPENDED"; + case DATA_DISCONNECTING: return "DISCONNECTING"; } return "UNKNOWN(" + state + ")"; } diff --git a/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java b/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java index f7f0f29fcb29..8640acca7c8c 100644 --- a/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstantConversions.java @@ -16,14 +16,10 @@ package com.android.internal.telephony; -import android.telephony.ServiceState; import android.telephony.TelephonyManager; -import android.telephony.PreciseCallState; import com.android.internal.telephony.PhoneConstants; -import java.util.List; - public class PhoneConstantConversions { /** * Convert the {@link PhoneConstants.State} enum into the TelephonyManager.CALL_STATE_* @@ -67,6 +63,8 @@ public class PhoneConstantConversions { return TelephonyManager.DATA_CONNECTED; case SUSPENDED: return TelephonyManager.DATA_SUSPENDED; + case DISCONNECTING: + return TelephonyManager.DATA_DISCONNECTING; default: return TelephonyManager.DATA_DISCONNECTED; } @@ -84,6 +82,8 @@ public class PhoneConstantConversions { return PhoneConstants.DataState.CONNECTED; case TelephonyManager.DATA_SUSPENDED: return PhoneConstants.DataState.SUSPENDED; + case TelephonyManager.DATA_DISCONNECTING: + return PhoneConstants.DataState.DISCONNECTING; default: return PhoneConstants.DataState.DISCONNECTED; } diff --git a/telephony/java/com/android/internal/telephony/PhoneConstants.java b/telephony/java/com/android/internal/telephony/PhoneConstants.java index 6e635143a8e5..888746a53244 100644 --- a/telephony/java/com/android/internal/telephony/PhoneConstants.java +++ b/telephony/java/com/android/internal/telephony/PhoneConstants.java @@ -49,6 +49,7 @@ public class PhoneConstants { * <ul> * <li>CONNECTED = IP traffic should be available</li> * <li>CONNECTING = Currently setting up data connection</li> + * <li>DISCONNECTING = IP temporarily available</li> * <li>DISCONNECTED = IP not available</li> * <li>SUSPENDED = connection is created but IP traffic is * temperately not available. i.e. voice call is in place @@ -65,7 +66,8 @@ public class PhoneConstants { @UnsupportedAppUsage DISCONNECTED, @UnsupportedAppUsage - SUSPENDED; + SUSPENDED, + DISCONNECTING; }; public static final String STATE_KEY = "state"; @@ -98,20 +100,12 @@ public class PhoneConstants { public static final String PHONE_NAME_KEY = "phoneName"; public static final String DATA_NETWORK_TYPE_KEY = "networkType"; - public static final String DATA_FAILURE_CAUSE_KEY = "failCause"; public static final String DATA_APN_TYPE_KEY = "apnType"; public static final String DATA_APN_KEY = "apn"; - public static final String DATA_LINK_PROPERTIES_KEY = "linkProperties"; - public static final String DATA_NETWORK_CAPABILITIES_KEY = "networkCapabilities"; - public static final String DATA_IFACE_NAME_KEY = "iface"; - public static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable"; - public static final String DATA_NETWORK_ROAMING_KEY = "networkRoaming"; public static final String PHONE_IN_ECM_STATE = "phoneinECMState"; public static final String PHONE_IN_EMERGENCY_CALL = "phoneInEmergencyCall"; - public static final String REASON_LINK_PROPERTIES_CHANGED = "linkPropertiesChanged"; - /** * Return codes for supplyPinReturnResult and * supplyPukReturnResult APIs |