1b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey/*
2b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * Copyright (C) 2011 The Android Open Source Project
3b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey *
4b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * you may not use this file except in compliance with the License.
6b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * You may obtain a copy of the License at
7b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey *
8b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey *
10b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * See the License for the specific language governing permissions and
14b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey * limitations under the License.
15b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey */
16b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
17b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeypackage com.android.settings.net;
18b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
193aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Banimport android.app.AppGlobals;
20b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.content.Context;
21b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.content.pm.ApplicationInfo;
223aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Banimport android.content.pm.IPackageManager;
23b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.content.pm.PackageInfo;
24b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.content.pm.PackageManager;
25b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
2638305fb1777147cbcb86774c466e88434daff141Jeff Sharkeyimport android.content.pm.UserInfo;
27b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.content.res.Resources;
28ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkeyimport android.graphics.drawable.Drawable;
29a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkeyimport android.net.ConnectivityManager;
30b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.net.TrafficStats;
3138305fb1777147cbcb86774c466e88434daff141Jeff Sharkeyimport android.os.UserManager;
320924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Banimport android.os.UserHandle;
333aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Banimport android.os.RemoteException;
34b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.text.TextUtils;
353aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Banimport android.util.Log;
36b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport android.util.SparseArray;
37b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
38b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeyimport com.android.settings.R;
39a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkeyimport com.android.settings.Utils;
40b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
4138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey/**
4238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey * Return details about a specific UID, handling special cases like
4338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey * {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
4438305fb1777147cbcb86774c466e88434daff141Jeff Sharkey */
45b98c55bd097e006703352f84f0271dec5181160aJeff Sharkeypublic class UidDetailProvider {
463aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban    private static final String TAG = "DataUsage";
47b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private final Context mContext;
48b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    private final SparseArray<UidDetail> mUidDetailCache;
49b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
500924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban    public static final int OTHER_USER_RANGE_START = -2000;
510924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban
5238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey    public static int buildKeyForUser(int userHandle) {
530924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban        return OTHER_USER_RANGE_START - userHandle;
540924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban    }
550924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban
560924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban    public static boolean isKeyForUser(int key) {
570924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban        return key <= OTHER_USER_RANGE_START;
580924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban    }
590924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban
600924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban    public static int getUserIdForKey(int key) {
610924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban        return OTHER_USER_RANGE_START - key;
6238305fb1777147cbcb86774c466e88434daff141Jeff Sharkey    }
6338305fb1777147cbcb86774c466e88434daff141Jeff Sharkey
64b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    public UidDetailProvider(Context context) {
65b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        mContext = context.getApplicationContext();
66b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        mUidDetailCache = new SparseArray<UidDetail>();
67b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    }
68b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
69ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey    public void clearCache() {
70ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        synchronized (mUidDetailCache) {
71ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey            mUidDetailCache.clear();
72ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        }
73b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    }
74b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
75b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    /**
76b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey     * Resolve best descriptive label for the given UID.
77b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey     */
78ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey    public UidDetail getUidDetail(int uid, boolean blocking) {
79ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        UidDetail detail;
80ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey
81ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        synchronized (mUidDetailCache) {
82ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey            detail = mUidDetailCache.get(uid);
83ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        }
84ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey
85ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        if (detail != null) {
86ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey            return detail;
87b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        } else if (!blocking) {
88b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            return null;
89b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
90b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
91ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        detail = buildUidDetail(uid);
92ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey
93ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        synchronized (mUidDetailCache) {
94ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey            mUidDetailCache.put(uid, detail);
95ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        }
96ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey
97ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey        return detail;
98ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey    }
99ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey
100ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey    /**
101ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey     * Build {@link UidDetail} object, blocking until all {@link Drawable}
102ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey     * lookup is finished.
103ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey     */
104ae30d12a5f650ec6f2ba0604c908a0f5361334f3Jeff Sharkey    private UidDetail buildUidDetail(int uid) {
105b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        final Resources res = mContext.getResources();
106b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        final PackageManager pm = mContext.getPackageManager();
107b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
108b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        final UidDetail detail = new UidDetail();
109b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        detail.label = pm.getNameForUid(uid);
110b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        detail.icon = pm.getDefaultActivityIcon();
111b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
112b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        // handle special case labels
113b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        switch (uid) {
114b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            case android.os.Process.SYSTEM_UID:
115b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                detail.label = res.getString(R.string.process_kernel_label);
116b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                detail.icon = pm.getDefaultActivityIcon();
117b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                return detail;
118b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            case TrafficStats.UID_REMOVED:
1196bf72119fd2f53ae363f8dd5dc105790e86a8973Jeff Sharkey                detail.label = res.getString(UserManager.supportsMultipleUsers()
1206bf72119fd2f53ae363f8dd5dc105790e86a8973Jeff Sharkey                        ? R.string.data_usage_uninstalled_apps_users
1216bf72119fd2f53ae363f8dd5dc105790e86a8973Jeff Sharkey                        : R.string.data_usage_uninstalled_apps);
122b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                detail.icon = pm.getDefaultActivityIcon();
123b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                return detail;
124a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkey            case TrafficStats.UID_TETHERING:
125a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkey                final ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
126a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkey                        Context.CONNECTIVITY_SERVICE);
127a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkey                detail.label = res.getString(Utils.getTetheringLabel(cm));
128a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkey                detail.icon = pm.getDefaultActivityIcon();
129a83a24f48a8286ee3d67acc5fdcfb723acc56adaJeff Sharkey                return detail;
130b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
131b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
1320924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
1330924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban
13438305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        // Handle keys that are actually user handles
1350924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban        if (isKeyForUser(uid)) {
1360924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban            final int userHandle = getUserIdForKey(uid);
13738305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            final UserInfo info = um.getUserInfo(userHandle);
13838305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            if (info != null) {
1390924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban                if (info.isManagedProfile()) {
1406b3b751492d01b23b87a4ee6b807dc00c3b5770eAlexandra Gherghina                    detail.label = res.getString(R.string.managed_user_title);
1410924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban                    detail.icon = Resources.getSystem().getDrawable(
1429017d3fdd607b8978299578721303b8140a64c22Alexandra Gherghina                            com.android.internal.R.drawable.ic_corp_icon);
1430924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban                } else {
1440924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban                    detail.label = res.getString(R.string.running_process_item_user_label,
1450924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban                            info.name);
1460924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban                    detail.icon = Utils.getUserIcon(mContext, um, info);
1470924f199e530ce844362c79dfa60ddbe3eceac56Zoltan Szatmary-Ban                }
14838305fb1777147cbcb86774c466e88434daff141Jeff Sharkey                return detail;
14938305fb1777147cbcb86774c466e88434daff141Jeff Sharkey            }
15038305fb1777147cbcb86774c466e88434daff141Jeff Sharkey        }
15138305fb1777147cbcb86774c466e88434daff141Jeff Sharkey
152b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        // otherwise fall back to using packagemanager labels
153b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        final String[] packageNames = pm.getPackagesForUid(uid);
154b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        final int length = packageNames != null ? packageNames.length : 0;
155b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        try {
1563aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban            final int userId = UserHandle.getUserId(uid);
1573aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban            UserHandle userHandle = new UserHandle(userId);
1583aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban            IPackageManager ipm = AppGlobals.getPackageManager();
159b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            if (length == 1) {
1603aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
1613aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                        0 /* no flags */, userId);
1623aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                if (info != null) {
1633aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                    detail.label = info.loadLabel(pm).toString();
1643aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                    detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
1653aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                            new UserHandle(userId));
1663aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                }
167b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            } else if (length > 1) {
168b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                detail.detailLabels = new CharSequence[length];
169ebb36ec9207c9519f6ae6a1aa39909279aa1d0e9Zoltan Szatmary-Ban                detail.detailContentDescriptions = new CharSequence[length];
170b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                for (int i = 0; i < length; i++) {
171b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                    final String packageName = packageNames[i];
172b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                    final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
1733aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                    final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
1743aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                            0 /* no flags */, userId);
1753aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban
1763aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                    if (appInfo != null) {
1773aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                        detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
1783aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                        detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
1793aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                                detail.detailLabels[i], userHandle);
1803aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                        if (packageInfo.sharedUserLabel != 0) {
1813aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                            detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
1823aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                                    packageInfo.applicationInfo).toString();
1833aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                            detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
1843aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban                        }
185b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                    }
186b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey                }
187b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            }
188ebb36ec9207c9519f6ae6a1aa39909279aa1d0e9Zoltan Szatmary-Ban            detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
189b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        } catch (NameNotFoundException e) {
1903aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban            Log.w(TAG, "Error while building UI detail for uid "+uid, e);
1913aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban        } catch (RemoteException e) {
1923aaf0eb457639b52228143b84d9624bf73d862eaZoltan Szatmary-Ban            Log.w(TAG, "Error while building UI detail for uid "+uid, e);
193b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
194b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
195b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        if (TextUtils.isEmpty(detail.label)) {
196b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey            detail.label = Integer.toString(uid);
197b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        }
198b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey
199b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey        return detail;
200b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey    }
201b98c55bd097e006703352f84f0271dec5181160aJeff Sharkey}
202