Refactor UidDetailProvider and its dependencies to SettingsLib.

so that it can be reused by Wear app data usage.

Change-Id: Id05f888274e15fbeffa175ee8073de02a8966867
diff --git a/src/com/android/settings/DataUsageSummary.java b/src/com/android/settings/DataUsageSummary.java
index 1bb2a51..387331b 100644
--- a/src/com/android/settings/DataUsageSummary.java
+++ b/src/com/android/settings/DataUsageSummary.java
@@ -129,8 +129,6 @@
 import com.android.internal.telephony.PhoneConstants;
 import com.android.settings.drawable.InsetBoundsDrawable;
 import com.android.settings.net.DataUsageMeteredSettings;
-import com.android.settings.net.UidDetail;
-import com.android.settings.net.UidDetailProvider;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
@@ -142,6 +140,8 @@
 import com.android.settingslib.net.ChartData;
 import com.android.settingslib.net.ChartDataLoader;
 import com.android.settingslib.net.SummaryForAllUidLoader;
+import com.android.settingslib.net.UidDetail;
+import com.android.settingslib.net.UidDetailProvider;
 import com.google.android.collect.Lists;
 
 import libcore.util.Objects;
diff --git a/src/com/android/settings/UserAdapter.java b/src/com/android/settings/UserAdapter.java
index dcdc7eb..2ac908e 100644
--- a/src/com/android/settings/UserAdapter.java
+++ b/src/com/android/settings/UserAdapter.java
@@ -33,7 +33,7 @@
 import android.widget.TextView;
 
 import com.android.internal.util.UserIcons;
-import com.android.settings.drawable.CircleFramedDrawable;
+import com.android.settingslib.drawable.CircleFramedDrawable;
 
 import java.util.ArrayList;
 
@@ -173,4 +173,4 @@
     public boolean isEnabled(int position) {
         return true;
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index d25d8c3..7a6f165 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -89,8 +89,8 @@
 import com.android.internal.util.UserIcons;
 import com.android.settings.UserAdapter.UserDetails;
 import com.android.settings.dashboard.DashboardTile;
-import com.android.settings.drawable.CircleFramedDrawable;
 import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.drawable.CircleFramedDrawable;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -460,36 +460,6 @@
         view.setPaddingRelative(paddingStart, 0, paddingEnd, paddingBottom);
     }
 
