Loading src/com/android/launcher3/LauncherAppState.java +1 −1 Original line number Diff line number Diff line Loading @@ -176,7 +176,7 @@ public class LauncherAppState implements SafeCloseable { () -> LauncherPrefs.get(mContext).removeListener(observer, THEMED_ICONS)); InstallSessionTracker installSessionTracker = InstallSessionHelper.INSTANCE.get(context).registerInstallTracker(mModel); InstallSessionHelper.INSTANCE.get(context).registerInstallTracker(callbacks); mOnTerminateCallback.add(installSessionTracker::unregister); }); Loading src/com/android/launcher3/LauncherModel.kt +54 −156 Original line number Diff line number Diff line Loading @@ -16,10 +16,8 @@ package com.android.launcher3 import android.app.admin.DevicePolicyManager import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageInstaller import android.content.pm.ShortcutInfo import android.os.UserHandle import android.text.TextUtils Loading @@ -29,7 +27,6 @@ import androidx.annotation.WorkerThread import com.android.launcher3.celllayout.CellPosMapper import com.android.launcher3.config.FeatureFlags import com.android.launcher3.icons.IconCache import com.android.launcher3.icons.cache.BaseIconCache import com.android.launcher3.model.AddWorkspaceItemsTask import com.android.launcher3.model.AllAppsList import com.android.launcher3.model.BaseLauncherBinder Loading @@ -42,23 +39,17 @@ import com.android.launcher3.model.ModelDelegate import com.android.launcher3.model.ModelLauncherCallbacks import com.android.launcher3.model.ModelTaskController import com.android.launcher3.model.ModelWriter import com.android.launcher3.model.PackageInstallStateChangedTask import com.android.launcher3.model.PackageUpdatedTask import com.android.launcher3.model.ReloadStringCacheTask import com.android.launcher3.model.ShortcutsChangedTask import com.android.launcher3.model.UserLockStateChangedTask import com.android.launcher3.model.data.ItemInfo import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.pm.InstallSessionTracker import com.android.launcher3.pm.PackageInstallInfo import com.android.launcher3.pm.UserCache import com.android.launcher3.shortcuts.ShortcutRequest import com.android.launcher3.testing.shared.TestProtocol.sDebugTracing import com.android.launcher3.util.ApplicationInfoWrapper import com.android.launcher3.util.Executors.MAIN_EXECUTOR import com.android.launcher3.util.Executors.MODEL_EXECUTOR import com.android.launcher3.util.IntSet import com.android.launcher3.util.ItemInfoMatcher import com.android.launcher3.util.PackageManagerHelper import com.android.launcher3.util.PackageUserKey import com.android.launcher3.util.Preconditions Loading @@ -66,7 +57,6 @@ import java.io.FileDescriptor import java.io.PrintWriter import java.util.concurrent.CancellationException import java.util.function.Consumer import java.util.function.Supplier /** * Maintains in-memory state of the Launcher. It is expected that there should be only one Loading @@ -80,7 +70,7 @@ class LauncherModel( private val appFilter: AppFilter, private val mPmHelper: PackageManagerHelper, isPrimaryInstance: Boolean, ) : InstallSessionTracker.Callback { ) { private val mCallbacksList = ArrayList<BgDataModel.Callbacks>(1) Loading Loading @@ -156,10 +146,10 @@ class LauncherModel( fun onAppIconChanged(packageName: String, user: UserHandle) { // Update the icon for the calendar package enqueueModelUpdateTask(PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE, user, packageName)) val pinnedShortcuts: List<ShortcutInfo> = ShortcutRequest(context, user).forPackage(packageName).query(ShortcutRequest.PINNED) if (pinnedShortcuts.isNotEmpty()) { enqueueModelUpdateTask(ShortcutsChangedTask(packageName, pinnedShortcuts, user, false)) ShortcutRequest(context, user).forPackage(packageName).query(ShortcutRequest.PINNED).let { if (it.isNotEmpty()) { enqueueModelUpdateTask(ShortcutsChangedTask(packageName, it, user, false)) } } } Loading @@ -176,14 +166,13 @@ class LauncherModel( fun onBroadcastIntent(intent: Intent) { if (DEBUG_RECEIVER || sDebugTracing) Log.d(TAG, "onReceive intent=$intent") val action = intent.action if (Intent.ACTION_LOCALE_CHANGED == action) { when (intent.action) { Intent.ACTION_LOCALE_CHANGED, LauncherAppState.ACTION_FORCE_ROLOAD -> // If we have changed locale we need to clear out the labels in all apps/workspace. forceReload() } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED == action) { DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED -> enqueueModelUpdateTask(ReloadStringCacheTask(this.modelDelegate)) } else if (BuildConfig.IS_STUDIO_BUILD && LauncherAppState.ACTION_FORCE_ROLOAD == action) { forceReload() } } Loading @@ -193,43 +182,43 @@ class LauncherModel( * @see UserCache.addUserEventListener */ fun onUserEvent(user: UserHandle, action: String) { if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE == action && mShouldReloadWorkProfile) { mShouldReloadWorkProfile = false when (action) { Intent.ACTION_MANAGED_PROFILE_AVAILABLE -> { if (mShouldReloadWorkProfile) { forceReload() } else if ( Intent.ACTION_MANAGED_PROFILE_AVAILABLE == action || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE == action ) { mShouldReloadWorkProfile = false } else { enqueueModelUpdateTask( PackageUpdatedTask(PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user) ) } else if ( UserCache.ACTION_PROFILE_LOCKED == action || UserCache.ACTION_PROFILE_UNLOCKED == action ) { } mShouldReloadWorkProfile = false } Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE -> { mShouldReloadWorkProfile = false enqueueModelUpdateTask( UserLockStateChangedTask(user, UserCache.ACTION_PROFILE_UNLOCKED == action) PackageUpdatedTask(PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user) ) } else if ( UserCache.ACTION_PROFILE_ADDED == action || UserCache.ACTION_PROFILE_REMOVED == action ) { } UserCache.ACTION_PROFILE_LOCKED -> enqueueModelUpdateTask(UserLockStateChangedTask(user, false)) UserCache.ACTION_PROFILE_UNLOCKED -> enqueueModelUpdateTask(UserLockStateChangedTask(user, true)) Intent.ACTION_MANAGED_PROFILE_REMOVED -> { LauncherPrefs.get(mApp.context).put(LauncherPrefs.WORK_EDU_STEP, 0) forceReload() } else if ( UserCache.ACTION_PROFILE_AVAILABLE == action || UserCache.ACTION_PROFILE_UNAVAILABLE == action ) { /* * This broadcast is only available when android.os.Flags.allowPrivateProfile() is set. * For Work-profile this broadcast will be sent in addition to * ACTION_MANAGED_PROFILE_AVAILABLE/UNAVAILABLE. * So effectively, this if block only handles the non-work profile case. */ } UserCache.ACTION_PROFILE_ADDED, UserCache.ACTION_PROFILE_REMOVED -> forceReload() UserCache.ACTION_PROFILE_AVAILABLE, UserCache.ACTION_PROFILE_UNAVAILABLE -> { // This broadcast is only available when android.os.Flags.allowPrivateProfile() is // set. For Work-profile this broadcast will be sent in addition to // ACTION_MANAGED_PROFILE_AVAILABLE/UNAVAILABLE. So effectively, this if block only // handles the non-work profile case. enqueueModelUpdateTask( PackageUpdatedTask(PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user) ) } if (Intent.ACTION_MANAGED_PROFILE_REMOVED == action) { LauncherPrefs.get(mApp.context).put(LauncherPrefs.WORK_EDU_STEP, 0) } } Loading @@ -243,12 +232,7 @@ class LauncherModel( stopLoader() mModelLoaded = false } // Start the loader if launcher is already running, otherwise the loader will run, // the next time launcher starts if (hasCallbacks()) { startLoader() } rebindCallbacks() } /** Rebinds all existing callbacks with already loaded model */ Loading Loading @@ -325,7 +309,6 @@ class LauncherModel( } return true } else { stopLoader() mLoaderTask = LoaderTask( mApp, Loading Loading @@ -375,83 +358,6 @@ class LauncherModel( MODEL_EXECUTOR.post { callback.accept(if (isModelLoaded()) mBgDataModel else null) } } override fun onInstallSessionCreated(sessionInfo: PackageInstallInfo) { if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) { enqueueModelUpdateTask { taskController, _, apps -> apps.addPromiseApp(mApp.context, sessionInfo) taskController.bindApplicationsIfNeeded() } } } override fun onSessionFailure(packageName: String, user: UserHandle) { enqueueModelUpdateTask { taskController, dataModel, apps -> val iconCache = mApp.iconCache val removedIds = IntSet() val archivedWorkspaceItemsToCacheRefresh = HashSet<WorkspaceItemInfo>() val isAppArchived = ApplicationInfoWrapper(mApp.context, packageName, user).isArchived() synchronized(dataModel) { if (isAppArchived) { // Remove package icon cache entry for archived app in case of a session // failure. mApp.iconCache.remove( ComponentName(packageName, packageName + BaseIconCache.EMPTY_CLASS_NAME), user, ) } for (info in dataModel.itemsIdMap) { if ( (info is WorkspaceItemInfo && info.hasPromiseIconUi()) && user == info.user && info.intent != null ) { if (TextUtils.equals(packageName, info.intent!!.getPackage())) { removedIds.add(info.id) } if (info.isArchived()) { // Refresh icons on the workspace for archived apps. iconCache.getTitleAndIcon(info, info.usingLowResIcon()) archivedWorkspaceItemsToCacheRefresh.add(info) } } } if (isAppArchived) { apps.updateIconsAndLabels(hashSetOf(packageName), user) } } if (!removedIds.isEmpty && !isAppArchived) { taskController.deleteAndBindComponentsRemoved( ItemInfoMatcher.ofItemIds(removedIds), "removed because install session failed", ) } if (archivedWorkspaceItemsToCacheRefresh.isNotEmpty()) { taskController.bindUpdatedWorkspaceItems( archivedWorkspaceItemsToCacheRefresh.stream().toList() ) } if (isAppArchived) { taskController.bindApplicationsIfNeeded() } } } override fun onPackageStateChanged(installInfo: PackageInstallInfo) { enqueueModelUpdateTask(PackageInstallStateChangedTask(installInfo)) } /** Updates the icons and label of all pending icons for the provided package name. */ override fun onUpdateSessionDisplay(key: PackageUserKey, info: PackageInstaller.SessionInfo) { mApp.iconCache.updateSessionCache(key, info) val packages = HashSet<String>() packages.add(key.mPackageName) enqueueModelUpdateTask( CacheDataUpdatedTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, key.mUser, packages) ) } inner class LoaderTransaction(task: LoaderTask) : AutoCloseable { private var mTask: LoaderTask? = null Loading Loading @@ -545,19 +451,11 @@ class LauncherModel( } fun updateAndBindWorkspaceItem(si: WorkspaceItemInfo, info: ShortcutInfo) { updateAndBindWorkspaceItem { si.updateFromDeepShortcutInfo(info, mApp.context) mApp.iconCache.getShortcutIcon(si, info) si } } /** Utility method to update a shortcut on the background thread. */ private fun updateAndBindWorkspaceItem(itemProvider: Supplier<WorkspaceItemInfo>) { enqueueModelUpdateTask { taskController, _, _ -> val info = itemProvider.get() taskController.getModelWriter().updateItemInDatabase(info) taskController.bindUpdatedWorkspaceItems(listOf(info)) si.updateFromDeepShortcutInfo(info, context) iconCache.getShortcutIcon(si, info) taskController.getModelWriter().updateItemInDatabase(si) taskController.bindUpdatedWorkspaceItems(listOf(si)) } } Loading src/com/android/launcher3/model/ModelLauncherCallbacks.kt +41 −5 Original line number Diff line number Diff line Loading @@ -17,10 +17,12 @@ package com.android.launcher3.model import android.content.pm.LauncherApps import android.content.pm.PackageInstaller.SessionInfo import android.content.pm.ShortcutInfo import android.os.UserHandle import android.text.TextUtils import com.android.launcher3.LauncherModel.ModelUpdateTask import com.android.launcher3.config.FeatureFlags import com.android.launcher3.logging.FileLog import com.android.launcher3.model.PackageUpdatedTask.OP_ADD import com.android.launcher3.model.PackageUpdatedTask.OP_REMOVE Loading @@ -28,6 +30,9 @@ import com.android.launcher3.model.PackageUpdatedTask.OP_SUSPEND import com.android.launcher3.model.PackageUpdatedTask.OP_UNAVAILABLE import com.android.launcher3.model.PackageUpdatedTask.OP_UNSUSPEND import com.android.launcher3.model.PackageUpdatedTask.OP_UPDATE import com.android.launcher3.pm.InstallSessionTracker import com.android.launcher3.pm.PackageInstallInfo import com.android.launcher3.util.PackageUserKey import java.util.function.Consumer /** Loading @@ -35,7 +40,7 @@ import java.util.function.Consumer * model tasks */ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask>) : LauncherApps.Callback() { LauncherApps.Callback(), InstallSessionTracker.Callback { override fun onPackageAdded(packageName: String, user: UserHandle) { FileLog.d(TAG, "onPackageAdded triggered for packageName=$packageName, user=$user") Loading @@ -49,7 +54,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> override fun onPackageLoadingProgressChanged( packageName: String, user: UserHandle, progress: Float progress: Float, ) { taskExecutor.accept(PackageIncrementalDownloadUpdatedTask(packageName, user, progress)) } Loading @@ -62,7 +67,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> override fun onPackagesAvailable( vararg packageNames: String, user: UserHandle, replacing: Boolean replacing: Boolean, ) { taskExecutor.accept(PackageUpdatedTask(OP_UPDATE, user, *packageNames)) } Loading @@ -74,7 +79,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> override fun onPackagesUnavailable( packageNames: Array<String>, user: UserHandle, replacing: Boolean replacing: Boolean, ) { if (!replacing) { taskExecutor.accept(PackageUpdatedTask(OP_UNAVAILABLE, user, *packageNames)) Loading @@ -88,7 +93,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> override fun onShortcutsChanged( packageName: String, shortcuts: MutableList<ShortcutInfo>, user: UserHandle user: UserHandle, ) { taskExecutor.accept(ShortcutsChangedTask(packageName, shortcuts, user, true)) } Loading @@ -98,6 +103,37 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> taskExecutor.accept(PackageUpdatedTask(OP_REMOVE, user, *packages.toTypedArray())) } override fun onSessionFailure(packageName: String, user: UserHandle) { taskExecutor.accept(SessionFailureTask(packageName, user)) } override fun onPackageStateChanged(installInfo: PackageInstallInfo) { taskExecutor.accept(PackageInstallStateChangedTask(installInfo)) } override fun onUpdateSessionDisplay(key: PackageUserKey, info: SessionInfo) { /** Updates the icons and label of all pending icons for the provided package name. */ taskExecutor.accept { controller, _, _ -> controller.app.iconCache.updateSessionCache(key, info) } taskExecutor.accept( CacheDataUpdatedTask( CacheDataUpdatedTask.OP_SESSION_UPDATE, key.mUser, hashSetOf(key.mPackageName), ) ) } override fun onInstallSessionCreated(sessionInfo: PackageInstallInfo) { if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) { taskExecutor.accept { taskController, _, apps -> apps.addPromiseApp(taskController.app.context, sessionInfo) taskController.bindApplicationsIfNeeded() } } } companion object { private const val TAG = "LauncherAppsCallbackImpl" } Loading src/com/android/launcher3/model/SessionFailureTask.kt 0 → 100644 +77 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.model import android.content.ComponentName import android.os.UserHandle import android.text.TextUtils import com.android.launcher3.LauncherModel.ModelUpdateTask import com.android.launcher3.icons.cache.BaseIconCache import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.util.ApplicationInfoWrapper import com.android.launcher3.util.ItemInfoMatcher /** Model task run when there is a package install session failure */ class SessionFailureTask(val packageName: String, val user: UserHandle) : ModelUpdateTask { override fun execute( taskController: ModelTaskController, dataModel: BgDataModel, apps: AllAppsList, ) { val iconCache = taskController.app.iconCache val isAppArchived = ApplicationInfoWrapper(taskController.app.context, packageName, user).isArchived() synchronized(dataModel) { if (isAppArchived) { val updatedItems = mutableListOf<WorkspaceItemInfo>() // Remove package icon cache entry for archived app in case of a session // failure. iconCache.remove( ComponentName(packageName, packageName + BaseIconCache.EMPTY_CLASS_NAME), user, ) for (info in dataModel.itemsIdMap) { if (info is WorkspaceItemInfo && info.isArchived && user == info.user) { // Refresh icons on the workspace for archived apps. iconCache.getTitleAndIcon(info, info.usingLowResIcon()) updatedItems.add(info) } } if (updatedItems.isNotEmpty()) { taskController.bindUpdatedWorkspaceItems(updatedItems) } apps.updateIconsAndLabels(hashSetOf(packageName), user) taskController.bindApplicationsIfNeeded() } else { val removedItems = dataModel.itemsIdMap.filter { info -> (info is WorkspaceItemInfo && info.hasPromiseIconUi()) && user == info.user && TextUtils.equals(packageName, info.intent.getPackage()) } if (removedItems.isNotEmpty()) { taskController.deleteAndBindComponentsRemoved( ItemInfoMatcher.ofItems(removedItems), "removed because install session failed", ) } } } } } Loading
src/com/android/launcher3/LauncherAppState.java +1 −1 Original line number Diff line number Diff line Loading @@ -176,7 +176,7 @@ public class LauncherAppState implements SafeCloseable { () -> LauncherPrefs.get(mContext).removeListener(observer, THEMED_ICONS)); InstallSessionTracker installSessionTracker = InstallSessionHelper.INSTANCE.get(context).registerInstallTracker(mModel); InstallSessionHelper.INSTANCE.get(context).registerInstallTracker(callbacks); mOnTerminateCallback.add(installSessionTracker::unregister); }); Loading
src/com/android/launcher3/LauncherModel.kt +54 −156 Original line number Diff line number Diff line Loading @@ -16,10 +16,8 @@ package com.android.launcher3 import android.app.admin.DevicePolicyManager import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.pm.PackageInstaller import android.content.pm.ShortcutInfo import android.os.UserHandle import android.text.TextUtils Loading @@ -29,7 +27,6 @@ import androidx.annotation.WorkerThread import com.android.launcher3.celllayout.CellPosMapper import com.android.launcher3.config.FeatureFlags import com.android.launcher3.icons.IconCache import com.android.launcher3.icons.cache.BaseIconCache import com.android.launcher3.model.AddWorkspaceItemsTask import com.android.launcher3.model.AllAppsList import com.android.launcher3.model.BaseLauncherBinder Loading @@ -42,23 +39,17 @@ import com.android.launcher3.model.ModelDelegate import com.android.launcher3.model.ModelLauncherCallbacks import com.android.launcher3.model.ModelTaskController import com.android.launcher3.model.ModelWriter import com.android.launcher3.model.PackageInstallStateChangedTask import com.android.launcher3.model.PackageUpdatedTask import com.android.launcher3.model.ReloadStringCacheTask import com.android.launcher3.model.ShortcutsChangedTask import com.android.launcher3.model.UserLockStateChangedTask import com.android.launcher3.model.data.ItemInfo import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.pm.InstallSessionTracker import com.android.launcher3.pm.PackageInstallInfo import com.android.launcher3.pm.UserCache import com.android.launcher3.shortcuts.ShortcutRequest import com.android.launcher3.testing.shared.TestProtocol.sDebugTracing import com.android.launcher3.util.ApplicationInfoWrapper import com.android.launcher3.util.Executors.MAIN_EXECUTOR import com.android.launcher3.util.Executors.MODEL_EXECUTOR import com.android.launcher3.util.IntSet import com.android.launcher3.util.ItemInfoMatcher import com.android.launcher3.util.PackageManagerHelper import com.android.launcher3.util.PackageUserKey import com.android.launcher3.util.Preconditions Loading @@ -66,7 +57,6 @@ import java.io.FileDescriptor import java.io.PrintWriter import java.util.concurrent.CancellationException import java.util.function.Consumer import java.util.function.Supplier /** * Maintains in-memory state of the Launcher. It is expected that there should be only one Loading @@ -80,7 +70,7 @@ class LauncherModel( private val appFilter: AppFilter, private val mPmHelper: PackageManagerHelper, isPrimaryInstance: Boolean, ) : InstallSessionTracker.Callback { ) { private val mCallbacksList = ArrayList<BgDataModel.Callbacks>(1) Loading Loading @@ -156,10 +146,10 @@ class LauncherModel( fun onAppIconChanged(packageName: String, user: UserHandle) { // Update the icon for the calendar package enqueueModelUpdateTask(PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE, user, packageName)) val pinnedShortcuts: List<ShortcutInfo> = ShortcutRequest(context, user).forPackage(packageName).query(ShortcutRequest.PINNED) if (pinnedShortcuts.isNotEmpty()) { enqueueModelUpdateTask(ShortcutsChangedTask(packageName, pinnedShortcuts, user, false)) ShortcutRequest(context, user).forPackage(packageName).query(ShortcutRequest.PINNED).let { if (it.isNotEmpty()) { enqueueModelUpdateTask(ShortcutsChangedTask(packageName, it, user, false)) } } } Loading @@ -176,14 +166,13 @@ class LauncherModel( fun onBroadcastIntent(intent: Intent) { if (DEBUG_RECEIVER || sDebugTracing) Log.d(TAG, "onReceive intent=$intent") val action = intent.action if (Intent.ACTION_LOCALE_CHANGED == action) { when (intent.action) { Intent.ACTION_LOCALE_CHANGED, LauncherAppState.ACTION_FORCE_ROLOAD -> // If we have changed locale we need to clear out the labels in all apps/workspace. forceReload() } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED == action) { DevicePolicyManager.ACTION_DEVICE_POLICY_RESOURCE_UPDATED -> enqueueModelUpdateTask(ReloadStringCacheTask(this.modelDelegate)) } else if (BuildConfig.IS_STUDIO_BUILD && LauncherAppState.ACTION_FORCE_ROLOAD == action) { forceReload() } } Loading @@ -193,43 +182,43 @@ class LauncherModel( * @see UserCache.addUserEventListener */ fun onUserEvent(user: UserHandle, action: String) { if (Intent.ACTION_MANAGED_PROFILE_AVAILABLE == action && mShouldReloadWorkProfile) { mShouldReloadWorkProfile = false when (action) { Intent.ACTION_MANAGED_PROFILE_AVAILABLE -> { if (mShouldReloadWorkProfile) { forceReload() } else if ( Intent.ACTION_MANAGED_PROFILE_AVAILABLE == action || Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE == action ) { mShouldReloadWorkProfile = false } else { enqueueModelUpdateTask( PackageUpdatedTask(PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user) ) } else if ( UserCache.ACTION_PROFILE_LOCKED == action || UserCache.ACTION_PROFILE_UNLOCKED == action ) { } mShouldReloadWorkProfile = false } Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE -> { mShouldReloadWorkProfile = false enqueueModelUpdateTask( UserLockStateChangedTask(user, UserCache.ACTION_PROFILE_UNLOCKED == action) PackageUpdatedTask(PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user) ) } else if ( UserCache.ACTION_PROFILE_ADDED == action || UserCache.ACTION_PROFILE_REMOVED == action ) { } UserCache.ACTION_PROFILE_LOCKED -> enqueueModelUpdateTask(UserLockStateChangedTask(user, false)) UserCache.ACTION_PROFILE_UNLOCKED -> enqueueModelUpdateTask(UserLockStateChangedTask(user, true)) Intent.ACTION_MANAGED_PROFILE_REMOVED -> { LauncherPrefs.get(mApp.context).put(LauncherPrefs.WORK_EDU_STEP, 0) forceReload() } else if ( UserCache.ACTION_PROFILE_AVAILABLE == action || UserCache.ACTION_PROFILE_UNAVAILABLE == action ) { /* * This broadcast is only available when android.os.Flags.allowPrivateProfile() is set. * For Work-profile this broadcast will be sent in addition to * ACTION_MANAGED_PROFILE_AVAILABLE/UNAVAILABLE. * So effectively, this if block only handles the non-work profile case. */ } UserCache.ACTION_PROFILE_ADDED, UserCache.ACTION_PROFILE_REMOVED -> forceReload() UserCache.ACTION_PROFILE_AVAILABLE, UserCache.ACTION_PROFILE_UNAVAILABLE -> { // This broadcast is only available when android.os.Flags.allowPrivateProfile() is // set. For Work-profile this broadcast will be sent in addition to // ACTION_MANAGED_PROFILE_AVAILABLE/UNAVAILABLE. So effectively, this if block only // handles the non-work profile case. enqueueModelUpdateTask( PackageUpdatedTask(PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE, user) ) } if (Intent.ACTION_MANAGED_PROFILE_REMOVED == action) { LauncherPrefs.get(mApp.context).put(LauncherPrefs.WORK_EDU_STEP, 0) } } Loading @@ -243,12 +232,7 @@ class LauncherModel( stopLoader() mModelLoaded = false } // Start the loader if launcher is already running, otherwise the loader will run, // the next time launcher starts if (hasCallbacks()) { startLoader() } rebindCallbacks() } /** Rebinds all existing callbacks with already loaded model */ Loading Loading @@ -325,7 +309,6 @@ class LauncherModel( } return true } else { stopLoader() mLoaderTask = LoaderTask( mApp, Loading Loading @@ -375,83 +358,6 @@ class LauncherModel( MODEL_EXECUTOR.post { callback.accept(if (isModelLoaded()) mBgDataModel else null) } } override fun onInstallSessionCreated(sessionInfo: PackageInstallInfo) { if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) { enqueueModelUpdateTask { taskController, _, apps -> apps.addPromiseApp(mApp.context, sessionInfo) taskController.bindApplicationsIfNeeded() } } } override fun onSessionFailure(packageName: String, user: UserHandle) { enqueueModelUpdateTask { taskController, dataModel, apps -> val iconCache = mApp.iconCache val removedIds = IntSet() val archivedWorkspaceItemsToCacheRefresh = HashSet<WorkspaceItemInfo>() val isAppArchived = ApplicationInfoWrapper(mApp.context, packageName, user).isArchived() synchronized(dataModel) { if (isAppArchived) { // Remove package icon cache entry for archived app in case of a session // failure. mApp.iconCache.remove( ComponentName(packageName, packageName + BaseIconCache.EMPTY_CLASS_NAME), user, ) } for (info in dataModel.itemsIdMap) { if ( (info is WorkspaceItemInfo && info.hasPromiseIconUi()) && user == info.user && info.intent != null ) { if (TextUtils.equals(packageName, info.intent!!.getPackage())) { removedIds.add(info.id) } if (info.isArchived()) { // Refresh icons on the workspace for archived apps. iconCache.getTitleAndIcon(info, info.usingLowResIcon()) archivedWorkspaceItemsToCacheRefresh.add(info) } } } if (isAppArchived) { apps.updateIconsAndLabels(hashSetOf(packageName), user) } } if (!removedIds.isEmpty && !isAppArchived) { taskController.deleteAndBindComponentsRemoved( ItemInfoMatcher.ofItemIds(removedIds), "removed because install session failed", ) } if (archivedWorkspaceItemsToCacheRefresh.isNotEmpty()) { taskController.bindUpdatedWorkspaceItems( archivedWorkspaceItemsToCacheRefresh.stream().toList() ) } if (isAppArchived) { taskController.bindApplicationsIfNeeded() } } } override fun onPackageStateChanged(installInfo: PackageInstallInfo) { enqueueModelUpdateTask(PackageInstallStateChangedTask(installInfo)) } /** Updates the icons and label of all pending icons for the provided package name. */ override fun onUpdateSessionDisplay(key: PackageUserKey, info: PackageInstaller.SessionInfo) { mApp.iconCache.updateSessionCache(key, info) val packages = HashSet<String>() packages.add(key.mPackageName) enqueueModelUpdateTask( CacheDataUpdatedTask(CacheDataUpdatedTask.OP_SESSION_UPDATE, key.mUser, packages) ) } inner class LoaderTransaction(task: LoaderTask) : AutoCloseable { private var mTask: LoaderTask? = null Loading Loading @@ -545,19 +451,11 @@ class LauncherModel( } fun updateAndBindWorkspaceItem(si: WorkspaceItemInfo, info: ShortcutInfo) { updateAndBindWorkspaceItem { si.updateFromDeepShortcutInfo(info, mApp.context) mApp.iconCache.getShortcutIcon(si, info) si } } /** Utility method to update a shortcut on the background thread. */ private fun updateAndBindWorkspaceItem(itemProvider: Supplier<WorkspaceItemInfo>) { enqueueModelUpdateTask { taskController, _, _ -> val info = itemProvider.get() taskController.getModelWriter().updateItemInDatabase(info) taskController.bindUpdatedWorkspaceItems(listOf(info)) si.updateFromDeepShortcutInfo(info, context) iconCache.getShortcutIcon(si, info) taskController.getModelWriter().updateItemInDatabase(si) taskController.bindUpdatedWorkspaceItems(listOf(si)) } } Loading
src/com/android/launcher3/model/ModelLauncherCallbacks.kt +41 −5 Original line number Diff line number Diff line Loading @@ -17,10 +17,12 @@ package com.android.launcher3.model import android.content.pm.LauncherApps import android.content.pm.PackageInstaller.SessionInfo import android.content.pm.ShortcutInfo import android.os.UserHandle import android.text.TextUtils import com.android.launcher3.LauncherModel.ModelUpdateTask import com.android.launcher3.config.FeatureFlags import com.android.launcher3.logging.FileLog import com.android.launcher3.model.PackageUpdatedTask.OP_ADD import com.android.launcher3.model.PackageUpdatedTask.OP_REMOVE Loading @@ -28,6 +30,9 @@ import com.android.launcher3.model.PackageUpdatedTask.OP_SUSPEND import com.android.launcher3.model.PackageUpdatedTask.OP_UNAVAILABLE import com.android.launcher3.model.PackageUpdatedTask.OP_UNSUSPEND import com.android.launcher3.model.PackageUpdatedTask.OP_UPDATE import com.android.launcher3.pm.InstallSessionTracker import com.android.launcher3.pm.PackageInstallInfo import com.android.launcher3.util.PackageUserKey import java.util.function.Consumer /** Loading @@ -35,7 +40,7 @@ import java.util.function.Consumer * model tasks */ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask>) : LauncherApps.Callback() { LauncherApps.Callback(), InstallSessionTracker.Callback { override fun onPackageAdded(packageName: String, user: UserHandle) { FileLog.d(TAG, "onPackageAdded triggered for packageName=$packageName, user=$user") Loading @@ -49,7 +54,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> override fun onPackageLoadingProgressChanged( packageName: String, user: UserHandle, progress: Float progress: Float, ) { taskExecutor.accept(PackageIncrementalDownloadUpdatedTask(packageName, user, progress)) } Loading @@ -62,7 +67,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> override fun onPackagesAvailable( vararg packageNames: String, user: UserHandle, replacing: Boolean replacing: Boolean, ) { taskExecutor.accept(PackageUpdatedTask(OP_UPDATE, user, *packageNames)) } Loading @@ -74,7 +79,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> override fun onPackagesUnavailable( packageNames: Array<String>, user: UserHandle, replacing: Boolean replacing: Boolean, ) { if (!replacing) { taskExecutor.accept(PackageUpdatedTask(OP_UNAVAILABLE, user, *packageNames)) Loading @@ -88,7 +93,7 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> override fun onShortcutsChanged( packageName: String, shortcuts: MutableList<ShortcutInfo>, user: UserHandle user: UserHandle, ) { taskExecutor.accept(ShortcutsChangedTask(packageName, shortcuts, user, true)) } Loading @@ -98,6 +103,37 @@ class ModelLauncherCallbacks(private var taskExecutor: Consumer<ModelUpdateTask> taskExecutor.accept(PackageUpdatedTask(OP_REMOVE, user, *packages.toTypedArray())) } override fun onSessionFailure(packageName: String, user: UserHandle) { taskExecutor.accept(SessionFailureTask(packageName, user)) } override fun onPackageStateChanged(installInfo: PackageInstallInfo) { taskExecutor.accept(PackageInstallStateChangedTask(installInfo)) } override fun onUpdateSessionDisplay(key: PackageUserKey, info: SessionInfo) { /** Updates the icons and label of all pending icons for the provided package name. */ taskExecutor.accept { controller, _, _ -> controller.app.iconCache.updateSessionCache(key, info) } taskExecutor.accept( CacheDataUpdatedTask( CacheDataUpdatedTask.OP_SESSION_UPDATE, key.mUser, hashSetOf(key.mPackageName), ) ) } override fun onInstallSessionCreated(sessionInfo: PackageInstallInfo) { if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) { taskExecutor.accept { taskController, _, apps -> apps.addPromiseApp(taskController.app.context, sessionInfo) taskController.bindApplicationsIfNeeded() } } } companion object { private const val TAG = "LauncherAppsCallbackImpl" } Loading
src/com/android/launcher3/model/SessionFailureTask.kt 0 → 100644 +77 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.model import android.content.ComponentName import android.os.UserHandle import android.text.TextUtils import com.android.launcher3.LauncherModel.ModelUpdateTask import com.android.launcher3.icons.cache.BaseIconCache import com.android.launcher3.model.data.WorkspaceItemInfo import com.android.launcher3.util.ApplicationInfoWrapper import com.android.launcher3.util.ItemInfoMatcher /** Model task run when there is a package install session failure */ class SessionFailureTask(val packageName: String, val user: UserHandle) : ModelUpdateTask { override fun execute( taskController: ModelTaskController, dataModel: BgDataModel, apps: AllAppsList, ) { val iconCache = taskController.app.iconCache val isAppArchived = ApplicationInfoWrapper(taskController.app.context, packageName, user).isArchived() synchronized(dataModel) { if (isAppArchived) { val updatedItems = mutableListOf<WorkspaceItemInfo>() // Remove package icon cache entry for archived app in case of a session // failure. iconCache.remove( ComponentName(packageName, packageName + BaseIconCache.EMPTY_CLASS_NAME), user, ) for (info in dataModel.itemsIdMap) { if (info is WorkspaceItemInfo && info.isArchived && user == info.user) { // Refresh icons on the workspace for archived apps. iconCache.getTitleAndIcon(info, info.usingLowResIcon()) updatedItems.add(info) } } if (updatedItems.isNotEmpty()) { taskController.bindUpdatedWorkspaceItems(updatedItems) } apps.updateIconsAndLabels(hashSetOf(packageName), user) taskController.bindApplicationsIfNeeded() } else { val removedItems = dataModel.itemsIdMap.filter { info -> (info is WorkspaceItemInfo && info.hasPromiseIconUi()) && user == info.user && TextUtils.equals(packageName, info.intent.getPackage()) } if (removedItems.isNotEmpty()) { taskController.deleteAndBindComponentsRemoved( ItemInfoMatcher.ofItems(removedItems), "removed because install session failed", ) } } } } }