diff --git a/AndroidManifest.xml b/AndroidManifest.xml index bc0cd97685..b031ffbee4 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -49,7 +49,7 @@ android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto index 561196941c..1a8ab65370 100644 --- a/protos/launcher_atom.proto +++ b/protos/launcher_atom.proto @@ -55,6 +55,7 @@ message ContainerInfo { SettingsContainer settings_container = 9; PredictedHotseatContainer predicted_hotseat_container = 10; TaskSwitcherContainer task_switcher_container = 11; + TaskForegroundContainer task_foreground_container = 12; } } @@ -92,8 +93,14 @@ message ShortcutsContainer { message SettingsContainer { } -message TaskSwitcherContainer { -} +// Container for tasks in the Overview UI. +// Typically entered using either the overview gesture or overview button. +message TaskSwitcherContainer {} + +// Container for tasks from another foreground app, when not on launcher screen. +// Typically home gesture or overview gesture can be triggered from +// this container. +message TaskForegroundContainer {} enum Attribute { UNKNOWN = 0; diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml index d680507e3b..60afddb0a8 100644 --- a/quickstep/AndroidManifest-launcher.xml +++ b/quickstep/AndroidManifest-launcher.xml @@ -49,7 +49,7 @@ android:stateNotNeeded="true" android:windowSoftInputMode="adjustPan" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index bb83b761e7..e49f2ecdc0 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -60,7 +60,7 @@ android:stateNotNeeded="true" android:theme="@style/LauncherTheme" android:screenOrientation="unspecified" - android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode" + android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize" android:resizeableActivity="true" android:resumeWhilePausing="true" android:taskAffinity="" /> diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java index 0aa14862a7..f4687884bf 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandlerV2.java @@ -47,6 +47,7 @@ import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.TargetApi; import android.app.ActivityManager; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.graphics.PointF; @@ -62,12 +63,14 @@ import androidx.annotation.UiThread; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.DeviceProfile; +import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.UserEventDispatcher; +import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; @@ -717,6 +720,8 @@ public abstract class BaseSwipeUpHandlerV2, Q exte } private void onSettledOnEndTarget() { + // Fast-finish the attaching animation if it's still running. + maybeUpdateRecentsAttachedState(false); switch (mGestureState.getEndTarget()) { case HOME: mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT); @@ -928,12 +933,25 @@ public abstract class BaseSwipeUpHandlerV2, Q exte default: event = IGNORE; } + ComponentName componentName = mGestureState.getRunningTask().baseActivity; StatsLogManager.newInstance(mContext).logger() .withSrcState(LAUNCHER_STATE_BACKGROUND) .withDstState(StatsLogManager.containerTypeToAtomState(endTarget.containerType)) + .withItemInfo(getItemInfo(componentName)) .log(event); } + /** + * Builds proto for logging + */ + public WorkspaceItemInfo getItemInfo(ComponentName componentName) { + WorkspaceItemInfo placeholderInfo = new WorkspaceItemInfo(); + placeholderInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK; + placeholderInfo.container = LauncherSettings.Favorites.CONTAINER_TASKFOREGROUND; + placeholderInfo.intent = new Intent().setComponent(componentName); + return placeholderInfo; + } + /** Animates to the given progress, where 0 is the current app and 1 is overview. */ @UiThread private void animateToProgress(float start, float end, long duration, Interpolator interpolator, diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java index 16bd9ed384..7a7cbb4d9b 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/StatusBarTouchController.java @@ -19,6 +19,7 @@ import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.ACTION_CANCEL; +import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN; import android.graphics.PointF; import android.util.SparseArray; @@ -136,6 +137,8 @@ public class StatusBarTouchController implements TouchController { mLauncher.getUserEventDispatcher().logActionOnContainer(action == ACTION_UP ? Touch.FLING : Touch.SWIPE, Direction.DOWN, ContainerType.WORKSPACE, mLauncher.getWorkspace().getCurrentPage()); + mLauncher.getStatsLogManager().logger() + .log(LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN); setWindowSlippery(false); return true; } diff --git a/robolectric_tests/src/com/android/launcher3/model/LoaderCursorTest.java b/robolectric_tests/src/com/android/launcher3/model/LoaderCursorTest.java index 9aa4a9e714..3a252dcce9 100644 --- a/robolectric_tests/src/com/android/launcher3/model/LoaderCursorTest.java +++ b/robolectric_tests/src/com/android/launcher3/model/LoaderCursorTest.java @@ -136,7 +136,7 @@ public class LoaderCursorTest { initCursor(ITEM_TYPE_APPLICATION, ""); assertTrue(mLoaderCursor.moveToNext()); - ComponentName cn = new ComponentName(mContext.getPackageName(), "placeholder-do"); + ComponentName cn = new ComponentName(mContext.getPackageName(), "dummy-do"); WorkspaceItemInfo info = Executors.MODEL_EXECUTOR.submit(() -> mLoaderCursor.getAppShortcutInfo( new Intent().setComponent(cn), true /* allowMissingTarget */, true)) diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index 833ce1501d..f2a5c656ff 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -42,7 +42,6 @@ import android.widget.Toast; import androidx.annotation.Nullable; -import com.android.launcher3.Launcher.OnResumeCallback; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.InstanceIdSequence; @@ -109,20 +108,10 @@ public abstract class BaseDraggingActivity extends BaseActivity private void updateTheme() { if (mThemeRes != Themes.getActivityThemeRes(this)) { - // Workaround (b/162812884): The system currently doesn't allow recreating an activity - // when it is not resumed, in such a case defer recreation until it is possible - if (hasBeenResumed()) { - recreate(); - } else { - addOnResumeCallback(this::recreate); - } + recreate(); } } - protected void addOnResumeCallback(OnResumeCallback callback) { - // To be overridden - } - @Override public void onActionModeStarted(ActionMode mode) { super.onActionModeStarted(mode); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index dede9542a1..ae89deda47 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -18,6 +18,7 @@ package com.android.launcher3; import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION; import static android.content.pm.ActivityInfo.CONFIG_SCREEN_SIZE; +import static android.content.pm.ActivityInfo.CONFIG_UI_MODE; import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED; import static com.android.launcher3.AbstractFloatingView.TYPE_ALL; @@ -1103,7 +1104,11 @@ public class Launcher extends StatefulActivity implements Launche int stateOrdinal = savedState.getInt(RUNTIME_STATE, NORMAL.ordinal); LauncherState[] stateValues = LauncherState.values(); LauncherState state = stateValues[stateOrdinal]; - if (!state.shouldDisableRestore()) { + + NonConfigInstance lastInstance = (NonConfigInstance) getLastNonConfigurationInstance(); + boolean forceRestore = lastInstance != null + && (lastInstance.config.diff(mOldConfig) & CONFIG_UI_MODE) != 0; + if (forceRestore || !state.shouldDisableRestore()) { mStateManager.goToState(state, false /* animated */); } @@ -1343,6 +1348,13 @@ public class Launcher extends StatefulActivity implements Launche closeContextMenu(); } + @Override + public Object onRetainNonConfigurationInstance() { + NonConfigInstance instance = new NonConfigInstance(); + instance.config = new Configuration(mOldConfig); + return instance; + } + public AllAppsTransitionController getAllAppsController() { return mAllAppsController; } @@ -1944,7 +1956,6 @@ public class Launcher extends StatefulActivity implements Launche return result; } - @Override public void addOnResumeCallback(OnResumeCallback callback) { mOnResumeCallbacks.add(callback); } @@ -2746,4 +2757,8 @@ public class Launcher extends StatefulActivity implements Launche void onLauncherResume(); } + + private static class NonConfigInstance { + public Configuration config; + } } diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java index 58a418edec..a1ac229ae7 100644 --- a/src/com/android/launcher3/LauncherSettings.java +++ b/src/com/android/launcher3/LauncherSettings.java @@ -164,6 +164,7 @@ public class LauncherSettings { public static final int CONTAINER_SHORTCUTS = -107; public static final int CONTAINER_SETTINGS = -108; public static final int CONTAINER_TASKSWITCHER = -109; + public static final int CONTAINER_TASKFOREGROUND = -110; public static final String containerToString(int container) { switch (container) { diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java index e754618a10..c4a4c98699 100644 --- a/src/com/android/launcher3/logging/StatsLogManager.java +++ b/src/com/android/launcher3/logging/StatsLogManager.java @@ -319,8 +319,10 @@ public class StatsLogManager implements ResourceBasedOverride { LAUNCHER_NAVIGATION_MODE_GESTURE_BUTTON(625), @UiEvent(doc = "User tapped on image content in Overview Select mode.") - LAUNCHER_SELECT_MODE_IMAGE(627); + LAUNCHER_SELECT_MODE_IMAGE(627), + @UiEvent(doc = "User swiped down on workspace (triggering noti shade to open).") + LAUNCHER_SWIPE_DOWN_WORKSPACE_NOTISHADE_OPEN(651); // ADD MORE private final int mId; diff --git a/src/com/android/launcher3/model/AppLaunchTracker.java b/src/com/android/launcher3/model/AppLaunchTracker.java index 629a0ee496..906c2e018b 100644 --- a/src/com/android/launcher3/model/AppLaunchTracker.java +++ b/src/com/android/launcher3/model/AppLaunchTracker.java @@ -41,6 +41,7 @@ public class AppLaunchTracker implements ResourceBasedOverride { public static final String CONTAINER_PREDICTIONS = Integer.toString(ContainerType.PREDICTION); public static final String CONTAINER_SEARCH = Integer.toString(ContainerType.SEARCHRESULT); public static final String CONTAINER_OVERVIEW = Integer.toString(ContainerType.OVERVIEW); + public static final String CONTAINER_HOTSEAT = Integer.toString(ContainerType.HOTSEAT); public static final MainThreadInitializedObject INSTANCE = diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java index 0d3ddad183..b9b3d382c8 100644 --- a/src/com/android/launcher3/model/data/ItemInfo.java +++ b/src/com/android/launcher3/model/data/ItemInfo.java @@ -24,6 +24,7 @@ import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICT import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SEARCH_RESULTS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SETTINGS; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS; +import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_TASKFOREGROUND; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_TASKSWITCHER; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY; import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; @@ -51,6 +52,7 @@ import com.android.launcher3.logger.LauncherAtom.PredictionContainer; import com.android.launcher3.logger.LauncherAtom.SearchResultContainer; import com.android.launcher3.logger.LauncherAtom.SettingsContainer; import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer; +import com.android.launcher3.logger.LauncherAtom.TaskForegroundContainer; import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer; import com.android.launcher3.model.ModelWriter; import com.android.launcher3.util.ContentWriter; @@ -392,6 +394,11 @@ public class ItemInfo { return ContainerInfo.newBuilder() .setTaskSwitcherContainer(TaskSwitcherContainer.getDefaultInstance()) .build(); + case CONTAINER_TASKFOREGROUND: + return ContainerInfo.newBuilder() + .setTaskForegroundContainer(TaskForegroundContainer.getDefaultInstance()) + .build(); + } return ContainerInfo.getDefaultInstance(); diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java index dbe5f42e31..601e117f1c 100644 --- a/src/com/android/launcher3/statemanager/StatefulActivity.java +++ b/src/com/android/launcher3/statemanager/StatefulActivity.java @@ -121,7 +121,9 @@ public abstract class StatefulActivity> final int origDragLayerChildCount = dragLayer.getChildCount(); super.onStop(); - getStateManager().moveToRestState(); + if (!isChangingConfigurations()) { + getStateManager().moveToRestState(); + } // Workaround for b/78520668, explicitly trim memory once UI is hidden onTrimMemory(TRIM_MEMORY_UI_HIDDEN); diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java index 848666674d..f50b2b30de 100644 --- a/src/com/android/launcher3/touch/ItemClickHandler.java +++ b/src/com/android/launcher3/touch/ItemClickHandler.java @@ -19,6 +19,7 @@ import static com.android.launcher3.Launcher.REQUEST_BIND_PENDING_APPWIDGET; import static com.android.launcher3.Launcher.REQUEST_RECONFIGURE_APPWIDGET; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_OPEN; import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_ALL_APPS; +import static com.android.launcher3.model.AppLaunchTracker.CONTAINER_HOTSEAT; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_BY_PUBLISHER; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_LOCKED_USER; import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_DISABLED_QUIET_USER; @@ -42,6 +43,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.BubbleTextView; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherAppWidgetProviderInfo; +import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.folder.Folder; @@ -240,6 +242,12 @@ public class ItemClickHandler { } } + if (sourceContainer == null && ( + shortcut.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT + || shortcut.container + == LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION)) { + sourceContainer = CONTAINER_HOTSEAT; + } // Start activities startAppShortcutOrInfoActivity(v, shortcut, launcher, sourceContainer); } diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml index 33c8fbd96e..1c8f095810 100644 --- a/tests/AndroidManifest-common.xml +++ b/tests/AndroidManifest-common.xml @@ -92,7 +92,7 @@