• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
5  * except in compliance with the License. You may obtain a copy of the License at
6  *
7  *      http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software distributed under the
10  * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
11  * KIND, either express or implied. See the License for the specific language governing
12  * permissions and limitations under the License.
13  */
14 
15 package com.android.settings.datausage;
16 
17 import static android.net.ConnectivityManager.TYPE_MOBILE;
18 import static android.net.ConnectivityManager.TYPE_WIFI;
19 import static android.telephony.TelephonyManager.SIM_STATE_READY;
20 
21 import android.app.usage.NetworkStats.Bucket;
22 import android.app.usage.NetworkStatsManager;
23 import android.content.Context;
24 import android.net.ConnectivityManager;
25 import android.net.NetworkTemplate;
26 import android.os.RemoteException;
27 import android.os.SystemProperties;
28 import android.telephony.SubscriptionInfo;
29 import android.telephony.SubscriptionManager;
30 import android.telephony.TelephonyManager;
31 import android.text.BidiFormatter;
32 import android.text.format.Formatter;
33 import android.text.format.Formatter.BytesResult;
34 import android.util.Log;
35 
36 import java.util.ArrayList;
37 import java.util.List;
38 
39 /**
40  * Utility methods for data usage classes.
41  */
42 public final class DataUsageUtils extends com.android.settingslib.net.DataUsageUtils {
43     static final boolean TEST_RADIOS = false;
44     static final String TEST_RADIOS_PROP = "test.radios";
45     private static final boolean LOGD = false;
46     private static final String ETHERNET = "ethernet";
47     private static final String TAG = "DataUsageUtils";
48 
DataUsageUtils()49     private DataUsageUtils() {
50     }
51 
52     /**
53      * Format byte value to readable string using IEC units.
54      */
formatDataUsage(Context context, long byteValue)55     public static CharSequence formatDataUsage(Context context, long byteValue) {
56         final BytesResult res = Formatter.formatBytes(context.getResources(), byteValue,
57                 Formatter.FLAG_IEC_UNITS);
58         return BidiFormatter.getInstance().unicodeWrap(context.getString(
59                 com.android.internal.R.string.fileSizeSuffix, res.value, res.units));
60     }
61 
62     /**
63      * Test if device has an ethernet network connection.
64      */
hasEthernet(Context context)65     public static boolean hasEthernet(Context context) {
66         if (DataUsageUtils.TEST_RADIOS) {
67             return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains(ETHERNET);
68         }
69 
70         final ConnectivityManager conn = ConnectivityManager.from(context);
71         if (!conn.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET)) {
72             return false;
73         }
74 
75         final TelephonyManager telephonyManager = TelephonyManager.from(context);
76         final NetworkStatsManager networkStatsManager =
77                 context.getSystemService(NetworkStatsManager.class);
78         boolean hasEthernetUsage = false;
79         try {
80             final Bucket bucket = networkStatsManager.querySummaryForUser(
81                     ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(),
82                     0L /* startTime */, System.currentTimeMillis() /* endTime */);
83             if (bucket != null) {
84                 hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0;
85             }
86         } catch (RemoteException e) {
87             Log.e(TAG, "Exception querying network detail.", e);
88         }
89         return hasEthernetUsage;
90     }
91 
92     /**
93      * Returns whether device has mobile data.
94      * TODO: This is the opposite to Utils.isWifiOnly(), it should be refactored into 1 method.
95      */
hasMobileData(Context context)96     public static boolean hasMobileData(Context context) {
97         ConnectivityManager connectivityManager = ConnectivityManager.from(context);
98         return connectivityManager != null && connectivityManager
99                 .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
100     }
101 
102     /**
103      * Test if device has a mobile data radio with SIM in ready state.
104      */
hasReadyMobileRadio(Context context)105     public static boolean hasReadyMobileRadio(Context context) {
106         if (DataUsageUtils.TEST_RADIOS) {
107             return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains("mobile");
108         }
109         final List<SubscriptionInfo> subInfoList =
110                 SubscriptionManager.from(context).getActiveSubscriptionInfoList(true);
111         // No activated Subscriptions
112         if (subInfoList == null) {
113             if (LOGD) {
114                 Log.d(TAG, "hasReadyMobileRadio: subInfoList=null");
115             }
116             return false;
117         }
118         final TelephonyManager tele = TelephonyManager.from(context);
119         // require both supported network and ready SIM
120         boolean isReady = true;
121         for (SubscriptionInfo subInfo : subInfoList) {
122             isReady = isReady & tele.getSimState(subInfo.getSimSlotIndex()) == SIM_STATE_READY;
123             if (LOGD) {
124                 Log.d(TAG, "hasReadyMobileRadio: subInfo=" + subInfo);
125             }
126         }
127         final ConnectivityManager conn = ConnectivityManager.from(context);
128         final boolean retVal = conn.isNetworkSupported(TYPE_MOBILE) && isReady;
129         if (LOGD) {
130             Log.d(TAG, "hasReadyMobileRadio:"
131                     + " conn.isNetworkSupported(TYPE_MOBILE)="
132                     + conn.isNetworkSupported(TYPE_MOBILE)
133                     + " isReady=" + isReady);
134         }
135         return retVal;
136     }
137 
138     /**
139      * Whether device has a Wi-Fi data radio.
140      */
hasWifiRadio(Context context)141     public static boolean hasWifiRadio(Context context) {
142         if (TEST_RADIOS) {
143             return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi");
144         }
145 
146         final ConnectivityManager connectivityManager = ConnectivityManager.from(context);
147         return connectivityManager != null && connectivityManager.isNetworkSupported(TYPE_WIFI);
148     }
149 
hasSim(Context context)150     public static boolean hasSim(Context context) {
151         TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
152         final int simState = telephonyManager.getSimState();
153         // Note that pulling the SIM card returns UNKNOWN, not ABSENT.
154         return simState != TelephonyManager.SIM_STATE_ABSENT
155                 && simState != TelephonyManager.SIM_STATE_UNKNOWN;
156     }
157 
158     /**
159      * Returns the default subscription if available else returns
160      * SubscriptionManager#INVALID_SUBSCRIPTION_ID
161      */
getDefaultSubscriptionId(Context context)162     public static int getDefaultSubscriptionId(Context context) {
163         SubscriptionManager subManager = SubscriptionManager.from(context);
164         if (subManager == null) {
165             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
166         }
167         SubscriptionInfo subscriptionInfo = subManager.getDefaultDataSubscriptionInfo();
168         if (subscriptionInfo == null) {
169             List<SubscriptionInfo> list = subManager.getAllSubscriptionInfoList();
170             if (list.size() == 0) {
171                 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
172             }
173             subscriptionInfo = list.get(0);
174         }
175         return subscriptionInfo.getSubscriptionId();
176     }
177 
178     /**
179      * Returns the default network template based on the availability of mobile data, Wifi. Returns
180      * ethernet template if both mobile data and Wifi are not available.
181      */
getDefaultTemplate(Context context, int defaultSubId)182     public static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) {
183         if (hasMobileData(context) && defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
184             return getMobileTemplate(context, defaultSubId);
185         } else if (hasWifiRadio(context)) {
186             return NetworkTemplate.buildTemplateWifiWildcard();
187         } else {
188             return NetworkTemplate.buildTemplateEthernet();
189         }
190     }
191 
192 }
193