Loading core/java/android/net/NetworkTemplate.java +30 −7 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Objects; /** Loading Loading @@ -481,19 +482,41 @@ public class NetworkTemplate implements Parcelable { * For example, given an incoming template matching B, and the currently * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. * TODO: remove and use {@link #normalize(NetworkTemplate, List)}. */ @UnsupportedAppUsage public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) { if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) { return normalize(template, Arrays.<String[]>asList(merged)); } /** * Examine the given template and normalize if it refers to a "merged" * mobile subscriber. We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * * There can be multiple merged subscriberIds for multi-SIM devices. * * <p> * For example, given an incoming template matching B, and the currently * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. */ public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) { if (!template.isMatchRuleMobile()) return template; for (String[] merged : mergedList) { if (ArrayUtils.contains(merged, template.mSubscriberId)) { // Requested template subscriber is part of the merge group; return // a template that matches all merged subscribers. return new NetworkTemplate(template.mMatchRule, merged[0], merged, template.mNetworkId); } else { return template; } } return template; } @UnsupportedAppUsage public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() { @Override Loading packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java +12 −6 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ package com.android.settingslib.net; import android.content.Context; import android.net.NetworkTemplate; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; import com.android.internal.util.ArrayUtils; /** * Utils class for data usage */ Loading @@ -34,19 +34,25 @@ public class DataUsageUtils { */ public static NetworkTemplate getMobileTemplate(Context context, int subId) { final TelephonyManager telephonyManager = context.getSystemService( TelephonyManager.class).createForSubscriptionId(subId); TelephonyManager.class); final SubscriptionManager subscriptionManager = context.getSystemService( SubscriptionManager.class); final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(subId); final NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll( telephonyManager.getSubscriberId(subId)); if (info == null) { if (!subscriptionManager.isActiveSubId(subId)) { Log.i(TAG, "Subscription is not active: " + subId); return mobileAll; } // Use old API to build networkTemplate return NetworkTemplate.normalize(mobileAll, telephonyManager.getMergedSubscriberIds()); final String[] mergedSubscriberIds = telephonyManager.createForSubscriptionId(subId) .getMergedSubscriberIdsFromGroup(); if (ArrayUtils.isEmpty(mergedSubscriberIds)) { Log.i(TAG, "mergedSubscriberIds is null."); return mobileAll; } return NetworkTemplate.normalize(mobileAll, mergedSubscriberIds); } } packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java +21 −11 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.settingslib.net; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; Loading @@ -37,13 +38,13 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) public class DataUsageUtilsTest { private static final int SUB_ID = 1; private static final int SUB_ID_2 = 2; private static final String SUBSCRIBER_ID = "Test Subscriber"; private static final String SUBSCRIBER_ID_2 = "Test Subscriber 2"; Loading @@ -66,21 +67,28 @@ public class DataUsageUtilsTest { mContext = spy(RuntimeEnvironment.application); when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager); when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); when(mTelephonyManager.getSubscriberId(SUB_ID)).thenReturn(SUBSCRIBER_ID); when(mTelephonyManager.getMergedSubscriberIds()).thenReturn( new String[]{SUBSCRIBER_ID, SUBSCRIBER_ID_2}); mInfos = new ArrayList<>(); mInfos.add(mInfo1); mInfos.add(mInfo2); when(mSubscriptionManager.getSubscriptionsInGroup(mParcelUuid)).thenReturn(mInfos); when(mTelephonyManager.getSubscriberId(SUB_ID_2)).thenReturn(SUBSCRIBER_ID_2); when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); when(mSubscriptionManager.isActiveSubId(anyInt())).thenReturn(true); } @Test public void getMobileTemplate_infoNull_returnMobileAll() { when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(null); when(mSubscriptionManager.isActiveSubId(SUB_ID)).thenReturn(false); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse(); } @Test public void getMobileTemplate_groupUuidNull_returnMobileAll() { when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1); when(mInfo1.getGroupUuid()).thenReturn(null); when(mTelephonyManager.getMergedSubscriberIdsFromGroup()) .thenReturn(new String[] {SUBSCRIBER_ID}); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); Loading @@ -88,9 +96,11 @@ public class DataUsageUtilsTest { } @Test public void getMobileTemplate_infoExisted_returnMobileMerged() { public void getMobileTemplate_groupUuidExist_returnMobileMerged() { when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1); when(mInfo1.getGroupUuid()).thenReturn(mParcelUuid); when(mTelephonyManager.getMergedSubscriberIdsFromGroup()) .thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2}); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); Loading services/core/java/com/android/server/net/NetworkPolicyManagerService.java +11 −6 Original line number Diff line number Diff line Loading @@ -232,7 +232,6 @@ import com.android.server.ServiceThread; import com.android.server.SystemConfig; import libcore.io.IoUtils; import libcore.util.EmptyArray; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; Loading Loading @@ -540,7 +539,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final SparseArray<String> mSubIdToSubscriberId = new SparseArray<>(); /** Set of all merged subscriberId as of last update */ @GuardedBy("mNetworkPoliciesSecondLock") private String[] mMergedSubscriberIds = EmptyArray.STRING; private List<String[]> mMergedSubscriberIds = new ArrayList<>(); /** * Indicates the uids restricted by admin from accessing metered data. It's a mapping from Loading Loading @@ -1801,7 +1800,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class); final int[] subIds = ArrayUtils.defeatNullable(sm.getActiveSubscriptionIdList()); final String[] mergedSubscriberIds = ArrayUtils.defeatNullable(tm.getMergedSubscriberIds()); final List<String[]> mergedSubscriberIdsList = new ArrayList(); final SparseArray<String> subIdToSubscriberId = new SparseArray<>(subIds.length); for (int subId : subIds) { Loading @@ -1811,6 +1810,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } else { Slog.wtf(TAG, "Missing subscriberId for subId " + subId); } String[] mergedSubscriberId = ArrayUtils.defeatNullable( tm.createForSubscriptionId(subId).getMergedSubscriberIdsFromGroup()); mergedSubscriberIdsList.add(mergedSubscriberId); } synchronized (mNetworkPoliciesSecondLock) { Loading @@ -1820,7 +1823,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { subIdToSubscriberId.valueAt(i)); } mMergedSubscriberIds = mergedSubscriberIds; mMergedSubscriberIds = mergedSubscriberIdsList; } Trace.traceEnd(TRACE_TAG_NETWORK); Loading Loading @@ -3373,8 +3376,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.decreaseIndent(); fout.println(); fout.println("Merged subscriptions: " + Arrays.toString(NetworkIdentity.scrubSubscriberId(mMergedSubscriberIds))); for (String[] mergedSubscribers : mMergedSubscriberIds) { fout.println("Merged subscriptions: " + Arrays.toString( NetworkIdentity.scrubSubscriberId(mergedSubscribers))); } fout.println(); fout.println("Policy for UIDs:"); Loading telephony/java/android/telephony/TelephonyManager.java +27 −0 Original line number Diff line number Diff line Loading @@ -3972,9 +3972,14 @@ public class TelephonyManager { * The returned set of subscriber IDs will include the subscriber ID corresponding to this * TelephonyManager's subId. * * This is deprecated and {@link #getMergedSubscriberIdsFromGroup()} should be used for data * usage merging purpose. * TODO: remove this API. * * @hide */ @UnsupportedAppUsage @Deprecated public @Nullable String[] getMergedSubscriberIds() { try { ITelephony telephony = getITelephony(); Loading @@ -3986,6 +3991,28 @@ public class TelephonyManager { return null; } /** * Return the set of subscriber IDs that should be considered "merged together" for data usage * purposes. Unlike {@link #getMergedSubscriberIds()} this API merge subscriberIds based on * subscription grouping: subscriberId of those in the same group will all be returned. * * <p>Requires the calling app to have READ_PRIVILEGED_PHONE_STATE permission. * * @hide */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @Nullable String[] getMergedSubscriberIdsFromGroup() { try { ITelephony telephony = getITelephony(); if (telephony != null) { return telephony.getMergedSubscriberIdsFromGroup(getSubId(), getOpPackageName()); } } catch (RemoteException ex) { } catch (NullPointerException ex) { } return null; } /** * Returns the MSISDN string. * for a GSM phone. Return null if it is unavailable. Loading Loading
core/java/android/net/NetworkTemplate.java +30 −7 Original line number Diff line number Diff line Loading @@ -48,6 +48,7 @@ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Objects; /** Loading Loading @@ -481,19 +482,41 @@ public class NetworkTemplate implements Parcelable { * For example, given an incoming template matching B, and the currently * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. * TODO: remove and use {@link #normalize(NetworkTemplate, List)}. */ @UnsupportedAppUsage public static NetworkTemplate normalize(NetworkTemplate template, String[] merged) { if (template.isMatchRuleMobile() && ArrayUtils.contains(merged, template.mSubscriberId)) { return normalize(template, Arrays.<String[]>asList(merged)); } /** * Examine the given template and normalize if it refers to a "merged" * mobile subscriber. We pick the "lowest" merged subscriber as the primary * for key purposes, and expand the template to match all other merged * subscribers. * * There can be multiple merged subscriberIds for multi-SIM devices. * * <p> * For example, given an incoming template matching B, and the currently * active merge set [A,B], we'd return a new template that primarily matches * A, but also matches B. */ public static NetworkTemplate normalize(NetworkTemplate template, List<String[]> mergedList) { if (!template.isMatchRuleMobile()) return template; for (String[] merged : mergedList) { if (ArrayUtils.contains(merged, template.mSubscriberId)) { // Requested template subscriber is part of the merge group; return // a template that matches all merged subscribers. return new NetworkTemplate(template.mMatchRule, merged[0], merged, template.mNetworkId); } else { return template; } } return template; } @UnsupportedAppUsage public static final @android.annotation.NonNull Creator<NetworkTemplate> CREATOR = new Creator<NetworkTemplate>() { @Override Loading
packages/SettingsLib/src/com/android/settingslib/net/DataUsageUtils.java +12 −6 Original line number Diff line number Diff line Loading @@ -18,11 +18,11 @@ package com.android.settingslib.net; import android.content.Context; import android.net.NetworkTemplate; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; import com.android.internal.util.ArrayUtils; /** * Utils class for data usage */ Loading @@ -34,19 +34,25 @@ public class DataUsageUtils { */ public static NetworkTemplate getMobileTemplate(Context context, int subId) { final TelephonyManager telephonyManager = context.getSystemService( TelephonyManager.class).createForSubscriptionId(subId); TelephonyManager.class); final SubscriptionManager subscriptionManager = context.getSystemService( SubscriptionManager.class); final SubscriptionInfo info = subscriptionManager.getActiveSubscriptionInfo(subId); final NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll( telephonyManager.getSubscriberId(subId)); if (info == null) { if (!subscriptionManager.isActiveSubId(subId)) { Log.i(TAG, "Subscription is not active: " + subId); return mobileAll; } // Use old API to build networkTemplate return NetworkTemplate.normalize(mobileAll, telephonyManager.getMergedSubscriberIds()); final String[] mergedSubscriberIds = telephonyManager.createForSubscriptionId(subId) .getMergedSubscriberIdsFromGroup(); if (ArrayUtils.isEmpty(mergedSubscriberIds)) { Log.i(TAG, "mergedSubscriberIds is null."); return mobileAll; } return NetworkTemplate.normalize(mobileAll, mergedSubscriberIds); } }
packages/SettingsLib/tests/robotests/src/com/android/settingslib/net/DataUsageUtilsTest.java +21 −11 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.settingslib.net; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; Loading @@ -37,13 +38,13 @@ import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import java.util.ArrayList; import java.util.List; @RunWith(RobolectricTestRunner.class) public class DataUsageUtilsTest { private static final int SUB_ID = 1; private static final int SUB_ID_2 = 2; private static final String SUBSCRIBER_ID = "Test Subscriber"; private static final String SUBSCRIBER_ID_2 = "Test Subscriber 2"; Loading @@ -66,21 +67,28 @@ public class DataUsageUtilsTest { mContext = spy(RuntimeEnvironment.application); when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager); when(mTelephonyManager.createForSubscriptionId(SUB_ID)).thenReturn(mTelephonyManager); when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager); when(mTelephonyManager.getSubscriberId(SUB_ID)).thenReturn(SUBSCRIBER_ID); when(mTelephonyManager.getMergedSubscriberIds()).thenReturn( new String[]{SUBSCRIBER_ID, SUBSCRIBER_ID_2}); mInfos = new ArrayList<>(); mInfos.add(mInfo1); mInfos.add(mInfo2); when(mSubscriptionManager.getSubscriptionsInGroup(mParcelUuid)).thenReturn(mInfos); when(mTelephonyManager.getSubscriberId(SUB_ID_2)).thenReturn(SUBSCRIBER_ID_2); when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager); when(mSubscriptionManager.isActiveSubId(anyInt())).thenReturn(true); } @Test public void getMobileTemplate_infoNull_returnMobileAll() { when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(null); when(mSubscriptionManager.isActiveSubId(SUB_ID)).thenReturn(false); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID_2)).isFalse(); } @Test public void getMobileTemplate_groupUuidNull_returnMobileAll() { when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1); when(mInfo1.getGroupUuid()).thenReturn(null); when(mTelephonyManager.getMergedSubscriberIdsFromGroup()) .thenReturn(new String[] {SUBSCRIBER_ID}); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); Loading @@ -88,9 +96,11 @@ public class DataUsageUtilsTest { } @Test public void getMobileTemplate_infoExisted_returnMobileMerged() { public void getMobileTemplate_groupUuidExist_returnMobileMerged() { when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mInfo1); when(mInfo1.getGroupUuid()).thenReturn(mParcelUuid); when(mTelephonyManager.getMergedSubscriberIdsFromGroup()) .thenReturn(new String[] {SUBSCRIBER_ID, SUBSCRIBER_ID_2}); final NetworkTemplate networkTemplate = DataUsageUtils.getMobileTemplate(mContext, SUB_ID); assertThat(networkTemplate.matchesSubscriberId(SUBSCRIBER_ID)).isTrue(); Loading
services/core/java/com/android/server/net/NetworkPolicyManagerService.java +11 −6 Original line number Diff line number Diff line Loading @@ -232,7 +232,6 @@ import com.android.server.ServiceThread; import com.android.server.SystemConfig; import libcore.io.IoUtils; import libcore.util.EmptyArray; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; Loading Loading @@ -540,7 +539,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final SparseArray<String> mSubIdToSubscriberId = new SparseArray<>(); /** Set of all merged subscriberId as of last update */ @GuardedBy("mNetworkPoliciesSecondLock") private String[] mMergedSubscriberIds = EmptyArray.STRING; private List<String[]> mMergedSubscriberIds = new ArrayList<>(); /** * Indicates the uids restricted by admin from accessing metered data. It's a mapping from Loading Loading @@ -1801,7 +1800,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final SubscriptionManager sm = mContext.getSystemService(SubscriptionManager.class); final int[] subIds = ArrayUtils.defeatNullable(sm.getActiveSubscriptionIdList()); final String[] mergedSubscriberIds = ArrayUtils.defeatNullable(tm.getMergedSubscriberIds()); final List<String[]> mergedSubscriberIdsList = new ArrayList(); final SparseArray<String> subIdToSubscriberId = new SparseArray<>(subIds.length); for (int subId : subIds) { Loading @@ -1811,6 +1810,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } else { Slog.wtf(TAG, "Missing subscriberId for subId " + subId); } String[] mergedSubscriberId = ArrayUtils.defeatNullable( tm.createForSubscriptionId(subId).getMergedSubscriberIdsFromGroup()); mergedSubscriberIdsList.add(mergedSubscriberId); } synchronized (mNetworkPoliciesSecondLock) { Loading @@ -1820,7 +1823,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { subIdToSubscriberId.valueAt(i)); } mMergedSubscriberIds = mergedSubscriberIds; mMergedSubscriberIds = mergedSubscriberIdsList; } Trace.traceEnd(TRACE_TAG_NETWORK); Loading Loading @@ -3373,8 +3376,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { fout.decreaseIndent(); fout.println(); fout.println("Merged subscriptions: " + Arrays.toString(NetworkIdentity.scrubSubscriberId(mMergedSubscriberIds))); for (String[] mergedSubscribers : mMergedSubscriberIds) { fout.println("Merged subscriptions: " + Arrays.toString( NetworkIdentity.scrubSubscriberId(mergedSubscribers))); } fout.println(); fout.println("Policy for UIDs:"); Loading
telephony/java/android/telephony/TelephonyManager.java +27 −0 Original line number Diff line number Diff line Loading @@ -3972,9 +3972,14 @@ public class TelephonyManager { * The returned set of subscriber IDs will include the subscriber ID corresponding to this * TelephonyManager's subId. * * This is deprecated and {@link #getMergedSubscriberIdsFromGroup()} should be used for data * usage merging purpose. * TODO: remove this API. * * @hide */ @UnsupportedAppUsage @Deprecated public @Nullable String[] getMergedSubscriberIds() { try { ITelephony telephony = getITelephony(); Loading @@ -3986,6 +3991,28 @@ public class TelephonyManager { return null; } /** * Return the set of subscriber IDs that should be considered "merged together" for data usage * purposes. Unlike {@link #getMergedSubscriberIds()} this API merge subscriberIds based on * subscription grouping: subscriberId of those in the same group will all be returned. * * <p>Requires the calling app to have READ_PRIVILEGED_PHONE_STATE permission. * * @hide */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public @Nullable String[] getMergedSubscriberIdsFromGroup() { try { ITelephony telephony = getITelephony(); if (telephony != null) { return telephony.getMergedSubscriberIdsFromGroup(getSubId(), getOpPackageName()); } } catch (RemoteException ex) { } catch (NullPointerException ex) { } return null; } /** * Returns the MSISDN string. * for a GSM phone. Return null if it is unavailable. Loading