From 241b1fa96487d3336a81a53a3715b113024999d1 Mon Sep 17 00:00:00 2001 From: Rambo Wang Date: Fri, 19 Nov 2021 11:01:48 -0800 Subject: [PATCH] Support CarrierService#notifyCarrierNetworkChange with subscription Current APIs does not include subId or phoneId to locate which carrier network reported the change. A patch based on carrier privilege were deployed in Q to temprarily fix the issue. However, multiple subscriptions which all have the carrier privileges will all get notified, even only one of them has the real change. To throughly resolve the issue, the subscription is introduced in the API to distinguish which network actually has the change. Bug: 131697791 Test: atest TelephonyRegistryManagerTest CarrierServiceTest Change-Id: Ie7ee25f53da605c15e1a9228482cc8c4e7406d2a --- core/api/current.txt | 3 +- .../telephony/TelephonyRegistryManager.java | 27 +++++++++ .../telephony/ITelephonyRegistry.aidl | 1 + .../com/android/server/TelephonyRegistry.java | 57 ++++++++++++------- .../service/carrier/CarrierService.java | 30 ++++++++++ 5 files changed, 98 insertions(+), 20 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index c3b5b943477f..6aeed38e0adb 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -38281,7 +38281,8 @@ package android.service.carrier { public abstract class CarrierService extends android.app.Service { ctor public CarrierService(); - method public final void notifyCarrierNetworkChange(boolean); + method @Deprecated public final void notifyCarrierNetworkChange(boolean); + method public final void notifyCarrierNetworkChange(int, boolean); method @CallSuper public android.os.IBinder onBind(android.content.Intent); method public abstract android.os.PersistableBundle onLoadConfig(android.service.carrier.CarrierIdentifier); field public static final String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService"; diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java index 859fd804dea5..e7f89204c1ec 100644 --- a/core/java/android/telephony/TelephonyRegistryManager.java +++ b/core/java/android/telephony/TelephonyRegistryManager.java @@ -285,6 +285,8 @@ public class TelephonyRegistryManager { * UI. There is no timeout associated with showing this UX, so a carrier app must be sure to * call with active set to false sometime after calling with it set to {@code true}. *

+ * This will apply to all subscriptions the carrier app has carrier privileges on. + *

