130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu/*
230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * Copyright (C) 2011 The Android Open Source Project
330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu *
430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * Licensed under the Apache License, Version 2.0 (the "License");
530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * you may not use this file except in compliance with the License.
630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * You may obtain a copy of the License at
730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu *
830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu *      http://www.apache.org/licenses/LICENSE-2.0
930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu *
1030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * Unless required by applicable law or agreed to in writing, software
1130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * distributed under the License is distributed on an "AS IS" BASIS,
1230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * See the License for the specific language governing permissions and
1430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * limitations under the License.
1530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu */
1630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
1730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liupackage com.android.settingslib.net;
1830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
1930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.app.AppGlobals;
2030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.content.Context;
2130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.content.pm.ApplicationInfo;
2230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.content.pm.IPackageManager;
2330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.content.pm.PackageInfo;
2430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.content.pm.PackageManager;
2530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.content.pm.PackageManager.NameNotFoundException;
2630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.content.pm.UserInfo;
2730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.content.res.Resources;
2830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.graphics.drawable.Drawable;
2930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.net.ConnectivityManager;
3030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.net.TrafficStats;
3130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.os.UserManager;
3230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.os.UserHandle;
3330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.os.RemoteException;
3430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.text.TextUtils;
3530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.util.Log;
3630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport android.util.SparseArray;
3730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
3830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport com.android.settingslib.R;
3930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liuimport com.android.settingslib.Utils;
4030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
4130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu/**
4230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * Return details about a specific UID, handling special cases like
4330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu * {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
4430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu */
4530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liupublic class UidDetailProvider {
4630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    private static final String TAG = "DataUsage";
4730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    private final Context mContext;
4830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    private final SparseArray<UidDetail> mUidDetailCache;
4930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
5030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    public static final int OTHER_USER_RANGE_START = -2000;
5130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
5230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    public static int buildKeyForUser(int userHandle) {
5330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        return OTHER_USER_RANGE_START - userHandle;
5430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    }
5530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
5630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    public static boolean isKeyForUser(int key) {
5730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        return key <= OTHER_USER_RANGE_START;
5830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    }
5930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
6030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    public static int getUserIdForKey(int key) {
6130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        return OTHER_USER_RANGE_START - key;
6230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    }
6330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
6430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    public UidDetailProvider(Context context) {
6530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        mContext = context.getApplicationContext();
6630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        mUidDetailCache = new SparseArray<UidDetail>();
6730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    }
6830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
6930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    public void clearCache() {
7030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        synchronized (mUidDetailCache) {
7130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            mUidDetailCache.clear();
7230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        }
7330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    }
7430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
7530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    /**
7630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu     * Resolve best descriptive label for the given UID.
7730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu     */
7830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    public UidDetail getUidDetail(int uid, boolean blocking) {
7930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        UidDetail detail;
8030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
8130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        synchronized (mUidDetailCache) {
8230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            detail = mUidDetailCache.get(uid);
8330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        }
8430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
8530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        if (detail != null) {
8630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            return detail;
8730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        } else if (!blocking) {
8830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            return null;
8930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        }
9030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
9130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        detail = buildUidDetail(uid);
9230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
9330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        synchronized (mUidDetailCache) {
9430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            mUidDetailCache.put(uid, detail);
9530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        }
9630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
9730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        return detail;
9830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    }
9930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
10030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    /**
10130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu     * Build {@link UidDetail} object, blocking until all {@link Drawable}
10230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu     * lookup is finished.
10330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu     */
10430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    private UidDetail buildUidDetail(int uid) {
10530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        final Resources res = mContext.getResources();
10630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        final PackageManager pm = mContext.getPackageManager();
10730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
10830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        final UidDetail detail = new UidDetail();
10930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        detail.label = pm.getNameForUid(uid);
11030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        detail.icon = pm.getDefaultActivityIcon();
11130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
11230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        // handle special case labels
11330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        switch (uid) {
11430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            case android.os.Process.SYSTEM_UID:
11530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.label = res.getString(R.string.process_kernel_label);
11630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.icon = pm.getDefaultActivityIcon();
11730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                return detail;
11830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            case TrafficStats.UID_REMOVED:
11930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.label = res.getString(UserManager.supportsMultipleUsers()
12030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                        ? R.string.data_usage_uninstalled_apps_users
12130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                        : R.string.data_usage_uninstalled_apps);
12230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.icon = pm.getDefaultActivityIcon();
12330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                return detail;
12430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            case TrafficStats.UID_TETHERING:
12530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                final ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
12630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                        Context.CONNECTIVITY_SERVICE);
12730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.label = res.getString(Utils.getTetheringLabel(cm));
12830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.icon = pm.getDefaultActivityIcon();
12930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                return detail;
13030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        }
13130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
13230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
13330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
13430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        // Handle keys that are actually user handles
13530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        if (isKeyForUser(uid)) {
13630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            final int userHandle = getUserIdForKey(uid);
13730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            final UserInfo info = um.getUserInfo(userHandle);
13830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            if (info != null) {
13930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.label = Utils.getUserLabel(mContext, info);
14030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.icon = Utils.getUserIcon(mContext, um, info);
14130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                return detail;
14230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            }
14330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        }
14430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
14530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        // otherwise fall back to using packagemanager labels
14630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        final String[] packageNames = pm.getPackagesForUid(uid);
14730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        final int length = packageNames != null ? packageNames.length : 0;
14830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        try {
14930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            final int userId = UserHandle.getUserId(uid);
15030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            UserHandle userHandle = new UserHandle(userId);
15130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            IPackageManager ipm = AppGlobals.getPackageManager();
15230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            if (length == 1) {
15330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
15430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                        0 /* no flags */, userId);
15530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                if (info != null) {
15630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                    detail.label = info.loadLabel(pm).toString();
15730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                    detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
15830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                            new UserHandle(userId));
15930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                }
16030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            } else if (length > 1) {
16130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.detailLabels = new CharSequence[length];
16230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                detail.detailContentDescriptions = new CharSequence[length];
16330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                for (int i = 0; i < length; i++) {
16430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                    final String packageName = packageNames[i];
16530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                    final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
16630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                    final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
16730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                            0 /* no flags */, userId);
16830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
16930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                    if (appInfo != null) {
17030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                        detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
17130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                        detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
17230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                                detail.detailLabels[i], userHandle);
17330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                        if (packageInfo.sharedUserLabel != 0) {
17430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                            detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
17530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                                    packageInfo.applicationInfo).toString();
17630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                            detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
17730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                        }
17830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                    }
17930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu                }
18030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            }
18130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
18230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        } catch (NameNotFoundException e) {
18330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            Log.w(TAG, "Error while building UI detail for uid "+uid, e);
18430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        } catch (RemoteException e) {
18530275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            Log.w(TAG, "Error while building UI detail for uid "+uid, e);
18630275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        }
18730275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
18830275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        if (TextUtils.isEmpty(detail.label)) {
18930275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu            detail.label = Integer.toString(uid);
19030275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        }
19130275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu
19230275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu        return detail;
19330275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu    }
19430275c1924b2bd45b05bd9c98f8648ecbc71374fWei Liu}
195