-    /**
-     * 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;
-        }
-    }
-
     /* Used by UserSettings as well. Call this on a non-ui thread. */
     public static boolean copyMeProfilePhoto(Context context, UserInfo user) {
         Uri contactUri = Profile.CONTENT_URI;
@@ -905,45 +875,6 @@
     }
 
     /**
-     * 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)));
-    }
-
-    /**
-     * 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);
-    }
-
-    /**
      * Return whether or not the user should have a SIM Cards option in Settings.
      * TODO: Change back to returning true if count is greater than one after testing.
      * TODO: See bug 16533525.
diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java
index 8cc98cc..9253eac 100644
--- a/src/com/android/settings/WirelessSettings.java
+++ b/src/com/android/settings/WirelessSettings.java
@@ -329,7 +329,7 @@
             getPreferenceScreen().removePreference(findPreference(KEY_TETHER_SETTINGS));
         } else {
             Preference p = findPreference(KEY_TETHER_SETTINGS);
-            p.setTitle(Utils.getTetheringLabel(cm));
+            p.setTitle(com.android.settingslib.Utils.getTetheringLabel(cm));
 
             // Grey out if provisioning is not available.
             p.setEnabled(!TetherSettings
diff --git a/src/com/android/settings/applications/RunningState.java b/src/com/android/settings/applications/RunningState.java
index 2286a24..c63bcd8 100644
--- a/src/com/android/settings/applications/RunningState.java
+++ b/src/com/android/settings/applications/RunningState.java
@@ -45,8 +45,8 @@
 import android.util.SparseArray;
 
 import com.android.settings.R;
-import com.android.settings.Utils;
 import com.android.settingslib.applications.InterestingConfigChanges;
+import com.android.settingslib.Utils;
 
 import java.util.ArrayList;
 import java.util.Collections;
diff --git a/src/com/android/settings/drawable/CircleFramedDrawable.java b/src/com/android/settings/drawable/CircleFramedDrawable.java
deleted file mode 100644
index 31b8922..0000000
--- a/src/com/android/settings/drawable/CircleFramedDrawable.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.settings.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.settings.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;
-    }
-}
diff --git a/src/com/android/settings/fuelgauge/BatteryEntry.java b/src/com/android/settings/fuelgauge/BatteryEntry.java
index fbde228..b0e6969 100644
--- a/src/com/android/settings/fuelgauge/BatteryEntry.java
+++ b/src/com/android/settings/fuelgauge/BatteryEntry.java
@@ -32,7 +32,7 @@
 
 import com.android.internal.os.BatterySipper;
 import com.android.settings.R;
-import com.android.settings.Utils;
+import com.android.settingslib.Utils;
 
 import java.util.ArrayList;
 import java.util.HashMap;
diff --git a/src/com/android/settings/net/UidDetail.java b/src/com/android/settings/net/UidDetail.java
deleted file mode 100644
index 0b14254..0000000
--- a/src/com/android/settings/net/UidDetail.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * 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.settings.net;
-
-import android.graphics.drawable.Drawable;
-
-public class UidDetail {
-    public CharSequence label;
-    public CharSequence contentDescription;
-    public CharSequence[] detailLabels;
-    public CharSequence[] detailContentDescriptions;
-    public Drawable icon;
-}
diff --git a/src/com/android/settings/net/UidDetailProvider.java b/src/com/android/settings/net/UidDetailProvider.java
deleted file mode 100644
index a08c7de..0000000
--- a/src/com/android/settings/net/UidDetailProvider.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * 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.settings.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.settings.R;
-import com.android.settings.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;
-    }
-}
diff --git a/src/com/android/settings/users/EditUserInfoController.java b/src/com/android/settings/users/EditUserInfoController.java
index ab77101..a4c07bd 100644
--- a/src/com/android/settings/users/EditUserInfoController.java
+++ b/src/com/android/settings/users/EditUserInfoController.java
@@ -37,8 +37,8 @@
 import android.widget.ImageView;
 
 import com.android.settings.R;
-import com.android.settings.Utils;
-import com.android.settings.drawable.CircleFramedDrawable;
+import com.android.settingslib.Utils;
+import com.android.settingslib.drawable.CircleFramedDrawable;
 
 /**
  * This class encapsulates a Dialog for editing the user nickname and photo.
diff --git a/src/com/android/settings/users/EditUserPhotoController.java b/src/com/android/settings/users/EditUserPhotoController.java
index 82e550e..f9f867d 100644
--- a/src/com/android/settings/users/EditUserPhotoController.java
+++ b/src/com/android/settings/users/EditUserPhotoController.java
@@ -45,7 +45,7 @@
 import android.widget.ListPopupWindow;
 
 import com.android.settings.R;
-import com.android.settings.drawable.CircleFramedDrawable;
+import com.android.settingslib.drawable.CircleFramedDrawable;
 
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -343,4 +343,4 @@
             return title;
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/users/RestrictedProfileSettings.java b/src/com/android/settings/users/RestrictedProfileSettings.java
index b0b86e4..2531aaa 100644
--- a/src/com/android/settings/users/RestrictedProfileSettings.java
+++ b/src/com/android/settings/users/RestrictedProfileSettings.java
@@ -86,7 +86,7 @@
         } else {
             ((TextView) mHeaderView.findViewById(android.R.id.title)).setText(info.name);
             ((ImageView) mHeaderView.findViewById(android.R.id.icon)).setImageDrawable(
-                    Utils.getUserIcon(getActivity(), mUserManager, info));
+                    com.android.settingslib.Utils.getUserIcon(getActivity(), mUserManager, info));
         }
     }
 
diff --git a/src/com/android/settings/users/UserSettings.java b/src/com/android/settings/users/UserSettings.java
index 1849a9a..85d2700 100644
--- a/src/com/android/settings/users/UserSettings.java
+++ b/src/com/android/settings/users/UserSettings.java
@@ -64,10 +64,10 @@
 import com.android.settings.SettingsActivity;
 import com.android.settings.SettingsPreferenceFragment;
 import com.android.settings.Utils;
-import com.android.settings.drawable.CircleFramedDrawable;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.search.Indexable;
 import com.android.settings.search.SearchIndexableRaw;
+import com.android.settingslib.drawable.CircleFramedDrawable;
 
 import java.util.ArrayList;
 import java.util.Collections;