From e4beb931497ec7b602e855afda168a68ba1a3e7c Mon Sep 17 00:00:00 2001 From: Paul Hu Date: Wed, 25 Mar 2020 06:22:43 +0000 Subject: [PATCH] [TNU02] Update tethering notification by active data subid Tethering notification can be customized by different subid. Thus update notification when active data subid changed. Bug: 122085773 Bug: 130596698 Test: atest TetheringTests Change-Id: I799d713326cfbf4dc96c712c6b15ed5a4ac18dd2 Merged-In: I799d713326cfbf4dc96c712c6b15ed5a4ac18dd2 (cherry picked from aosp/1209984) --- .../connectivity/tethering/Tethering.java | 3 +- .../TetheringNotificationUpdater.java | 42 +++++++++++++++---- .../connectivity/tethering/TetheringTest.java | 2 +- 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/Tethering/src/com/android/server/connectivity/tethering/Tethering.java index 36113acf97..490b83f48e 100644 --- a/Tethering/src/com/android/server/connectivity/tethering/Tethering.java +++ b/Tethering/src/com/android/server/connectivity/tethering/Tethering.java @@ -369,9 +369,10 @@ public class Tethering { mActiveDataSubId = subId; updateConfiguration(); + mNotificationUpdater.onActiveDataSubscriptionIdChanged(subId); // To avoid launching unexpected provisioning checks, ignore re-provisioning // when no CarrierConfig loaded yet. Assume reevaluateSimCardProvisioning() - // ill be triggered again when CarrierConfig is loaded. + // will be triggered again when CarrierConfig is loaded. if (mEntitlementMgr.getCarrierConfig(mConfig) != null) { mEntitlementMgr.reevaluateSimCardProvisioning(mConfig); } else { diff --git a/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java b/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java index b97f75268a..c3fd170a11 100644 --- a/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java +++ b/Tethering/src/com/android/server/connectivity/tethering/TetheringNotificationUpdater.java @@ -29,6 +29,7 @@ import android.content.Intent; import android.content.res.Resources; import android.os.UserHandle; import android.provider.Settings; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; @@ -54,6 +55,9 @@ import com.android.networkstack.tethering.R; public class TetheringNotificationUpdater { private static final String TAG = TetheringNotificationUpdater.class.getSimpleName(); private static final String CHANNEL_ID = "TETHERING_STATUS"; + private static final String WIFI_DOWNSTREAM = "WIFI"; + private static final String USB_DOWNSTREAM = "USB"; + private static final String BLUETOOTH_DOWNSTREAM = "BT"; private static final boolean NOTIFY_DONE = true; private static final boolean NO_NOTIFY = false; // Id to update and cancel tethering notification. Must be unique within the tethering app. @@ -65,14 +69,22 @@ public class TetheringNotificationUpdater { private final Context mContext; private final NotificationManager mNotificationManager; private final NotificationChannel mChannel; - // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. - // This value has to be made 1 2 and 4, and OR'd with the others. + // WARNING : the constructor is called on a different thread. Thread safety therefore // relies on this value being initialized to 0, and not any other value. If you need // to change this, you will need to change the thread where the constructor is invoked, // or to introduce synchronization. + // Downstream type is one of ConnectivityManager.TETHERING_* constants, 0 1 or 2. + // This value has to be made 1 2 and 4, and OR'd with the others. private int mDownstreamTypesMask = DOWNSTREAM_NONE; + // WARNING : this value is not able to being initialized to 0 and must have volatile because + // telephony service is not guaranteed that is up before tethering service starts. If telephony + // is up later than tethering, TetheringNotificationUpdater will use incorrect and valid + // subscription id(0) to query resources. Therefore, initialized subscription id must be + // INVALID_SUBSCRIPTION_ID. + private volatile int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + public TetheringNotificationUpdater(@NonNull final Context context) { mContext = context; mNotificationManager = (NotificationManager) context.createContextAsUser(UserHandle.ALL, 0) @@ -91,6 +103,18 @@ public class TetheringNotificationUpdater { updateNotification(); } + /** Called when active data subscription id changed */ + public void onActiveDataSubscriptionIdChanged(final int subId) { + if (mActiveDataSubId == subId) return; + mActiveDataSubId = subId; + updateNotification(); + } + + @VisibleForTesting + Resources getResourcesForSubId(@NonNull final Context c, final int subId) { + return SubscriptionManager.getResourcesForSubId(c, subId); + } + private void updateNotification() { final boolean tetheringInactive = mDownstreamTypesMask <= DOWNSTREAM_NONE; @@ -115,11 +139,11 @@ public class TetheringNotificationUpdater { int downstreamTypesMask = DOWNSTREAM_NONE; final String[] downstreams = types.split("\\|"); for (String downstream : downstreams) { - if ("USB".equals(downstream.trim())) { + if (USB_DOWNSTREAM.equals(downstream.trim())) { downstreamTypesMask |= (1 << TETHERING_USB); - } else if ("WIFI".equals(downstream.trim())) { + } else if (WIFI_DOWNSTREAM.equals(downstream.trim())) { downstreamTypesMask |= (1 << TETHERING_WIFI); - } else if ("BT".equals(downstream.trim())) { + } else if (BLUETOOTH_DOWNSTREAM.equals(downstream.trim())) { downstreamTypesMask |= (1 << TETHERING_BLUETOOTH); } } @@ -135,8 +159,7 @@ public class TetheringNotificationUpdater { * @return {@link android.util.SparseArray} with downstream types and icon id info. */ @NonNull - private SparseArray getIcons(@ArrayRes int id) { - final Resources res = mContext.getResources(); + private SparseArray getIcons(@ArrayRes int id, @NonNull Resources res) { final String[] array = res.getStringArray(id); final SparseArray icons = new SparseArray<>(); for (String config : array) { @@ -161,8 +184,9 @@ public class TetheringNotificationUpdater { } private boolean setupNotification() { - final Resources res = mContext.getResources(); - final SparseArray downstreamIcons = getIcons(R.array.tethering_notification_icons); + final Resources res = getResourcesForSubId(mContext, mActiveDataSubId); + final SparseArray downstreamIcons = + getIcons(R.array.tethering_notification_icons, res); final int iconId = downstreamIcons.get(mDownstreamTypesMask, NO_ICON_ID); if (iconId == NO_ICON_ID) return NO_NOTIFY; diff --git a/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java index 60d7ad1c5b..8116f9d74b 100644 --- a/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java +++ b/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java @@ -210,7 +210,6 @@ public class TetheringTest { private PhoneStateListener mPhoneStateListener; private InterfaceConfigurationParcel mInterfaceConfiguration; - private class TestContext extends BroadcastInterceptingContext { TestContext(Context base) { super(base); @@ -1399,6 +1398,7 @@ public class TetheringTest { mPhoneStateListener.onActiveDataSubscriptionIdChanged(fakeSubId); final TetheringConfiguration newConfig = mTethering.getTetheringConfiguration(); assertEquals(fakeSubId, newConfig.activeDataSubId); + verify(mNotificationUpdater, times(1)).onActiveDataSubscriptionIdChanged(eq(fakeSubId)); } @Test