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.content.pm.PackageManager.FEATURE_ETHERNET; 18 import static android.content.pm.PackageManager.FEATURE_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.content.pm.PackageManager; 25 import android.net.ConnectivityManager; 26 import android.net.NetworkTemplate; 27 import android.os.RemoteException; 28 import android.os.SystemProperties; 29 import android.telephony.SubscriptionInfo; 30 import android.telephony.SubscriptionManager; 31 import android.telephony.TelephonyManager; 32 import android.text.BidiFormatter; 33 import android.text.format.Formatter; 34 import android.text.format.Formatter.BytesResult; 35 import android.util.Log; 36 37 import com.android.settings.datausage.lib.DataUsageLib; 38 import com.android.settings.network.ProxySubscriptionManager; 39 40 import java.util.List; 41 42 /** 43 * Utility methods for data usage classes. 44 */ 45 public final class DataUsageUtils extends com.android.settingslib.net.DataUsageUtils { 46 static final boolean TEST_RADIOS = false; 47 static final String TEST_RADIOS_PROP = "test.radios"; 48 private static final boolean LOGD = false; 49 private static final String ETHERNET = "ethernet"; 50 private static final String TAG = "DataUsageUtils"; 51 DataUsageUtils()52 private DataUsageUtils() { 53 } 54 55 /** 56 * Format byte value to readable string using IEC units. 57 */ formatDataUsage(Context context, long byteValue)58 public static CharSequence formatDataUsage(Context context, long byteValue) { 59 final BytesResult res = Formatter.formatBytes(context.getResources(), byteValue, 60 Formatter.FLAG_IEC_UNITS); 61 return BidiFormatter.getInstance().unicodeWrap(context.getString( 62 com.android.internal.R.string.fileSizeSuffix, res.value, res.units)); 63 } 64 65 /** 66 * Test if device has an ethernet network connection. 67 */ hasEthernet(Context context)68 public static boolean hasEthernet(Context context) { 69 if (DataUsageUtils.TEST_RADIOS) { 70 return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains(ETHERNET); 71 } 72 73 if (!context.getPackageManager().hasSystemFeature(FEATURE_ETHERNET)) { 74 return false; 75 } 76 77 final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 78 final NetworkStatsManager networkStatsManager = 79 context.getSystemService(NetworkStatsManager.class); 80 boolean hasEthernetUsage = false; 81 try { 82 final Bucket bucket = networkStatsManager.querySummaryForUser( 83 ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(), 84 0L /* startTime */, System.currentTimeMillis() /* endTime */); 85 if (bucket != null) { 86 hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0; 87 } 88 } catch (RemoteException e) { 89 Log.e(TAG, "Exception querying network detail.", e); 90 } 91 return hasEthernetUsage; 92 } 93 94 /** 95 * Returns whether device has mobile data. 96 * TODO: This is the opposite to Utils.isWifiOnly(), it should be refactored into 1 method. 97 */ hasMobileData(Context context)98 public static boolean hasMobileData(Context context) { 99 final TelephonyManager tele = context.getSystemService(TelephonyManager.class); 100 return tele.isDataCapable(); 101 } 102 103 /** 104 * Test if device has a mobile data radio with SIM in ready state. 105 */ hasReadyMobileRadio(Context context)106 public static boolean hasReadyMobileRadio(Context context) { 107 if (DataUsageUtils.TEST_RADIOS) { 108 return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains("mobile"); 109 } 110 final List<SubscriptionInfo> subInfoList = 111 ProxySubscriptionManager.getInstance(context) 112 .getActiveSubscriptionsInfo(); 113 // No activated Subscriptions 114 if (subInfoList == null) { 115 if (LOGD) { 116 Log.d(TAG, "hasReadyMobileRadio: subInfoList=null"); 117 } 118 return false; 119 } 120 final TelephonyManager tele = context.getSystemService(TelephonyManager.class); 121 // require both supported network and ready SIM 122 boolean isReady = true; 123 for (SubscriptionInfo subInfo : subInfoList) { 124 isReady = isReady & tele.getSimState(subInfo.getSimSlotIndex()) == SIM_STATE_READY; 125 if (LOGD) { 126 Log.d(TAG, "hasReadyMobileRadio: subInfo=" + subInfo); 127 } 128 } 129 130 final boolean isDataCapable = tele.isDataCapable(); 131 final boolean retVal = isDataCapable && isReady; 132 if (LOGD) { 133 Log.d(TAG, "hasReadyMobileRadio:" 134 + " telephonManager.isDataCapable()=" 135 + isDataCapable 136 + " isReady=" + isReady); 137 } 138 return retVal; 139 } 140 141 /** 142 * Whether device has a Wi-Fi data radio. 143 */ hasWifiRadio(Context context)144 public static boolean hasWifiRadio(Context context) { 145 if (TEST_RADIOS) { 146 return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi"); 147 } 148 149 final PackageManager packageManager = context.getPackageManager(); 150 return packageManager != null && packageManager.hasSystemFeature(FEATURE_WIFI); 151 } 152 153 /** 154 * Returns the default subscription if available else returns 155 * SubscriptionManager#INVALID_SUBSCRIPTION_ID 156 */ getDefaultSubscriptionId(Context context)157 public static int getDefaultSubscriptionId(Context context) { 158 // default data subscription is first choice 159 final int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 160 if (SubscriptionManager.isValidSubscriptionId(dataSubId)) { 161 return dataSubId; 162 } 163 164 final ProxySubscriptionManager proxySubscriptionMgr = 165 ProxySubscriptionManager.getInstance(context); 166 167 // any active subscription is second choice 168 List<SubscriptionInfo> subList = proxySubscriptionMgr.getActiveSubscriptionsInfo(); 169 if ((subList == null) || (subList.size() <= 0)) { 170 // any subscription is third choice 171 subList = proxySubscriptionMgr.getAccessibleSubscriptionsInfo(); 172 } 173 if ((subList == null) || (subList.size() <= 0)) { 174 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 175 } 176 return subList.get(0).getSubscriptionId(); 177 } 178 179 /** 180 * Returns the default network template based on the availability of mobile data, Wifi. Returns 181 * ethernet template if both mobile data and Wifi are not available. 182 */ getDefaultTemplate(Context context, int defaultSubId)183 public static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) { 184 if (SubscriptionManager.isValidSubscriptionId(defaultSubId) && hasMobileData(context)) { 185 return DataUsageLib.getMobileTemplate(context, defaultSubId); 186 } else if (hasWifiRadio(context)) { 187 return NetworkTemplate.buildTemplateWifi(NetworkTemplate.WIFI_NETWORKID_ALL, 188 null /* subscriberId */); 189 } else { 190 return NetworkTemplate.buildTemplateEthernet(); 191 } 192 } 193 194 } 195