Merge "Adding repository for AppsList data" into main
This commit is contained in:
@@ -127,12 +127,11 @@ public class AllAppsStore<T extends Context & ActivityContext> {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.android.launcher3.model.BgDataModel.Callbacks#FLAG_QUIET_MODE_ENABLED
|
||||
* @see com.android.launcher3.model.BgDataModel.Callbacks#FLAG_HAS_SHORTCUT_PERMISSION
|
||||
* @see com.android.launcher3.model.BgDataModel.Callbacks#FLAG_QUIET_MODE_CHANGE_PERMISSION
|
||||
* @see com.android.launcher3.model.BgDataModel.Callbacks#FLAG_WORK_PROFILE_QUIET_MODE_ENABLED
|
||||
* @see
|
||||
* com.android.launcher3.model.BgDataModel.Callbacks#FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED
|
||||
* @see com.android.launcher3.model.data.AppsListData#FLAG_QUIET_MODE_ENABLED
|
||||
* @see com.android.launcher3.model.data.AppsListData#FLAG_HAS_SHORTCUT_PERMISSION
|
||||
* @see com.android.launcher3.model.data.AppsListData#FLAG_QUIET_MODE_CHANGE_PERMISSION
|
||||
* @see com.android.launcher3.model.data.AppsListData#FLAG_WORK_PROFILE_QUIET_MODE_ENABLED
|
||||
* @see com.android.launcher3.model.data.AppsListData#FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED
|
||||
*/
|
||||
public boolean hasModelFlag(int mask) {
|
||||
return (mModelFlags & mask) != 0;
|
||||
|
||||
@@ -32,7 +32,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_BEGIN;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_ANIMATION_END;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_PRIVATE_SPACE_UNLOCK_TAP;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_NOT_PINNABLE;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
@@ -22,10 +22,10 @@ import static com.android.launcher3.allapps.ActivityAllAppsContainerView.Adapter
|
||||
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_DISABLED_CARD;
|
||||
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_EDU_CARD;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TURN_OFF_WORK_APPS_TAP;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_HAS_SHORTCUT_PERMISSION;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_QUIET_MODE_CHANGE_PERMISSION;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED;
|
||||
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
|
||||
@@ -33,12 +33,14 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.AppFilter;
|
||||
import com.android.launcher3.Flags;
|
||||
import com.android.launcher3.compat.AlphabeticIndexCompat;
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.AppsListData;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.repository.AppsListRepository;
|
||||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
import com.android.launcher3.pm.UserCache;
|
||||
import com.android.launcher3.util.ApiWrapper;
|
||||
@@ -55,6 +57,7 @@ import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Provider;
|
||||
|
||||
|
||||
/**
|
||||
@@ -78,17 +81,19 @@ public class AllAppsList {
|
||||
@NonNull
|
||||
private final AppFilter mAppFilter;
|
||||
|
||||
@NonNull private final Provider<AppsListRepository> mRepo;
|
||||
|
||||
private boolean mDataChanged = false;
|
||||
private Consumer<AppInfo> mRemoveListener = NO_OP_CONSUMER;
|
||||
|
||||
private AlphabeticIndexCompat mIndex;
|
||||
|
||||
/**
|
||||
* @see Callbacks#FLAG_HAS_SHORTCUT_PERMISSION
|
||||
* @see Callbacks#FLAG_QUIET_MODE_ENABLED
|
||||
* @see Callbacks#FLAG_QUIET_MODE_CHANGE_PERMISSION
|
||||
* @see Callbacks#FLAG_WORK_PROFILE_QUIET_MODE_ENABLED
|
||||
* @see Callbacks#FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED
|
||||
* @see AppsListData#FLAG_HAS_SHORTCUT_PERMISSION
|
||||
* @see AppsListData#FLAG_QUIET_MODE_ENABLED
|
||||
* @see AppsListData#FLAG_QUIET_MODE_CHANGE_PERMISSION
|
||||
* @see AppsListData#FLAG_WORK_PROFILE_QUIET_MODE_ENABLED
|
||||
* @see AppsListData#FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED
|
||||
*/
|
||||
private int mFlags;
|
||||
|
||||
@@ -96,9 +101,12 @@ public class AllAppsList {
|
||||
* Boring constructor.
|
||||
*/
|
||||
@Inject
|
||||
public AllAppsList(IconCache iconCache, AppFilter appFilter) {
|
||||
public AllAppsList(@NonNull IconCache iconCache,
|
||||
@NonNull AppFilter appFilter,
|
||||
@NonNull Provider<AppsListRepository> repositoryProvider) {
|
||||
mIconCache = iconCache;
|
||||
mAppFilter = appFilter;
|
||||
mRepo = repositoryProvider;
|
||||
mIndex = new AlphabeticIndexCompat(LocaleList.getDefault());
|
||||
}
|
||||
|
||||
@@ -108,14 +116,18 @@ public class AllAppsList {
|
||||
public boolean getAndResetChangeFlag() {
|
||||
boolean result = mDataChanged;
|
||||
mDataChanged = false;
|
||||
|
||||
if (Flags.modelRepository() && result) {
|
||||
mRepo.get().dispatchChange(getImmutableData());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to checking {@link Callbacks#FLAG_HAS_SHORTCUT_PERMISSION}
|
||||
* Helper to checking {@link AppsListData#FLAG_HAS_SHORTCUT_PERMISSION}
|
||||
*/
|
||||
public boolean hasShortcutHostPermission() {
|
||||
return (mFlags & Callbacks.FLAG_HAS_SHORTCUT_PERMISSION) != 0;
|
||||
return (mFlags & AppsListData.FLAG_HAS_SHORTCUT_PERMISSION) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,14 +142,11 @@ public class AllAppsList {
|
||||
mDataChanged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the model flags
|
||||
*/
|
||||
public int getFlags() {
|
||||
return mFlags;
|
||||
/** Returns an immutable representation of the current data */
|
||||
public AppsListData getImmutableData() {
|
||||
return new AppsListData(copyData(), mFlags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the supplied ApplicationInfo objects to the list, and enqueue it into the
|
||||
* list to broadcast when notify() is called.
|
||||
@@ -200,7 +209,8 @@ public class AllAppsList {
|
||||
}
|
||||
|
||||
/** Updates the given PackageInstallInfo's associated AppInfo's installation info. */
|
||||
public List<AppInfo> updatePromiseInstallInfo(PackageInstallInfo installInfo) {
|
||||
public List<AppInfo> updatePromiseInstallInfo(PackageInstallInfo installInfo,
|
||||
FlagOp runtimeFlagUpdate) {
|
||||
List<AppInfo> updatedAppInfos = new ArrayList<>();
|
||||
UserHandle user = installInfo.user;
|
||||
for (int i = data.size() - 1; i >= 0; i--) {
|
||||
@@ -222,7 +232,11 @@ public class AllAppsList {
|
||||
continue;
|
||||
}
|
||||
appInfo.setProgressLevel(installInfo);
|
||||
|
||||
appInfo.runtimeStatusFlags =
|
||||
runtimeFlagUpdate.apply(appInfo.runtimeStatusFlags);
|
||||
if (Flags.modelRepository()) {
|
||||
mRepo.get().dispatchIncrementationUpdate(appInfo);
|
||||
}
|
||||
updatedAppInfos.add(appInfo);
|
||||
} else if (installInfo.state == PackageInstallInfo.STATUS_FAILED
|
||||
&& !appInfo.isAppStartable()) {
|
||||
|
||||
@@ -28,12 +28,11 @@ import com.android.launcher3.LauncherModel.CallbackTask;
|
||||
import com.android.launcher3.dagger.ApplicationContext;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.BgDataModel.FixedContainerItems;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.AppsListData;
|
||||
import com.android.launcher3.model.data.WorkspaceData;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.LooperExecutor;
|
||||
import com.android.launcher3.util.LooperIdleLock;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
|
||||
@@ -42,12 +41,9 @@ import dagger.assisted.AssistedFactory;
|
||||
import dagger.assisted.AssistedInject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Binds the results of {@link com.android.launcher3.model.LoaderTask} to the Callbacks objects.
|
||||
@@ -136,13 +132,9 @@ public class BaseLauncherBinder {
|
||||
*/
|
||||
public void bindAllApps() {
|
||||
// shallow copy
|
||||
AppInfo[] apps = mBgAllAppsList.copyData();
|
||||
int flags = mBgAllAppsList.getFlags();
|
||||
Map<PackageUserKey, Integer> packageUserKeytoUidMap = Arrays.stream(apps).collect(
|
||||
Collectors.toMap(
|
||||
appInfo -> new PackageUserKey(appInfo.componentName.getPackageName(),
|
||||
appInfo.user), appInfo -> appInfo.uid, (a, b) -> a));
|
||||
executeCallbacksTask(c -> c.bindAllApplications(apps, flags, packageUserKeytoUidMap),
|
||||
AppsListData data = mBgAllAppsList.getImmutableData();
|
||||
executeCallbacksTask(c -> c.bindAllApplications(
|
||||
data.getApps(), data.getFlags(), data.getPackageUserKeyToUidMap()),
|
||||
mUiExecutor);
|
||||
}
|
||||
|
||||
|
||||
@@ -418,23 +418,6 @@ constructor(
|
||||
|
||||
/** Binds the cache of string resources */
|
||||
fun bindStringCache(cache: StringCache) {}
|
||||
|
||||
companion object {
|
||||
// If the launcher has permission to access deep shortcuts.
|
||||
const val FLAG_HAS_SHORTCUT_PERMISSION: Int = 1 shl 0
|
||||
|
||||
// If quiet mode is enabled for any user
|
||||
const val FLAG_QUIET_MODE_ENABLED: Int = 1 shl 1
|
||||
|
||||
// If launcher can change quiet mode
|
||||
const val FLAG_QUIET_MODE_CHANGE_PERMISSION: Int = 1 shl 2
|
||||
|
||||
// If quiet mode is enabled for work profile user
|
||||
const val FLAG_WORK_PROFILE_QUIET_MODE_ENABLED: Int = 1 shl 3
|
||||
|
||||
// If quiet mode is enabled for private profile user
|
||||
const val FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED: Int = 1 shl 4
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -20,13 +20,13 @@ import static com.android.launcher3.Flags.enableLauncherBrMetricsFixed;
|
||||
import static com.android.launcher3.LauncherPrefs.IS_FIRST_LOAD_AFTER_RESTORE;
|
||||
import static com.android.launcher3.icons.CacheableShortcutInfo.convertShortcutsToCacheableShortcuts;
|
||||
import static com.android.launcher3.icons.cache.CacheLookupFlag.DEFAULT_LOOKUP_FLAG;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.ModelUtils.WIDGET_FILTER;
|
||||
import static com.android.launcher3.model.ModelUtils.currentScreenContentFilter;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_HAS_SHORTCUT_PERMISSION;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_QUIET_MODE_CHANGE_PERMISSION;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.util.LooperExecutor.CALLER_LOADER_TASK;
|
||||
|
||||
@@ -23,9 +23,9 @@ import com.android.launcher3.celllayout.CellPosMapper
|
||||
import com.android.launcher3.dagger.ApplicationContext
|
||||
import com.android.launcher3.icons.IconCache
|
||||
import com.android.launcher3.model.BgDataModel.FixedContainerItems
|
||||
import com.android.launcher3.model.data.AppInfo
|
||||
import com.android.launcher3.model.data.ItemInfo
|
||||
import com.android.launcher3.util.Executors.MAIN_EXECUTOR
|
||||
import com.android.launcher3.util.PackageUserKey
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder
|
||||
import java.util.function.Predicate
|
||||
import javax.inject.Inject
|
||||
@@ -90,14 +90,19 @@ constructor(
|
||||
|
||||
fun bindApplicationsIfNeeded() {
|
||||
if (allAppsList.getAndResetChangeFlag()) {
|
||||
val apps = allAppsList.copyData()
|
||||
val flags = allAppsList.flags
|
||||
val packageUserKeyToUidMap =
|
||||
apps.associateBy(
|
||||
keySelector = { PackageUserKey(it.componentName!!.packageName, it.user) },
|
||||
valueTransform = { it.uid },
|
||||
)
|
||||
scheduleCallbackTask { it.bindAllApplications(apps, flags, packageUserKeyToUidMap) }
|
||||
// shallow copy
|
||||
val data = allAppsList.immutableData
|
||||
scheduleCallbackTask {
|
||||
it.bindAllApplications(data.apps, data.flags, data.packageUserKeyToUidMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun bindIncrementalUpdates(updatedAppInfos: List<AppInfo>) {
|
||||
if (updatedAppInfos.isNotEmpty()) {
|
||||
updatedAppInfos.forEach { info ->
|
||||
scheduleCallbackTask { it.bindIncrementalDownloadProgressUpdated(info) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,10 @@ import android.os.UserHandle;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.LauncherModel.ModelUpdateTask;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
import com.android.launcher3.util.FlagOp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -57,14 +57,9 @@ public class PackageIncrementalDownloadUpdatedTask implements ModelUpdateTask {
|
||||
mUser);
|
||||
|
||||
synchronized (appsList) {
|
||||
List<AppInfo> updatedAppInfos = appsList.updatePromiseInstallInfo(downloadInfo);
|
||||
if (!updatedAppInfos.isEmpty()) {
|
||||
for (AppInfo appInfo : updatedAppInfos) {
|
||||
appInfo.runtimeStatusFlags &= ~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
|
||||
taskController.scheduleCallbackTask(
|
||||
c -> c.bindIncrementalDownloadProgressUpdated(appInfo));
|
||||
}
|
||||
}
|
||||
taskController.bindIncrementalUpdates(appsList.updatePromiseInstallInfo(
|
||||
downloadInfo,
|
||||
FlagOp.NO_OP.removeFlag(ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE)));
|
||||
taskController.bindApplicationsIfNeeded();
|
||||
}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ import android.content.pm.PackageManager;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.LauncherModel.ModelUpdateTask;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
import com.android.launcher3.util.FlagOp;
|
||||
import com.android.launcher3.util.InstantAppResolver;
|
||||
|
||||
import java.util.List;
|
||||
@@ -63,13 +63,8 @@ public class PackageInstallStateChangedTask implements ModelUpdateTask {
|
||||
}
|
||||
|
||||
synchronized (apps) {
|
||||
List<AppInfo> updatedAppInfos = apps.updatePromiseInstallInfo(mInstallInfo);
|
||||
if (!updatedAppInfos.isEmpty()) {
|
||||
for (AppInfo appInfo : updatedAppInfos) {
|
||||
taskController.scheduleCallbackTask(
|
||||
c -> c.bindIncrementalDownloadProgressUpdated(appInfo));
|
||||
}
|
||||
}
|
||||
taskController.bindIncrementalUpdates(
|
||||
apps.updatePromiseInstallInfo(mInstallInfo, FlagOp.NO_OP));
|
||||
taskController.bindApplicationsIfNeeded();
|
||||
}
|
||||
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
package com.android.launcher3.model;
|
||||
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_ARCHIVED;
|
||||
import static com.android.launcher3.model.data.LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
|
||||
import static com.android.launcher3.model.data.WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.data
|
||||
|
||||
import com.android.launcher3.util.PackageUserKey
|
||||
|
||||
/** Immutable representation of all-apps list data */
|
||||
class AppsListData(
|
||||
val apps: Array<AppInfo>,
|
||||
// Current model flags
|
||||
val flags: Int,
|
||||
) {
|
||||
|
||||
val packageUserKeyToUidMap: Map<PackageUserKey, Int> =
|
||||
apps.associateBy(
|
||||
keySelector = { PackageUserKey(it.targetComponent.packageName, it.user) },
|
||||
valueTransform = { it.uid },
|
||||
)
|
||||
|
||||
companion object {
|
||||
// If the launcher has permission to access deep shortcuts.
|
||||
const val FLAG_HAS_SHORTCUT_PERMISSION: Int = 1 shl 0
|
||||
|
||||
// If quiet mode is enabled for any user
|
||||
const val FLAG_QUIET_MODE_ENABLED: Int = 1 shl 1
|
||||
|
||||
// If launcher can change quiet mode
|
||||
const val FLAG_QUIET_MODE_CHANGE_PERMISSION: Int = 1 shl 2
|
||||
|
||||
// If quiet mode is enabled for work profile user
|
||||
const val FLAG_WORK_PROFILE_QUIET_MODE_ENABLED: Int = 1 shl 3
|
||||
|
||||
// If quiet mode is enabled for private profile user
|
||||
const val FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED: Int = 1 shl 4
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2025 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.repository
|
||||
|
||||
import com.android.launcher3.dagger.LauncherAppSingleton
|
||||
import com.android.launcher3.model.data.AppInfo
|
||||
import com.android.launcher3.model.data.AppsListData
|
||||
import com.android.launcher3.util.Executors.MODEL_EXECUTOR
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.asCoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/** Repository for app-list daya. */
|
||||
@LauncherAppSingleton
|
||||
class AppsListRepository(private val scope: CoroutineScope) {
|
||||
|
||||
@Inject constructor() : this(CoroutineScope(MODEL_EXECUTOR.asCoroutineDispatcher()))
|
||||
|
||||
private val mutableStateFlow: MutableStateFlow<AppsListData> =
|
||||
MutableStateFlow(AppsListData(emptyArray(), 0))
|
||||
|
||||
/** Represents the current home screen data model. There are two ways this can change: */
|
||||
val appsListStateFlow = mutableStateFlow.asStateFlow()
|
||||
|
||||
/** sets a new value to [appsListStateFlow] */
|
||||
fun dispatchChange(appsListData: AppsListData) {
|
||||
mutableStateFlow.value = appsListData
|
||||
}
|
||||
|
||||
private val mutableIncrementalUpdate = MutableSharedFlow<AppInfo>()
|
||||
/** Represents incremental download apps to apps list items */
|
||||
val incrementalUpdates = mutableIncrementalUpdate.asSharedFlow()
|
||||
|
||||
/** Dispatches an incremental download update to [incrementalUpdates] */
|
||||
fun dispatchIncrementationUpdate(appInfo: AppInfo) {
|
||||
scope.launch { mutableIncrementalUpdate.emit(appInfo) }
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -20,7 +20,7 @@ import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
||||
|
||||
import static com.android.launcher3.allapps.UserProfileManager.STATE_DISABLED;
|
||||
import static com.android.launcher3.allapps.UserProfileManager.STATE_ENABLED;
|
||||
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.model.data.AppsListData.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.platform.test.annotations.EnableFlags
|
||||
import android.platform.test.flag.junit.SetFlagsRule
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import com.android.launcher3.AppFilter
|
||||
import com.android.launcher3.Flags
|
||||
import com.android.launcher3.Flags.FLAG_ENABLE_PRIVATE_SPACE
|
||||
import com.android.launcher3.LauncherSettings
|
||||
import com.android.launcher3.dagger.LauncherAppComponent
|
||||
@@ -40,6 +41,7 @@ import com.android.launcher3.model.PackageUpdatedTask.OP_UPDATE
|
||||
import com.android.launcher3.model.PackageUpdatedTask.OP_USER_AVAILABILITY_CHANGE
|
||||
import com.android.launcher3.model.data.AppInfo
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo
|
||||
import com.android.launcher3.model.repository.AppsListRepository
|
||||
import com.android.launcher3.util.AllModulesForTest
|
||||
import com.android.launcher3.util.Executors
|
||||
import com.android.launcher3.util.SandboxApplication
|
||||
@@ -73,6 +75,7 @@ class PackageUpdatedTaskTest {
|
||||
|
||||
private val mockIconCache: IconCache = mock()
|
||||
private val mockAppFilter: AppFilter = mock<AppFilter>()
|
||||
private val appsListRepo = AppsListRepository()
|
||||
private lateinit var mAllAppsList: AllAppsList
|
||||
|
||||
private val mockApplicationInfo: ApplicationInfo = mock<ApplicationInfo>()
|
||||
@@ -83,7 +86,7 @@ class PackageUpdatedTaskTest {
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
mAllAppsList = spy(AllAppsList(mockIconCache, mockAppFilter))
|
||||
mAllAppsList = spy(AllAppsList(mockIconCache, mockAppFilter) { appsListRepo })
|
||||
mContext.initDaggerComponent(
|
||||
DaggerPackageUpdatedTaskTest_TestComponent.builder()
|
||||
.bindAllAppsList(mAllAppsList)
|
||||
@@ -186,6 +189,7 @@ class PackageUpdatedTaskTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_MODEL_REPOSITORY)
|
||||
fun `OP_SUSPEND triggers model callbacks and updates flags in AllAppsList`() {
|
||||
// Given
|
||||
val taskUnderTest = PackageUpdatedTask(OP_SUSPEND, mUser, expectedPackage)
|
||||
@@ -201,9 +205,11 @@ class PackageUpdatedTaskTest {
|
||||
verify(mAllAppsList).updateDisabledFlags(any(), any())
|
||||
verify(mockTaskController).bindUpdatedWorkspaceItems(listOf(expectedWorkspaceItem))
|
||||
assertThat(mAllAppsList.getAndResetChangeFlag()).isTrue()
|
||||
assertThat(appsListRepo.appsListStateFlow.value.apps).isNotEmpty()
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableFlags(Flags.FLAG_MODEL_REPOSITORY)
|
||||
fun `OP_UNSUSPEND triggers no callbacks when app not suspended`() {
|
||||
// Given
|
||||
val taskUnderTest = PackageUpdatedTask(OP_UNSUSPEND, mUser, expectedPackage)
|
||||
@@ -218,6 +224,7 @@ class PackageUpdatedTaskTest {
|
||||
verify(mAllAppsList).updateDisabledFlags(any(), any())
|
||||
verify(mockTaskController).bindUpdatedWorkspaceItems(emptyList())
|
||||
assertThat(mAllAppsList.getAndResetChangeFlag()).isFalse()
|
||||
assertThat(appsListRepo.appsListStateFlow.value.apps).isEmpty()
|
||||
}
|
||||
|
||||
@EnableFlags(FLAG_ENABLE_PRIVATE_SPACE)
|
||||
|
||||
@@ -35,6 +35,9 @@ import com.android.launcher3.icons.cache.CachingLogic
|
||||
import com.android.launcher3.icons.cache.IconCacheUpdateHandler
|
||||
import com.android.launcher3.model.LoaderTask.LoaderTaskFactory
|
||||
import com.android.launcher3.model.data.AppInfo
|
||||
import com.android.launcher3.model.data.AppsListData.Companion.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED
|
||||
import com.android.launcher3.model.data.AppsListData.Companion.FLAG_QUIET_MODE_ENABLED
|
||||
import com.android.launcher3.model.data.AppsListData.Companion.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED
|
||||
import com.android.launcher3.model.data.IconRequestInfo
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo
|
||||
import com.android.launcher3.pm.UserCache
|
||||
@@ -243,12 +246,9 @@ class LoaderTaskTest {
|
||||
.newLoaderTask(launcherBinder, userManagerState)
|
||||
.runSyncOnBackgroundThread()
|
||||
|
||||
verify(bgAllAppsList)
|
||||
.setFlags(BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED, true)
|
||||
verify(bgAllAppsList)
|
||||
.setFlags(BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED, false)
|
||||
verify(bgAllAppsList, Mockito.never())
|
||||
.setFlags(BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED, true)
|
||||
verify(bgAllAppsList).setFlags(FLAG_WORK_PROFILE_QUIET_MODE_ENABLED, true)
|
||||
verify(bgAllAppsList).setFlags(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED, false)
|
||||
verify(bgAllAppsList, Mockito.never()).setFlags(FLAG_QUIET_MODE_ENABLED, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -266,12 +266,9 @@ class LoaderTaskTest {
|
||||
.newLoaderTask(launcherBinder, userManagerState)
|
||||
.runSyncOnBackgroundThread()
|
||||
|
||||
verify(bgAllAppsList)
|
||||
.setFlags(BgDataModel.Callbacks.FLAG_WORK_PROFILE_QUIET_MODE_ENABLED, false)
|
||||
verify(bgAllAppsList)
|
||||
.setFlags(BgDataModel.Callbacks.FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED, true)
|
||||
verify(bgAllAppsList, Mockito.never())
|
||||
.setFlags(BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED, true)
|
||||
verify(bgAllAppsList).setFlags(FLAG_WORK_PROFILE_QUIET_MODE_ENABLED, false)
|
||||
verify(bgAllAppsList).setFlags(FLAG_PRIVATE_PROFILE_QUIET_MODE_ENABLED, true)
|
||||
verify(bgAllAppsList, Mockito.never()).setFlags(FLAG_QUIET_MODE_ENABLED, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user