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_USB_HOST; 19 import static android.content.pm.PackageManager.FEATURE_WIFI; 20 21 import android.app.usage.NetworkStats.Bucket; 22 import android.app.usage.NetworkStatsManager; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.net.ConnectivityManager; 27 import android.net.NetworkTemplate; 28 import android.os.RemoteException; 29 import android.os.SystemProperties; 30 import android.provider.Settings; 31 import android.telephony.SubscriptionInfo; 32 import android.telephony.SubscriptionManager; 33 import android.telephony.TelephonyManager; 34 import android.text.BidiFormatter; 35 import android.text.format.Formatter; 36 import android.text.format.Formatter.BytesResult; 37 import android.util.Log; 38 39 import com.android.settings.datausage.lib.DataUsageLib; 40 import com.android.settings.network.ProxySubscriptionManager; 41 42 import java.util.List; 43 import java.util.Optional; 44 45 /** 46 * Utility methods for data usage classes. 47 */ 48 public final class DataUsageUtils { 49 static final boolean TEST_RADIOS = false; 50 static final String TEST_RADIOS_PROP = "test.radios"; 51 private static final String ETHERNET = "ethernet"; 52 private static final String TAG = "DataUsageUtils"; 53 DataUsageUtils()54 private DataUsageUtils() { 55 } 56 57 /** 58 * Format byte value to readable string using IEC units. 59 * 60 * @deprecated Use {@link com.android.settings.datausage.lib.DataUsageFormatter} instead. 61 */ 62 @Deprecated formatDataUsage(Context context, long byteValue)63 public static CharSequence formatDataUsage(Context context, long byteValue) { 64 final BytesResult res = Formatter.formatBytes(context.getResources(), byteValue, 65 Formatter.FLAG_IEC_UNITS); 66 return BidiFormatter.getInstance().unicodeWrap(context.getString( 67 com.android.internal.R.string.fileSizeSuffix, res.value, res.units)); 68 } 69 70 /** 71 * Test if device has an ethernet network connection. 72 */ hasEthernet(Context context)73 public static boolean hasEthernet(Context context) { 74 if (DataUsageUtils.TEST_RADIOS) { 75 return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains(ETHERNET); 76 } 77 78 // See ConnectivityService#deviceSupportsEthernet. 79 final PackageManager pm = context.getPackageManager(); 80 if (!pm.hasSystemFeature(FEATURE_ETHERNET) && !pm.hasSystemFeature(FEATURE_USB_HOST)) { 81 return false; 82 } 83 84 final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 85 final NetworkStatsManager networkStatsManager = 86 context.getSystemService(NetworkStatsManager.class); 87 boolean hasEthernetUsage = false; 88 try { 89 final Bucket bucket = networkStatsManager.querySummaryForUser( 90 ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(), 91 0L /* startTime */, System.currentTimeMillis() /* endTime */); 92 if (bucket != null) { 93 hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0; 94 } 95 } catch (RemoteException e) { 96 Log.e(TAG, "Exception querying network detail.", e); 97 } 98 return hasEthernetUsage; 99 } 100 101 /** 102 * Returns whether device has mobile data. 103 * TODO: This is the opposite to Utils.isWifiOnly(), it should be refactored into 1 method. 104 */ hasMobileData(Context context)105 public static boolean hasMobileData(Context context) { 106 final TelephonyManager tele = context.getSystemService(TelephonyManager.class); 107 return tele.isDataCapable(); 108 } 109 110 /** 111 * Whether device has a Wi-Fi data radio. 112 */ hasWifiRadio(Context context)113 public static boolean hasWifiRadio(Context context) { 114 if (TEST_RADIOS) { 115 return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi"); 116 } 117 118 final PackageManager packageManager = context.getPackageManager(); 119 return packageManager != null && packageManager.hasSystemFeature(FEATURE_WIFI); 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 // default data subscription is first choice 128 final int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 129 if (SubscriptionManager.isValidSubscriptionId(dataSubId)) { 130 return dataSubId; 131 } 132 133 final ProxySubscriptionManager proxySubscriptionMgr = 134 ProxySubscriptionManager.getInstance(context); 135 136 // any active subscription is second choice 137 List<SubscriptionInfo> subList = proxySubscriptionMgr.getActiveSubscriptionsInfo(); 138 if ((subList == null) || (subList.size() <= 0)) { 139 // any subscription is third choice 140 subList = proxySubscriptionMgr.getAccessibleSubscriptionsInfo(); 141 } 142 if ((subList == null) || (subList.size() <= 0)) { 143 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 144 } 145 return subList.get(0).getSubscriptionId(); 146 } 147 148 /** 149 * Returns the default network template based on the availability of mobile data, Wifi. Returns 150 * ethernet template if both mobile data and Wifi are not available. 151 */ getDefaultTemplate(Context context, int defaultSubId)152 public static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) { 153 if (SubscriptionManager.isValidSubscriptionId(defaultSubId) && hasMobileData(context)) { 154 return DataUsageLib.getMobileTemplate(context, defaultSubId); 155 } else if (hasWifiRadio(context)) { 156 return new NetworkTemplate.Builder(NetworkTemplate.MATCH_WIFI).build(); 157 } else { 158 return new NetworkTemplate.Builder(NetworkTemplate.MATCH_ETHERNET).build(); 159 } 160 } 161 162 /** 163 * Returns a mobile NetworkTemplate if EXTRA_SUB_ID of the Intent is available and the subId 164 * is valid & hasMobileData. Otherwise, returns empty data. 165 */ getMobileNetworkTemplateFromSubId(Context context, Intent intent)166 public static Optional<NetworkTemplate> getMobileNetworkTemplateFromSubId(Context context, 167 Intent intent) { 168 if (intent == null || !intent.hasExtra(Settings.EXTRA_SUB_ID)) { 169 return Optional.empty(); 170 } 171 172 int subId = intent.getIntExtra(Settings.EXTRA_SUB_ID, 173 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 174 if (SubscriptionManager.isValidSubscriptionId(subId) && hasMobileData(context)) { 175 return Optional.of(DataUsageLib.getMobileTemplate(context, subId)); 176 } 177 178 return Optional.empty(); 179 } 180 } 181