• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.app.usage.NetworkStats;
21 import android.content.Context;
22 import android.content.pm.ApplicationInfo;
23 import android.content.pm.IPackageManager;
24 import android.content.pm.PackageInfo;
25 import android.content.pm.PackageManager;
26 import android.content.pm.PackageManager.NameNotFoundException;
27 import android.content.pm.UserInfo;
28 import android.content.res.Resources;
29 import android.graphics.drawable.Drawable;
30 import android.net.TetheringManager;
31 import android.net.TrafficStats;
32 import android.os.Process;
33 import android.os.RemoteException;
34 import android.os.UserHandle;
35 import android.os.UserManager;
36 import android.text.TextUtils;
37 import android.util.Log;
38 import android.util.SparseArray;
39 
40 import com.android.settingslib.R;
41 import com.android.settingslib.Utils;
42 
43 /**
44  * Return details about a specific UID, handling special cases like
45  * {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
46  */
47 public class UidDetailProvider {
48     private static final String TAG = "DataUsage";
49     private final Context mContext;
50     private final SparseArray<UidDetail> mUidDetailCache;
51 
52     public static final int OTHER_USER_RANGE_START = -2000;
53 
buildKeyForUser(int userHandle)54     public static int buildKeyForUser(int userHandle) {
55         return OTHER_USER_RANGE_START - userHandle;
56     }
57 
isKeyForUser(int key)58     public static boolean isKeyForUser(int key) {
59         return key <= OTHER_USER_RANGE_START;
60     }
61 
getUserIdForKey(int key)62     public static int getUserIdForKey(int key) {
63         return OTHER_USER_RANGE_START - key;
64     }
65 
UidDetailProvider(Context context)66     public UidDetailProvider(Context context) {
67         mContext = context;
68         mUidDetailCache = new SparseArray<UidDetail>();
69     }
70 
clearCache()71     public void clearCache() {
72         synchronized (mUidDetailCache) {
73             mUidDetailCache.clear();
74         }
75     }
76 
77     /**
78      * Resolve best descriptive label for the given UID.
79      */
getUidDetail(int uid, boolean blocking)80     public UidDetail getUidDetail(int uid, boolean blocking) {
81         UidDetail detail;
82 
83         synchronized (mUidDetailCache) {
84             detail = mUidDetailCache.get(uid);
85         }
86 
87         if (detail != null) {
88             return detail;
89         } else if (!blocking) {
90             return null;
91         }
92 
93         detail = buildUidDetail(uid);
94 
95         synchronized (mUidDetailCache) {
96             mUidDetailCache.put(uid, detail);
97         }
98 
99         return detail;
100     }
101 
102     /**
103      * Build {@link UidDetail} object, blocking until all {@link Drawable}
104      * lookup is finished.
105      */
buildUidDetail(int uid)106     private UidDetail buildUidDetail(int uid) {
107         final Resources res = mContext.getResources();
108         final PackageManager pm = mContext.getPackageManager();
109 
110         final UidDetail detail = new UidDetail();
111         detail.label = pm.getNameForUid(uid);
112         detail.icon = pm.getDefaultActivityIcon();
113 
114         // handle special case labels
115         switch (uid) {
116             case Process.SYSTEM_UID:
117                 detail.label = res.getString(R.string.process_kernel_label);
118                 detail.icon = pm.getDefaultActivityIcon();
119                 return detail;
120             case NetworkStats.Bucket.UID_REMOVED:
121                 detail.label = res.getString(UserManager.supportsMultipleUsers()
122                         ? R.string.data_usage_uninstalled_apps_users
123                         : R.string.data_usage_uninstalled_apps);
124                 detail.icon = pm.getDefaultActivityIcon();
125                 return detail;
126             case NetworkStats.Bucket.UID_TETHERING:
127                 final TetheringManager tm = mContext.getSystemService(TetheringManager.class);
128                 detail.label = res.getString(Utils.getTetheringLabel(tm));
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         String packageName = "";
154         try {
155             final int userId = UserHandle.getUserId(uid);
156             UserHandle userHandle = new UserHandle(userId);
157             IPackageManager ipm = AppGlobals.getPackageManager();
158             if (length == 1) {
159                 final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
160                         0 /* no flags */, userId);
161                 if (info != null) {
162                     detail.label = info.loadLabel(pm).toString();
163                     detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
164                             new UserHandle(userId));
165                     packageName = packageNames[0];
166                 }
167             } else if (length > 1) {
168                 detail.detailLabels = new CharSequence[length];
169                 detail.detailContentDescriptions = new CharSequence[length];
170                 for (int i = 0; i < length; i++) {
171                     packageName = packageNames[i];
172                     final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
173                     final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
174                             0 /* no flags */, userId);
175 
176                     if (appInfo != null) {
177                         detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
178                         detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
179                                 detail.detailLabels[i], userHandle);
180                         if (packageInfo.sharedUserLabel != 0) {
181                             detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
182                                     packageInfo.applicationInfo).toString();
183                             detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
184                         }
185                     }
186                 }
187             }
188             detail.packageName = packageName;
189             detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
190         } catch (NameNotFoundException e) {
191             Log.w(TAG, "Error while building UI detail for uid "+uid, e);
192         } catch (RemoteException e) {
193             Log.w(TAG, "Error while building UI detail for uid "+uid, e);
194         }
195 
196         if (TextUtils.isEmpty(detail.label)) {
197             detail.label = Integer.toString(uid);
198         }
199 
200         return detail;
201     }
202 }
203