Loading src/com/android/launcher3/LauncherAppState.java +3 −2 Original line number Diff line number Diff line Loading @@ -81,6 +81,8 @@ public class LauncherAppState { public LauncherAppState(Context context) { this(context, LauncherFiles.APP_ICONS_DB); Log.v(Launcher.TAG, "LauncherAppState initiated"); Preconditions.assertUIThread(); mInvariantDeviceProfile.addOnChangeListener(idp -> refreshAndReloadLauncher()); Loading Loading @@ -132,8 +134,6 @@ public class LauncherAppState { } public LauncherAppState(Context context, @Nullable String iconCacheFileName) { Log.v(Launcher.TAG, "LauncherAppState initiated"); Preconditions.assertUIThread(); mContext = context; mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(context); Loading @@ -142,6 +142,7 @@ public class LauncherAppState { iconCacheFileName, mIconProvider); mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache); mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext)); mOnTerminateCallback.add(mIconCache::close); } private void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) { Loading src/com/android/launcher3/graphics/GridCustomizationsProvider.java +82 −2 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import static com.android.launcher3.Utilities.getPrefs; import static com.android.launcher3.util.Themes.KEY_THEMED_ICONS; import static com.android.launcher3.util.Themes.isThemedIconEnabled; import android.annotation.TargetApi; import android.content.ContentProvider; import android.content.ContentValues; import android.content.pm.PackageManager; Loading @@ -12,14 +13,24 @@ import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.util.ArrayMap; import android.util.Log; import android.util.Xml; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.InvariantDeviceProfile.GridOption; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.Executors; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; Loading Loading @@ -65,6 +76,11 @@ public class GridCustomizationsProvider extends ContentProvider { private static final String ICON_THEMED = "/icon_themed"; private static final String BOOLEAN_VALUE = "boolean_value"; private static final String KEY_SURFACE_PACKAGE = "surface_package"; private static final String KEY_CALLBACK = "callback"; private final ArrayMap<IBinder, PreviewLifecycleObserver> mActivePreviews = new ArrayMap<>(); @Override public boolean onCreate() { return true; Loading Loading @@ -177,10 +193,74 @@ public class GridCustomizationsProvider extends ContentProvider { return null; } if (!METHOD_GET_PREVIEW.equals(method)) { if (!Utilities.ATLEAST_R || !METHOD_GET_PREVIEW.equals(method)) { return null; } return getPreview(extras); } @TargetApi(Build.VERSION_CODES.R) private synchronized Bundle getPreview(Bundle request) { PreviewLifecycleObserver observer = null; try { PreviewSurfaceRenderer renderer = new PreviewSurfaceRenderer(getContext(), request); // Destroy previous destroyObserver(mActivePreviews.get(renderer.getHostToken())); observer = new PreviewLifecycleObserver(renderer); mActivePreviews.put(renderer.getHostToken(), observer); renderer.loadAsync(); renderer.getHostToken().linkToDeath(observer, 0); Bundle result = new Bundle(); result.putParcelable(KEY_SURFACE_PACKAGE, renderer.getSurfacePackage()); Messenger messenger = new Messenger(new Handler(Looper.getMainLooper(), observer)); Message msg = Message.obtain(); msg.replyTo = messenger; result.putParcelable(KEY_CALLBACK, msg); return result; } catch (Exception e) { Log.e(TAG, "Unable to generate preview", e); if (observer != null) { destroyObserver(observer); } return null; } } return new PreviewSurfaceRenderer(getContext(), extras).render(); private synchronized void destroyObserver(PreviewLifecycleObserver observer) { if (observer == null || observer.destroyed) { return; } observer.destroyed = true; Executors.MAIN_EXECUTOR.execute(observer.renderer::destroy); PreviewLifecycleObserver cached = mActivePreviews.get(observer.renderer.getHostToken()); if (cached == observer) { mActivePreviews.remove(observer.renderer.getHostToken()); } } private class PreviewLifecycleObserver implements Handler.Callback, DeathRecipient { public final PreviewSurfaceRenderer renderer; public boolean destroyed = false; PreviewLifecycleObserver(PreviewSurfaceRenderer renderer) { this.renderer = renderer; } @Override public boolean handleMessage(Message message) { destroyObserver(this); return true; } @Override public void binderDied() { destroyObserver(this); } } } src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +28 −172 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks; import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.annotation.TargetApi; import android.app.Fragment; Loading @@ -32,7 +31,6 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ShortcutInfo; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; Loading @@ -43,7 +41,6 @@ import android.os.Handler; import android.os.Looper; import android.os.Process; import android.util.AttributeSet; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; Loading @@ -57,8 +54,6 @@ import com.android.launcher3.Hotseat; import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.R; import com.android.launcher3.WorkspaceLayoutManager; Loading @@ -67,13 +62,8 @@ import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.AllAppsList; import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.LoaderResults; import com.android.launcher3.model.LoaderTask; import com.android.launcher3.model.ModelDelegate; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.model.data.FolderInfo; Loading @@ -100,13 +90,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * Utility class for generating the preview of Launcher for a given InvariantDeviceProfile. Loading @@ -120,8 +104,6 @@ import java.util.concurrent.TimeoutException; public class LauncherPreviewRenderer extends ContextWrapper implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 { private static final String TAG = "LauncherPreviewRenderer"; /** * Context used just for preview. It also provides a few objects (e.g. UserCache) just for * preview purposes. Loading @@ -138,9 +120,15 @@ public class LauncherPreviewRenderer extends ContextWrapper private final ConcurrentLinkedQueue<LauncherIconsForPreview> mIconPool = new ConcurrentLinkedQueue<>(); private boolean mDestroyed = false; public PreviewContext(Context base, InvariantDeviceProfile idp) { super(base); mIdp = idp; mObjectMap.put(InvariantDeviceProfile.INSTANCE, idp); mObjectMap.put(LauncherAppState.INSTANCE, new LauncherAppState(this, null /* iconCacheFileName */)); } @Override Loading @@ -149,11 +137,9 @@ public class LauncherPreviewRenderer extends ContextWrapper } public void onDestroy() { CustomWidgetManager customWidgetManager = (CustomWidgetManager) mObjectMap.get( CustomWidgetManager.INSTANCE); if (customWidgetManager != null) { customWidgetManager.onDestroy(); } CustomWidgetManager.INSTANCE.get(this).onDestroy(); LauncherAppState.INSTANCE.get(this).onTerminate(); mDestroyed = true; } /** Loading @@ -162,17 +148,12 @@ public class LauncherPreviewRenderer extends ContextWrapper */ public <T> T getObject(MainThreadInitializedObject<T> mainThreadInitializedObject, MainThreadInitializedObject.ObjectProvider<T> provider) { if (FeatureFlags.IS_STUDIO_BUILD && mDestroyed) { throw new RuntimeException("Context already destroyed"); } if (!mAllowedObjects.contains(mainThreadInitializedObject)) { throw new IllegalStateException("Leaking unknown objects"); } if (mainThreadInitializedObject == LauncherAppState.INSTANCE) { throw new IllegalStateException( "Should not use MainThreadInitializedObject to initialize this with " + "PreviewContext"); } if (mainThreadInitializedObject == InvariantDeviceProfile.INSTANCE) { return (T) mIdp; } if (mObjectMap.containsKey(mainThreadInitializedObject)) { return (T) mObjectMap.get(mainThreadInitializedObject); } Loading Loading @@ -210,7 +191,6 @@ public class LauncherPreviewRenderer extends ContextWrapper private final Context mContext; private final InvariantDeviceProfile mIdp; private final DeviceProfile mDp; private final boolean mMigrated; private final Rect mInsets; private final WorkspaceItemInfo mWorkspaceItemInfo; private final LayoutInflater mHomeElementInflater; Loading @@ -218,13 +198,12 @@ public class LauncherPreviewRenderer extends ContextWrapper private final Hotseat mHotseat; private final CellLayout mWorkspace; public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) { public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp) { super(context); mUiHandler = new Handler(Looper.getMainLooper()); mContext = context; mIdp = idp; mDp = idp.getDeviceProfile(context).copy(context); mMigrated = migrated; // TODO: get correct insets once display cutout API is available. mInsets = new Rect(); Loading Loading @@ -265,8 +244,9 @@ public class LauncherPreviewRenderer extends ContextWrapper } /** Populate preview and render it. */ public View getRenderedView() { populate(); public View getRenderedView(BgDataModel dataModel, Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) { populate(dataModel, widgetProviderInfoMap); return mRootView; } Loading Loading @@ -392,38 +372,17 @@ public class LauncherPreviewRenderer extends ContextWrapper } } private void populate() { WorkspaceFetcher fetcher; PreviewContext previewContext = null; if (mMigrated) { previewContext = new PreviewContext(mContext, mIdp); LauncherAppState appForPreview = new LauncherAppState( previewContext, null /* iconCacheFileName */); fetcher = new WorkspaceItemsInfoFromPreviewFetcher(appForPreview); MODEL_EXECUTOR.execute(fetcher); } else { fetcher = new WorkspaceItemsInfoFetcher(); LauncherAppState.getInstance(mContext).getModel().enqueueModelUpdateTask( (LauncherModel.ModelUpdateTask) fetcher); } WorkspaceResult workspaceResult = fetcher.get(); if (previewContext != null) { previewContext.onDestroy(); } if (workspaceResult == null) { return; } private void populate(BgDataModel dataModel, Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) { // Separate the items that are on the current screen, and the other remaining items. ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>(); ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>(); ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<>(); ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<>(); filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceResult.mWorkspaceItems, currentWorkspaceItems, dataModel.workspaceItems, currentWorkspaceItems, otherWorkspaceItems); filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceResult.mAppWidgets, filterCurrentWorkspaceItems(0 /* currentScreenId */, dataModel.appWidgets, currentAppWidgets, otherAppWidgets); sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems); for (ItemInfo itemInfo : currentWorkspaceItems) { Loading @@ -444,12 +403,12 @@ public class LauncherPreviewRenderer extends ContextWrapper switch (itemInfo.itemType) { case Favorites.ITEM_TYPE_APPWIDGET: case Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: if (mMigrated) { inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo, workspaceResult.mWidgetProvidersMap); if (widgetProviderInfoMap != null) { inflateAndAddWidgets( (LauncherAppWidgetInfo) itemInfo, widgetProviderInfoMap); } else { inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo, workspaceResult.mWidgetsModel); dataModel.widgetsModel); } break; default: Loading @@ -458,8 +417,10 @@ public class LauncherPreviewRenderer extends ContextWrapper } IntArray ranks = getMissingHotseatRanks(currentWorkspaceItems, mDp.numShownHotseatIcons); List<ItemInfo> predictions = workspaceResult.mHotseatPredictions == null ? Collections.emptyList() : workspaceResult.mHotseatPredictions.items; FixedContainerItems hotseatpredictions = dataModel.extraItems.get(CONTAINER_HOTSEAT_PREDICTION); List<ItemInfo> predictions = hotseatpredictions == null ? Collections.emptyList() : hotseatpredictions.items; int count = Math.min(ranks.size(), predictions.size()); for (int i = 0; i < count; i++) { int rank = ranks.get(i); Loading Loading @@ -494,109 +455,4 @@ public class LauncherPreviewRenderer extends ContextWrapper view.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY)); view.layout(0, 0, width, height); } private static class WorkspaceItemsInfoFetcher implements LauncherModel.ModelUpdateTask, WorkspaceFetcher { private final FutureTask<WorkspaceResult> mTask = new FutureTask<>(this); private LauncherAppState mApp; private LauncherModel mModel; private BgDataModel mBgDataModel; private AllAppsList mAllAppsList; @Override public void init(LauncherAppState app, LauncherModel model, BgDataModel dataModel, AllAppsList allAppsList, Executor uiExecutor) { mApp = app; mModel = model; mBgDataModel = dataModel; mAllAppsList = allAppsList; } @Override public FutureTask<WorkspaceResult> getTask() { return mTask; } @Override public void run() { mTask.run(); } @Override public WorkspaceResult call() throws Exception { if (!mModel.isModelLoaded()) { Log.d(TAG, "Workspace not loaded, loading now"); mModel.startLoaderForResults( new LoaderResults(mApp, mBgDataModel, mAllAppsList, new Callbacks[0])); return null; } return new WorkspaceResult(mBgDataModel, mBgDataModel.widgetsModel, null); } } private static class WorkspaceItemsInfoFromPreviewFetcher extends LoaderTask implements WorkspaceFetcher { private final FutureTask<WorkspaceResult> mTask = new FutureTask<>(this); WorkspaceItemsInfoFromPreviewFetcher(LauncherAppState app) { super(app, null, new BgDataModel(), new ModelDelegate(), null); } @Override public FutureTask<WorkspaceResult> getTask() { return mTask; } @Override public void run() { mTask.run(); } @Override public WorkspaceResult call() { List<ShortcutInfo> allShortcuts = new ArrayList<>(); loadWorkspace(allShortcuts, LauncherSettings.Favorites.PREVIEW_CONTENT_URI, LauncherSettings.Favorites.SCREEN + " = 0 or " + LauncherSettings.Favorites.CONTAINER + " = " + LauncherSettings.Favorites.CONTAINER_HOTSEAT); return new WorkspaceResult(mBgDataModel, null, mWidgetProvidersMap); } } private interface WorkspaceFetcher extends Runnable, Callable<WorkspaceResult> { FutureTask<WorkspaceResult> getTask(); default WorkspaceResult get() { try { return getTask().get(5, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { Log.d(TAG, "Error fetching workspace items info", e); return null; } } } private static class WorkspaceResult { private final ArrayList<ItemInfo> mWorkspaceItems; private final ArrayList<LauncherAppWidgetInfo> mAppWidgets; private final FixedContainerItems mHotseatPredictions; private final WidgetsModel mWidgetsModel; private final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap; private WorkspaceResult(BgDataModel dataModel, WidgetsModel widgetsModel, Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) { synchronized (dataModel) { mWorkspaceItems = dataModel.workspaceItems; mAppWidgets = dataModel.appWidgets; mHotseatPredictions = dataModel.extraItems.get(CONTAINER_HOTSEAT_PREDICTION); mWidgetsModel = widgetsModel; mWidgetProvidersMap = widgetProviderInfoMap; } } } } src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +125 −93 File changed.Preview size limit exceeded, changes collapsed. Show changes src/com/android/launcher3/icons/IconCache.java +7 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,13 @@ public class IconCache extends BaseIconCache { } } /** * Closes the cache DB. This will clear any in-memory cache. */ public void close() { mIconDb.close(); } /** * Fetches high-res icon for the provided ItemInfo and updates the caller when done. * Loading Loading
src/com/android/launcher3/LauncherAppState.java +3 −2 Original line number Diff line number Diff line Loading @@ -81,6 +81,8 @@ public class LauncherAppState { public LauncherAppState(Context context) { this(context, LauncherFiles.APP_ICONS_DB); Log.v(Launcher.TAG, "LauncherAppState initiated"); Preconditions.assertUIThread(); mInvariantDeviceProfile.addOnChangeListener(idp -> refreshAndReloadLauncher()); Loading Loading @@ -132,8 +134,6 @@ public class LauncherAppState { } public LauncherAppState(Context context, @Nullable String iconCacheFileName) { Log.v(Launcher.TAG, "LauncherAppState initiated"); Preconditions.assertUIThread(); mContext = context; mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(context); Loading @@ -142,6 +142,7 @@ public class LauncherAppState { iconCacheFileName, mIconProvider); mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache); mModel = new LauncherModel(context, this, mIconCache, new AppFilter(mContext)); mOnTerminateCallback.add(mIconCache::close); } private void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) { Loading
src/com/android/launcher3/graphics/GridCustomizationsProvider.java +82 −2 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ import static com.android.launcher3.Utilities.getPrefs; import static com.android.launcher3.util.Themes.KEY_THEMED_ICONS; import static com.android.launcher3.util.Themes.isThemedIconEnabled; import android.annotation.TargetApi; import android.content.ContentProvider; import android.content.ContentValues; import android.content.pm.PackageManager; Loading @@ -12,14 +13,24 @@ import android.database.Cursor; import android.database.MatrixCursor; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.Looper; import android.os.Message; import android.os.Messenger; import android.util.ArrayMap; import android.util.Log; import android.util.Xml; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.InvariantDeviceProfile.GridOption; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.util.Executors; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; Loading Loading @@ -65,6 +76,11 @@ public class GridCustomizationsProvider extends ContentProvider { private static final String ICON_THEMED = "/icon_themed"; private static final String BOOLEAN_VALUE = "boolean_value"; private static final String KEY_SURFACE_PACKAGE = "surface_package"; private static final String KEY_CALLBACK = "callback"; private final ArrayMap<IBinder, PreviewLifecycleObserver> mActivePreviews = new ArrayMap<>(); @Override public boolean onCreate() { return true; Loading Loading @@ -177,10 +193,74 @@ public class GridCustomizationsProvider extends ContentProvider { return null; } if (!METHOD_GET_PREVIEW.equals(method)) { if (!Utilities.ATLEAST_R || !METHOD_GET_PREVIEW.equals(method)) { return null; } return getPreview(extras); } @TargetApi(Build.VERSION_CODES.R) private synchronized Bundle getPreview(Bundle request) { PreviewLifecycleObserver observer = null; try { PreviewSurfaceRenderer renderer = new PreviewSurfaceRenderer(getContext(), request); // Destroy previous destroyObserver(mActivePreviews.get(renderer.getHostToken())); observer = new PreviewLifecycleObserver(renderer); mActivePreviews.put(renderer.getHostToken(), observer); renderer.loadAsync(); renderer.getHostToken().linkToDeath(observer, 0); Bundle result = new Bundle(); result.putParcelable(KEY_SURFACE_PACKAGE, renderer.getSurfacePackage()); Messenger messenger = new Messenger(new Handler(Looper.getMainLooper(), observer)); Message msg = Message.obtain(); msg.replyTo = messenger; result.putParcelable(KEY_CALLBACK, msg); return result; } catch (Exception e) { Log.e(TAG, "Unable to generate preview", e); if (observer != null) { destroyObserver(observer); } return null; } } return new PreviewSurfaceRenderer(getContext(), extras).render(); private synchronized void destroyObserver(PreviewLifecycleObserver observer) { if (observer == null || observer.destroyed) { return; } observer.destroyed = true; Executors.MAIN_EXECUTOR.execute(observer.renderer::destroy); PreviewLifecycleObserver cached = mActivePreviews.get(observer.renderer.getHostToken()); if (cached == observer) { mActivePreviews.remove(observer.renderer.getHostToken()); } } private class PreviewLifecycleObserver implements Handler.Callback, DeathRecipient { public final PreviewSurfaceRenderer renderer; public boolean destroyed = false; PreviewLifecycleObserver(PreviewSurfaceRenderer renderer) { this.renderer = renderer; } @Override public boolean handleMessage(Message message) { destroyObserver(this); return true; } @Override public void binderDied() { destroyObserver(this); } } }
src/com/android/launcher3/graphics/LauncherPreviewRenderer.java +28 −172 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT import static com.android.launcher3.model.ModelUtils.filterCurrentWorkspaceItems; import static com.android.launcher3.model.ModelUtils.getMissingHotseatRanks; import static com.android.launcher3.model.ModelUtils.sortWorkspaceItemsSpatially; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; import android.annotation.TargetApi; import android.app.Fragment; Loading @@ -32,7 +31,6 @@ import android.appwidget.AppWidgetProviderInfo; import android.content.Context; import android.content.ContextWrapper; import android.content.Intent; import android.content.pm.ShortcutInfo; import android.content.res.TypedArray; import android.graphics.Color; import android.graphics.Rect; Loading @@ -43,7 +41,6 @@ import android.os.Handler; import android.os.Looper; import android.os.Process; import android.util.AttributeSet; import android.util.Log; import android.view.ContextThemeWrapper; import android.view.LayoutInflater; import android.view.View; Loading @@ -57,8 +54,6 @@ import com.android.launcher3.Hotseat; import com.android.launcher3.InsettableFrameLayout; import com.android.launcher3.InvariantDeviceProfile; import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherModel; import com.android.launcher3.LauncherSettings; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.R; import com.android.launcher3.WorkspaceLayoutManager; Loading @@ -67,13 +62,8 @@ import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.BitmapInfo; import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.AllAppsList; import com.android.launcher3.model.BgDataModel; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.BgDataModel.FixedContainerItems; import com.android.launcher3.model.LoaderResults; import com.android.launcher3.model.LoaderTask; import com.android.launcher3.model.ModelDelegate; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.model.data.FolderInfo; Loading @@ -100,13 +90,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.FutureTask; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; /** * Utility class for generating the preview of Launcher for a given InvariantDeviceProfile. Loading @@ -120,8 +104,6 @@ import java.util.concurrent.TimeoutException; public class LauncherPreviewRenderer extends ContextWrapper implements ActivityContext, WorkspaceLayoutManager, LayoutInflater.Factory2 { private static final String TAG = "LauncherPreviewRenderer"; /** * Context used just for preview. It also provides a few objects (e.g. UserCache) just for * preview purposes. Loading @@ -138,9 +120,15 @@ public class LauncherPreviewRenderer extends ContextWrapper private final ConcurrentLinkedQueue<LauncherIconsForPreview> mIconPool = new ConcurrentLinkedQueue<>(); private boolean mDestroyed = false; public PreviewContext(Context base, InvariantDeviceProfile idp) { super(base); mIdp = idp; mObjectMap.put(InvariantDeviceProfile.INSTANCE, idp); mObjectMap.put(LauncherAppState.INSTANCE, new LauncherAppState(this, null /* iconCacheFileName */)); } @Override Loading @@ -149,11 +137,9 @@ public class LauncherPreviewRenderer extends ContextWrapper } public void onDestroy() { CustomWidgetManager customWidgetManager = (CustomWidgetManager) mObjectMap.get( CustomWidgetManager.INSTANCE); if (customWidgetManager != null) { customWidgetManager.onDestroy(); } CustomWidgetManager.INSTANCE.get(this).onDestroy(); LauncherAppState.INSTANCE.get(this).onTerminate(); mDestroyed = true; } /** Loading @@ -162,17 +148,12 @@ public class LauncherPreviewRenderer extends ContextWrapper */ public <T> T getObject(MainThreadInitializedObject<T> mainThreadInitializedObject, MainThreadInitializedObject.ObjectProvider<T> provider) { if (FeatureFlags.IS_STUDIO_BUILD && mDestroyed) { throw new RuntimeException("Context already destroyed"); } if (!mAllowedObjects.contains(mainThreadInitializedObject)) { throw new IllegalStateException("Leaking unknown objects"); } if (mainThreadInitializedObject == LauncherAppState.INSTANCE) { throw new IllegalStateException( "Should not use MainThreadInitializedObject to initialize this with " + "PreviewContext"); } if (mainThreadInitializedObject == InvariantDeviceProfile.INSTANCE) { return (T) mIdp; } if (mObjectMap.containsKey(mainThreadInitializedObject)) { return (T) mObjectMap.get(mainThreadInitializedObject); } Loading Loading @@ -210,7 +191,6 @@ public class LauncherPreviewRenderer extends ContextWrapper private final Context mContext; private final InvariantDeviceProfile mIdp; private final DeviceProfile mDp; private final boolean mMigrated; private final Rect mInsets; private final WorkspaceItemInfo mWorkspaceItemInfo; private final LayoutInflater mHomeElementInflater; Loading @@ -218,13 +198,12 @@ public class LauncherPreviewRenderer extends ContextWrapper private final Hotseat mHotseat; private final CellLayout mWorkspace; public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp, boolean migrated) { public LauncherPreviewRenderer(Context context, InvariantDeviceProfile idp) { super(context); mUiHandler = new Handler(Looper.getMainLooper()); mContext = context; mIdp = idp; mDp = idp.getDeviceProfile(context).copy(context); mMigrated = migrated; // TODO: get correct insets once display cutout API is available. mInsets = new Rect(); Loading Loading @@ -265,8 +244,9 @@ public class LauncherPreviewRenderer extends ContextWrapper } /** Populate preview and render it. */ public View getRenderedView() { populate(); public View getRenderedView(BgDataModel dataModel, Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) { populate(dataModel, widgetProviderInfoMap); return mRootView; } Loading Loading @@ -392,38 +372,17 @@ public class LauncherPreviewRenderer extends ContextWrapper } } private void populate() { WorkspaceFetcher fetcher; PreviewContext previewContext = null; if (mMigrated) { previewContext = new PreviewContext(mContext, mIdp); LauncherAppState appForPreview = new LauncherAppState( previewContext, null /* iconCacheFileName */); fetcher = new WorkspaceItemsInfoFromPreviewFetcher(appForPreview); MODEL_EXECUTOR.execute(fetcher); } else { fetcher = new WorkspaceItemsInfoFetcher(); LauncherAppState.getInstance(mContext).getModel().enqueueModelUpdateTask( (LauncherModel.ModelUpdateTask) fetcher); } WorkspaceResult workspaceResult = fetcher.get(); if (previewContext != null) { previewContext.onDestroy(); } if (workspaceResult == null) { return; } private void populate(BgDataModel dataModel, Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) { // Separate the items that are on the current screen, and the other remaining items. ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>(); ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>(); ArrayList<LauncherAppWidgetInfo> currentAppWidgets = new ArrayList<>(); ArrayList<LauncherAppWidgetInfo> otherAppWidgets = new ArrayList<>(); filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceResult.mWorkspaceItems, currentWorkspaceItems, dataModel.workspaceItems, currentWorkspaceItems, otherWorkspaceItems); filterCurrentWorkspaceItems(0 /* currentScreenId */, workspaceResult.mAppWidgets, filterCurrentWorkspaceItems(0 /* currentScreenId */, dataModel.appWidgets, currentAppWidgets, otherAppWidgets); sortWorkspaceItemsSpatially(mIdp, currentWorkspaceItems); for (ItemInfo itemInfo : currentWorkspaceItems) { Loading @@ -444,12 +403,12 @@ public class LauncherPreviewRenderer extends ContextWrapper switch (itemInfo.itemType) { case Favorites.ITEM_TYPE_APPWIDGET: case Favorites.ITEM_TYPE_CUSTOM_APPWIDGET: if (mMigrated) { inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo, workspaceResult.mWidgetProvidersMap); if (widgetProviderInfoMap != null) { inflateAndAddWidgets( (LauncherAppWidgetInfo) itemInfo, widgetProviderInfoMap); } else { inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo, workspaceResult.mWidgetsModel); dataModel.widgetsModel); } break; default: Loading @@ -458,8 +417,10 @@ public class LauncherPreviewRenderer extends ContextWrapper } IntArray ranks = getMissingHotseatRanks(currentWorkspaceItems, mDp.numShownHotseatIcons); List<ItemInfo> predictions = workspaceResult.mHotseatPredictions == null ? Collections.emptyList() : workspaceResult.mHotseatPredictions.items; FixedContainerItems hotseatpredictions = dataModel.extraItems.get(CONTAINER_HOTSEAT_PREDICTION); List<ItemInfo> predictions = hotseatpredictions == null ? Collections.emptyList() : hotseatpredictions.items; int count = Math.min(ranks.size(), predictions.size()); for (int i = 0; i < count; i++) { int rank = ranks.get(i); Loading Loading @@ -494,109 +455,4 @@ public class LauncherPreviewRenderer extends ContextWrapper view.measure(makeMeasureSpec(width, EXACTLY), makeMeasureSpec(height, EXACTLY)); view.layout(0, 0, width, height); } private static class WorkspaceItemsInfoFetcher implements LauncherModel.ModelUpdateTask, WorkspaceFetcher { private final FutureTask<WorkspaceResult> mTask = new FutureTask<>(this); private LauncherAppState mApp; private LauncherModel mModel; private BgDataModel mBgDataModel; private AllAppsList mAllAppsList; @Override public void init(LauncherAppState app, LauncherModel model, BgDataModel dataModel, AllAppsList allAppsList, Executor uiExecutor) { mApp = app; mModel = model; mBgDataModel = dataModel; mAllAppsList = allAppsList; } @Override public FutureTask<WorkspaceResult> getTask() { return mTask; } @Override public void run() { mTask.run(); } @Override public WorkspaceResult call() throws Exception { if (!mModel.isModelLoaded()) { Log.d(TAG, "Workspace not loaded, loading now"); mModel.startLoaderForResults( new LoaderResults(mApp, mBgDataModel, mAllAppsList, new Callbacks[0])); return null; } return new WorkspaceResult(mBgDataModel, mBgDataModel.widgetsModel, null); } } private static class WorkspaceItemsInfoFromPreviewFetcher extends LoaderTask implements WorkspaceFetcher { private final FutureTask<WorkspaceResult> mTask = new FutureTask<>(this); WorkspaceItemsInfoFromPreviewFetcher(LauncherAppState app) { super(app, null, new BgDataModel(), new ModelDelegate(), null); } @Override public FutureTask<WorkspaceResult> getTask() { return mTask; } @Override public void run() { mTask.run(); } @Override public WorkspaceResult call() { List<ShortcutInfo> allShortcuts = new ArrayList<>(); loadWorkspace(allShortcuts, LauncherSettings.Favorites.PREVIEW_CONTENT_URI, LauncherSettings.Favorites.SCREEN + " = 0 or " + LauncherSettings.Favorites.CONTAINER + " = " + LauncherSettings.Favorites.CONTAINER_HOTSEAT); return new WorkspaceResult(mBgDataModel, null, mWidgetProvidersMap); } } private interface WorkspaceFetcher extends Runnable, Callable<WorkspaceResult> { FutureTask<WorkspaceResult> getTask(); default WorkspaceResult get() { try { return getTask().get(5, TimeUnit.SECONDS); } catch (InterruptedException | ExecutionException | TimeoutException e) { Log.d(TAG, "Error fetching workspace items info", e); return null; } } } private static class WorkspaceResult { private final ArrayList<ItemInfo> mWorkspaceItems; private final ArrayList<LauncherAppWidgetInfo> mAppWidgets; private final FixedContainerItems mHotseatPredictions; private final WidgetsModel mWidgetsModel; private final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap; private WorkspaceResult(BgDataModel dataModel, WidgetsModel widgetsModel, Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) { synchronized (dataModel) { mWorkspaceItems = dataModel.workspaceItems; mAppWidgets = dataModel.appWidgets; mHotseatPredictions = dataModel.extraItems.get(CONTAINER_HOTSEAT_PREDICTION); mWidgetsModel = widgetsModel; mWidgetProvidersMap = widgetProviderInfoMap; } } } }
src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java +125 −93 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/com/android/launcher3/icons/IconCache.java +7 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,13 @@ public class IconCache extends BaseIconCache { } } /** * Closes the cache DB. This will clear any in-memory cache. */ public void close() { mIconDb.close(); } /** * Fetches high-res icon for the provided ItemInfo and updates the caller when done. * Loading