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.util.Log; 35 36 import com.android.settings.datausage.lib.DataUsageLib; 37 import com.android.settings.network.ProxySubscriptionManager; 38 39 import java.util.List; 40 import java.util.Optional; 41 42 /** 43 * Utility methods for data usage classes. 44 */ 45 public final class DataUsageUtils { 46 static final boolean TEST_RADIOS = false; 47 static final String TEST_RADIOS_PROP = "test.radios"; 48 private static final String ETHERNET = "ethernet"; 49 private static final String TAG = "DataUsageUtils"; 50 DataUsageUtils()51 private DataUsageUtils() { 52 } 53 54 /** 55 * Test if device has an ethernet network connection. 56 */ hasEthernet(Context context)57 public static boolean hasEthernet(Context context) { 58 if (DataUsageUtils.TEST_RADIOS) { 59 return SystemProperties.get(DataUsageUtils.TEST_RADIOS_PROP).contains(ETHERNET); 60 } 61 62 // See ConnectivityService#deviceSupportsEthernet. 63 final PackageManager pm = context.getPackageManager(); 64 if (!pm.hasSystemFeature(FEATURE_ETHERNET) && !pm.hasSystemFeature(FEATURE_USB_HOST)) { 65 return false; 66 } 67 68 final TelephonyManager telephonyManager = context.getSystemService(TelephonyManager.class); 69 final NetworkStatsManager networkStatsManager = 70 context.getSystemService(NetworkStatsManager.class); 71 boolean hasEthernetUsage = false; 72 try { 73 final Bucket bucket = networkStatsManager.querySummaryForUser( 74 ConnectivityManager.TYPE_ETHERNET, telephonyManager.getSubscriberId(), 75 0L /* startTime */, System.currentTimeMillis() /* endTime */); 76 if (bucket != null) { 77 hasEthernetUsage = bucket.getRxBytes() > 0 || bucket.getTxBytes() > 0; 78 } 79 } catch (RemoteException e) { 80 Log.e(TAG, "Exception querying network detail.", e); 81 } 82 return hasEthernetUsage; 83 } 84 85 /** 86 * Returns whether device has mobile data. 87 * TODO: This is the opposite to Utils.isWifiOnly(), it should be refactored into 1 method. 88 */ hasMobileData(Context context)89 public static boolean hasMobileData(Context context) { 90 final TelephonyManager tele = context.getSystemService(TelephonyManager.class); 91 return tele.isDataCapable(); 92 } 93 94 /** 95 * Whether device has a Wi-Fi data radio. 96 */ hasWifiRadio(Context context)97 public static boolean hasWifiRadio(Context context) { 98 if (TEST_RADIOS) { 99 return SystemProperties.get(TEST_RADIOS_PROP).contains("wifi"); 100 } 101 102 final PackageManager packageManager = context.getPackageManager(); 103 return packageManager != null && packageManager.hasSystemFeature(FEATURE_WIFI); 104 } 105 106 /** 107 * Returns the default subscription if available else returns 108 * SubscriptionManager#INVALID_SUBSCRIPTION_ID 109 */ getDefaultSubscriptionId(Context context)110 public static int getDefaultSubscriptionId(Context context) { 111 // default data subscription is first choice 112 final int dataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 113 if (SubscriptionManager.isValidSubscriptionId(dataSubId)) { 114 return dataSubId; 115 } 116 117 final ProxySubscriptionManager proxySubscriptionMgr = 118 ProxySubscriptionManager.getInstance(context); 119 120 // any active subscription is second choice 121 List<SubscriptionInfo> subList = proxySubscriptionMgr.getActiveSubscriptionsInfo(); 122 if ((subList == null) || (subList.size() <= 0)) { 123 // any subscription is third choice 124 subList = proxySubscriptionMgr.getAccessibleSubscriptionsInfo(); 125 } 126 if ((subList == null) || (subList.size() <= 0)) { 127 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 128 } 129 return subList.get(0).getSubscriptionId(); 130 } 131 132 /** 133 * Returns the default network template based on the availability of mobile data, Wifi. Returns 134 * ethernet template if both mobile data and Wifi are not available. 135 */ getDefaultTemplate(Context context, int defaultSubId)136 public static NetworkTemplate getDefaultTemplate(Context context, int defaultSubId) { 137 if (SubscriptionManager.isValidSubscriptionId(defaultSubId) && hasMobileData(context)) { 138 return DataUsageLib.getMobileTemplate(context, defaultSubId); 139 } else if (hasWifiRadio(context)) { 140 return new NetworkTemplate.Builder(NetworkTemplate.MATCH_WIFI).build(); 141 } else { 142 return new NetworkTemplate.Builder(NetworkTemplate.MATCH_ETHERNET).build(); 143 } 144 } 145 146 /** 147 * Returns a mobile NetworkTemplate if EXTRA_SUB_ID of the Intent is available and the subId 148 * is valid & hasMobileData. Otherwise, returns empty data. 149 */ getMobileNetworkTemplateFromSubId(Context context, Intent intent)150 public static Optional<NetworkTemplate> getMobileNetworkTemplateFromSubId(Context context, 151 Intent intent) { 152 if (intent == null || !intent.hasExtra(Settings.EXTRA_SUB_ID)) { 153 return Optional.empty(); 154 } 155 156 int subId = intent.getIntExtra(Settings.EXTRA_SUB_ID, 157 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 158 if (SubscriptionManager.isValidSubscriptionId(subId) && hasMobileData(context)) { 159 return Optional.of(DataUsageLib.getMobileTemplate(context, subId)); 160 } 161 162 return Optional.empty(); 163 } 164 } 165