diff options
Diffstat (limited to 'quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java')
-rw-r--r-- | quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java | 140 |
1 files changed, 123 insertions, 17 deletions
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java index a9c2a5e51d..4d0695631c 100644 --- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java +++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java @@ -25,7 +25,13 @@ import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICA import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.Utilities.getDevicePrefs; import static com.android.launcher3.hybridhotseat.HotseatPredictionModel.convertDataModelToAppTargetBundle; +import static com.android.launcher3.model.PredictionHelper.getAppTargetFromItemInfo; +import static com.android.launcher3.model.PredictionHelper.wrapAppTargetWithItemLocation; +import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import static java.util.stream.Collectors.toCollection; + +import android.app.StatsManager; import android.app.prediction.AppPredictionContext; import android.app.prediction.AppPredictionManager; import android.app.prediction.AppPredictor; @@ -37,15 +43,17 @@ import android.content.SharedPreferences; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; import android.content.pm.ShortcutInfo; +import android.os.Bundle; import android.os.UserHandle; import android.util.Log; +import android.util.StatsEvent; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.InvariantDeviceProfile.OnIDPChangeListener; import com.android.launcher3.LauncherAppState; +import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.InstanceIdSequence; import com.android.launcher3.model.BgDataModel.FixedContainerItems; @@ -54,11 +62,13 @@ import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.shortcuts.ShortcutKey; -import com.android.launcher3.util.Executors; import com.android.launcher3.util.IntSparseArrayMap; import com.android.launcher3.util.PersistedItemArray; +import com.android.quickstep.logging.SettingsChangeLogger; import com.android.quickstep.logging.StatsLogCompatManager; +import com.android.systemui.shared.system.SysUiStatsLog; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; @@ -68,10 +78,11 @@ import java.util.stream.IntStream; /** * Model delegate which loads prediction items */ -public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChangeListener { +public class QuickstepModelDelegate extends ModelDelegate { public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state"; private static final String LAST_SNAPSHOT_TIME_MILLIS = "LAST_SNAPSHOT_TIME_MILLIS"; + private static final String BUNDLE_KEY_ADDED_APP_WIDGETS = "added_app_widgets"; private static final int NUM_OF_RECOMMENDED_WIDGETS_PREDICATION = 20; private static final boolean IS_DEBUG = false; @@ -86,15 +97,18 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange private final InvariantDeviceProfile mIDP; private final AppEventProducer mAppEventProducer; + private final StatsManager mStatsManager; + private final Context mContext; protected boolean mActive = false; public QuickstepModelDelegate(Context context) { + mContext = context; mAppEventProducer = new AppEventProducer(context, this::onAppTargetEvent); mIDP = InvariantDeviceProfile.INSTANCE.get(context); - mIDP.addOnChangeListener(this); StatsLogCompatManager.LOGS_CONSUMER.add(mAppEventProducer); + mStatsManager = context.getSystemService(StatsManager.class); } @Override @@ -150,17 +164,82 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange } InstanceId instanceId = new InstanceIdSequence().newInstanceId(); for (ItemInfo info : itemsIdMap) { - FolderInfo parent = info.container > 0 - ? (FolderInfo) itemsIdMap.get(info.container) : null; + FolderInfo parent = getContainer(info, itemsIdMap); StatsLogCompatManager.writeSnapshot(info.buildProto(parent), instanceId); } additionalSnapshotEvents(instanceId); prefs.edit().putLong(LAST_SNAPSHOT_TIME_MILLIS, now).apply(); } + + // Only register for launcher snapshot logging if this is the primary ModelDelegate + // instance, as there will be additional instances that may be destroyed at any time. + if (mIsPrimaryInstance) { + registerSnapshotLoggingCallback(); + } } protected void additionalSnapshotEvents(InstanceId snapshotInstanceId){} + /** + * Registers a callback to log launcher workspace layout using Statsd pulled atom. + */ + protected void registerSnapshotLoggingCallback() { + if (mStatsManager == null) { + Log.d(TAG, "Failed to get StatsManager"); + } + + try { + mStatsManager.setPullAtomCallback( + SysUiStatsLog.LAUNCHER_LAYOUT_SNAPSHOT, + null /* PullAtomMetadata */, + MODEL_EXECUTOR, + (i, eventList) -> { + InstanceId instanceId = new InstanceIdSequence().newInstanceId(); + IntSparseArrayMap<ItemInfo> itemsIdMap; + synchronized (mDataModel) { + itemsIdMap = mDataModel.itemsIdMap.clone(); + } + + for (ItemInfo info : itemsIdMap) { + FolderInfo parent = getContainer(info, itemsIdMap); + LauncherAtom.ItemInfo itemInfo = info.buildProto(parent); + Log.d(TAG, itemInfo.toString()); + StatsEvent statsEvent = StatsLogCompatManager.buildStatsEvent(itemInfo, + instanceId); + eventList.add(statsEvent); + } + Log.d(TAG, + String.format( + "Successfully logged %d workspace items with instanceId=%d", + itemsIdMap.size(), instanceId.getId())); + additionalSnapshotEvents(instanceId); + SettingsChangeLogger.INSTANCE.get(mContext).logSnapshot(instanceId); + return StatsManager.PULL_SUCCESS; + } + ); + Log.d(TAG, "Successfully registered for launcher snapshot logging!"); + } catch (RuntimeException e) { + Log.e(TAG, "Failed to register launcher snapshot logging callback with StatsManager", + e); + } + } + + private static FolderInfo getContainer(ItemInfo info, IntSparseArrayMap<ItemInfo> itemsIdMap) { + if (info.container > 0) { + ItemInfo containerInfo = itemsIdMap.get(info.container); + + if (!(containerInfo instanceof FolderInfo)) { + Log.e(TAG, String.format( + "Item info: %s found with invalid container: %s", + info, + containerInfo)); + } else { + return (FolderInfo) containerInfo; + } + } + return null; + } + @Override public void validateData() { super.validateData(); @@ -177,9 +256,10 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange super.destroy(); mActive = false; StatsLogCompatManager.LOGS_CONSUMER.remove(mAppEventProducer); - + if (mIsPrimaryInstance) { + mStatsManager.clearPullAtomCallback(SysUiStatsLog.LAUNCHER_LAYOUT_SNAPSHOT); + } destroyPredictors(); - mIDP.removeOnChangeListener(this); } private void destroyPredictors() { @@ -217,6 +297,7 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange registerWidgetsPredictor(apm.createAppPredictionSession( new AppPredictionContext.Builder(context) .setUiSurface("widgets") + .setExtras(getBundleForWidgetsOnWorkspace(context, mDataModel)) .setPredictedTargetCount(NUM_OF_RECOMMENDED_WIDGETS_PREDICATION) .build())); } @@ -224,7 +305,7 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange private void registerPredictor(PredictorState state, AppPredictor predictor) { state.predictor = predictor; state.predictor.registerPredictionUpdates( - Executors.MODEL_EXECUTOR, t -> handleUpdate(state, t)); + MODEL_EXECUTOR, t -> handleUpdate(state, t)); state.predictor.requestPredictionUpdate(); } @@ -239,7 +320,7 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange private void registerWidgetsPredictor(AppPredictor predictor) { mWidgetsRecommendationState.predictor = predictor; mWidgetsRecommendationState.predictor.registerPredictionUpdates( - Executors.MODEL_EXECUTOR, targets -> { + MODEL_EXECUTOR, targets -> { if (mWidgetsRecommendationState.setTargets(targets)) { // No diff, skip return; @@ -250,19 +331,44 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange mWidgetsRecommendationState.predictor.requestPredictionUpdate(); } - @Override - public void onIdpChanged(InvariantDeviceProfile profile) { - // Reinitialize everything - Executors.MODEL_EXECUTOR.execute(this::recreatePredictors); - } - private void onAppTargetEvent(AppTargetEvent event, int client) { - PredictorState state = client == CONTAINER_PREDICTION ? mAllAppsState : mHotseatState; + PredictorState state; + switch(client) { + case CONTAINER_PREDICTION: + state = mAllAppsState; + break; + case CONTAINER_WIDGETS_PREDICTION: + state = mWidgetsRecommendationState; + break; + case CONTAINER_HOTSEAT_PREDICTION: + default: + state = mHotseatState; + break; + } if (state.predictor != null) { state.predictor.notifyAppTargetEvent(event); + Log.d(TAG, "notifyAppTargetEvent action=" + event.getAction() + + " launchLocation=" + event.getLaunchLocation()); } } + private Bundle getBundleForWidgetsOnWorkspace(Context context, BgDataModel dataModel) { + Bundle bundle = new Bundle(); + ArrayList<AppTargetEvent> widgetEvents = + dataModel.getAllWorkspaceItems().stream() + .filter(PredictionHelper::isTrackedForWidgetPrediction) + .map(item -> { + AppTarget target = getAppTargetFromItemInfo(context, item); + if (target == null) return null; + return wrapAppTargetWithItemLocation( + target, AppTargetEvent.ACTION_PIN, item); + }) + .filter(Objects::nonNull) + .collect(toCollection(ArrayList::new)); + bundle.putParcelableArrayList(BUNDLE_KEY_ADDED_APP_WIDGETS, widgetEvents); + return bundle; + } + static class PredictorState { public final FixedContainerItems items; |