Loading services/core/java/com/android/server/net/NetworkPolicyManagerService.java +51 −1 Original line number Diff line number Diff line Loading @@ -220,6 +220,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.text.format.DateUtils; Loading Loading @@ -801,6 +802,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } return buckets; } /** Require IPC call. Don't call when holding a lock. */ int getDefaultDataSubId() { return SubscriptionManager.getDefaultDataSubscriptionId(); } /** Require IPC call. Don't call when holding a lock. */ int getActivateDataSubId() { return SubscriptionManager.getActiveDataSubscriptionId(); } } @VisibleForTesting Loading Loading @@ -828,7 +839,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mSuppressDefaultPolicy = suppressDefaultPolicy; mDeps = Objects.requireNonNull(deps, "missing Dependencies"); mActiveDataSubIdListener = new ActiveDataSubIdListener(); mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy"); mAppOps = context.getSystemService(AppOpsManager.class); Loading Loading @@ -1088,6 +1099,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }); // Listen for active data sub Id change, upon which data notifications is shown/hidden. mContext.getSystemService(TelephonyManager.class).registerTelephonyCallback(executor, mActiveDataSubIdListener); // tell systemReady() that the service has been initialized initCompleteSignal.countDown(); } finally { Loading Loading @@ -1256,6 +1271,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; /** * Listener that watches for active data sub Id change, upon which data notifications are * shown/hidden. */ private final ActiveDataSubIdListener mActiveDataSubIdListener; private class ActiveDataSubIdListener extends TelephonyCallback implements TelephonyCallback.ActiveDataSubscriptionIdListener { /** * In most cases active data sub is the same as the default data sub, but if user enabled * auto data switch {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH}, * active data sub could be the non-default data sub. * * If the listener is initialized before the phone process is up, the IPC call to the * static method of SubscriptionManager lead to INVALID_SUBSCRIPTION_ID to be returned, * indicating the phone process is unable to determine a valid data sub Id at this point, in * which case no data notifications should be shown anyway. Later on when an active data * sub is known, notifications will be re-evaluated by this callback. */ private int mDefaultDataSubId = mDeps.getDefaultDataSubId(); private int mActiveDataSubId = mDeps.getActivateDataSubId(); // Only listen to active data sub change is sufficient because default data sub change // leads to active data sub change as well. @Override public void onActiveDataSubscriptionIdChanged(int subId) { mActiveDataSubId = subId; mDefaultDataSubId = mDeps.getDefaultDataSubId(); synchronized (mNetworkPoliciesSecondLock) { updateNotificationsNL(); } } } /** * Listener that watches for {@link NetworkStatsManager} updates, which * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}. Loading Loading @@ -1445,6 +1492,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // ignore policies that aren't relevant to user if (subId == INVALID_SUBSCRIPTION_ID) continue; // ignore if the data sub is neither default nor active for data at the moment. if (subId != mActiveDataSubIdListener.mDefaultDataSubId && subId != mActiveDataSubIdListener.mActiveDataSubId) continue; if (!policy.hasCycle()) continue; final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager Loading services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +70 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.MediumTest; import android.text.TextUtils; Loading Loading @@ -241,6 +242,7 @@ public class NetworkPolicyManagerServiceTest { private static final String TEST_WIFI_NETWORK_KEY = "TestWifiNetworkKey"; private static final String TEST_IMSI = "310210"; private static final int TEST_SUB_ID = 42; private static final int TEST_SUB_ID2 = 24; private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS); private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI) Loading Loading @@ -282,6 +284,8 @@ public class NetworkPolicyManagerServiceTest { private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor = ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); private TelephonyCallback.ActiveDataSubscriptionIdListener mActiveDataSubIdListener; private ActivityManagerInternal mActivityManagerInternal; private PackageManagerInternal mPackageManagerInternal; Loading Loading @@ -357,6 +361,8 @@ public class NetworkPolicyManagerServiceTest { private class TestDependencies extends NetworkPolicyManagerService.Dependencies { private final SparseArray<NetworkStats.Bucket> mMockedStats = new SparseArray<>(); private int mMockDefaultDataSubId; private int mMockedActiveDataSubId; TestDependencies(Context context) { super(context); Loading Loading @@ -394,6 +400,21 @@ public class NetworkPolicyManagerServiceTest { final NetworkStats.Bucket bucket = mMockedStats.get(uid); setMockedTotalBytes(uid, bucket.getRxBytes() + rxBytes, bucket.getTxBytes() + txBytes); } void setDefaultAndActiveDataSubId(int defaultDataSubId, int activeDataSubId) { mMockDefaultDataSubId = defaultDataSubId; mMockedActiveDataSubId = activeDataSubId; } @Override int getDefaultDataSubId() { return mMockDefaultDataSubId; } @Override int getActivateDataSubId() { return mMockedActiveDataSubId; } } @Before Loading Loading @@ -551,6 +572,14 @@ public class NetworkPolicyManagerServiceTest { NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, ""); mDefaultWarningBytes = defaultPolicy.warningBytes; mDefaultLimitBytes = defaultPolicy.limitBytes; // Catch TelephonyCallback during systemReady(). ArgumentCaptor<TelephonyCallback> telephonyCallbackArgumentCaptor = ArgumentCaptor.forClass(TelephonyCallback.class); verify(mTelephonyManager).registerTelephonyCallback(any(), telephonyCallbackArgumentCaptor.capture()); mActiveDataSubIdListener = (TelephonyCallback.ActiveDataSubscriptionIdListener) telephonyCallbackArgumentCaptor.getValue(); } @After Loading Loading @@ -1243,6 +1272,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1258,6 +1288,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1275,6 +1306,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); expectDefaultCarrierConfig(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1291,6 +1323,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1304,6 +1337,7 @@ public class NetworkPolicyManagerServiceTest { { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.snoozeLimit(sTemplateCarrierMetered); mService.updateNetworks(); Loading @@ -1314,6 +1348,31 @@ public class NetworkPolicyManagerServiceTest { verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), isA(Notification.class), eq(UserHandle.ALL)); } // The sub is no longer used for data(e.g. user uses another sub), hide the notifications. { reset(mTelephonyManager, mNetworkManager, mNotifManager); notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID2); verify(mNotifManager, atLeastOnce()).cancel(any(), eq(TYPE_LIMIT_SNOOZED)); } // The sub is not active for data(e.g. due to auto data switch), but still default for data, // show notification. { reset(mTelephonyManager, mNetworkManager, mNotifManager); notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID, TEST_SUB_ID2); verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), isA(Notification.class), eq(UserHandle.ALL)); } // The sub is active for data, but not the default(e.g. due to auto data switch), // show notification. { reset(mTelephonyManager, mNetworkManager, mNotifManager); notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID); verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), isA(Notification.class), eq(UserHandle.ALL)); } } @Test Loading Loading @@ -2377,6 +2436,7 @@ public class NetworkPolicyManagerServiceTest { String subscriberId) { when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn( createSubscriptionInfoList(subscriptionId)); notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId); TelephonyManager subTelephonyManager; subTelephonyManager = mock(TelephonyManager.class); Loading @@ -2387,6 +2447,16 @@ public class NetworkPolicyManagerServiceTest { return subTelephonyManager; } /** * Telephony Manager callback notifies data sub Id changes. * @param defaultDataSubId The mock default data sub Id. * @param activeDataSubId The mock active data sub Id. */ private void notifyDefaultAndActiveDataSubIdChange(int defaultDataSubId, int activeDataSubId) { mDeps.setDefaultAndActiveDataSubId(defaultDataSubId, activeDataSubId); mActiveDataSubIdListener.onActiveDataSubscriptionIdChanged(activeDataSubId); } /** * Creates mock {@link SubscriptionInfo} from subscription id. */ Loading Loading
services/core/java/com/android/server/net/NetworkPolicyManagerService.java +51 −1 Original line number Diff line number Diff line Loading @@ -220,6 +220,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.text.format.DateUtils; Loading Loading @@ -801,6 +802,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } return buckets; } /** Require IPC call. Don't call when holding a lock. */ int getDefaultDataSubId() { return SubscriptionManager.getDefaultDataSubscriptionId(); } /** Require IPC call. Don't call when holding a lock. */ int getActivateDataSubId() { return SubscriptionManager.getActiveDataSubscriptionId(); } } @VisibleForTesting Loading Loading @@ -828,7 +839,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mSuppressDefaultPolicy = suppressDefaultPolicy; mDeps = Objects.requireNonNull(deps, "missing Dependencies"); mActiveDataSubIdListener = new ActiveDataSubIdListener(); mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"), "net-policy"); mAppOps = context.getSystemService(AppOpsManager.class); Loading Loading @@ -1088,6 +1099,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }); // Listen for active data sub Id change, upon which data notifications is shown/hidden. mContext.getSystemService(TelephonyManager.class).registerTelephonyCallback(executor, mActiveDataSubIdListener); // tell systemReady() that the service has been initialized initCompleteSignal.countDown(); } finally { Loading Loading @@ -1256,6 +1271,38 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; /** * Listener that watches for active data sub Id change, upon which data notifications are * shown/hidden. */ private final ActiveDataSubIdListener mActiveDataSubIdListener; private class ActiveDataSubIdListener extends TelephonyCallback implements TelephonyCallback.ActiveDataSubscriptionIdListener { /** * In most cases active data sub is the same as the default data sub, but if user enabled * auto data switch {@link TelephonyManager#MOBILE_DATA_POLICY_AUTO_DATA_SWITCH}, * active data sub could be the non-default data sub. * * If the listener is initialized before the phone process is up, the IPC call to the * static method of SubscriptionManager lead to INVALID_SUBSCRIPTION_ID to be returned, * indicating the phone process is unable to determine a valid data sub Id at this point, in * which case no data notifications should be shown anyway. Later on when an active data * sub is known, notifications will be re-evaluated by this callback. */ private int mDefaultDataSubId = mDeps.getDefaultDataSubId(); private int mActiveDataSubId = mDeps.getActivateDataSubId(); // Only listen to active data sub change is sufficient because default data sub change // leads to active data sub change as well. @Override public void onActiveDataSubscriptionIdChanged(int subId) { mActiveDataSubId = subId; mDefaultDataSubId = mDeps.getDefaultDataSubId(); synchronized (mNetworkPoliciesSecondLock) { updateNotificationsNL(); } } } /** * Listener that watches for {@link NetworkStatsManager} updates, which * NetworkPolicyManagerService uses to check against {@link NetworkPolicy#warningBytes}. Loading Loading @@ -1445,6 +1492,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // ignore policies that aren't relevant to user if (subId == INVALID_SUBSCRIPTION_ID) continue; // ignore if the data sub is neither default nor active for data at the moment. if (subId != mActiveDataSubIdListener.mDefaultDataSubId && subId != mActiveDataSubIdListener.mActiveDataSubId) continue; if (!policy.hasCycle()) continue; final Pair<ZonedDateTime, ZonedDateTime> cycle = NetworkPolicyManager Loading
services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java +70 −0 Original line number Diff line number Diff line Loading @@ -151,6 +151,7 @@ import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.MediumTest; import android.text.TextUtils; Loading Loading @@ -241,6 +242,7 @@ public class NetworkPolicyManagerServiceTest { private static final String TEST_WIFI_NETWORK_KEY = "TestWifiNetworkKey"; private static final String TEST_IMSI = "310210"; private static final int TEST_SUB_ID = 42; private static final int TEST_SUB_ID2 = 24; private static final Network TEST_NETWORK = mock(Network.class, CALLS_REAL_METHODS); private static NetworkTemplate sTemplateWifi = new NetworkTemplate.Builder(MATCH_WIFI) Loading Loading @@ -282,6 +284,8 @@ public class NetworkPolicyManagerServiceTest { private ArgumentCaptor<ConnectivityManager.NetworkCallback> mNetworkCallbackCaptor = ArgumentCaptor.forClass(ConnectivityManager.NetworkCallback.class); private TelephonyCallback.ActiveDataSubscriptionIdListener mActiveDataSubIdListener; private ActivityManagerInternal mActivityManagerInternal; private PackageManagerInternal mPackageManagerInternal; Loading Loading @@ -357,6 +361,8 @@ public class NetworkPolicyManagerServiceTest { private class TestDependencies extends NetworkPolicyManagerService.Dependencies { private final SparseArray<NetworkStats.Bucket> mMockedStats = new SparseArray<>(); private int mMockDefaultDataSubId; private int mMockedActiveDataSubId; TestDependencies(Context context) { super(context); Loading Loading @@ -394,6 +400,21 @@ public class NetworkPolicyManagerServiceTest { final NetworkStats.Bucket bucket = mMockedStats.get(uid); setMockedTotalBytes(uid, bucket.getRxBytes() + rxBytes, bucket.getTxBytes() + txBytes); } void setDefaultAndActiveDataSubId(int defaultDataSubId, int activeDataSubId) { mMockDefaultDataSubId = defaultDataSubId; mMockedActiveDataSubId = activeDataSubId; } @Override int getDefaultDataSubId() { return mMockDefaultDataSubId; } @Override int getActivateDataSubId() { return mMockedActiveDataSubId; } } @Before Loading Loading @@ -551,6 +572,14 @@ public class NetworkPolicyManagerServiceTest { NetworkPolicy defaultPolicy = mService.buildDefaultCarrierPolicy(0, ""); mDefaultWarningBytes = defaultPolicy.warningBytes; mDefaultLimitBytes = defaultPolicy.limitBytes; // Catch TelephonyCallback during systemReady(). ArgumentCaptor<TelephonyCallback> telephonyCallbackArgumentCaptor = ArgumentCaptor.forClass(TelephonyCallback.class); verify(mTelephonyManager).registerTelephonyCallback(any(), telephonyCallbackArgumentCaptor.capture()); mActiveDataSubIdListener = (TelephonyCallback.ActiveDataSubscriptionIdListener) telephonyCallbackArgumentCaptor.getValue(); } @After Loading Loading @@ -1243,6 +1272,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1258,6 +1288,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1275,6 +1306,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); expectDefaultCarrierConfig(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1291,6 +1323,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1304,6 +1337,7 @@ public class NetworkPolicyManagerServiceTest { { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.snoozeLimit(sTemplateCarrierMetered); mService.updateNetworks(); Loading @@ -1314,6 +1348,31 @@ public class NetworkPolicyManagerServiceTest { verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), isA(Notification.class), eq(UserHandle.ALL)); } // The sub is no longer used for data(e.g. user uses another sub), hide the notifications. { reset(mTelephonyManager, mNetworkManager, mNotifManager); notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID2); verify(mNotifManager, atLeastOnce()).cancel(any(), eq(TYPE_LIMIT_SNOOZED)); } // The sub is not active for data(e.g. due to auto data switch), but still default for data, // show notification. { reset(mTelephonyManager, mNetworkManager, mNotifManager); notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID, TEST_SUB_ID2); verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), isA(Notification.class), eq(UserHandle.ALL)); } // The sub is active for data, but not the default(e.g. due to auto data switch), // show notification. { reset(mTelephonyManager, mNetworkManager, mNotifManager); notifyDefaultAndActiveDataSubIdChange(TEST_SUB_ID2, TEST_SUB_ID); verify(mNotifManager, atLeastOnce()).notifyAsUser(any(), eq(TYPE_LIMIT_SNOOZED), isA(Notification.class), eq(UserHandle.ALL)); } } @Test Loading Loading @@ -2377,6 +2436,7 @@ public class NetworkPolicyManagerServiceTest { String subscriberId) { when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn( createSubscriptionInfoList(subscriptionId)); notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId); TelephonyManager subTelephonyManager; subTelephonyManager = mock(TelephonyManager.class); Loading @@ -2387,6 +2447,16 @@ public class NetworkPolicyManagerServiceTest { return subTelephonyManager; } /** * Telephony Manager callback notifies data sub Id changes. * @param defaultDataSubId The mock default data sub Id. * @param activeDataSubId The mock active data sub Id. */ private void notifyDefaultAndActiveDataSubIdChange(int defaultDataSubId, int activeDataSubId) { mDeps.setDefaultAndActiveDataSubId(defaultDataSubId, activeDataSubId); mActiveDataSubIdListener.onActiveDataSubscriptionIdChanged(activeDataSubId); } /** * Creates mock {@link SubscriptionInfo} from subscription id. */ Loading