Home | History | Annotate | Download | only in datausage
      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 
     45     private DataUsageUtils() {
     46     }
     47 
     48     /**
     49      * Format byte value to readable string using IEC units.
     50      */
     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      */
     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      */
     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      */
    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 
    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      */
    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      */
    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