• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.settings.datausage.lib;
18 
19 import android.content.Context;
20 import android.net.NetworkStats;
21 import android.net.NetworkTemplate;
22 import android.telephony.SubscriptionInfo;
23 import android.telephony.SubscriptionManager;
24 import android.telephony.TelephonyManager;
25 import android.util.ArraySet;
26 import android.util.Log;
27 
28 import androidx.annotation.NonNull;
29 
30 import com.android.internal.util.ArrayUtils;
31 
32 import java.util.Arrays;
33 import java.util.List;
34 import java.util.Set;
35 
36 /**
37  * Lib class for data usage
38  */
39 public class DataUsageLib {
40     private static final String TAG = "DataUsageLib";
41 
42     /**
43      * Return mobile NetworkTemplate based on {@code subId}
44      */
getMobileTemplate(Context context, int subId)45     public static NetworkTemplate getMobileTemplate(Context context, int subId) {
46         final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
47         final int mobileDefaultSubId = telephonyManager.getSubscriptionId();
48 
49         final SubscriptionManager subscriptionManager =
50                 context.getSystemService(SubscriptionManager.class);
51         final List<SubscriptionInfo> subInfoList =
52                 subscriptionManager.getAvailableSubscriptionInfoList();
53         if (subInfoList == null) {
54             Log.i(TAG, "Subscription is not inited: " + subId);
55             return getMobileTemplateForSubId(telephonyManager, mobileDefaultSubId);
56         }
57 
58         for (SubscriptionInfo subInfo : subInfoList) {
59             if ((subInfo != null) && (subInfo.getSubscriptionId() == subId)) {
60                 return getNormalizedMobileTemplate(telephonyManager, subId);
61             }
62         }
63         Log.i(TAG, "Subscription is not active: " + subId);
64         return getMobileTemplateForSubId(telephonyManager, mobileDefaultSubId);
65     }
66 
getNormalizedMobileTemplate( TelephonyManager telephonyManager, int subId)67     private static NetworkTemplate getNormalizedMobileTemplate(
68             TelephonyManager telephonyManager, int subId) {
69         final NetworkTemplate mobileTemplate = getMobileTemplateForSubId(telephonyManager, subId);
70         final String[] mergedSubscriberIds = telephonyManager
71                 .createForSubscriptionId(subId).getMergedImsisFromGroup();
72         if (ArrayUtils.isEmpty(mergedSubscriberIds)) {
73             Log.i(TAG, "mergedSubscriberIds is null.");
74             return mobileTemplate;
75         }
76 
77         return normalizeMobileTemplate(mobileTemplate, mergedSubscriberIds);
78     }
79 
normalizeMobileTemplate( @onNull NetworkTemplate template, @NonNull String[] merged)80     private static NetworkTemplate normalizeMobileTemplate(
81             @NonNull NetworkTemplate template, @NonNull String[] merged) {
82         if (template.getSubscriberIds().isEmpty()) return template;
83         // The input template should have at most 1 subscriberId.
84         final String subscriberId = template.getSubscriberIds().iterator().next();
85         // In some rare cases (e.g. b/243015487), merged subscriberId list might contain
86         // duplicated items. Deduplication for better error handling.
87         final ArraySet mergedSet = new ArraySet(merged);
88         if (mergedSet.size() != merged.length) {
89             Log.wtf(TAG, "Duplicated merged list detected: " + Arrays.toString(merged));
90         }
91         if (mergedSet.contains(subscriberId)) {
92             // Requested template subscriber is part of the merge group; return
93             // a template that matches all merged subscribers.
94             return new NetworkTemplate.Builder(template.getMatchRule())
95                     .setSubscriberIds(mergedSet)
96                     .setMeteredness(template.getMeteredness()).build();
97         }
98 
99         return template;
100     }
101 
getMobileTemplateForSubId( TelephonyManager telephonyManager, int subId)102     public static NetworkTemplate getMobileTemplateForSubId(
103             TelephonyManager telephonyManager, int subId) {
104         // Create template that matches any mobile network when the subscriberId is null.
105         String subscriberId = telephonyManager.getSubscriberId(subId);
106         return subscriberId != null
107                 ? new NetworkTemplate.Builder(NetworkTemplate.MATCH_CARRIER)
108                 .setSubscriberIds(Set.of(subscriberId))
109                 .setMeteredness(NetworkStats.METERED_YES)
110                 .build()
111                 : new NetworkTemplate.Builder(NetworkTemplate.MATCH_MOBILE)
112                         .setMeteredness(NetworkStats.METERED_YES)
113                         .build();
114     }
115 }
116