Loading services/core/java/com/android/server/net/NetworkPolicyManagerService.java +51 −1 Original line number Diff line number Diff line Loading @@ -222,6 +222,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 @@ -803,6 +804,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 @@ -830,7 +841,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 @@ -1090,6 +1101,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 @@ -1260,6 +1275,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 @@ -1449,6 +1496,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 @@ -157,6 +157,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 @@ -247,6 +248,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 @@ -288,6 +290,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 @@ -363,6 +367,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 @@ -400,6 +406,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; } } // TODO: Use TestLooperManager instead. Loading Loading @@ -577,6 +598,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 @@ -1357,6 +1386,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1372,6 +1402,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1389,6 +1420,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); expectDefaultCarrierConfig(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1405,6 +1437,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1418,6 +1451,7 @@ public class NetworkPolicyManagerServiceTest { { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.snoozeLimit(sTemplateCarrierMetered); mService.updateNetworks(); Loading @@ -1428,6 +1462,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 @@ -2508,6 +2567,7 @@ public class NetworkPolicyManagerServiceTest { String subscriberId) { when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn( createSubscriptionInfoList(subscriptionId)); notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId); TelephonyManager subTelephonyManager; subTelephonyManager = mock(TelephonyManager.class); Loading @@ -2518,6 +2578,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 @@ -222,6 +222,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 @@ -803,6 +804,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 @@ -830,7 +841,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 @@ -1090,6 +1101,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 @@ -1260,6 +1275,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 @@ -1449,6 +1496,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 @@ -157,6 +157,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 @@ -247,6 +248,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 @@ -288,6 +290,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 @@ -363,6 +367,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 @@ -400,6 +406,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; } } // TODO: Use TestLooperManager instead. Loading Loading @@ -577,6 +598,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 @@ -1357,6 +1386,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1372,6 +1402,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1389,6 +1420,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); expectDefaultCarrierConfig(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1405,6 +1437,7 @@ public class NetworkPolicyManagerServiceTest { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.updateNetworks(); Loading @@ -1418,6 +1451,7 @@ public class NetworkPolicyManagerServiceTest { { reset(mTelephonyManager, mNetworkManager, mNotifManager); TelephonyManager tmSub = expectMobileDefaults(); clearInvocations(mNotifManager); mService.snoozeLimit(sTemplateCarrierMetered); mService.updateNetworks(); Loading @@ -1428,6 +1462,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 @@ -2508,6 +2567,7 @@ public class NetworkPolicyManagerServiceTest { String subscriberId) { when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn( createSubscriptionInfoList(subscriptionId)); notifyDefaultAndActiveDataSubIdChange(subscriptionId, subscriptionId); TelephonyManager subTelephonyManager; subTelephonyManager = mock(TelephonyManager.class); Loading @@ -2518,6 +2578,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