Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.settingslib.net;
     18 
     19 import android.app.AppGlobals;
     20 import android.content.Context;
     21 import android.content.pm.ApplicationInfo;
     22 import android.content.pm.IPackageManager;
     23 import android.content.pm.PackageInfo;
     24 import android.content.pm.PackageManager;
     25 import android.content.pm.PackageManager.NameNotFoundException;
     26 import android.content.pm.UserInfo;
     27 import android.content.res.Resources;
     28 import android.graphics.drawable.Drawable;
     29 import android.net.ConnectivityManager;
     30 import android.net.TrafficStats;
     31 import android.os.Process;
     32 import android.os.RemoteException;
     33 import android.os.UserHandle;
     34 import android.os.UserManager;
     35 import android.text.TextUtils;
     36 import android.util.Log;
     37 import android.util.SparseArray;
     38 
     39 import com.android.settingslib.R;
     40 import com.android.settingslib.Utils;
     41 
     42 /**
     43  * Return details about a specific UID, handling special cases like
     44  * {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
     45  */
     46 public class UidDetailProvider {
     47     private static final String TAG = "DataUsage";
     48     private final Context mContext;
     49     private final SparseArray<UidDetail> mUidDetailCache;
     50 
     51     public static final int OTHER_USER_RANGE_START = -2000;
     52 
     53     public static int buildKeyForUser(int userHandle) {
     54         return OTHER_USER_RANGE_START - userHandle;
     55     }
     56 
     57     public static boolean isKeyForUser(int key) {
     58         return key <= OTHER_USER_RANGE_START;
     59     }
     60 
     61     public static int getUserIdForKey(int key) {
     62         return OTHER_USER_RANGE_START - key;
     63     }
     64 
     65     public UidDetailProvider(Context context) {
     66         mContext = context.getApplicationContext();
     67         mUidDetailCache = new SparseArray<UidDetail>();
     68     }
     69 
     70     public void clearCache() {
     71         synchronized (mUidDetailCache) {
     72             mUidDetailCache.clear();
     73         }
     74     }
     75 
     76     /**
     77      * Resolve best descriptive label for the given UID.
     78      */
     79     public UidDetail getUidDetail(int uid, boolean blocking) {
     80         UidDetail detail;
     81 
     82         synchronized (mUidDetailCache) {
     83             detail = mUidDetailCache.get(uid);
     84         }
     85 
     86         if (detail != null) {
     87             return detail;
     88         } else if (!blocking) {
     89             return null;
     90         }
     91 
     92         detail = buildUidDetail(uid);
     93 
     94         synchronized (mUidDetailCache) {
     95             mUidDetailCache.put(uid, detail);
     96         }
     97 
     98         return detail;
     99     }
    100 
    101     /**
    102      * Build {@link UidDetail} object, blocking until all {@link Drawable}
    103      * lookup is finished.
    104      */
    105     private UidDetail buildUidDetail(int uid) {
    106         final Resources res = mContext.getResources();
    107         final PackageManager pm = mContext.getPackageManager();
    108 
    109         final UidDetail detail = new UidDetail();
    110         detail.label = pm.getNameForUid(uid);
    111         detail.icon = pm.getDefaultActivityIcon();
    112 
    113         // handle special case labels
    114         switch (uid) {
    115             case Process.SYSTEM_UID:
    116                 detail.label = res.getString(R.string.process_kernel_label);
    117                 detail.icon = pm.getDefaultActivityIcon();
    118                 return detail;
    119             case TrafficStats.UID_REMOVED:
    120                 detail.label = res.getString(UserManager.supportsMultipleUsers()
    121                         ? R.string.data_usage_uninstalled_apps_users
    122                         : R.string.data_usage_uninstalled_apps);
    123                 detail.icon = pm.getDefaultActivityIcon();
    124                 return detail;
    125             case TrafficStats.UID_TETHERING:
    126                 final ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
    127                         Context.CONNECTIVITY_SERVICE);
    128                 detail.label = res.getString(Utils.getTetheringLabel(cm));
    129                 detail.icon = pm.getDefaultActivityIcon();
    130                 return detail;
    131             case Process.OTA_UPDATE_UID:
    132                 detail.label = res.getString(R.string.data_usage_ota);
    133                 detail.icon = mContext.getDrawable(R.drawable.ic_system_update);
    134                 return detail;
    135         }
    136 
    137         final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
    138 
    139         // Handle keys that are actually user handles
    140         if (isKeyForUser(uid)) {
    141             final int userHandle = getUserIdForKey(uid);
    142             final UserInfo info = um.getUserInfo(userHandle);
    143             if (info != null) {
    144                 detail.label = Utils.getUserLabel(mContext, info);
    145                 detail.icon = Utils.getUserIcon(mContext, um, info);
    146                 return detail;
    147             }
    148         }
    149 
    150         // otherwise fall back to using packagemanager labels
    151         final String[] packageNames = pm.getPackagesForUid(uid);
    152         final int length = packageNames != null ? packageNames.length : 0;
    153         try {
    154             final int userId = UserHandle.getUserId(uid);
    155             UserHandle userHandle = new UserHandle(userId);
    156             IPackageManager ipm = AppGlobals.getPackageManager();
    157             if (length == 1) {
    158                 final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
    159                         0 /* no flags */, userId);
    160                 if (info != null) {
    161                     detail.label = info.loadLabel(pm).toString();
    162                     detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
    163                             new UserHandle(userId));
    164                 }
    165             } else if (length > 1) {
    166                 detail.detailLabels = new CharSequence[length];
    167                 detail.detailContentDescriptions = new CharSequence[length];
    168                 for (int i = 0; i < length; i++) {
    169                     final String packageName = packageNames[i];
    170                     final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
    171                     final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
    172                             0 /* no flags */, userId);
    173 
    174                     if (appInfo != null) {
    175                         detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
    176                         detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
    177                                 detail.detailLabels[i], userHandle);
    178                         if (packageInfo.sharedUserLabel != 0) {
    179                             detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
    180                                     packageInfo.applicationInfo).toString();
    181                             detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
    182                         }
    183                     }
    184                 }
    185             }
    186             detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
    187         } catch (NameNotFoundException e) {
    188             Log.w(TAG, "Error while building UI detail for uid "+uid, e);
    189         } catch (RemoteException e) {
    190             Log.w(TAG, "Error while building UI detail for uid "+uid, e);
    191         }
    192 
    193         if (TextUtils.isEmpty(detail.label)) {
    194             detail.label = Integer.toString(uid);
    195         }
    196 
    197         return detail;
    198     }
    199 }
    200