* Requires Permission: calling app has carrier privileges. * * @param active Whether the carrier network change is or shortly will be @@ -299,6 +301,31 @@ public class TelephonyRegistryManager { } } + /** + * Informs the system of an intentional upcoming carrier network change by a carrier app on the + * given {@code subscriptionId}. This call only used to allow the system to provide alternative + * UI while telephony is performing an action that may result in intentional, temporary network + * lack of connectivity. + *

+ * Based on the active parameter passed in, this method will either show or hide the + * alternative UI. There is no timeout associated with showing this UX, so a carrier app must be + * sure to call with active set to false sometime after calling with it set to {@code true}. + *

+ * Requires Permission: calling app has carrier privileges. + * + * @param subscriptionId the subscription of the carrier network. + * @param active whether the carrier network change is or shortly will be active. Set this value + * to true to begin showing alternative UI and false to stop. + * @see TelephonyManager#hasCarrierPrivileges + */ + public void notifyCarrierNetworkChange(int subscriptionId, boolean active) { + try { + sRegistry.notifyCarrierNetworkChangeWithSubId(subscriptionId, active); + } catch (RemoteException ex) { + // system server crash + } + } + /** * Notify call state changed on certain subscription. * diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 6ba0279313b1..15d4246e302a 100644 --- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -77,6 +77,7 @@ interface ITelephonyRegistry { void notifySubscriptionInfoChanged(); void notifyOpportunisticSubscriptionInfoChanged(); void notifyCarrierNetworkChange(in boolean active); + void notifyCarrierNetworkChangeWithSubId(in int subId, in boolean active); void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state); void notifyDisplayInfoChanged(int slotIndex, int subId, in TelephonyDisplayInfo telephonyDisplayInfo); void notifyPhoneCapabilityChanged(in PhoneCapability capability); diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 91cd2f6ad676..d7c1cfb7d1ed 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -366,7 +366,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { private List mBarringInfo = null; - private boolean mCarrierNetworkChangeState = false; + private boolean[] mCarrierNetworkChangeState = null; private PhoneCapability mPhoneCapability = null; @@ -675,6 +675,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mOutgoingCallEmergencyNumber = copyOf(mOutgoingCallEmergencyNumber, mNumPhones); mOutgoingSmsEmergencyNumber = copyOf(mOutgoingSmsEmergencyNumber, mNumPhones); mTelephonyDisplayInfos = copyOf(mTelephonyDisplayInfos, mNumPhones); + mCarrierNetworkChangeState = copyOf(mCarrierNetworkChangeState, mNumPhones); mIsDataEnabled= copyOf(mIsDataEnabled, mNumPhones); mDataEnabledReason = copyOf(mDataEnabledReason, mNumPhones); mAllowedNetworkTypeReason = copyOf(mAllowedNetworkTypeReason, mNumPhones); @@ -720,6 +721,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mPreciseDataConnectionStates.add(new ArrayMap<>()); mBarringInfo.add(i, new BarringInfo()); + mCarrierNetworkChangeState[i] = false; mTelephonyDisplayInfos[i] = null; mIsDataEnabled[i] = false; mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER; @@ -784,6 +786,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mOutgoingCallEmergencyNumber = new EmergencyNumber[numPhones]; mOutgoingSmsEmergencyNumber = new EmergencyNumber[numPhones]; mBarringInfo = new ArrayList<>(); + mCarrierNetworkChangeState = new boolean[numPhones]; mTelephonyDisplayInfos = new TelephonyDisplayInfo[numPhones]; mPhysicalChannelConfigs = new ArrayList<>(); mAllowedNetworkTypeReason = new int[numPhones]; @@ -820,6 +823,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { mBackgroundCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE; mPreciseDataConnectionStates.add(new ArrayMap<>()); mBarringInfo.add(i, new BarringInfo()); + mCarrierNetworkChangeState[i] = false; mTelephonyDisplayInfos[i] = null; mIsDataEnabled[i] = false; mDataEnabledReason[i] = TelephonyManager.DATA_ENABLED_REASON_USER; @@ -1230,7 +1234,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { } if (events.contains(TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED)) { try { - r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState); + r.callback.onCarrierNetworkChange(mCarrierNetworkChangeState[r.phoneId]); } catch (RemoteException ex) { remove(r.binder); } @@ -1724,23 +1728,37 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { throw new SecurityException("notifyCarrierNetworkChange without carrier privilege"); } - synchronized (mRecords) { - mCarrierNetworkChangeState = active; - for (int subId : subIds) { - int phoneId = getPhoneIdFromSubId(subId); + for (int subId : subIds) { + notifyCarrierNetworkChangeWithPermission(subId, active); + } + } - if (VDBG) { - log("notifyCarrierNetworkChange: active=" + active + "subId: " + subId); - } - for (Record r : mRecords) { - if (r.matchTelephonyCallbackEvent( - TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED) - && idMatch(r, subId, phoneId)) { - try { - r.callback.onCarrierNetworkChange(active); - } catch (RemoteException ex) { - mRemoveList.add(r.binder); - } + @Override + public void notifyCarrierNetworkChangeWithSubId(int subId, boolean active) { + if (!TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext, subId)) { + throw new SecurityException( + "notifyCarrierNetworkChange without carrier privilege on subId " + subId); + } + + notifyCarrierNetworkChangeWithPermission(subId, active); + } + + private void notifyCarrierNetworkChangeWithPermission(int subId, boolean active) { + synchronized (mRecords) { + int phoneId = getPhoneIdFromSubId(subId); + mCarrierNetworkChangeState[phoneId] = active; + + if (VDBG) { + log("notifyCarrierNetworkChange: active=" + active + "subId: " + subId); + } + for (Record r : mRecords) { + if (r.matchTelephonyCallbackEvent( + TelephonyCallback.EVENT_CARRIER_NETWORK_CHANGED) + && idMatch(r, subId, phoneId)) { + try { + r.callback.onCarrierNetworkChange(active); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); } } } @@ -2788,6 +2806,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]); pw.println("mOutgoingSmsEmergencyNumber=" + mOutgoingSmsEmergencyNumber[i]); pw.println("mBarringInfo=" + mBarringInfo.get(i)); + pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState[i]); pw.println("mTelephonyDisplayInfo=" + mTelephonyDisplayInfos[i]); pw.println("mIsDataEnabled=" + mIsDataEnabled); pw.println("mDataEnabledReason=" + mDataEnabledReason); @@ -2797,7 +2816,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mLinkCapacityEstimateList=" + mLinkCapacityEstimateLists.get(i)); pw.decreaseIndent(); } - pw.println("mCarrierNetworkChangeState=" + mCarrierNetworkChangeState); + pw.println("mPhoneCapability=" + mPhoneCapability); pw.println("mActiveDataSubId=" + mActiveDataSubId); pw.println("mRadioPowerState=" + mRadioPowerState); diff --git a/telephony/java/android/service/carrier/CarrierService.java b/telephony/java/android/service/carrier/CarrierService.java index d06ec11f3e61..ca27998ec8a8 100644 --- a/telephony/java/android/service/carrier/CarrierService.java +++ b/telephony/java/android/service/carrier/CarrierService.java @@ -115,7 +115,12 @@ public abstract class CarrierService extends Service { * active. Set this value to true to begin showing * alternative UI and false to stop. * @see android.telephony.TelephonyManager#hasCarrierPrivileges + * @deprecated use {@link #notifyCarrierNetworkChange(int, boolean)} instead. + * With no parameter to specify the subscription, this API will + * apply to all subscriptions that the carrier app has carrier + * privileges on. */ + @Deprecated public final void notifyCarrierNetworkChange(boolean active) { TelephonyRegistryManager telephonyRegistryMgr = (TelephonyRegistryManager) this.getSystemService( @@ -125,6 +130,31 @@ public abstract class CarrierService extends Service { } } + /** + * Informs the system of an intentional upcoming carrier network change by a carrier app on the + * given {@code subscriptionId}. This call is optional and is only used to allow the system to + * provide alternative UI while telephony is performing an action that may result in + * intentional, temporary network lack of connectivity. + * + *

Based on the active parameter passed in, this method will either show or hide the + * alternative UI. There is no timeout associated with showing this UX, so a carrier app must + * be sure to call with active set to false sometime after calling with it set to true. + * + *

Requires Permission: calling app has carrier privileges. + * + * @param subscriptionId the subscription of the carrier network that trigger the change. + * @param active whether the carrier network change is or shortly will be active. Set this + * value to true to begin showing alternative UI and false to stop. + * @see android.telephony.TelephonyManager#hasCarrierPrivileges + */ + public final void notifyCarrierNetworkChange(int subscriptionId, boolean active) { + TelephonyRegistryManager telephonyRegistryMgr = this.getSystemService( + TelephonyRegistryManager.class); + if (telephonyRegistryMgr != null) { + telephonyRegistryMgr.notifyCarrierNetworkChange(subscriptionId, active); + } + } + /** * If overriding this method, call through to the super method for any unknown actions. * {@inheritDoc}