Refactor UidDetailProvider and its dependencies to SettingsLib.
so that it can be reused by Wear app data usage. Change-Id: Ifd5709647ba031bb38b2293c35def01bcdee1448
This commit is contained in:
@@ -21,4 +21,6 @@
|
|||||||
|
|
||||||
<!-- The translation for disappearing security views after having solved them. -->
|
<!-- The translation for disappearing security views after having solved them. -->
|
||||||
<dimen name="disappear_y_translation">-32dp</dimen>
|
<dimen name="disappear_y_translation">-32dp</dimen>
|
||||||
</resources>
|
|
||||||
|
<dimen name="circle_avatar_size">40dp</dimen>
|
||||||
|
</resources>
|
||||||
|
|||||||
@@ -195,4 +195,34 @@
|
|||||||
<!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
|
<!-- Content description of the WIFI signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_wifi_signal_full">Wifi signal full.</string>
|
<string name="accessibility_wifi_signal_full">Wifi signal full.</string>
|
||||||
|
|
||||||
|
<!-- Label for kernel threads in battery usage -->
|
||||||
|
<string name="process_kernel_label">Android OS</string>
|
||||||
|
<!-- Title of data usage item that represents all uninstalled applications. [CHAR LIMIT=48] -->
|
||||||
|
<string name="data_usage_uninstalled_apps">Removed apps</string>
|
||||||
|
<!-- Title of data usage item that represents all uninstalled applications or removed users. [CHAR LIMIT=48] -->
|
||||||
|
<string name="data_usage_uninstalled_apps_users">Removed apps and users</string>
|
||||||
|
|
||||||
|
<!-- Tethering controls, item title to go into the tethering settings -->
|
||||||
|
<!-- Tethering controls, item title to go into the tethering settings when only USB tethering is available [CHAR LIMIT=25]-->
|
||||||
|
<string name="tether_settings_title_usb">USB tethering</string>
|
||||||
|
<!-- Tethering controls, item title to go into the tethering settings when only Wifi tethering is available [CHAR LIMIT=25]-->
|
||||||
|
<string name="tether_settings_title_wifi">Portable hotspot</string>
|
||||||
|
<!-- Tethering controls, item title to go into the tethering settings when only Bluetooth tethering is available [CHAR LIMIT=25]-->
|
||||||
|
<string name="tether_settings_title_bluetooth">Bluetooth tethering</string>
|
||||||
|
<!-- Tethering controls, item title to go into the tethering settings when USB and Bluetooth tethering are available [CHAR LIMIT=25]-->
|
||||||
|
<string name="tether_settings_title_usb_bluetooth">Tethering</string>
|
||||||
|
<!-- Tethering controls, item title to go into the tethering settings when USB, Bluetooth and Wifi tethering are available [CHAR LIMIT=25]-->
|
||||||
|
<string name="tether_settings_title_all">Tethering & portable hotspot</string>
|
||||||
|
|
||||||
|
<!-- Title for a work profile. [CHAR LIMIT=25] -->
|
||||||
|
<string name="managed_user_title">Work profile</string>
|
||||||
|
|
||||||
|
<!-- Title for Guest user [CHAR LIMIT=35] -->
|
||||||
|
<string name="user_guest">Guest</string>
|
||||||
|
|
||||||
|
<!-- Manage apps, individual app screen, substituted for the application's label when the app's label CAN NOT be determined.-->
|
||||||
|
<string name="unknown">Unknown</string>
|
||||||
|
|
||||||
|
<!-- [CHAR LIMIT=NONE] Label of a running process that represents another user -->
|
||||||
|
<string name="running_process_item_user_label">User: <xliff:g id="user_name">%1$s</xliff:g></string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
84
packages/SettingsLib/src/com/android/settingslib/Utils.java
Normal file
84
packages/SettingsLib/src/com/android/settingslib/Utils.java
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
package com.android.settingslib;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.os.UserManager;
|
||||||
|
|
||||||
|
import com.android.internal.util.UserIcons;
|
||||||
|
import com.android.settingslib.drawable.CircleFramedDrawable;
|
||||||
|
|
||||||
|
public final class Utils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return string resource that best describes combination of tethering
|
||||||
|
* options available on this device.
|
||||||
|
*/
|
||||||
|
public static int getTetheringLabel(ConnectivityManager cm) {
|
||||||
|
String[] usbRegexs = cm.getTetherableUsbRegexs();
|
||||||
|
String[] wifiRegexs = cm.getTetherableWifiRegexs();
|
||||||
|
String[] bluetoothRegexs = cm.getTetherableBluetoothRegexs();
|
||||||
|
|
||||||
|
boolean usbAvailable = usbRegexs.length != 0;
|
||||||
|
boolean wifiAvailable = wifiRegexs.length != 0;
|
||||||
|
boolean bluetoothAvailable = bluetoothRegexs.length != 0;
|
||||||
|
|
||||||
|
if (wifiAvailable && usbAvailable && bluetoothAvailable) {
|
||||||
|
return R.string.tether_settings_title_all;
|
||||||
|
} else if (wifiAvailable && usbAvailable) {
|
||||||
|
return R.string.tether_settings_title_all;
|
||||||
|
} else if (wifiAvailable && bluetoothAvailable) {
|
||||||
|
return R.string.tether_settings_title_all;
|
||||||
|
} else if (wifiAvailable) {
|
||||||
|
return R.string.tether_settings_title_wifi;
|
||||||
|
} else if (usbAvailable && bluetoothAvailable) {
|
||||||
|
return R.string.tether_settings_title_usb_bluetooth;
|
||||||
|
} else if (usbAvailable) {
|
||||||
|
return R.string.tether_settings_title_usb;
|
||||||
|
} else {
|
||||||
|
return R.string.tether_settings_title_bluetooth;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a label for the user, in the form of "User: user name" or "Work profile".
|
||||||
|
*/
|
||||||
|
public static String getUserLabel(Context context, UserInfo info) {
|
||||||
|
String name = info != null ? info.name : null;
|
||||||
|
if (info.isManagedProfile()) {
|
||||||
|
// We use predefined values for managed profiles
|
||||||
|
return context.getString(R.string.managed_user_title);
|
||||||
|
} else if (info.isGuest()) {
|
||||||
|
name = context.getString(R.string.user_guest);
|
||||||
|
}
|
||||||
|
if (name == null && info != null) {
|
||||||
|
name = Integer.toString(info.id);
|
||||||
|
} else if (info == null) {
|
||||||
|
name = context.getString(R.string.unknown);
|
||||||
|
}
|
||||||
|
return context.getResources().getString(R.string.running_process_item_user_label, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a circular icon for a user.
|
||||||
|
*/
|
||||||
|
public static Drawable getUserIcon(Context context, UserManager um, UserInfo user) {
|
||||||
|
if (user.isManagedProfile()) {
|
||||||
|
// We use predefined values for managed profiles
|
||||||
|
Bitmap b = BitmapFactory.decodeResource(context.getResources(),
|
||||||
|
com.android.internal.R.drawable.ic_corp_icon);
|
||||||
|
return CircleFramedDrawable.getInstance(context, b);
|
||||||
|
}
|
||||||
|
if (user.iconPath != null) {
|
||||||
|
Bitmap icon = um.getUserIcon(user.id);
|
||||||
|
if (icon != null) {
|
||||||
|
return CircleFramedDrawable.getInstance(context, icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CircleFramedDrawable.getInstance(context, UserIcons.convertToBitmap(
|
||||||
|
UserIcons.getDefaultUserIcon(user.id, /* light= */ false)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2013 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settingslib.drawable;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.ColorFilter;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Path;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.graphics.PorterDuffXfermode;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.RectF;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
import com.android.settingslib.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the user avatar icon to a circularly clipped one.
|
||||||
|
* TODO: Move this to an internal framework class and share with the one in Keyguard.
|
||||||
|
*/
|
||||||
|
public class CircleFramedDrawable extends Drawable {
|
||||||
|
|
||||||
|
private final Bitmap mBitmap;
|
||||||
|
private final int mSize;
|
||||||
|
private final Paint mPaint;
|
||||||
|
|
||||||
|
private float mScale;
|
||||||
|
private Rect mSrcRect;
|
||||||
|
private RectF mDstRect;
|
||||||
|
|
||||||
|
public static CircleFramedDrawable getInstance(Context context, Bitmap icon) {
|
||||||
|
Resources res = context.getResources();
|
||||||
|
float iconSize = res.getDimension(R.dimen.circle_avatar_size);
|
||||||
|
|
||||||
|
CircleFramedDrawable instance = new CircleFramedDrawable(icon, (int) iconSize);
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CircleFramedDrawable(Bitmap icon, int size) {
|
||||||
|
super();
|
||||||
|
mSize = size;
|
||||||
|
|
||||||
|
mBitmap = Bitmap.createBitmap(mSize, mSize, Bitmap.Config.ARGB_8888);
|
||||||
|
final Canvas canvas = new Canvas(mBitmap);
|
||||||
|
|
||||||
|
final int width = icon.getWidth();
|
||||||
|
final int height = icon.getHeight();
|
||||||
|
final int square = Math.min(width, height);
|
||||||
|
|
||||||
|
final Rect cropRect = new Rect((width - square) / 2, (height - square) / 2, square, square);
|
||||||
|
final RectF circleRect = new RectF(0f, 0f, mSize, mSize);
|
||||||
|
|
||||||
|
final Path fillPath = new Path();
|
||||||
|
fillPath.addArc(circleRect, 0f, 360f);
|
||||||
|
|
||||||
|
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
|
||||||
|
|
||||||
|
// opaque circle matte
|
||||||
|
mPaint = new Paint();
|
||||||
|
mPaint.setAntiAlias(true);
|
||||||
|
mPaint.setColor(Color.BLACK);
|
||||||
|
mPaint.setStyle(Paint.Style.FILL);
|
||||||
|
canvas.drawPath(fillPath, mPaint);
|
||||||
|
|
||||||
|
// mask in the icon where the bitmap is opaque
|
||||||
|
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
|
||||||
|
canvas.drawBitmap(icon, cropRect, circleRect, mPaint);
|
||||||
|
|
||||||
|
// prepare paint for frame drawing
|
||||||
|
mPaint.setXfermode(null);
|
||||||
|
|
||||||
|
mScale = 1f;
|
||||||
|
|
||||||
|
mSrcRect = new Rect(0, 0, mSize, mSize);
|
||||||
|
mDstRect = new RectF(0, 0, mSize, mSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw(Canvas canvas) {
|
||||||
|
final float inside = mScale * mSize;
|
||||||
|
final float pad = (mSize - inside) / 2f;
|
||||||
|
|
||||||
|
mDstRect.set(pad, pad, mSize - pad, mSize - pad);
|
||||||
|
canvas.drawBitmap(mBitmap, mSrcRect, mDstRect, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScale(float scale) {
|
||||||
|
mScale = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getScale() {
|
||||||
|
return mScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOpacity() {
|
||||||
|
return PixelFormat.TRANSLUCENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAlpha(int alpha) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColorFilter(ColorFilter cf) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntrinsicWidth() {
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getIntrinsicHeight() {
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settingslib.net;
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
|
public class UidDetail {
|
||||||
|
public CharSequence label;
|
||||||
|
public CharSequence contentDescription;
|
||||||
|
public CharSequence[] detailLabels;
|
||||||
|
public CharSequence[] detailContentDescriptions;
|
||||||
|
public Drawable icon;
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2011 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.android.settingslib.net;
|
||||||
|
|
||||||
|
import android.app.AppGlobals;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ApplicationInfo;
|
||||||
|
import android.content.pm.IPackageManager;
|
||||||
|
import android.content.pm.PackageInfo;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
|
import android.content.pm.UserInfo;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.TrafficStats;
|
||||||
|
import android.os.UserManager;
|
||||||
|
import android.os.UserHandle;
|
||||||
|
import android.os.RemoteException;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
|
import com.android.settingslib.R;
|
||||||
|
import com.android.settingslib.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return details about a specific UID, handling special cases like
|
||||||
|
* {@link TrafficStats#UID_TETHERING} and {@link UserInfo}.
|
||||||
|
*/
|
||||||
|
public class UidDetailProvider {
|
||||||
|
private static final String TAG = "DataUsage";
|
||||||
|
private final Context mContext;
|
||||||
|
private final SparseArray<UidDetail> mUidDetailCache;
|
||||||
|
|
||||||
|
public static final int OTHER_USER_RANGE_START = -2000;
|
||||||
|
|
||||||
|
public static int buildKeyForUser(int userHandle) {
|
||||||
|
return OTHER_USER_RANGE_START - userHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isKeyForUser(int key) {
|
||||||
|
return key <= OTHER_USER_RANGE_START;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getUserIdForKey(int key) {
|
||||||
|
return OTHER_USER_RANGE_START - key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UidDetailProvider(Context context) {
|
||||||
|
mContext = context.getApplicationContext();
|
||||||
|
mUidDetailCache = new SparseArray<UidDetail>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearCache() {
|
||||||
|
synchronized (mUidDetailCache) {
|
||||||
|
mUidDetailCache.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve best descriptive label for the given UID.
|
||||||
|
*/
|
||||||
|
public UidDetail getUidDetail(int uid, boolean blocking) {
|
||||||
|
UidDetail detail;
|
||||||
|
|
||||||
|
synchronized (mUidDetailCache) {
|
||||||
|
detail = mUidDetailCache.get(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (detail != null) {
|
||||||
|
return detail;
|
||||||
|
} else if (!blocking) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
detail = buildUidDetail(uid);
|
||||||
|
|
||||||
|
synchronized (mUidDetailCache) {
|
||||||
|
mUidDetailCache.put(uid, detail);
|
||||||
|
}
|
||||||
|
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build {@link UidDetail} object, blocking until all {@link Drawable}
|
||||||
|
* lookup is finished.
|
||||||
|
*/
|
||||||
|
private UidDetail buildUidDetail(int uid) {
|
||||||
|
final Resources res = mContext.getResources();
|
||||||
|
final PackageManager pm = mContext.getPackageManager();
|
||||||
|
|
||||||
|
final UidDetail detail = new UidDetail();
|
||||||
|
detail.label = pm.getNameForUid(uid);
|
||||||
|
detail.icon = pm.getDefaultActivityIcon();
|
||||||
|
|
||||||
|
// handle special case labels
|
||||||
|
switch (uid) {
|
||||||
|
case android.os.Process.SYSTEM_UID:
|
||||||
|
detail.label = res.getString(R.string.process_kernel_label);
|
||||||
|
detail.icon = pm.getDefaultActivityIcon();
|
||||||
|
return detail;
|
||||||
|
case TrafficStats.UID_REMOVED:
|
||||||
|
detail.label = res.getString(UserManager.supportsMultipleUsers()
|
||||||
|
? R.string.data_usage_uninstalled_apps_users
|
||||||
|
: R.string.data_usage_uninstalled_apps);
|
||||||
|
detail.icon = pm.getDefaultActivityIcon();
|
||||||
|
return detail;
|
||||||
|
case TrafficStats.UID_TETHERING:
|
||||||
|
final ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService(
|
||||||
|
Context.CONNECTIVITY_SERVICE);
|
||||||
|
detail.label = res.getString(Utils.getTetheringLabel(cm));
|
||||||
|
detail.icon = pm.getDefaultActivityIcon();
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||||
|
|
||||||
|
// Handle keys that are actually user handles
|
||||||
|
if (isKeyForUser(uid)) {
|
||||||
|
final int userHandle = getUserIdForKey(uid);
|
||||||
|
final UserInfo info = um.getUserInfo(userHandle);
|
||||||
|
if (info != null) {
|
||||||
|
detail.label = Utils.getUserLabel(mContext, info);
|
||||||
|
detail.icon = Utils.getUserIcon(mContext, um, info);
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise fall back to using packagemanager labels
|
||||||
|
final String[] packageNames = pm.getPackagesForUid(uid);
|
||||||
|
final int length = packageNames != null ? packageNames.length : 0;
|
||||||
|
try {
|
||||||
|
final int userId = UserHandle.getUserId(uid);
|
||||||
|
UserHandle userHandle = new UserHandle(userId);
|
||||||
|
IPackageManager ipm = AppGlobals.getPackageManager();
|
||||||
|
if (length == 1) {
|
||||||
|
final ApplicationInfo info = ipm.getApplicationInfo(packageNames[0],
|
||||||
|
0 /* no flags */, userId);
|
||||||
|
if (info != null) {
|
||||||
|
detail.label = info.loadLabel(pm).toString();
|
||||||
|
detail.icon = um.getBadgedIconForUser(info.loadIcon(pm),
|
||||||
|
new UserHandle(userId));
|
||||||
|
}
|
||||||
|
} else if (length > 1) {
|
||||||
|
detail.detailLabels = new CharSequence[length];
|
||||||
|
detail.detailContentDescriptions = new CharSequence[length];
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
final String packageName = packageNames[i];
|
||||||
|
final PackageInfo packageInfo = pm.getPackageInfo(packageName, 0);
|
||||||
|
final ApplicationInfo appInfo = ipm.getApplicationInfo(packageName,
|
||||||
|
0 /* no flags */, userId);
|
||||||
|
|
||||||
|
if (appInfo != null) {
|
||||||
|
detail.detailLabels[i] = appInfo.loadLabel(pm).toString();
|
||||||
|
detail.detailContentDescriptions[i] = um.getBadgedLabelForUser(
|
||||||
|
detail.detailLabels[i], userHandle);
|
||||||
|
if (packageInfo.sharedUserLabel != 0) {
|
||||||
|
detail.label = pm.getText(packageName, packageInfo.sharedUserLabel,
|
||||||
|
packageInfo.applicationInfo).toString();
|
||||||
|
detail.icon = um.getBadgedIconForUser(appInfo.loadIcon(pm), userHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
detail.contentDescription = um.getBadgedLabelForUser(detail.label, userHandle);
|
||||||
|
} catch (NameNotFoundException e) {
|
||||||
|
Log.w(TAG, "Error while building UI detail for uid "+uid, e);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Error while building UI detail for uid "+uid, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TextUtils.isEmpty(detail.label)) {
|
||||||
|
detail.label = Integer.toString(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user