Merge "Changing the widget loading strategy" into ub-launcher3-calgary
am: d856074d90
* commit 'd856074d90b31390f1a70d09fde374cae925bf20':
Changing the widget loading strategy
This commit is contained in:
@@ -1560,8 +1560,7 @@ public class Launcher extends Activity
|
||||
|
||||
ItemInfo info = mPendingAddInfo;
|
||||
if (appWidgetInfo == null) {
|
||||
appWidgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(this,
|
||||
mAppWidgetManager.getAppWidgetInfo(appWidgetId));
|
||||
appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(appWidgetId);
|
||||
}
|
||||
|
||||
if (appWidgetInfo.isCustomWidget) {
|
||||
@@ -2558,10 +2557,10 @@ public class Launcher extends Activity
|
||||
final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) v.getTag();
|
||||
if (v.isReadyForClickSetup()) {
|
||||
int widgetId = info.appWidgetId;
|
||||
AppWidgetProviderInfo appWidgetInfo = mAppWidgetManager.getAppWidgetInfo(widgetId);
|
||||
LauncherAppWidgetProviderInfo appWidgetInfo =
|
||||
mAppWidgetManager.getLauncherAppWidgetInfo(widgetId);
|
||||
if (appWidgetInfo != null) {
|
||||
mPendingAddWidgetInfo = LauncherAppWidgetProviderInfo.fromProviderInfo(
|
||||
this, appWidgetInfo);
|
||||
mPendingAddWidgetInfo = appWidgetInfo;
|
||||
mPendingAddInfo.copyFrom(info);
|
||||
mPendingAddWidgetId = widgetId;
|
||||
|
||||
@@ -3538,10 +3537,6 @@ public class Launcher extends Activity
|
||||
// TODO
|
||||
}
|
||||
|
||||
protected void disableVoiceButtonProxy(boolean disable) {
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
public boolean launcherCallbacksProvidesSearch() {
|
||||
return (mLauncherCallbacks != null && mLauncherCallbacks.providesSearch());
|
||||
}
|
||||
@@ -3955,6 +3950,16 @@ public class Launcher extends Activity
|
||||
sFolders = folders.clone();
|
||||
}
|
||||
|
||||
private void bindSafeModeWidget(LauncherAppWidgetInfo item) {
|
||||
PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item, true);
|
||||
view.updateIcon(mIconCache);
|
||||
item.hostView = view;
|
||||
item.hostView.updateAppWidget(null);
|
||||
item.hostView.setOnClickListener(this);
|
||||
addAppWidgetToWorkspace(item, null, false);
|
||||
mWorkspace.requestLayout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the views for a widget to the workspace.
|
||||
*
|
||||
@@ -3970,19 +3975,31 @@ public class Launcher extends Activity
|
||||
return;
|
||||
}
|
||||
|
||||
if (mIsSafeModeEnabled) {
|
||||
bindSafeModeWidget(item);
|
||||
return;
|
||||
}
|
||||
|
||||
final long start = DEBUG_WIDGETS ? SystemClock.uptimeMillis() : 0;
|
||||
if (DEBUG_WIDGETS) {
|
||||
Log.d(TAG, "bindAppWidget: " + item);
|
||||
}
|
||||
final Workspace workspace = mWorkspace;
|
||||
|
||||
LauncherAppWidgetProviderInfo appWidgetInfo =
|
||||
LauncherModel.getProviderInfo(this, item.providerName, item.user);
|
||||
final LauncherAppWidgetProviderInfo appWidgetInfo;
|
||||
|
||||
if (!mIsSafeModeEnabled
|
||||
&& ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0)
|
||||
&& (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
|
||||
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) {
|
||||
// If the provider is not ready, bind as a pending widget.
|
||||
appWidgetInfo = null;
|
||||
} else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
|
||||
// The widget id is not valid. Try to find the widget based on the provider info.
|
||||
appWidgetInfo = mAppWidgetManager.findProvider(item.providerName, item.user);
|
||||
} else {
|
||||
appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(item.appWidgetId);
|
||||
}
|
||||
|
||||
// If the provider is ready, but the width is not yet restored, try to restore it.
|
||||
if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) &&
|
||||
(item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) {
|
||||
if (appWidgetInfo == null) {
|
||||
if (DEBUG_WIDGETS) {
|
||||
Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId
|
||||
@@ -3994,7 +4011,7 @@ public class Launcher extends Activity
|
||||
}
|
||||
|
||||
// If we do not have a valid id, try to bind an id.
|
||||
if ((item.restoreStatus & LauncherAppWidgetInfo.FLAG_ID_NOT_VALID) != 0) {
|
||||
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
|
||||
// Note: This assumes that the id remap broadcast is received before this step.
|
||||
// If that is not the case, the id remap will be ignored and user may see the
|
||||
// click to setup view.
|
||||
@@ -4030,46 +4047,42 @@ public class Launcher extends Activity
|
||||
: LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
|
||||
|
||||
LauncherModel.updateItemInDatabase(this, item);
|
||||
} else if (((item.restoreStatus & LauncherAppWidgetInfo.FLAG_UI_NOT_READY) != 0)
|
||||
} else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY)
|
||||
&& (appWidgetInfo.configure == null)) {
|
||||
// If the ID is already valid, verify if we need to configure or not.
|
||||
// The widget was marked as UI not ready, but there is no configure activity to
|
||||
// update the UI.
|
||||
item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED;
|
||||
LauncherModel.updateItemInDatabase(this, item);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mIsSafeModeEnabled && item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
|
||||
final int appWidgetId = item.appWidgetId;
|
||||
if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
|
||||
if (DEBUG_WIDGETS) {
|
||||
Log.d(TAG, "bindAppWidget: id=" + item.appWidgetId + " belongs to component "
|
||||
+ appWidgetInfo.provider);
|
||||
}
|
||||
|
||||
// Verify that we own the widget
|
||||
AppWidgetProviderInfo info = mAppWidgetManager.getAppWidgetInfo(appWidgetId);
|
||||
if (info == null || appWidgetInfo == null ||
|
||||
!info.provider.equals(appWidgetInfo.provider)) {
|
||||
Log.e(TAG, "Removing invalid widget: id=" + item.appWidgetId + " info=" + info
|
||||
+ " appWidgetInfo=" + appWidgetInfo);
|
||||
if (appWidgetInfo == null) {
|
||||
Log.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
|
||||
deleteWidgetInfo(item);
|
||||
return;
|
||||
}
|
||||
|
||||
item.hostView = mAppWidgetHost.createView(this, appWidgetId, appWidgetInfo);
|
||||
item.hostView = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo);
|
||||
item.minSpanX = appWidgetInfo.minSpanX;
|
||||
item.minSpanY = appWidgetInfo.minSpanY;
|
||||
addAppWidgetToWorkspace(item, appWidgetInfo, false);
|
||||
} else {
|
||||
appWidgetInfo = null;
|
||||
PendingAppWidgetHostView view = new PendingAppWidgetHostView(this, item,
|
||||
mIsSafeModeEnabled);
|
||||
view.updateIcon(mIconCache);
|
||||
item.hostView = view;
|
||||
item.hostView.updateAppWidget(null);
|
||||
item.hostView.setOnClickListener(this);
|
||||
addAppWidgetToWorkspace(item, null, false);
|
||||
}
|
||||
|
||||
addAppWidgetToWorkspace(item, appWidgetInfo, false);
|
||||
workspace.requestLayout();
|
||||
mWorkspace.requestLayout();
|
||||
|
||||
if (DEBUG_WIDGETS) {
|
||||
Log.d(TAG, "bound widget id="+item.appWidgetId+" in "
|
||||
@@ -4407,15 +4420,15 @@ public class Launcher extends Activity
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable mBindPackagesUpdatedRunnable = new Runnable() {
|
||||
private Runnable mBindWidgetModelRunnable = new Runnable() {
|
||||
public void run() {
|
||||
bindAllPackages(mWidgetsModel);
|
||||
bindWidgetsModel(mWidgetsModel);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void bindAllPackages(final WidgetsModel model) {
|
||||
if (waitUntilResume(mBindPackagesUpdatedRunnable, true)) {
|
||||
public void bindWidgetsModel(WidgetsModel model) {
|
||||
if (waitUntilResume(mBindWidgetModelRunnable, true)) {
|
||||
mWidgetsModel = model;
|
||||
return;
|
||||
}
|
||||
@@ -4426,6 +4439,13 @@ public class Launcher extends Activity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyWidgetProvidersChanged() {
|
||||
if (mWorkspace.getState().shouldUpdateWidget) {
|
||||
mModel.refreshAndBindWidgetsAndShortcuts(this, mWidgetsView.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
private int mapConfigurationOriActivityInfoOri(int configOri) {
|
||||
final Display d = getWindowManager().getDefaultDisplay();
|
||||
int naturalOri = Configuration.ORIENTATION_LANDSCAPE;
|
||||
|
||||
@@ -102,6 +102,10 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
|
||||
callback.run();
|
||||
}
|
||||
}
|
||||
|
||||
if (Utilities.ATLEAST_MARSHMALLOW) {
|
||||
mLauncher.notifyWidgetProvidersChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public AppWidgetHostView createView(Context context, int appWidgetId,
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.android.launcher3.backup.nano.BackupProtos.Key;
|
||||
import com.android.launcher3.backup.nano.BackupProtos.Resource;
|
||||
import com.android.launcher3.backup.nano.BackupProtos.Screen;
|
||||
import com.android.launcher3.backup.nano.BackupProtos.Widget;
|
||||
import com.android.launcher3.compat.AppWidgetManagerCompat;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.compat.UserManagerCompat;
|
||||
import com.android.launcher3.model.GridSizeMigrationTask;
|
||||
@@ -660,12 +661,14 @@ public class LauncherBackupHelper implements BackupHelper {
|
||||
+ getUserSelectionArg();
|
||||
Cursor cursor = cr.query(Favorites.CONTENT_URI, FAVORITE_PROJECTION,
|
||||
where, null, null);
|
||||
AppWidgetManagerCompat widgetManager = AppWidgetManagerCompat.getInstance(mContext);
|
||||
try {
|
||||
cursor.moveToPosition(-1);
|
||||
while(cursor.moveToNext()) {
|
||||
final long id = cursor.getLong(ID_INDEX);
|
||||
final String providerName = cursor.getString(APPWIDGET_PROVIDER_INDEX);
|
||||
final ComponentName provider = ComponentName.unflattenFromString(providerName);
|
||||
|
||||
Key key = null;
|
||||
String backupKey = null;
|
||||
if (provider != null) {
|
||||
@@ -684,11 +687,14 @@ public class LauncherBackupHelper implements BackupHelper {
|
||||
} else if (backupKey != null) {
|
||||
if (DEBUG) Log.d(TAG, "I can count this high: " + backupWidgetCount);
|
||||
if (backupWidgetCount < MAX_WIDGETS_PER_PASS) {
|
||||
if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
|
||||
UserHandleCompat user = UserHandleCompat.myUserHandle();
|
||||
writeRowToBackup(key, packWidget(dpi, provider, user), data);
|
||||
mKeys.add(key);
|
||||
backupWidgetCount ++;
|
||||
LauncherAppWidgetProviderInfo widgetInfo = widgetManager
|
||||
.getLauncherAppWidgetInfo(cursor.getInt(APPWIDGET_ID_INDEX));
|
||||
if (widgetInfo != null) {
|
||||
if (DEBUG) Log.d(TAG, "saving widget " + backupKey);
|
||||
writeRowToBackup(key, packWidget(dpi, widgetInfo), data);
|
||||
mKeys.add(key);
|
||||
backupWidgetCount ++;
|
||||
}
|
||||
} else {
|
||||
if (VERBOSE) Log.v(TAG, "deferring widget backup " + backupKey);
|
||||
// too many widgets for this pass, request another.
|
||||
@@ -1004,16 +1010,14 @@ public class LauncherBackupHelper implements BackupHelper {
|
||||
}
|
||||
|
||||
/** Serialize a widget for persistence, including a checksum wrapper. */
|
||||
private Widget packWidget(int dpi, ComponentName provider, UserHandleCompat user) {
|
||||
final LauncherAppWidgetProviderInfo info =
|
||||
LauncherModel.getProviderInfo(mContext, provider, user);
|
||||
private Widget packWidget(int dpi, LauncherAppWidgetProviderInfo info) {
|
||||
Widget widget = new Widget();
|
||||
widget.provider = provider.flattenToShortString();
|
||||
widget.provider = info.provider.flattenToShortString();
|
||||
widget.label = info.label;
|
||||
widget.configure = info.configure != null;
|
||||
if (info.icon != 0) {
|
||||
widget.icon = new Resource();
|
||||
Drawable fullResIcon = mIconCache.getFullResIcon(provider.getPackageName(), info.icon);
|
||||
Drawable fullResIcon = mIconCache.getFullResIcon(info.provider.getPackageName(), info.icon);
|
||||
Bitmap icon = Utilities.createIconBitmap(fullResIcon, mContext);
|
||||
widget.icon.data = Utilities.flattenBitmap(icon);
|
||||
widget.icon.dpi = dpi;
|
||||
@@ -1022,7 +1026,6 @@ public class LauncherBackupHelper implements BackupHelper {
|
||||
Point spans = info.getMinSpans(mIdp, mContext);
|
||||
widget.minSpanX = spans.x;
|
||||
widget.minSpanY = spans.y;
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.launcher3;
|
||||
|
||||
import android.app.SearchManager;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
@@ -34,7 +33,6 @@ import android.content.pm.ResolveInfo;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.DeadObjectException;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
@@ -42,7 +40,6 @@ import android.os.Looper;
|
||||
import android.os.Parcelable;
|
||||
import android.os.Process;
|
||||
import android.os.SystemClock;
|
||||
import android.os.TransactionTooLargeException;
|
||||
import android.provider.BaseColumns;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
@@ -73,7 +70,6 @@ import java.net.URISyntaxException;
|
||||
import java.security.InvalidParameterException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@@ -137,11 +133,9 @@ public class LauncherModel extends BroadcastReceiver
|
||||
@Thunk WeakReference<Callbacks> mCallbacks;
|
||||
|
||||
// < only access in worker thread >
|
||||
AllAppsList mBgAllAppsList;
|
||||
private final AllAppsList mBgAllAppsList;
|
||||
// Entire list of widgets.
|
||||
WidgetsModel mBgWidgetsModel;
|
||||
// Keep a clone of widgets that can be accessed from non-worker thread.
|
||||
WidgetsModel mFgWidgetsModel;
|
||||
private final WidgetsModel mBgWidgetsModel;
|
||||
|
||||
// The lock that must be acquired before referencing any static bg data structures. Unlike
|
||||
// other locks, this one can generally be held long-term because we never expect any of these
|
||||
@@ -168,12 +162,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
// sBgWorkspaceScreens is the ordered set of workspace screens.
|
||||
static final ArrayList<Long> sBgWorkspaceScreens = new ArrayList<Long>();
|
||||
|
||||
// sBgWidgetProviders is the set of widget providers including custom internal widgets
|
||||
public static HashMap<ComponentKey, LauncherAppWidgetProviderInfo> sBgWidgetProviders;
|
||||
|
||||
// sBgShortcutProviders is the set of custom shortcut providers
|
||||
public static List<ResolveInfo> sBgShortcutProviders;
|
||||
|
||||
// sPendingPackages is a set of packages which could be on sdcard and are not available yet
|
||||
static final HashMap<UserHandleCompat, HashSet<String>> sPendingPackages =
|
||||
new HashMap<UserHandleCompat, HashSet<String>>();
|
||||
@@ -209,7 +197,8 @@ public class LauncherModel extends BroadcastReceiver
|
||||
public void bindRestoreItemsChange(HashSet<ItemInfo> updates);
|
||||
public void bindComponentsRemoved(ArrayList<String> packageNames,
|
||||
ArrayList<AppInfo> appInfos, UserHandleCompat user, int reason);
|
||||
public void bindAllPackages(WidgetsModel model);
|
||||
public void notifyWidgetProvidersChanged();
|
||||
public void bindWidgetsModel(WidgetsModel model);
|
||||
public void bindSearchProviderChanged();
|
||||
public boolean isAllAppsButtonRank(int rank);
|
||||
public void onPageBoundSynchronously(int page);
|
||||
@@ -245,7 +234,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
mApp = app;
|
||||
mBgAllAppsList = new AllAppsList(iconCache, appFilter);
|
||||
mBgWidgetsModel = new WidgetsModel(context, iconCache, appFilter);
|
||||
mFgWidgetsModel = mBgWidgetsModel.clone();
|
||||
mIconCache = iconCache;
|
||||
|
||||
mLauncherApps = LauncherAppsCompat.getInstance(context);
|
||||
@@ -1701,8 +1689,8 @@ public class LauncherModel extends BroadcastReceiver
|
||||
.getInstance(mContext).updateAndGetActiveSessionCache();
|
||||
sBgWorkspaceScreens.addAll(loadWorkspaceScreensDb(mContext));
|
||||
|
||||
final ArrayList<Long> itemsToRemove = new ArrayList<Long>();
|
||||
final ArrayList<Long> restoredRows = new ArrayList<Long>();
|
||||
final ArrayList<Long> itemsToRemove = new ArrayList<>();
|
||||
final ArrayList<Long> restoredRows = new ArrayList<>();
|
||||
final Uri contentUri = LauncherSettings.Favorites.CONTENT_URI;
|
||||
if (DEBUG_LOADERS) Log.d(TAG, "loading model from " + contentUri);
|
||||
final Cursor c = contentResolver.query(contentUri, null, null, null, null);
|
||||
@@ -1711,6 +1699,7 @@ public class LauncherModel extends BroadcastReceiver
|
||||
// Load workspace in reverse order to ensure that latest items are loaded first (and
|
||||
// before any earlier duplicates)
|
||||
final LongArrayMap<ItemInfo[][]> occupied = new LongArrayMap<>();
|
||||
HashMap<ComponentKey, AppWidgetProviderInfo> widgetProvidersMap = null;
|
||||
|
||||
try {
|
||||
final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
|
||||
@@ -2070,10 +2059,14 @@ public class LauncherModel extends BroadcastReceiver
|
||||
final boolean wasProviderReady = (restoreStatus &
|
||||
LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) == 0;
|
||||
|
||||
final LauncherAppWidgetProviderInfo provider =
|
||||
LauncherModel.getProviderInfo(context,
|
||||
if (widgetProvidersMap == null) {
|
||||
widgetProvidersMap = AppWidgetManagerCompat
|
||||
.getInstance(mContext).getAllProvidersMap();
|
||||
}
|
||||
final AppWidgetProviderInfo provider = widgetProvidersMap.get(
|
||||
new ComponentKey(
|
||||
ComponentName.unflattenFromString(savedProvider),
|
||||
user);
|
||||
user));
|
||||
|
||||
final boolean isProviderReady = isValidProvider(provider);
|
||||
if (!isSafeMode && !customWidget &&
|
||||
@@ -2695,7 +2688,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
final Callbacks callbacks = tryGetCallbacks(oldCallbacks);
|
||||
if (callbacks != null) {
|
||||
callbacks.bindAllApplications(list);
|
||||
callbacks.bindAllPackages(mFgWidgetsModel);
|
||||
}
|
||||
if (DEBUG_LOADERS) {
|
||||
Log.d(TAG, "bound all " + list.size() + " apps from cache in "
|
||||
@@ -2787,7 +2779,7 @@ public class LauncherModel extends BroadcastReceiver
|
||||
callbacks.bindAllApplications(added);
|
||||
if (DEBUG_LOADERS) {
|
||||
Log.d(TAG, "bound " + added.size() + " apps in "
|
||||
+ (SystemClock.uptimeMillis() - bindTime) + "ms");
|
||||
+ (SystemClock.uptimeMillis() - bindTime) + "ms");
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "not binding apps: no Launcher activity");
|
||||
@@ -2796,8 +2788,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
});
|
||||
// Cleanup any data stored for a deleted user.
|
||||
ManagedProfileHeuristic.processAllUsers(profiles, mContext);
|
||||
|
||||
loadAndBindWidgetsAndShortcuts(tryGetCallbacks(oldCallbacks), true /* refresh */);
|
||||
if (DEBUG_LOADERS) {
|
||||
Log.d(TAG, "Icons processed in "
|
||||
+ (SystemClock.uptimeMillis() - loadTime) + "ms");
|
||||
@@ -2864,9 +2854,6 @@ public class LauncherModel extends BroadcastReceiver
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Reload widget list. No need to refresh, as we only want to update the icons and labels.
|
||||
loadAndBindWidgetsAndShortcuts(callbacks, false);
|
||||
}
|
||||
|
||||
void enqueuePackageUpdated(PackageUpdatedTask task) {
|
||||
@@ -3230,167 +3217,49 @@ public class LauncherModel extends BroadcastReceiver
|
||||
});
|
||||
}
|
||||
|
||||
// Update widgets
|
||||
if (mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE) {
|
||||
// Always refresh for a package event on secondary user
|
||||
boolean needToRefresh = !mUser.equals(UserHandleCompat.myUserHandle());
|
||||
|
||||
// Refresh widget list, if the package already had a widget.
|
||||
synchronized (sBgLock) {
|
||||
if (sBgWidgetProviders != null) {
|
||||
HashSet<String> pkgSet = new HashSet<>();
|
||||
Collections.addAll(pkgSet, mPackages);
|
||||
|
||||
for (ComponentKey key : sBgWidgetProviders.keySet()) {
|
||||
needToRefresh |= key.user.equals(mUser) &&
|
||||
pkgSet.contains(key.componentName.getPackageName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!needToRefresh && mOp != OP_REMOVE) {
|
||||
// Refresh widget list, if there is any newly added widget
|
||||
PackageManager pm = context.getPackageManager();
|
||||
for (String pkg : mPackages) {
|
||||
try {
|
||||
List<ResolveInfo> widgets = pm.queryBroadcastReceivers(
|
||||
new Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE)
|
||||
.setPackage(pkg), 0);
|
||||
needToRefresh |= widgets != null && !widgets.isEmpty();
|
||||
} catch (RuntimeException e) {
|
||||
if (ProviderConfig.IS_DOGFOOD_BUILD) {
|
||||
throw e;
|
||||
}
|
||||
// Ignore the crash. We can live with a state widget list.
|
||||
Log.e(TAG, "PM call failed for " + pkg, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadAndBindWidgetsAndShortcuts(callbacks, needToRefresh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<LauncherAppWidgetProviderInfo> getWidgetProviders(Context context,
|
||||
boolean refresh) {
|
||||
ArrayList<LauncherAppWidgetProviderInfo> results =
|
||||
new ArrayList<LauncherAppWidgetProviderInfo>();
|
||||
try {
|
||||
synchronized (sBgLock) {
|
||||
if (sBgWidgetProviders == null || refresh) {
|
||||
HashMap<ComponentKey, LauncherAppWidgetProviderInfo> tmpWidgetProviders
|
||||
= new HashMap<>();
|
||||
AppWidgetManagerCompat wm = AppWidgetManagerCompat.getInstance(context);
|
||||
LauncherAppWidgetProviderInfo info;
|
||||
|
||||
List<AppWidgetProviderInfo> widgets = wm.getAllProviders();
|
||||
for (AppWidgetProviderInfo pInfo : widgets) {
|
||||
info = LauncherAppWidgetProviderInfo.fromProviderInfo(context, pInfo);
|
||||
UserHandleCompat user = wm.getUser(info);
|
||||
tmpWidgetProviders.put(new ComponentKey(info.provider, user), info);
|
||||
}
|
||||
|
||||
Collection<CustomAppWidget> customWidgets = Launcher.getCustomAppWidgets().values();
|
||||
for (CustomAppWidget widget : customWidgets) {
|
||||
info = new LauncherAppWidgetProviderInfo(context, widget);
|
||||
UserHandleCompat user = wm.getUser(info);
|
||||
tmpWidgetProviders.put(new ComponentKey(info.provider, user), info);
|
||||
}
|
||||
// Replace the global list at the very end, so that if there is an exception,
|
||||
// previously loaded provider list is used.
|
||||
sBgWidgetProviders = tmpWidgetProviders;
|
||||
}
|
||||
results.addAll(sBgWidgetProviders.values());
|
||||
return results;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (!ProviderConfig.IS_DOGFOOD_BUILD &&
|
||||
(e.getCause() instanceof TransactionTooLargeException ||
|
||||
e.getCause() instanceof DeadObjectException)) {
|
||||
// the returned value may be incomplete and will not be refreshed until the next
|
||||
// time Launcher starts.
|
||||
// TODO: after figuring out a repro step, introduce a dirty bit to check when
|
||||
// onResume is called to refresh the widget provider list.
|
||||
synchronized (sBgLock) {
|
||||
if (sBgWidgetProviders != null) {
|
||||
results.addAll(sBgWidgetProviders.values());
|
||||
}
|
||||
return results;
|
||||
}
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static LauncherAppWidgetProviderInfo getProviderInfo(Context ctx, ComponentName name,
|
||||
UserHandleCompat user) {
|
||||
synchronized (sBgLock) {
|
||||
if (sBgWidgetProviders == null) {
|
||||
getWidgetProviders(ctx, false /* refresh */);
|
||||
}
|
||||
return sBgWidgetProviders.get(new ComponentKey(name, user));
|
||||
}
|
||||
}
|
||||
|
||||
public void loadAndBindWidgetsAndShortcuts(final Callbacks callbacks, final boolean refresh) {
|
||||
|
||||
runOnWorkerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateWidgetsModel(refresh);
|
||||
// Notify launcher of widget update. From marshmallow onwards we use AppWidgetHost to
|
||||
// get widget update signals.
|
||||
if (!Utilities.ATLEAST_MARSHMALLOW &&
|
||||
(mOp == OP_ADD || mOp == OP_REMOVE || mOp == OP_UPDATE)) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Callbacks cb = getCallback();
|
||||
if (callbacks == cb && cb != null) {
|
||||
callbacks.bindAllPackages(mFgWidgetsModel);
|
||||
callbacks.notifyWidgetProvidersChanged();
|
||||
}
|
||||
}
|
||||
});
|
||||
// update the Widget entries inside DB on the worker thread.
|
||||
LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
|
||||
mFgWidgetsModel.getRawList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void bindWidgetsModel(final Callbacks callbacks, final WidgetsModel model) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Callbacks cb = getCallback();
|
||||
if (callbacks == cb && cb != null) {
|
||||
callbacks.bindWidgetsModel(model);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of ResolveInfos/AppWidgetInfos.
|
||||
*
|
||||
* @see #loadAndBindWidgetsAndShortcuts
|
||||
*/
|
||||
@Thunk void updateWidgetsModel(boolean refresh) {
|
||||
Utilities.assertWorkerThread();
|
||||
PackageManager packageManager = mApp.getContext().getPackageManager();
|
||||
final ArrayList<Object> widgetsAndShortcuts = new ArrayList<Object>();
|
||||
widgetsAndShortcuts.addAll(getWidgetProviders(mApp.getContext(), refresh));
|
||||
|
||||
// Update shortcut providers
|
||||
synchronized (sBgLock) {
|
||||
try {
|
||||
Intent shortcutsIntent = new Intent(Intent.ACTION_CREATE_SHORTCUT);
|
||||
List<ResolveInfo> providers = packageManager.queryIntentActivities(shortcutsIntent, 0);
|
||||
sBgShortcutProviders = providers;
|
||||
} catch (RuntimeException e) {
|
||||
if (!ProviderConfig.IS_DOGFOOD_BUILD &&
|
||||
(e.getCause() instanceof TransactionTooLargeException ||
|
||||
e.getCause() instanceof DeadObjectException)) {
|
||||
/**
|
||||
* Ignore exception and use the cached list if available.
|
||||
* Refer to {@link #getWidgetProviders(Context, boolean}} for more info.
|
||||
*/
|
||||
} else {
|
||||
throw e;
|
||||
public void refreshAndBindWidgetsAndShortcuts(
|
||||
final Callbacks callbacks, final boolean bindFirst) {
|
||||
runOnWorkerThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (bindFirst && !mBgWidgetsModel.isEmpty()) {
|
||||
bindWidgetsModel(callbacks, mBgWidgetsModel.clone());
|
||||
}
|
||||
final WidgetsModel model = mBgWidgetsModel.updateAndClone(mApp.getContext());
|
||||
bindWidgetsModel(callbacks, model);
|
||||
// update the Widget entries inside DB on the worker thread.
|
||||
LauncherAppState.getInstance().getWidgetCache().removeObsoletePreviews(
|
||||
model.getRawList());
|
||||
}
|
||||
if (sBgShortcutProviders != null) {
|
||||
widgetsAndShortcuts.addAll(sBgShortcutProviders);
|
||||
}
|
||||
}
|
||||
mBgWidgetsModel.setWidgetsAndShortcuts(widgetsAndShortcuts);
|
||||
mFgWidgetsModel = mBgWidgetsModel.clone();
|
||||
});
|
||||
}
|
||||
|
||||
@Thunk static boolean isPackageDisabled(Context context, String packageName,
|
||||
|
||||
@@ -403,7 +403,7 @@ public class LauncherStateTransitionAnimation {
|
||||
|
||||
// Animate the search bar
|
||||
final SearchDropTargetBar.State toSearchBarState =
|
||||
toWorkspaceState.getSearchDropTargetBarState();
|
||||
toWorkspaceState.searchDropTargetBarState;
|
||||
mLauncher.getSearchDropTargetBar().animateToState(toSearchBarState,
|
||||
animated ? revealDuration : 0, animation);
|
||||
|
||||
|
||||
@@ -145,6 +145,8 @@ public class Stats {
|
||||
LaunchSourceUtils.populateSourceDataFromAncestorProvider(v, sourceExtras);
|
||||
broadcastIntent.putExtra(EXTRA_SOURCE, sourceExtras);
|
||||
mLauncher.sendBroadcast(broadcastIntent, mLaunchBroadcastPermission);
|
||||
mLauncher.getLogger().logAppLaunch(intent.getComponent().getPackageName(), shortcut, sourceExtras);
|
||||
if (intent.getComponent() != null) {
|
||||
mLauncher.getLogger().logAppLaunch(intent.getComponent().getPackageName(), shortcut, sourceExtras);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,11 +52,11 @@ import android.view.View;
|
||||
import android.view.ViewDebug;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.launcher3.compat.AppWidgetManagerCompat;
|
||||
import com.android.launcher3.folder.Folder;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
import com.android.launcher3.Launcher.CustomContentCallbacks;
|
||||
@@ -179,22 +179,20 @@ public class Workspace extends PagedView
|
||||
// in all apps or customize mode)
|
||||
|
||||
enum State {
|
||||
NORMAL (SearchDropTargetBar.State.SEARCH_BAR),
|
||||
NORMAL_HIDDEN (SearchDropTargetBar.State.INVISIBLE_TRANSLATED),
|
||||
SPRING_LOADED (SearchDropTargetBar.State.DROP_TARGET),
|
||||
OVERVIEW (SearchDropTargetBar.State.INVISIBLE),
|
||||
OVERVIEW_HIDDEN (SearchDropTargetBar.State.INVISIBLE);
|
||||
NORMAL (SearchDropTargetBar.State.SEARCH_BAR, false),
|
||||
NORMAL_HIDDEN (SearchDropTargetBar.State.INVISIBLE_TRANSLATED, false),
|
||||
SPRING_LOADED (SearchDropTargetBar.State.DROP_TARGET, false),
|
||||
OVERVIEW (SearchDropTargetBar.State.INVISIBLE, true),
|
||||
OVERVIEW_HIDDEN (SearchDropTargetBar.State.INVISIBLE, true);
|
||||
|
||||
private final SearchDropTargetBar.State mBarState;
|
||||
public final SearchDropTargetBar.State searchDropTargetBarState;
|
||||
public final boolean shouldUpdateWidget;
|
||||
|
||||
State(SearchDropTargetBar.State searchBarState) {
|
||||
mBarState = searchBarState;
|
||||
State(SearchDropTargetBar.State searchBarState, boolean shouldUpdateWidget) {
|
||||
searchDropTargetBarState = searchBarState;
|
||||
this.shouldUpdateWidget = shouldUpdateWidget;
|
||||
}
|
||||
|
||||
public SearchDropTargetBar.State getSearchDropTargetBarState() {
|
||||
return mBarState;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private State mState = State.NORMAL;
|
||||
@@ -1914,6 +1912,8 @@ public class Workspace extends PagedView
|
||||
Animator workspaceAnim = mStateTransitionAnimation.getAnimationToState(mState,
|
||||
toState, animated, layerViews);
|
||||
|
||||
boolean shouldNotifyWidgetChange = !mState.shouldUpdateWidget
|
||||
&& toState.shouldUpdateWidget;
|
||||
// Update the current state
|
||||
mState = toState;
|
||||
updateAccessibilityFlags();
|
||||
@@ -1923,6 +1923,10 @@ public class Workspace extends PagedView
|
||||
invalidate(); // This will call dispatchDraw(), which calls getVisiblePages().
|
||||
}
|
||||
|
||||
if (shouldNotifyWidgetChange) {
|
||||
mLauncher.notifyWidgetProvidersChanged();
|
||||
}
|
||||
|
||||
return workspaceAnim;
|
||||
}
|
||||
|
||||
@@ -4148,13 +4152,22 @@ public class Workspace extends PagedView
|
||||
});
|
||||
}
|
||||
|
||||
void widgetsRestored(ArrayList<LauncherAppWidgetInfo> changedInfo) {
|
||||
public void widgetsRestored(ArrayList<LauncherAppWidgetInfo> changedInfo) {
|
||||
if (!changedInfo.isEmpty()) {
|
||||
DeferredWidgetRefresh widgetRefresh = new DeferredWidgetRefresh(changedInfo,
|
||||
mLauncher.getAppWidgetHost());
|
||||
if (LauncherModel.getProviderInfo(getContext(),
|
||||
changedInfo.get(0).providerName,
|
||||
changedInfo.get(0).user) != null) {
|
||||
|
||||
LauncherAppWidgetInfo item = changedInfo.get(0);
|
||||
final AppWidgetProviderInfo widgetInfo;
|
||||
if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) {
|
||||
widgetInfo = AppWidgetManagerCompat
|
||||
.getInstance(mLauncher).findProvider(item.providerName, item.user);
|
||||
} else {
|
||||
widgetInfo = AppWidgetManagerCompat.getInstance(mLauncher)
|
||||
.getAppWidgetInfo(item.appWidgetId);
|
||||
}
|
||||
|
||||
if (widgetInfo != null) {
|
||||
// Re-inflate the widgets which have changed status
|
||||
widgetRefresh.run();
|
||||
} else {
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.app.Activity;
|
||||
import android.appwidget.AppWidgetHost;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -28,7 +29,9 @@ import android.os.Bundle;
|
||||
import com.android.launcher3.IconCache;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class AppWidgetManagerCompat {
|
||||
@@ -62,6 +65,11 @@ public abstract class AppWidgetManagerCompat {
|
||||
return mAppWidgetManager.getAppWidgetInfo(appWidgetId);
|
||||
}
|
||||
|
||||
public LauncherAppWidgetProviderInfo getLauncherAppWidgetInfo(int appWidgetId) {
|
||||
AppWidgetProviderInfo info = getAppWidgetInfo(appWidgetId);
|
||||
return info == null ? null : LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
|
||||
}
|
||||
|
||||
public abstract List<AppWidgetProviderInfo> getAllProviders();
|
||||
|
||||
public abstract String loadLabel(LauncherAppWidgetProviderInfo info);
|
||||
@@ -81,4 +89,8 @@ public abstract class AppWidgetManagerCompat {
|
||||
public abstract Bitmap getBadgeBitmap(LauncherAppWidgetProviderInfo info, Bitmap bitmap,
|
||||
int imageWidth, int imageHeight);
|
||||
|
||||
public abstract LauncherAppWidgetProviderInfo findProvider(
|
||||
ComponentName provider, UserHandleCompat user);
|
||||
|
||||
public abstract HashMap<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.app.Activity;
|
||||
import android.appwidget.AppWidgetHost;
|
||||
import android.appwidget.AppWidgetManager;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
@@ -31,7 +32,9 @@ import android.os.Bundle;
|
||||
import com.android.launcher3.IconCache;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat {
|
||||
@@ -91,4 +94,25 @@ class AppWidgetManagerCompatV16 extends AppWidgetManagerCompat {
|
||||
int imageWidth, int imageHeight) {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LauncherAppWidgetProviderInfo findProvider(
|
||||
ComponentName provider, UserHandleCompat user) {
|
||||
for (AppWidgetProviderInfo info : mAppWidgetManager.getInstalledProviders()) {
|
||||
if (info.provider.equals(provider)) {
|
||||
return LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap() {
|
||||
HashMap<ComponentKey, AppWidgetProviderInfo> result = new HashMap<>();
|
||||
UserHandleCompat user = UserHandleCompat.myUserHandle();
|
||||
for (AppWidgetProviderInfo info : mAppWidgetManager.getInstalledProviders()) {
|
||||
result.put(new ComponentKey(info.provider, user), info);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.app.Activity;
|
||||
import android.appwidget.AppWidgetHost;
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
@@ -40,8 +41,10 @@ import android.widget.Toast;
|
||||
import com.android.launcher3.IconCache;
|
||||
import com.android.launcher3.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
@@ -145,4 +148,28 @@ class AppWidgetManagerCompatVL extends AppWidgetManagerCompat {
|
||||
c.setBitmap(null);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LauncherAppWidgetProviderInfo findProvider(ComponentName provider, UserHandleCompat user) {
|
||||
for (AppWidgetProviderInfo info : mAppWidgetManager
|
||||
.getInstalledProvidersForProfile(user.getUser())) {
|
||||
if (info.provider.equals(provider)) {
|
||||
return LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<ComponentKey, AppWidgetProviderInfo> getAllProvidersMap() {
|
||||
HashMap<ComponentKey, AppWidgetProviderInfo> result = new HashMap<>();
|
||||
for (UserHandle user : mUserManager.getUserProfiles()) {
|
||||
UserHandleCompat userHandle = UserHandleCompat.fromUser(user);
|
||||
for (AppWidgetProviderInfo info :
|
||||
mAppWidgetManager.getInstalledProvidersForProfile(user)) {
|
||||
result.put(new ComponentKey(info.provider, userHandle), info);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.backup.nano.BackupProtos;
|
||||
import com.android.launcher3.compat.AppWidgetManagerCompat;
|
||||
import com.android.launcher3.compat.PackageInstallerCompat;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.util.LongArrayMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -696,7 +696,8 @@ public class GridSizeMigrationTask {
|
||||
Favorites.SPANX, // 4
|
||||
Favorites.SPANY, // 5
|
||||
Favorites.INTENT, // 6
|
||||
Favorites.APPWIDGET_PROVIDER}, // 7
|
||||
Favorites.APPWIDGET_PROVIDER, // 7
|
||||
Favorites.APPWIDGET_ID}, // 8
|
||||
Favorites.CONTAINER + " = " + Favorites.CONTAINER_DESKTOP
|
||||
+ " AND " + Favorites.SCREEN + " = " + screen, null, null, null);
|
||||
|
||||
@@ -708,6 +709,7 @@ public class GridSizeMigrationTask {
|
||||
final int indexSpanY = c.getColumnIndexOrThrow(Favorites.SPANY);
|
||||
final int indexIntent = c.getColumnIndexOrThrow(Favorites.INTENT);
|
||||
final int indexAppWidgetProvider = c.getColumnIndexOrThrow(Favorites.APPWIDGET_PROVIDER);
|
||||
final int indexAppWidgetId = c.getColumnIndexOrThrow(Favorites.APPWIDGET_ID);
|
||||
|
||||
ArrayList<DbEntry> entries = new ArrayList<>();
|
||||
while (c.moveToNext()) {
|
||||
@@ -737,9 +739,9 @@ public class GridSizeMigrationTask {
|
||||
entry.weight = Math.max(WT_WIDGET_MIN, WT_WIDGET_FACTOR
|
||||
* entry.spanX * entry.spanY);
|
||||
|
||||
// Migration happens for current user only.
|
||||
LauncherAppWidgetProviderInfo pInfo = LauncherModel.getProviderInfo(
|
||||
mContext, cn, UserHandleCompat.myUserHandle());
|
||||
int widgetId = c.getInt(indexAppWidgetId);
|
||||
LauncherAppWidgetProviderInfo pInfo = AppWidgetManagerCompat.getInstance(
|
||||
mContext).getLauncherAppWidgetInfo(widgetId);
|
||||
Point spans = pInfo == null ?
|
||||
mWidgetMinSize.get(provider) : pInfo.getMinSpans(mIdp, mContext);
|
||||
if (spans != null) {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.os.DeadObjectException;
|
||||
import android.os.TransactionTooLargeException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.AppFilter;
|
||||
@@ -16,6 +20,7 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.compat.AlphabeticIndexCompat;
|
||||
import com.android.launcher3.compat.AppWidgetManagerCompat;
|
||||
import com.android.launcher3.compat.UserHandleCompat;
|
||||
import com.android.launcher3.config.ProviderConfig;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -95,8 +100,41 @@ public class WidgetsModel {
|
||||
return mRawList;
|
||||
}
|
||||
|
||||
public void setWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) {
|
||||
public boolean isEmpty() {
|
||||
return mRawList.isEmpty();
|
||||
}
|
||||
|
||||
public WidgetsModel updateAndClone(Context context) {
|
||||
Utilities.assertWorkerThread();
|
||||
|
||||
try {
|
||||
final ArrayList<Object> widgetsAndShortcuts = new ArrayList<>();
|
||||
// Widgets
|
||||
for (AppWidgetProviderInfo widgetInfo :
|
||||
AppWidgetManagerCompat.getInstance(context).getAllProviders()) {
|
||||
widgetsAndShortcuts.add(LauncherAppWidgetProviderInfo
|
||||
.fromProviderInfo(context, widgetInfo));
|
||||
}
|
||||
// Shortcuts
|
||||
widgetsAndShortcuts.addAll(context.getPackageManager().queryIntentActivities(
|
||||
new Intent(Intent.ACTION_CREATE_SHORTCUT), 0));
|
||||
setWidgetsAndShortcuts(widgetsAndShortcuts);
|
||||
} catch (Exception e) {
|
||||
if (!ProviderConfig.IS_DOGFOOD_BUILD &&
|
||||
(e.getCause() instanceof TransactionTooLargeException ||
|
||||
e.getCause() instanceof DeadObjectException)) {
|
||||
// the returned value may be incomplete and will not be refreshed until the next
|
||||
// time Launcher starts.
|
||||
// TODO: after figuring out a repro step, introduce a dirty bit to check when
|
||||
// onResume is called to refresh the widget provider list.
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
return clone();
|
||||
}
|
||||
|
||||
private void setWidgetsAndShortcuts(ArrayList<Object> rawWidgetsShortcuts) {
|
||||
mRawList = rawWidgetsShortcuts;
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "addWidgetsAndShortcuts, widgetsShortcuts#=" + rawWidgetsShortcuts.size());
|
||||
|
||||
@@ -327,6 +327,10 @@ public class WidgetsContainerView extends BaseContainerView
|
||||
mAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return mAdapter.getItemCount() == 0;
|
||||
}
|
||||
|
||||
private WidgetPreviewLoader getWidgetPreviewLoader() {
|
||||
if (mWidgetPreviewLoader == null) {
|
||||
mWidgetPreviewLoader = LauncherAppState.getInstance().getWidgetCache();
|
||||
|
||||
Reference in New Issue
Block a user