• 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_WIFI;
18 
19 import android.content.Context;
20 import android.net.ConnectivityManager;
21 import android.net.INetworkStatsService;
22 import android.net.INetworkStatsSession;
23 import android.net.NetworkTemplate;
24 import android.net.TrafficStats;
25 import android.os.RemoteException;
26 import android.os.ServiceManager;
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 
35 import java.util.List;
36 
37 /**
38  * Utility methods for data usage classes.
39  */
40 public final class DataUsageUtils {
41     static final boolean TEST_RADIOS = false;
42     static final String TEST_RADIOS_PROP = "test.radios";
43     private static final String ETHERNET = "ethernet";
44 
DataUsageUtils()45     private DataUsageUtils() {
46     }
47 
48     /**
49      * Format byte value to readable string using IEC units.
50      */
formatDataUsage(Context context, long byteValue)51     public static CharSequence formatDataUsage(Context context, long byteValue) {
52         final BytesResult res = Formatter.formatBytes(context.getResources(), byteValue,
53                 Formatter.FLAG_IEC_UNITS);
54         return BidiFormatter.getInstance().unicodeWrap(context.getString(
55                 com.android.internal.R.string.fileSizeSuffix, res.value, res.units));
56     }
57 
58     /**
59      * Test if device has an ethernet network connection.
60      */
hasEthernet(Context context)61     public static boolean hasEthernet(Context context) {
62         if (DataUsageUtils.TEST_RADIOS) {
63             return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains(ETHERNET);
64         }
65 
66         final ConnectivityManager conn = ConnectivityManager.from(context);
67         final boolean hasEthernet = conn.isNetworkSupported(ConnectivityManager.TYPE_ETHERNET);
68 
69         final long ethernetBytes;
70         try {
71             INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
72                     ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
73 
74             INetworkStatsSession statsSession = statsService.openSession();
75             if (statsSession != null) {
76                 ethernetBytes = statsSession.getSummaryForNetwork(
77                         NetworkTemplate.buildTemplateEthernet(), Long.MIN_VALUE, Long.MAX_VALUE)
78                         .getTotalBytes();
79                 TrafficStats.closeQuietly(statsSession);
80             } else {
81                 ethernetBytes = 0;
82             }
83         } catch (RemoteException e) {
84             throw new RuntimeException(e);
85         }
86 
87         // only show ethernet when both hardware present and traffic has occurred
88         return hasEthernet && ethernetBytes > 0;
89     }
90 
91     /**
92      * Returns whether device has mobile data.
93      * TODO: This is the opposite to Utils.isWifiOnly(), it should be refactored into 1 method.
94      */
hasMobileData(Context context)95     public static boolean hasMobileData(Context context) {
96         ConnectivityManager connectivityManager = ConnectivityManager.from(context);
97         return connectivityManager != null && connectivityManager
98                 .isNetworkSupported(ConnectivityManager.TYPE_MOBILE);
99     }
100 
101     /**
102      * Whether device has a Wi-Fi data radio.
103      */
hasWifiRadio(Context context)104     public static boolean hasWifiRadio(Context context) {
105         if (TEST_RADIOS) {
106             return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi");
107         }
108 
109         ConnectivityManager connectivityManager =
110                 context.getSystemService(ConnectivityManager.class);
111         return connectivityManager != null && connectivityManager.isNetworkSupported(TYPE_WIFI);
112     }
113 
hasSim(Context context)114     public static boolean hasSim(Context context) {
115         TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class);
116         final int simState = telephonyManager.getSimState();
117         // Note that pulling the SIM card returns UNKNOWN, not ABSENT.
118         return simState != TelephonyManager.SIM_STATE_ABSENT
119                 && simState != TelephonyManager.SIM_STATE_UNKNOWN;
120     }
121 
122     /**
123      * Returns the default subscription if available else returns
124      * SubscriptionManager#INVALID_SUBSCRIPTION_ID
125      */
getDefaultSubscriptionId(Context context)126     public static int getDefaultSubscriptionId(Context context) {
127         SubscriptionManager subManager = SubscriptionManager.from(context);
128         if (subManager == null) {
129             return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
130         }
131         SubscriptionInfo subscriptionInfo = subManager.getDefaultDataSubscriptionInfo();
132         if (subscriptionInfo == null) {
133             List<SubscriptionInfo> list = subManager.getAllSubscriptionInfoList();
134             if (list.size() == 0) {
135                 return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
136             }
137             subscriptionInfo = list.get(0);
138         }
139         return subscriptionInfo.getSubscriptionId();
140     }
141 
142     /**
143      * Returns the default network template based on the availability of mobile data, Wifi. Returns
144      * ethernet template if both mobile data and Wifi are not available.
145      */
getDefaultTemplate(Context context, int defaultSubId)146     static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) {
147         if (hasMobileData(context) && defaultSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
148             TelephonyManager telephonyManager = TelephonyManager.from(context);
149             NetworkTemplate mobileAll = NetworkTemplate.buildTemplateMobileAll(
150                     telephonyManager.getSubscriberId(defaultSubId));
151             return NetworkTemplate.normalize(mobileAll,
152                     telephonyManager.getMergedSubscriberIds());
153         } else if (hasWifiRadio(context)) {
154             return NetworkTemplate.buildTemplateWifiWildcard();
155         } else {
156             return NetworkTemplate.buildTemplateEthernet();
157         }
158     }
159 }
160