Adding support for managed profiles in widget

issue: 16892811

Change-Id: If8c81f2a5a3bc846b02a5d225c5a8f27b1382dab
This commit is contained in:
Sunny Goyal
2014-08-14 17:39:34 -07:00
parent 22308ce1b8
commit ffe83f1331
12 changed files with 484 additions and 257 deletions
+4
View File
@@ -101,4 +101,8 @@
<!-- The amount that the preview contents are inset from the preview background --> <!-- The amount that the preview contents are inset from the preview background -->
<dimen name="folder_preview_padding">4dp</dimen> <dimen name="folder_preview_padding">4dp</dimen>
<dimen name="folder_name_padding">10dp</dimen> <dimen name="folder_name_padding">10dp</dimen>
<!-- Sizes for managed profile badges -->
<dimen name="profile_badge_size">24dp</dimen>
<dimen name="profile_badge_margin">4dp</dimen>
</resources> </resources>
@@ -28,7 +28,6 @@ import android.content.pm.ResolveInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
@@ -49,6 +48,7 @@ import android.widget.ImageView;
import android.widget.Toast; import android.widget.Toast;
import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -176,7 +176,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private int mClingFocusedY; private int mClingFocusedY;
// Caching // Caching
private Canvas mCanvas;
private IconCache mIconCache; private IconCache mIconCache;
// Dimens // Dimens
@@ -224,13 +223,10 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mApps = new ArrayList<AppInfo>(); mApps = new ArrayList<AppInfo>();
mWidgets = new ArrayList<Object>(); mWidgets = new ArrayList<Object>();
mIconCache = (LauncherAppState.getInstance()).getIconCache(); mIconCache = (LauncherAppState.getInstance()).getIconCache();
mCanvas = new Canvas();
mRunningTasks = new ArrayList<AppsCustomizeAsyncTask>(); mRunningTasks = new ArrayList<AppsCustomizeAsyncTask>();
// Save the default widget preview background // Save the default widget preview background
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0);
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2); mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2);
mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2); mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2);
mClingFocusedX = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedX, 0); mClingFocusedX = a.getInt(R.styleable.AppsCustomizePagedView_clingFocusedX, 0);
@@ -391,7 +387,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
if (!app.shouldShowAppOrWidgetProvider(widget.provider)) { if (!app.shouldShowAppOrWidgetProvider(widget.provider)) {
continue; continue;
} }
widget.label = widget.label.trim();
if (widget.minWidth > 0 && widget.minHeight > 0) { if (widget.minWidth > 0 && widget.minHeight > 0) {
// Ensure that all widgets we show can be added on a workspace of this size // Ensure that all widgets we show can be added on a workspace of this size
int[] spanXY = Launcher.getSpanForWidget(mLauncher, widget); int[] spanXY = Launcher.getSpanForWidget(mLauncher, widget);
@@ -520,18 +515,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
@Override @Override
public void run() { public void run() {
mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId(); mWidgetLoadingId = mLauncher.getAppWidgetHost().allocateAppWidgetId();
// Options will be null for platforms with JB or lower, so this serves as an if(AppWidgetManagerCompat.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
// SDK level check. mWidgetLoadingId, pInfo, options)) {
if (options == null) { mWidgetCleanupState = WIDGET_BOUND;
if (AppWidgetManager.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
mWidgetLoadingId, info.componentName)) {
mWidgetCleanupState = WIDGET_BOUND;
}
} else {
if (AppWidgetManager.getInstance(mLauncher).bindAppWidgetIdIfAllowed(
mWidgetLoadingId, info.componentName, options)) {
mWidgetCleanupState = WIDGET_BOUND;
}
} }
} }
}; };
@@ -659,9 +645,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int[] previewSizeBeforeScale = new int[1]; int[] previewSizeBeforeScale = new int[1];
preview = getWidgetPreviewLoader().generateWidgetPreview(createWidgetInfo.componentName, preview = getWidgetPreviewLoader().generateWidgetPreview(createWidgetInfo.info,
createWidgetInfo.previewImage, createWidgetInfo.icon, spanX, spanY, spanX, spanY, maxWidth, maxHeight, null, previewSizeBeforeScale);
maxWidth, maxHeight, null, previewSizeBeforeScale);
// Compare the size of the drag preview to the preview in the AppsCustomize tray // Compare the size of the drag preview to the preview in the AppsCustomize tray
int previewWidthInAppsCustomize = Math.min(previewSizeBeforeScale[0], int previewWidthInAppsCustomize = Math.min(previewSizeBeforeScale[0],
@@ -678,15 +663,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
} else { } else {
PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag(); PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.shortcutActivityInfo); Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.shortcutActivityInfo);
preview = Bitmap.createBitmap(icon.getIntrinsicWidth(), preview = Utilities.createIconBitmap(icon, mLauncher);
icon.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
mCanvas.setBitmap(preview);
mCanvas.save();
WidgetPreviewLoader.renderDrawableToBitmap(icon, preview, 0, 0,
icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
mCanvas.restore();
mCanvas.setBitmap(null);
createItemInfo.spanX = createItemInfo.spanY = 1; createItemInfo.spanX = createItemInfo.spanY = 1;
} }
+4
View File
@@ -146,6 +146,10 @@ public class IconCache {
return getFullResDefaultActivityIcon(); return getFullResDefaultActivityIcon();
} }
public int getFullResIconDpi() {
return mIconDpi;
}
public Drawable getFullResIcon(ResolveInfo info) { public Drawable getFullResIcon(ResolveInfo info) {
return getFullResIcon(info.activityInfo); return getFullResIcon(info.activityInfo);
} }
+15 -26
View File
@@ -99,6 +99,7 @@ import android.widget.Toast;
import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.DropTarget.DragObject;
import com.android.launcher3.PagedView.PageSwitchListener; import com.android.launcher3.PagedView.PageSwitchListener;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.compat.PackageInstallerCompat;
@@ -257,7 +258,7 @@ public class Launcher extends Activity
private View mWeightWatcher; private View mWeightWatcher;
private LauncherClings mLauncherClings; private LauncherClings mLauncherClings;
private AppWidgetManager mAppWidgetManager; private AppWidgetManagerCompat mAppWidgetManager;
private LauncherAppWidgetHost mAppWidgetHost; private LauncherAppWidgetHost mAppWidgetHost;
private ItemInfo mPendingAddInfo = new ItemInfo(); private ItemInfo mPendingAddInfo = new ItemInfo();
@@ -438,7 +439,7 @@ public class Launcher extends Activity
mStats = new Stats(this); mStats = new Stats(this);
mAppWidgetManager = AppWidgetManager.getInstance(this); mAppWidgetManager = AppWidgetManagerCompat.getInstance(this);
mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID); mAppWidgetHost = new LauncherAppWidgetHost(this, APPWIDGET_HOST_ID);
mAppWidgetHost.startListening(); mAppWidgetHost.startListening();
@@ -1569,6 +1570,7 @@ public class Launcher extends Activity
launcherInfo.spanY = spanXY[1]; launcherInfo.spanY = spanXY[1];
launcherInfo.minSpanX = mPendingAddInfo.minSpanX; launcherInfo.minSpanX = mPendingAddInfo.minSpanX;
launcherInfo.minSpanY = mPendingAddInfo.minSpanY; launcherInfo.minSpanY = mPendingAddInfo.minSpanY;
launcherInfo.user = mAppWidgetManager.getUser(appWidgetInfo);
LauncherModel.addItemToDatabase(this, launcherInfo, LauncherModel.addItemToDatabase(this, launcherInfo,
container, screenId, cellXY[0], cellXY[1], false); container, screenId, cellXY[0], cellXY[1], false);
@@ -2194,10 +2196,9 @@ public class Launcher extends Activity
mPendingAddWidgetId = appWidgetId; mPendingAddWidgetId = appWidgetId;
// Launch over to configure widget, if needed // Launch over to configure widget, if needed
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); mAppWidgetManager.startConfigActivity(appWidgetInfo, appWidgetId, this,
intent.setComponent(appWidgetInfo.configure); mAppWidgetHost, REQUEST_CREATE_APPWIDGET);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
Utilities.startActivityForResultSafely(this, intent, REQUEST_CREATE_APPWIDGET);
} else { } else {
// Otherwise just add it // Otherwise just add it
Runnable onComplete = new Runnable() { Runnable onComplete = new Runnable() {
@@ -2281,14 +2282,8 @@ public class Launcher extends Activity
appWidgetId = getAppWidgetHost().allocateAppWidgetId(); appWidgetId = getAppWidgetHost().allocateAppWidgetId();
Bundle options = info.bindOptions; Bundle options = info.bindOptions;
boolean success = false; boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
if (options != null) { appWidgetId, info.info, options);
success = mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
info.componentName, options);
} else {
success = mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId,
info.componentName);
}
if (success) { if (success) {
addAppWidgetImpl(appWidgetId, info, null, info.info); addAppWidgetImpl(appWidgetId, info, null, info.info);
} else { } else {
@@ -2296,6 +2291,8 @@ public class Launcher extends Activity
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND); Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, info.componentName);
mAppWidgetManager.getUser(mPendingAddWidgetInfo)
.addToIntent(intent, AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE);
// TODO: we need to make sure that this accounts for the options bundle. // TODO: we need to make sure that this accounts for the options bundle.
// intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options); // intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_OPTIONS, options);
startActivityForResult(intent, REQUEST_BIND_APPWIDGET); startActivityForResult(intent, REQUEST_BIND_APPWIDGET);
@@ -2476,10 +2473,8 @@ public class Launcher extends Activity
mPendingAddInfo.copyFrom(info); mPendingAddInfo.copyFrom(info);
mPendingAddWidgetId = widgetId; mPendingAddWidgetId = widgetId;
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE); AppWidgetManagerCompat.getInstance(this).startConfigActivity(appWidgetInfo,
intent.setComponent(appWidgetInfo.configure); info.appWidgetId, this, mAppWidgetHost, REQUEST_RECONFIGURE_APPWIDGET);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, info.appWidgetId);
Utilities.startActivityForResultSafely(this, intent, REQUEST_RECONFIGURE_APPWIDGET);
} }
} }
} }
@@ -4378,15 +4373,9 @@ public class Launcher extends Activity
Bundle options = Bundle options =
AppsCustomizePagedView.getDefaultOptionsForWidget(this, pendingInfo); AppsCustomizePagedView.getDefaultOptionsForWidget(this, pendingInfo);
boolean success = false;
int newWidgetId = mAppWidgetHost.allocateAppWidgetId(); int newWidgetId = mAppWidgetHost.allocateAppWidgetId();
if (options != null) { boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed(
success = mAppWidgetManager.bindAppWidgetIdIfAllowed(newWidgetId, newWidgetId, appWidgetInfo, options);
appWidgetInfo.provider, options);
} else {
success = mAppWidgetManager.bindAppWidgetIdIfAllowed(newWidgetId,
appWidgetInfo.provider);
}
// TODO consider showing a permission dialog when the widget is clicked. // TODO consider showing a permission dialog when the widget is clicked.
if (!success) { if (!success) {
@@ -299,36 +299,26 @@ public class LauncherBackupHelper implements BackupHelper {
Set<String> savedIds = getSavedIdsByType(Key.FAVORITE, in); Set<String> savedIds = getSavedIdsByType(Key.FAVORITE, in);
if (DEBUG) Log.d(TAG, "favorite savedIds.size()=" + savedIds.size()); if (DEBUG) Log.d(TAG, "favorite savedIds.size()=" + savedIds.size());
// Don't backup apps in other profiles for now.
UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
long userSerialNumber =
UserManagerCompat.getInstance(mContext).getSerialNumberForUser(myUserHandle);
// persist things that have changed since the last backup // persist things that have changed since the last backup
ContentResolver cr = mContext.getContentResolver(); ContentResolver cr = mContext.getContentResolver();
// Don't backup apps in other profiles for now.
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION, Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
null, null, null); getUserSelectionArg(), null, null);
Set<String> currentIds = new HashSet<String>(cursor.getCount()); Set<String> currentIds = new HashSet<String>(cursor.getCount());
try { try {
cursor.moveToPosition(-1); cursor.moveToPosition(-1);
while(cursor.moveToNext()) { while(cursor.moveToNext()) {
final long id = cursor.getLong(ID_INDEX); final long id = cursor.getLong(ID_INDEX);
final long profileId = cursor.getLong(PROFILE_ID_INDEX); final long updateTime = cursor.getLong(ID_MODIFIED);
if (userSerialNumber == profileId) { Key key = getKey(Key.FAVORITE, id);
final long updateTime = cursor.getLong(ID_MODIFIED); keys.add(key);
Key key = getKey(Key.FAVORITE, id); final String backupKey = keyToBackupKey(key);
keys.add(key); currentIds.add(backupKey);
final String backupKey = keyToBackupKey(key); if (!savedIds.contains(backupKey) || updateTime >= in.t) {
currentIds.add(backupKey); byte[] blob = packFavorite(cursor);
if (!savedIds.contains(backupKey) || updateTime >= in.t) { writeRowToBackup(key, blob, out, data);
byte[] blob = packFavorite(cursor);
writeRowToBackup(key, blob, out, data);
} else {
if (VERBOSE) Log.v(TAG, "favorite " + id + " was too old: " + updateTime);
}
} else { } else {
if (VERBOSE) Log.v(TAG, "favorite " + id + " is for other profile: " if (VERBOSE) Log.v(TAG, "favorite " + id + " was too old: " + updateTime);
+ profileId);
} }
} }
} finally { } finally {
@@ -469,20 +459,19 @@ public class LauncherBackupHelper implements BackupHelper {
} }
final ContentResolver cr = mContext.getContentResolver(); final ContentResolver cr = mContext.getContentResolver();
final int dpi = mContext.getResources().getDisplayMetrics().densityDpi; final int dpi = mContext.getResources().getDisplayMetrics().densityDpi;
final UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
// read the old ID set // read the old ID set
Set<String> savedIds = getSavedIdsByType(Key.ICON, in); Set<String> savedIds = getSavedIdsByType(Key.ICON, in);
if (DEBUG) Log.d(TAG, "icon savedIds.size()=" + savedIds.size()); if (DEBUG) Log.d(TAG, "icon savedIds.size()=" + savedIds.size());
// Don't backup apps in other profiles for now. // Don't backup apps in other profiles for now.
UserHandleCompat myUserHandle = UserHandleCompat.myUserHandle();
long userSerialNumber =
UserManagerCompat.getInstance(mContext).getSerialNumberForUser(myUserHandle);
int startRows = out.rows; int startRows = out.rows;
if (DEBUG) Log.d(TAG, "starting here: " + startRows); if (DEBUG) Log.d(TAG, "starting here: " + startRows);
String where = "(" + Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPLICATION + " OR " + String where = "(" + Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPLICATION + " OR " +
Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_SHORTCUT + ") AND " + Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_SHORTCUT + ") AND " +
Favorites.PROFILE_ID + "=" + userSerialNumber; getUserSelectionArg();
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION, Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
where, null, null); where, null, null);
Set<String> currentIds = new HashSet<String>(cursor.getCount()); Set<String> currentIds = new HashSet<String>(cursor.getCount());
@@ -617,7 +606,8 @@ public class LauncherBackupHelper implements BackupHelper {
int startRows = out.rows; int startRows = out.rows;
if (DEBUG) Log.d(TAG, "starting here: " + startRows); if (DEBUG) Log.d(TAG, "starting here: " + startRows);
String where = Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPWIDGET; String where = Favorites.ITEM_TYPE + "=" + Favorites.ITEM_TYPE_APPWIDGET + " AND "
+ getUserSelectionArg();
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION, Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
where, null, null); where, null, null);
Set<String> currentIds = new HashSet<String>(cursor.getCount()); Set<String> currentIds = new HashSet<String>(cursor.getCount());
@@ -1192,6 +1182,11 @@ public class LauncherBackupHelper implements BackupHelper {
return true; return true;
} }
private String getUserSelectionArg() {
return Favorites.PROFILE_ID + '=' + UserManagerCompat.getInstance(mContext)
.getSerialNumberForUser(UserHandleCompat.myUserHandle());
}
private class KeyParsingException extends Throwable { private class KeyParsingException extends Throwable {
private KeyParsingException(Throwable cause) { private KeyParsingException(Throwable cause) {
super(cause); super(cause);
+18 -62
View File
@@ -30,7 +30,6 @@ import android.content.Intent;
import android.content.Intent.ShortcutIconResource; import android.content.Intent.ShortcutIconResource;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo; import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
@@ -52,7 +51,7 @@ import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import com.android.launcher3.InstallWidgetReceiver.WidgetMimeTypeHandlerData; import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherActivityInfoCompat;
import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.LauncherAppsCompat;
import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
@@ -3040,11 +3039,11 @@ public class LauncherModel extends BroadcastReceiver
public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) { public static ArrayList<Object> getSortedWidgetsAndShortcuts(Context context) {
PackageManager packageManager = context.getPackageManager(); PackageManager packageManager = context.getPackageManager();
final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>(); final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
widgetsAndShortcuts.addAll(AppWidgetManager.getInstance(context).getInstalledProviders()); widgetsAndShortcuts.addAll(AppWidgetManagerCompat.getInstance(context).getAllProviders());
Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT); Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0)); widgetsAndShortcuts.addAll(packageManager.queryIntentActivities(shortcutsIntent, 0));
Collections.sort(widgetsAndShortcuts, Collections.sort(widgetsAndShortcuts, new WidgetAndShortcutNameComparator(context));
new LauncherModel.WidgetAndShortcutNameComparator(packageManager));
return widgetsAndShortcuts; return widgetsAndShortcuts;
} }
@@ -3390,44 +3389,6 @@ public class LauncherModel extends BroadcastReceiver
return null; return null;
} }
/**
* Returns a list of all the widgets that can handle configuration with a particular mimeType.
*/
List<WidgetMimeTypeHandlerData> resolveWidgetsForMimeType(Context context, String mimeType) {
final PackageManager packageManager = context.getPackageManager();
final List<WidgetMimeTypeHandlerData> supportedConfigurationActivities =
new ArrayList<WidgetMimeTypeHandlerData>();
final Intent supportsIntent =
new Intent(InstallWidgetReceiver.ACTION_SUPPORTS_CLIPDATA_MIMETYPE);
supportsIntent.setType(mimeType);
// Create a set of widget configuration components that we can test against
final List<AppWidgetProviderInfo> widgets =
AppWidgetManager.getInstance(context).getInstalledProviders();
final HashMap<ComponentName, AppWidgetProviderInfo> configurationComponentToWidget =
new HashMap<ComponentName, AppWidgetProviderInfo>();
for (AppWidgetProviderInfo info : widgets) {
configurationComponentToWidget.put(info.configure, info);
}
// Run through each of the intents that can handle this type of clip data, and cross
// reference them with the components that are actual configuration components
final List<ResolveInfo> activities = packageManager.queryIntentActivities(supportsIntent,
PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo info : activities) {
final ActivityInfo activityInfo = info.activityInfo;
final ComponentName infoComponent = new ComponentName(activityInfo.packageName,
activityInfo.name);
if (configurationComponentToWidget.containsKey(infoComponent)) {
supportedConfigurationActivities.add(
new InstallWidgetReceiver.WidgetMimeTypeHandlerData(info,
configurationComponentToWidget.get(infoComponent)));
}
}
return supportedConfigurationActivities;
}
ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) { ShortcutInfo infoFromShortcutIntent(Context context, Intent data, Bitmap fallbackIcon) {
Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
@@ -3570,14 +3531,6 @@ public class LauncherModel extends BroadcastReceiver
return 0; return 0;
} }
}; };
public static final Comparator<AppWidgetProviderInfo> getWidgetNameComparator() {
final Collator collator = Collator.getInstance();
return new Comparator<AppWidgetProviderInfo>() {
public final int compare(AppWidgetProviderInfo a, AppWidgetProviderInfo b) {
return collator.compare(a.label.toString().trim(), b.label.toString().trim());
}
};
}
static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) { static ComponentName getComponentNameFromResolveInfo(ResolveInfo info) {
if (info.activityInfo != null) { if (info.activityInfo != null) {
return new ComponentName(info.activityInfo.packageName, info.activityInfo.name); return new ComponentName(info.activityInfo.packageName, info.activityInfo.name);
@@ -3618,11 +3571,14 @@ public class LauncherModel extends BroadcastReceiver
} }
}; };
public static class WidgetAndShortcutNameComparator implements Comparator<Object> { public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
private Collator mCollator; private final AppWidgetManagerCompat mManager;
private PackageManager mPackageManager; private final PackageManager mPackageManager;
private HashMap<Object, String> mLabelCache; private final HashMap<Object, String> mLabelCache;
WidgetAndShortcutNameComparator(PackageManager pm) { private final Collator mCollator;
mPackageManager = pm;
WidgetAndShortcutNameComparator(Context context) {
mManager = AppWidgetManagerCompat.getInstance(context);
mPackageManager = context.getPackageManager();
mLabelCache = new HashMap<Object, String>(); mLabelCache = new HashMap<Object, String>();
mCollator = Collator.getInstance(); mCollator = Collator.getInstance();
} }
@@ -3631,17 +3587,17 @@ public class LauncherModel extends BroadcastReceiver
if (mLabelCache.containsKey(a)) { if (mLabelCache.containsKey(a)) {
labelA = mLabelCache.get(a); labelA = mLabelCache.get(a);
} else { } else {
labelA = (a instanceof AppWidgetProviderInfo) ? labelA = (a instanceof AppWidgetProviderInfo)
((AppWidgetProviderInfo) a).label : ? mManager.loadLabel((AppWidgetProviderInfo) a)
((ResolveInfo) a).loadLabel(mPackageManager).toString().trim(); : ((ResolveInfo) a).loadLabel(mPackageManager).toString().trim();
mLabelCache.put(a, labelA); mLabelCache.put(a, labelA);
} }
if (mLabelCache.containsKey(b)) { if (mLabelCache.containsKey(b)) {
labelB = mLabelCache.get(b); labelB = mLabelCache.get(b);
} else { } else {
labelB = (b instanceof AppWidgetProviderInfo) ? labelB = (b instanceof AppWidgetProviderInfo)
((AppWidgetProviderInfo) b).label : ? mManager.loadLabel((AppWidgetProviderInfo) b)
((ResolveInfo) b).loadLabel(mPackageManager).toString().trim(); : ((ResolveInfo) b).loadLabel(mPackageManager).toString().trim();
mLabelCache.put(b, labelB); mLabelCache.put(b, labelB);
} }
return mCollator.compare(labelA, labelB); return mCollator.compare(labelA, labelB);
@@ -30,6 +30,8 @@ import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.android.launcher3.compat.AppWidgetManagerCompat;
/** /**
* The linear layout used strictly for the widget/wallpaper tab of the customization tray * The linear layout used strictly for the widget/wallpaper tab of the customization tray
*/ */
@@ -127,7 +129,7 @@ public class PagedViewWidget extends LinearLayout {
image.setMaxWidth(maxWidth); image.setMaxWidth(maxWidth);
} }
final TextView name = (TextView) findViewById(R.id.widget_name); final TextView name = (TextView) findViewById(R.id.widget_name);
name.setText(info.label); name.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info));
final TextView dims = (TextView) findViewById(R.id.widget_dims); final TextView dims = (TextView) findViewById(R.id.widget_dims);
if (dims != null) { if (dims != null) {
int hSpan = Math.min(cellSpan[0], (int) grid.numColumns); int hSpan = Math.min(cellSpan[0], (int) grid.numColumns);
+1 -1
View File
@@ -78,7 +78,7 @@ public final class Utilities {
/** /**
* Returns a FastBitmapDrawable with the icon, accurately sized. * Returns a FastBitmapDrawable with the icon, accurately sized.
*/ */
static FastBitmapDrawable createIconDrawable(Bitmap icon) { public static FastBitmapDrawable createIconDrawable(Bitmap icon) {
FastBitmapDrawable d = new FastBitmapDrawable(icon); FastBitmapDrawable d = new FastBitmapDrawable(icon);
d.setFilterBitmap(true); d.setFilterBitmap(true);
resizeIconDrawable(d); resizeIconDrawable(d);
@@ -5,7 +5,6 @@ import android.content.ComponentName;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo; import android.content.pm.ResolveInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.Cursor; import android.database.Cursor;
@@ -29,6 +28,8 @@ import android.graphics.drawable.Drawable;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.util.Log; import android.util.Log;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -42,124 +43,123 @@ import java.util.List;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
abstract class SoftReferenceThreadLocal<T> { public class WidgetPreviewLoader {
private ThreadLocal<SoftReference<T>> mThreadLocal;
public SoftReferenceThreadLocal() {
mThreadLocal = new ThreadLocal<SoftReference<T>>();
}
abstract T initialValue(); private static abstract class SoftReferenceThreadLocal<T> {
private ThreadLocal<SoftReference<T>> mThreadLocal;
public SoftReferenceThreadLocal() {
mThreadLocal = new ThreadLocal<SoftReference<T>>();
}
public void set(T t) { abstract T initialValue();
mThreadLocal.set(new SoftReference<T>(t));
}
public T get() { public void set(T t) {
SoftReference<T> reference = mThreadLocal.get(); mThreadLocal.set(new SoftReference<T>(t));
T obj; }
if (reference == null) {
obj = initialValue(); public T get() {
mThreadLocal.set(new SoftReference<T>(obj)); SoftReference<T> reference = mThreadLocal.get();
return obj; T obj;
} else { if (reference == null) {
obj = reference.get();
if (obj == null) {
obj = initialValue(); obj = initialValue();
mThreadLocal.set(new SoftReference<T>(obj)); mThreadLocal.set(new SoftReference<T>(obj));
return obj;
} else {
obj = reference.get();
if (obj == null) {
obj = initialValue();
mThreadLocal.set(new SoftReference<T>(obj));
}
return obj;
} }
return obj;
} }
} }
}
class CanvasCache extends SoftReferenceThreadLocal<Canvas> { private static class CanvasCache extends SoftReferenceThreadLocal<Canvas> {
@Override @Override
protected Canvas initialValue() { protected Canvas initialValue() {
return new Canvas(); return new Canvas();
}
} }
}
class PaintCache extends SoftReferenceThreadLocal<Paint> { private static class PaintCache extends SoftReferenceThreadLocal<Paint> {
@Override @Override
protected Paint initialValue() { protected Paint initialValue() {
return null; return null;
}
} }
}
class BitmapCache extends SoftReferenceThreadLocal<Bitmap> { private static class BitmapCache extends SoftReferenceThreadLocal<Bitmap> {
@Override @Override
protected Bitmap initialValue() { protected Bitmap initialValue() {
return null; return null;
}
} }
}
class RectCache extends SoftReferenceThreadLocal<Rect> { private static class RectCache extends SoftReferenceThreadLocal<Rect> {
@Override @Override
protected Rect initialValue() { protected Rect initialValue() {
return new Rect(); return new Rect();
}
} }
}
class BitmapFactoryOptionsCache extends SoftReferenceThreadLocal<BitmapFactory.Options> { private static class BitmapFactoryOptionsCache extends
@Override SoftReferenceThreadLocal<BitmapFactory.Options> {
protected BitmapFactory.Options initialValue() { @Override
return new BitmapFactory.Options(); protected BitmapFactory.Options initialValue() {
return new BitmapFactory.Options();
}
} }
}
public class WidgetPreviewLoader { private static final String TAG = "WidgetPreviewLoader";
static final String TAG = "WidgetPreviewLoader"; private static final String ANDROID_INCREMENTAL_VERSION_NAME_KEY = "android.incremental.version";
static final String ANDROID_INCREMENTAL_VERSION_NAME_KEY = "android.incremental.version";
private static final float WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE = 0.25f;
private static final HashSet<String> sInvalidPackages = new HashSet<String>();
// Used for drawing shortcut previews
private final BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
private final PaintCache mCachedShortcutPreviewPaint = new PaintCache();
private final CanvasCache mCachedShortcutPreviewCanvas = new CanvasCache();
// Used for drawing widget previews
private final CanvasCache mCachedAppWidgetPreviewCanvas = new CanvasCache();
private final RectCache mCachedAppWidgetPreviewSrcRect = new RectCache();
private final RectCache mCachedAppWidgetPreviewDestRect = new RectCache();
private final PaintCache mCachedAppWidgetPreviewPaint = new PaintCache();
private final PaintCache mDefaultAppWidgetPreviewPaint = new PaintCache();
private final BitmapFactoryOptionsCache mCachedBitmapFactoryOptions = new BitmapFactoryOptionsCache();
private final HashMap<String, WeakReference<Bitmap>> mLoadedPreviews = new HashMap<>();
private final ArrayList<SoftReference<Bitmap>> mUnusedBitmaps = new ArrayList<>();
private final Context mContext;
private final int mAppIconSize;
private final IconCache mIconCache;
private final AppWidgetManagerCompat mManager;
private int mPreviewBitmapWidth; private int mPreviewBitmapWidth;
private int mPreviewBitmapHeight; private int mPreviewBitmapHeight;
private String mSize; private String mSize;
private Context mContext;
private PackageManager mPackageManager;
private PagedViewCellLayout mWidgetSpacingLayout; private PagedViewCellLayout mWidgetSpacingLayout;
// Used for drawing shortcut previews
private BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
private PaintCache mCachedShortcutPreviewPaint = new PaintCache();
private CanvasCache mCachedShortcutPreviewCanvas = new CanvasCache();
// Used for drawing widget previews
private CanvasCache mCachedAppWidgetPreviewCanvas = new CanvasCache();
private RectCache mCachedAppWidgetPreviewSrcRect = new RectCache();
private RectCache mCachedAppWidgetPreviewDestRect = new RectCache();
private PaintCache mCachedAppWidgetPreviewPaint = new PaintCache();
private PaintCache mDefaultAppWidgetPreviewPaint = new PaintCache();
private String mCachedSelectQuery; private String mCachedSelectQuery;
private BitmapFactoryOptionsCache mCachedBitmapFactoryOptions = new BitmapFactoryOptionsCache();
private int mAppIconSize;
private IconCache mIconCache;
private static final float sWidgetPreviewIconPaddingPercentage = 0.25f;
private CacheDb mDb; private CacheDb mDb;
private final HashMap<String, WeakReference<Bitmap>> mLoadedPreviews;
private final ArrayList<SoftReference<Bitmap>> mUnusedBitmaps;
private final static HashSet<String> sInvalidPackages;
private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor(); private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
static {
sInvalidPackages = new HashSet<String>();
}
public WidgetPreviewLoader(Context context) { public WidgetPreviewLoader(Context context) {
LauncherAppState app = LauncherAppState.getInstance(); LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
mContext = context; mContext = context;
mPackageManager = mContext.getPackageManager();
mAppIconSize = grid.iconSizePx; mAppIconSize = grid.iconSizePx;
mIconCache = app.getIconCache(); mIconCache = app.getIconCache();
mManager = AppWidgetManagerCompat.getInstance(context);
mDb = app.getWidgetPreviewCacheDb(); mDb = app.getWidgetPreviewCacheDb();
mLoadedPreviews = new HashMap<String, WeakReference<Bitmap>>();
mUnusedBitmaps = new ArrayList<SoftReference<Bitmap>>();
SharedPreferences sp = context.getSharedPreferences( SharedPreferences sp = context.getSharedPreferences(
LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE); LauncherAppState.getSharedPreferencesKey(), Context.MODE_PRIVATE);
@@ -175,7 +175,7 @@ public class WidgetPreviewLoader {
editor.commit(); editor.commit();
} }
} }
public void recreateDb() { public void recreateDb() {
LauncherAppState app = LauncherAppState.getInstance(); LauncherAppState app = LauncherAppState.getInstance();
app.recreateWidgetPreviewDb(); app.recreateWidgetPreviewDb();
@@ -328,7 +328,7 @@ public class WidgetPreviewLoader {
String output; String output;
if (o instanceof AppWidgetProviderInfo) { if (o instanceof AppWidgetProviderInfo) {
sb.append(WIDGET_PREFIX); sb.append(WIDGET_PREFIX);
sb.append(((AppWidgetProviderInfo) o).provider.flattenToString()); sb.append(((AppWidgetProviderInfo) o).toString());
output = sb.toString(); output = sb.toString();
sb.setLength(0); sb.setLength(0);
} else { } else {
@@ -413,7 +413,7 @@ public class WidgetPreviewLoader {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null); }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void) null);
} }
public static void removeItemFromDb(final CacheDb cacheDb, final String objectName) { private static void removeItemFromDb(final CacheDb cacheDb, final String objectName) {
new AsyncTask<Void, Void, Void>() { new AsyncTask<Void, Void, Void>() {
public Void doInBackground(Void ... args) { public Void doInBackground(Void ... args) {
SQLiteDatabase db = cacheDb.getWritableDatabase(); SQLiteDatabase db = cacheDb.getWritableDatabase();
@@ -473,7 +473,7 @@ public class WidgetPreviewLoader {
} }
} }
public Bitmap generatePreview(Object info, Bitmap preview) { private Bitmap generatePreview(Object info, Bitmap preview) {
if (preview != null && if (preview != null &&
(preview.getWidth() != mPreviewBitmapWidth || (preview.getWidth() != mPreviewBitmapWidth ||
preview.getHeight() != mPreviewBitmapHeight)) { preview.getHeight() != mPreviewBitmapHeight)) {
@@ -491,8 +491,8 @@ public class WidgetPreviewLoader {
int[] cellSpans = Launcher.getSpanForWidget(mContext, info); int[] cellSpans = Launcher.getSpanForWidget(mContext, info);
int maxWidth = maxWidthForWidgetPreview(cellSpans[0]); int maxWidth = maxWidthForWidgetPreview(cellSpans[0]);
int maxHeight = maxHeightForWidgetPreview(cellSpans[1]); int maxHeight = maxHeightForWidgetPreview(cellSpans[1]);
return generateWidgetPreview(info.provider, info.previewImage, info.icon, return generateWidgetPreview(info, cellSpans[0], cellSpans[1],
cellSpans[0], cellSpans[1], maxWidth, maxHeight, preview, null); maxWidth, maxHeight, preview, null);
} }
public int maxWidthForWidgetPreview(int spanX) { public int maxWidthForWidgetPreview(int spanX) {
@@ -505,22 +505,20 @@ public class WidgetPreviewLoader {
mWidgetSpacingLayout.estimateCellHeight(spanY)); mWidgetSpacingLayout.estimateCellHeight(spanY));
} }
public Bitmap generateWidgetPreview(ComponentName provider, int previewImage, public Bitmap generateWidgetPreview(AppWidgetProviderInfo info, int cellHSpan, int cellVSpan,
int iconId, int cellHSpan, int cellVSpan, int maxPreviewWidth, int maxPreviewHeight, int maxPreviewWidth, int maxPreviewHeight, Bitmap preview, int[] preScaledWidthOut) {
Bitmap preview, int[] preScaledWidthOut) {
// Load the preview image if possible // Load the preview image if possible
String packageName = provider.getPackageName();
if (maxPreviewWidth < 0) maxPreviewWidth = Integer.MAX_VALUE; if (maxPreviewWidth < 0) maxPreviewWidth = Integer.MAX_VALUE;
if (maxPreviewHeight < 0) maxPreviewHeight = Integer.MAX_VALUE; if (maxPreviewHeight < 0) maxPreviewHeight = Integer.MAX_VALUE;
Drawable drawable = null; Drawable drawable = null;
if (previewImage != 0) { if (info.previewImage != 0) {
drawable = mPackageManager.getDrawable(packageName, previewImage, null); drawable = mManager.loadPreview(info);
if (drawable != null) { if (drawable != null) {
drawable = mutateOnMainThread(drawable); drawable = mutateOnMainThread(drawable);
} else { } else {
Log.w(TAG, "Can't load widget preview drawable 0x" + Log.w(TAG, "Can't load widget preview drawable 0x" +
Integer.toHexString(previewImage) + " for provider: " + provider); Integer.toHexString(info.previewImage) + " for provider: " + info.provider);
} }
} }
@@ -562,21 +560,16 @@ public class WidgetPreviewLoader {
c.setBitmap(null); c.setBitmap(null);
// Draw the icon in the top left corner // Draw the icon in the top left corner
int minOffset = (int) (mAppIconSize * sWidgetPreviewIconPaddingPercentage); int minOffset = (int) (mAppIconSize * WIDGET_PREVIEW_ICON_PADDING_PERCENTAGE);
int smallestSide = Math.min(previewWidth, previewHeight); int smallestSide = Math.min(previewWidth, previewHeight);
float iconScale = Math.min((float) smallestSide float iconScale = Math.min((float) smallestSide
/ (mAppIconSize + 2 * minOffset), 1f); / (mAppIconSize + 2 * minOffset), 1f);
try { try {
Drawable icon = null; Drawable icon = mManager.loadIcon(info, mIconCache);
int hoffset =
(int) ((previewDrawableWidth - mAppIconSize * iconScale) / 2);
int yoffset =
(int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2);
if (iconId > 0) {
icon = mIconCache.getFullResIcon(packageName, iconId);
}
if (icon != null) { if (icon != null) {
int hoffset = (int) ((previewDrawableWidth - mAppIconSize * iconScale) / 2);
int yoffset = (int) ((previewDrawableHeight - mAppIconSize * iconScale) / 2);
icon = mutateOnMainThread(icon); icon = mutateOnMainThread(icon);
renderDrawableToBitmap(icon, defaultPreview, hoffset, renderDrawableToBitmap(icon, defaultPreview, hoffset,
yoffset, (int) (mAppIconSize * iconScale), yoffset, (int) (mAppIconSize * iconScale),
@@ -627,7 +620,7 @@ public class WidgetPreviewLoader {
c.drawBitmap(defaultPreview, src, dest, p); c.drawBitmap(defaultPreview, src, dest, p);
c.setBitmap(null); c.setBitmap(null);
} }
return preview; return mManager.getBadgeBitmap(info, preview);
} }
private Bitmap generateShortcutPreview( private Bitmap generateShortcutPreview(
@@ -685,18 +678,10 @@ public class WidgetPreviewLoader {
return preview; return preview;
} }
public static void renderDrawableToBitmap(
Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
renderDrawableToBitmap(d, bitmap, x, y, w, h, 1f);
}
private static void renderDrawableToBitmap( private static void renderDrawableToBitmap(
Drawable d, Bitmap bitmap, int x, int y, int w, int h, Drawable d, Bitmap bitmap, int x, int y, int w, int h) {
float scale) {
if (bitmap != null) { if (bitmap != null) {
Canvas c = new Canvas(bitmap); Canvas c = new Canvas(bitmap);
c.scale(scale, scale);
Rect oldBounds = d.copyBounds(); Rect oldBounds = d.copyBounds();
d.setBounds(x, y, x + w, y + h); d.setBounds(x, y, x + w, y + h);
d.draw(c); d.draw(c);
@@ -0,0 +1,83 @@
/*
* Copyright (C) 2014 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.launcher3.compat;
import android.app.Activity;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import com.android.launcher3.IconCache;
import com.android.launcher3.Utilities;
import java.util.List;
public abstract class AppWidgetManagerCompat {
private static final Object sInstanceLock = new Object();
private static AppWidgetManagerCompat sInstance;
public static AppWidgetManagerCompat getInstance(Context context) {
synchronized (sInstanceLock) {
// TODO change this to use api version once L gets an API number.
if (sInstance == null) {
if (Utilities.isLmp()) {
sInstance = new AppWidgetManagerCompatVL(context);
} else {
sInstance = new AppWidgetManagerCompatV16(context);
}
}
return sInstance;
}
}
final AppWidgetManager mAppWidgetManager;
final Context mContext;
AppWidgetManagerCompat(Context context) {
mContext = context;
mAppWidgetManager = AppWidgetManager.getInstance(context);
}
public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
return mAppWidgetManager.getAppWidgetInfo(appWidgetId);
}
public abstract List<AppWidgetProviderInfo> getAllProviders();
public abstract String loadLabel(AppWidgetProviderInfo info);
public abstract boolean bindAppWidgetIdIfAllowed(
int appWidgetId, AppWidgetProviderInfo info, Bundle options);
public abstract UserHandleCompat getUser(AppWidgetProviderInfo info);
public abstract void startConfigActivity(AppWidgetProviderInfo info, int widgetId,
Activity activity, AppWidgetHost host, int requestCode);
public abstract Drawable loadPreview(AppWidgetProviderInfo info);
public abstract Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache);
public abstract Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap);
}
@@ -0,0 +1,90 @@
/*
* Copyright (C) 2014 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.launcher3.compat;
import android.app.Activity;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import com.android.launcher3.IconCache;
import com.android.launcher3.Utilities;
import java.util.List;
class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat {
AppWidgetManagerCompatV16(Context context) {
super(context);
}
@Override
public List<AppWidgetProviderInfo> getAllProviders() {
return mAppWidgetManager.getInstalledProviders();
}
@Override
public String loadLabel(AppWidgetProviderInfo info) {
return info.label.trim();
}
@Override
public boolean bindAppWidgetIdIfAllowed(int appWidgetId, AppWidgetProviderInfo info,
Bundle options) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
return mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, info.provider);
} else {
return mAppWidgetManager.bindAppWidgetIdIfAllowed(appWidgetId, info.provider, options);
}
}
@Override
public UserHandleCompat getUser(AppWidgetProviderInfo info) {
return UserHandleCompat.myUserHandle();
}
@Override
public void startConfigActivity(AppWidgetProviderInfo info, int widgetId, Activity activity,
AppWidgetHost host, int requestCode) {
Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_CONFIGURE);
intent.setComponent(info.configure);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
Utilities.startActivityForResultSafely(activity, intent, requestCode);
}
@Override
public Drawable loadPreview(AppWidgetProviderInfo info) {
return mContext.getPackageManager().getDrawable(
info.provider.getPackageName(), info.previewImage, null);
}
@Override
public Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache) {
return cache.getFullResIcon(info.provider.getPackageName(), info.icon);
}
@Override
public Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap) {
return bitmap;
}
}
@@ -0,0 +1,142 @@
/*
* Copyright (C) 2014 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.launcher3.compat;
import android.annotation.TargetApi;
import android.app.Activity;
import android.appwidget.AppWidgetHost;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.view.View;
import android.widget.Toast;
import com.android.launcher3.IconCache;
import com.android.launcher3.R;
import java.util.ArrayList;
import java.util.List;
@TargetApi(Build.VERSION_CODES.L)
class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
private final UserManager mUserManager;
private final PackageManager mPm;
AppWidgetManagerCompatVL(Context context) {
super(context);
mPm = context.getPackageManager();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
}
@Override
public List<AppWidgetProviderInfo> getAllProviders() {
ArrayList<AppWidgetProviderInfo> providers = new ArrayList<AppWidgetProviderInfo>();
for (UserHandle user : mUserManager.getUserProfiles()) {
providers.addAll(mAppWidgetManager.getInstalledProvidersForProfile(user));
}
return providers;
}
@Override
public String loadLabel(AppWidgetProviderInfo info) {
return info.loadLabel(mPm);
}
@Override
public boolean bindAppWidgetIdIfAllowed(int appWidgetId, AppWidgetProviderInfo info,
Bundle options) {
return mAppWidgetManager.bindAppWidgetIdIfAllowed(
appWidgetId, info.getProfile(), info.provider, options);
}
@Override
public UserHandleCompat getUser(AppWidgetProviderInfo info) {
return UserHandleCompat.fromUser(info.getProfile());
}
@Override
public void startConfigActivity(AppWidgetProviderInfo info, int widgetId, Activity activity,
AppWidgetHost host, int requestCode) {
try {
host.startAppWidgetConfigureActivityForResult(activity, widgetId, 0, requestCode, null);
} catch (ActivityNotFoundException e) {
Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
} catch (SecurityException e) {
Toast.makeText(activity, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
}
}
@Override
public Drawable loadPreview(AppWidgetProviderInfo info) {
return info.loadPreviewImage(mContext, 0);
}
@Override
public Drawable loadIcon(AppWidgetProviderInfo info, IconCache cache) {
return info.loadIcon(mContext, cache.getFullResIconDpi());
}
@Override
public Bitmap getBadgeBitmap(AppWidgetProviderInfo info, Bitmap bitmap) {
if (info.getProfile().equals(android.os.Process.myUserHandle())) {
return bitmap;
}
// Add a user badge in the bottom right of the image.
final Resources res = mContext.getResources();
final int badgeSize = res.getDimensionPixelSize(R.dimen.profile_badge_size);
final int badgeMargin = res.getDimensionPixelSize(R.dimen.profile_badge_margin);
final Rect badgeLocation = new Rect(0, 0, badgeSize, badgeSize);
final int top = bitmap.getHeight() - badgeSize - badgeMargin;
if (res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
badgeLocation.offset(badgeMargin, top);
} else {
badgeLocation.offset(bitmap.getWidth() - badgeSize - badgeMargin, top);
}
UserManager userManager = (UserManager) mContext.getSystemService(
Context.USER_SERVICE);
Drawable drawable = userManager.getBadgedDrawableForUser(new BitmapDrawable(res, bitmap),
info.getProfile(), badgeLocation, 0);
if (drawable instanceof BitmapDrawable) {
return ((BitmapDrawable) drawable).getBitmap();
}
bitmap.eraseColor(Color.TRANSPARENT);
Canvas c = new Canvas(bitmap);
drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
drawable.draw(c);
c.setBitmap(null);
return bitmap;
}
}