Merge "Moving removing task after QS to a background thread."
diff --git a/Android.mk b/Android.mk
index 349a134..503f9ae 100644
--- a/Android.mk
+++ b/Android.mk
@@ -208,11 +208,13 @@
LOCAL_SRC_FILES := \
$(call all-java-files-under, src) \
$(call all-java-files-under, quickstep/src) \
- $(call all-java-files-under, go/src)
+ $(call all-java-files-under, go/src) \
+ $(call all-java-files-under, go/quickstep/src)
LOCAL_RESOURCE_DIR := \
$(LOCAL_PATH)/quickstep/res \
- $(LOCAL_PATH)/go/res
+ $(LOCAL_PATH)/go/res \
+ $(LOCAL_PATH)/go/quickstep/res
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
LOCAL_PROGUARD_ENABLED := full
@@ -225,7 +227,7 @@
LOCAL_FULL_LIBS_MANIFEST_FILES := \
$(LOCAL_PATH)/go/AndroidManifest.xml \
- $(LOCAL_PATH)/quickstep/AndroidManifest-launcher.xml \
+ $(LOCAL_PATH)/go/AndroidManifest-launcher.xml \
$(LOCAL_PATH)/AndroidManifest-common.xml
LOCAL_MANIFEST_FILE := quickstep/AndroidManifest.xml
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index a47a500..9e76ce3 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -40,6 +40,8 @@
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
<uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
<uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
+ <!-- for rotating surface by arbitrary degree -->
+ <uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
<!--
Permissions required for read/write access to the workspace data. These permission name
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 97bce9c..56a2595 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/go/AndroidManifest-launcher.xml b/go/AndroidManifest-launcher.xml
new file mode 100644
index 0000000..2223036
--- /dev/null
+++ b/go/AndroidManifest-launcher.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2020, 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.
+*/
+-->
+<manifest
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.launcher3">
+ <uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
+ <!--
+ Manifest entries specific to Launcher3. This is merged with AndroidManifest-common.xml.
+ Refer comments around specific entries on how to extend individual components.
+ -->
+
+ <application
+ android:backupAgent="com.android.launcher3.LauncherBackupAgent"
+ android:fullBackupOnly="true"
+ android:fullBackupContent="@xml/backupscheme"
+ android:hardwareAccelerated="true"
+ android:icon="@drawable/ic_launcher_home"
+ android:label="@string/derived_app_name"
+ android:theme="@style/AppTheme"
+ android:largeHeap="@bool/config_largeHeap"
+ android:restoreAnyVersion="true"
+ android:supportsRtl="true" >
+
+ <!--
+ Main launcher activity. When extending only change the name, and keep all the
+ attributes and intent filters the same
+ -->
+ <activity
+ android:name="com.android.launcher3.Launcher3QuickStepGo"
+ android:launchMode="singleTask"
+ android:clearTaskOnLaunch="true"
+ android:stateNotNeeded="true"
+ android:windowSoftInputMode="adjustPan"
+ android:screenOrientation="unspecified"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
+ android:resizeableActivity="true"
+ android:resumeWhilePausing="true"
+ android:taskAffinity=""
+ android:exported="true"
+ android:enabled="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.HOME" />
+ <category android:name="android.intent.category.DEFAULT" />
+ <category android:name="android.intent.category.MONKEY"/>
+ <category android:name="android.intent.category.LAUNCHER_APP" />
+ </intent-filter>
+ <meta-data
+ android:name="com.android.launcher3.grid.control"
+ android:value="${packageName}.grid_control" />
+ </activity>
+
+ </application>
+</manifest>
diff --git a/go/quickstep/res/values/config.xml b/go/quickstep/res/values/config.xml
new file mode 100644
index 0000000..f376774
--- /dev/null
+++ b/go/quickstep/res/values/config.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<resources>
+ <string name="app_sharing_component" translatable="false"/>
+</resources>
\ No newline at end of file
diff --git a/go/quickstep/res/values/strings.xml b/go/quickstep/res/values/strings.xml
new file mode 100644
index 0000000..fdd8397
--- /dev/null
+++ b/go/quickstep/res/values/strings.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Label for app share drop target. [CHAR_LIMIT=20] -->
+ <string name="app_share_drop_target_label">Share App</string>
+</resources>
diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java
new file mode 100644
index 0000000..b72e71c
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/AppSharing.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2020 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;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+
+import androidx.core.content.FileProvider;
+
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.popup.SystemShortcut;
+
+import java.io.File;
+
+/**
+ * Defines the Share system shortcut and its factory.
+ * This shortcut can be added to the app long-press menu on the home screen.
+ * Clicking the button will initiate peer-to-peer sharing of the app.
+ */
+public final class AppSharing {
+ /**
+ * This flag enables this feature. It is defined here rather than in launcher3's FeatureFlags
+ * because it is unique to Go and not toggleable at runtime.
+ */
+ public static final boolean ENABLE_APP_SHARING = true;
+
+ private static final String TAG = "AppSharing";
+ private static final String FILE_PROVIDER_SUFFIX = ".overview.fileprovider";
+ private static final String APP_EXSTENSION = ".apk";
+ private static final String APP_MIME_TYPE = "application/application";
+
+ private final String mSharingComponent;
+
+ private AppSharing(Launcher launcher) {
+ mSharingComponent = launcher.getText(R.string.app_sharing_component).toString();
+ }
+
+ private boolean canShare(ItemInfo info) {
+ /**
+ * TODO: Implement once b/168831749 has been resolved
+ * The implementation should check the validity of the app.
+ * It should also check whether the app is free or paid, returning false in the latter case.
+ * For now, all checks occur in the sharing app.
+ * So, we simply check whether the sharing app is defined.
+ */
+ return !TextUtils.isEmpty(mSharingComponent);
+ }
+
+ private Uri getShareableUri(Context context, String path, String displayName) {
+ String authority = BuildConfig.APPLICATION_ID + FILE_PROVIDER_SUFFIX;
+ File pathFile = new File(path);
+ return FileProvider.getUriForFile(context, authority, pathFile, displayName);
+ }
+
+ private SystemShortcut<Launcher> getShortcut(Launcher launcher, ItemInfo info) {
+ if (!canShare(info)) {
+ return null;
+ }
+
+ return new Share(launcher, info);
+ }
+
+ /**
+ * The Share App system shortcut, used to initiate p2p sharing of a given app
+ */
+ public final class Share extends SystemShortcut<Launcher> {
+ public Share(Launcher target, ItemInfo itemInfo) {
+ super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo);
+ }
+
+ @Override
+ public void onClick(View view) {
+ Intent sendIntent = new Intent();
+ sendIntent.setAction(Intent.ACTION_SEND);
+
+ ComponentName targetComponent = mItemInfo.getTargetComponent();
+ if (targetComponent == null) {
+ Log.e(TAG, "Item missing target component");
+ return;
+ }
+ String packageName = targetComponent.getPackageName();
+ PackageManager packageManager = view.getContext().getPackageManager();
+ String sourceDir, appLabel;
+ try {
+ PackageInfo packageInfo = packageManager.getPackageInfo(packageName, 0);
+ sourceDir = packageInfo.applicationInfo.sourceDir;
+ appLabel = packageManager.getApplicationLabel(packageInfo.applicationInfo)
+ .toString() + APP_EXSTENSION;
+ } catch (Exception e) {
+ Log.e(TAG, "Could not find info for package \"" + packageName + "\"");
+ return;
+ }
+ Uri uri = getShareableUri(view.getContext(), sourceDir, appLabel);
+ sendIntent.putExtra(Intent.EXTRA_STREAM, uri);
+ sendIntent.putExtra(Intent.EXTRA_PACKAGE_NAME, packageName);
+
+ sendIntent.setType(APP_MIME_TYPE);
+ sendIntent.setComponent(ComponentName.unflattenFromString(mSharingComponent));
+
+ mTarget.startActivitySafely(view, sendIntent, mItemInfo);
+
+ AbstractFloatingView.closeAllOpenViews(mTarget);
+ }
+ }
+
+ /**
+ * Shortcut factory for generating the Share App button
+ */
+ public static final SystemShortcut.Factory<Launcher> SHORTCUT_FACTORY = (launcher, itemInfo) ->
+ (new AppSharing(launcher)).getShortcut(launcher, itemInfo);
+}
diff --git a/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java b/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java
new file mode 100644
index 0000000..8bd0fec
--- /dev/null
+++ b/go/quickstep/src/com/android/launcher3/Launcher3QuickStepGo.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 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;
+
+import com.android.launcher3.popup.SystemShortcut;
+import com.android.launcher3.uioverrides.QuickstepLauncher;
+
+import java.util.stream.Stream;
+
+/**
+ * The Launcher variant used for Android Go Edition
+ */
+public class Launcher3QuickStepGo extends QuickstepLauncher {
+ private static final String TAG = "Launcher3QuickStepGo";
+
+ @Override
+ public Stream<SystemShortcut.Factory> getSupportedShortcuts() {
+ Stream<SystemShortcut.Factory> shortcuts = super.getSupportedShortcuts();
+
+ if (AppSharing.ENABLE_APP_SHARING) {
+ shortcuts = Stream.concat(shortcuts, Stream.of(AppSharing.SHORTCUT_FACTORY));
+ }
+
+ return shortcuts;
+ }
+}
diff --git a/quickstep/AndroidManifest-launcher.xml b/quickstep/AndroidManifest-launcher.xml
index 19f85e4..53910e3 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 5be32a8..4e7c3fa 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -59,7 +59,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/res/drawable/default_sandbox_app_icon.xml b/quickstep/res/drawable/default_sandbox_app_icon.xml
new file mode 100644
index 0000000..e9c9701
--- /dev/null
+++ b/quickstep/res/drawable/default_sandbox_app_icon.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="@color/gesture_tutorial_fake_task_view_color" />
+</shape>
diff --git a/quickstep/res/drawable/default_sandbox_app_task_thumbnail.xml b/quickstep/res/drawable/default_sandbox_app_task_thumbnail.xml
new file mode 100644
index 0000000..9d4cc95
--- /dev/null
+++ b/quickstep/res/drawable/default_sandbox_app_task_thumbnail.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@color/gesture_tutorial_fake_task_view_color" />
+</shape>
diff --git a/quickstep/res/drawable/default_sandbox_wallpaper.xml b/quickstep/res/drawable/default_sandbox_wallpaper.xml
new file mode 100644
index 0000000..816d1d6
--- /dev/null
+++ b/quickstep/res/drawable/default_sandbox_wallpaper.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 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.
+-->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="?android:attr/colorBackground" />
+</shape>
diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml
index 52475df..2ff3a5e 100644
--- a/quickstep/res/layout/gesture_tutorial_fragment.xml
+++ b/quickstep/res/layout/gesture_tutorial_fragment.xml
@@ -16,8 +16,7 @@
<com.android.quickstep.interaction.RootSandboxLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="?android:attr/colorBackground">
+ android:layout_height="match_parent">
<View
android:id="@+id/gesture_tutorial_ripple_view"
@@ -29,15 +28,12 @@
android:id="@+id/gesture_tutorial_fake_icon_view"
android:layout_width="20dp"
android:layout_height="20dp"
- android:background="@drawable/bg_circle"
- android:backgroundTint="@color/gesture_tutorial_fake_task_view_color"
android:visibility="invisible" />
<View
android:id="@+id/gesture_tutorial_fake_task_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/gesture_tutorial_fake_task_view_color"
android:visibility="invisible" />
<ImageView
diff --git a/quickstep/res/xml/overview_file_provider_paths.xml b/quickstep/res/xml/overview_file_provider_paths.xml
index 14d7459..07e3236 100644
--- a/quickstep/res/xml/overview_file_provider_paths.xml
+++ b/quickstep/res/xml/overview_file_provider_paths.xml
@@ -2,4 +2,5 @@
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<cache-path name="shared_images" path="/" />
<files-path name="log_files" path="/" />
+ <root-path name="apps" path="/" />
</paths>
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index c59c045..4dbc0f3 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -19,7 +19,9 @@
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
+import static com.android.launcher3.QuickstepAppTransitionManagerImpl.RECENTS_LAUNCH_DURATION;
import static com.android.launcher3.QuickstepAppTransitionManagerImpl.TRANSITION_OPEN_LAUNCHER;
+import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
@@ -52,6 +54,7 @@
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Matrix;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
@@ -92,7 +95,7 @@
import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.MotionPauseDetector;
-import com.android.quickstep.util.RecentsOrientedState;
+import com.android.quickstep.util.MultiValueUpdateListener;
import com.android.quickstep.util.ProtoTracer;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.RectFSpringAnim;
@@ -108,6 +111,7 @@
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
+import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
import com.android.systemui.shared.system.TaskInfoCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -1498,17 +1502,36 @@
}
private void launchOtherTaskInLiveTileMode(int taskId, RemoteAnimationTargetCompat[] apps) {
- TaskView taskView = mRecentsView.getTaskView(taskId);
- if (taskView == null) {
- return;
- }
-
AnimatorSet anim = new AnimatorSet();
- TaskViewUtils.composeRecentsLaunchAnimator(
- anim, taskView, apps,
- mRecentsAnimationTargets.wallpapers, true /* launcherClosing */,
- mActivity.getStateManager(), mRecentsView,
- mActivityInterface.getDepthController());
+ TaskView taskView = mRecentsView.getTaskView(taskId);
+ if (taskView == null || !mRecentsView.isTaskViewVisible(taskView)) {
+ // TODO: Refine this animation.
+ SurfaceTransactionApplier surfaceApplier =
+ new SurfaceTransactionApplier(mActivity.getDragLayer());
+ ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
+ appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
+ appAnimator.setInterpolator(ACCEL_DEACCEL);
+ appAnimator.addUpdateListener(new MultiValueUpdateListener() {
+ @Override
+ public void onUpdate(float percent) {
+ SurfaceParams.Builder builder = new SurfaceParams.Builder(
+ apps[apps.length - 1].leash);
+ Matrix matrix = new Matrix();
+ matrix.postScale(percent, percent);
+ matrix.postTranslate(mDp.widthPx * (1 - percent) / 2,
+ mDp.heightPx * (1 - percent) / 2);
+ builder.withAlpha(percent).withMatrix(matrix);
+ surfaceApplier.scheduleApply(builder.build());
+ }
+ });
+ anim.play(appAnimator);
+ } else {
+ TaskViewUtils.composeRecentsLaunchAnimator(
+ anim, taskView, apps,
+ mRecentsAnimationTargets.wallpapers, true /* launcherClosing */,
+ mActivity.getStateManager(), mRecentsView,
+ mActivityInterface.getDepthController());
+ }
anim.addListener(new AnimatorListenerAdapter(){
@Override
diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java
index 2aed76a..9da306e 100644
--- a/quickstep/src/com/android/quickstep/TaskViewUtils.java
+++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java
@@ -312,8 +312,10 @@
windowAnimEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- stateManager.moveToRestState();
- stateManager.reapplyState();
+ recentsView.post(() -> {
+ stateManager.moveToRestState();
+ stateManager.reapplyState();
+ });
}
};
} else {
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
index 22bd334..b10bdde 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java
@@ -54,6 +54,7 @@
private final PointF mLastPos = new PointF();
private boolean mPassedSlop;
+ private boolean mIsStopGesture;
public OneHandedModeInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
InputConsumer delegate, InputMonitorCompat inputMonitor) {
@@ -105,7 +106,7 @@
float distance = (float) Math.hypot(mLastPos.x - mDownPos.x,
mLastPos.y - mDownPos.y);
if (distance > mDragDistThreshold && mPassedSlop) {
- onStopGestureDetected();
+ mIsStopGesture = true;
}
}
break;
@@ -113,15 +114,14 @@
case ACTION_UP: {
if (mLastPos.y >= mDownPos.y && mPassedSlop) {
onStartGestureDetected();
+ } else if (mIsStopGesture) {
+ onStopGestureDetected();
}
-
- mPassedSlop = false;
- mState = STATE_INACTIVE;
+ clearState();
break;
}
case ACTION_CANCEL:
- mPassedSlop = false;
- mState = STATE_INACTIVE;
+ clearState();
break;
}
@@ -130,6 +130,12 @@
}
}
+ private void clearState() {
+ mPassedSlop = false;
+ mState = STATE_INACTIVE;
+ mIsStopGesture = false;
+ }
+
private void onStartGestureDetected() {
if (mDeviceState.isOneHandedModeEnabled()) {
if (!mDeviceState.isOneHandedModeActive()) {
diff --git a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
index d54efc5..4c1a595 100644
--- a/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SandboxModeTutorialController.java
@@ -46,7 +46,7 @@
@Nullable
@Override
Integer getActionButtonStringId() {
- return R.string.gesture_tutorial_action_button_label_done;
+ return null;
}
@Override
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index 2198ade..0d5a110 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -25,8 +25,10 @@
import android.widget.TextView;
import androidx.annotation.CallSuper;
+import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
+import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.views.ClipIconView;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
@@ -63,13 +65,13 @@
mTutorialType = tutorialType;
mContext = mTutorialFragment.getContext();
- View rootView = tutorialFragment.getRootView();
+ RootSandboxLayout rootView = tutorialFragment.getRootView();
mCloseButton = rootView.findViewById(R.id.gesture_tutorial_fragment_close_button);
mCloseButton.setOnClickListener(button -> mTutorialFragment.closeTutorial());
mTitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_title_view);
mSubtitleTextView = rootView.findViewById(R.id.gesture_tutorial_fragment_subtitle_view);
mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
- mLauncherView = tutorialFragment.getLauncherView();
+ mLauncherView = getMockLauncherView();
mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view);
mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view);
mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view);
@@ -84,6 +86,15 @@
mHideFeedbackRunnable =
() -> mFeedbackView.animate().alpha(0).setDuration(FEEDBACK_ANIMATION_MS)
.withEndAction(this::showHandCoachingAnimation).start();
+
+ if (mLauncherView != null) {
+ rootView.addView(mLauncherView, 0);
+ }
+ if (mContext != null) {
+ rootView.setBackground(mContext.getDrawable(getMockWallpaperResId()));
+ mFakeTaskView.setBackground(mContext.getDrawable(getMockAppTaskThumbnailResId()));
+ mFakeIconView.setBackground(mContext.getDrawable(getMockAppIconResId()));
+ }
}
void setTutorialType(TutorialType tutorialType) {
@@ -110,6 +121,28 @@
return null;
}
+ @DrawableRes
+ protected int getMockAppTaskThumbnailResId() {
+ return R.drawable.default_sandbox_app_task_thumbnail;
+ }
+
+ @Nullable
+ public View getMockLauncherView() {
+ InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(mContext);
+
+ return new SandboxLauncherRenderer(mContext, dp, true).getRenderedView();
+ }
+
+ @DrawableRes
+ public int getMockAppIconResId() {
+ return R.drawable.default_sandbox_app_icon;
+ }
+
+ @DrawableRes
+ public int getMockWallpaperResId() {
+ return R.drawable.default_sandbox_wallpaper;
+ }
+
void showFeedback(int resId) {
hideHandCoachingAnimation();
mFeedbackView.setText(resId);
@@ -167,10 +200,11 @@
if (isComplete()) {
hideHandCoachingAnimation();
- mLauncherView.setVisibility(View.INVISIBLE);
} else {
showHandCoachingAnimation();
- mLauncherView.setVisibility(View.VISIBLE);
+ }
+ if (mLauncherView != null) {
+ mLauncherView.setVisibility(isComplete() ? View.INVISIBLE : View.VISIBLE);
}
}
@@ -213,8 +247,7 @@
return mTutorialType == TutorialType.BACK_NAVIGATION_COMPLETE
|| mTutorialType == TutorialType.HOME_NAVIGATION_COMPLETE
|| mTutorialType == TutorialType.OVERVIEW_NAVIGATION_COMPLETE
- || mTutorialType == TutorialType.ASSISTANT_COMPLETE
- || mTutorialType == TutorialType.SANDBOX_MODE;
+ || mTutorialType == TutorialType.ASSISTANT_COMPLETE;
}
/** Denotes the type of the tutorial. */
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 608fe72..413387e 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -31,7 +31,6 @@
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
-import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.R;
import com.android.quickstep.interaction.TutorialController.TutorialType;
@@ -42,11 +41,10 @@
TutorialType mTutorialType;
@Nullable TutorialController mTutorialController = null;
- View mRootView;
+ RootSandboxLayout mRootView;
@Nullable TutorialHandAnimation mHandCoachingAnimation = null;
EdgeBackGestureHandler mEdgeBackGestureHandler;
NavBarGestureHandler mNavBarGestureHandler;
- private View mLauncherView;
public static TutorialFragment newInstance(TutorialType tutorialType) {
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
@@ -114,7 +112,8 @@
@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
- mRootView = inflater.inflate(R.layout.gesture_tutorial_fragment, container, false);
+ mRootView = (RootSandboxLayout) inflater.inflate(
+ R.layout.gesture_tutorial_fragment, container, false);
mRootView.setOnApplyWindowInsetsListener((view, insets) -> {
Insets systemInsets = insets.getInsets(WindowInsets.Type.systemBars());
mEdgeBackGestureHandler.setInsets(systemInsets.left, systemInsets.right);
@@ -126,9 +125,6 @@
mHandCoachingAnimation =
new TutorialHandAnimation(getContext(), mRootView, handAnimationResId);
}
- InvariantDeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(getContext());
- mLauncherView = new SandboxLauncherRenderer(getContext(), dp, true).getRenderedView();
- ((ViewGroup) mRootView).addView(mLauncherView, 0);
return mRootView;
}
@@ -161,7 +157,7 @@
}
void onAttachedToWindow() {
- mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
+ mEdgeBackGestureHandler.setViewGroupParent(getRootView());
}
void onDetachedFromWindow() {
@@ -186,14 +182,10 @@
super.onSaveInstanceState(savedInstanceState);
}
- View getRootView() {
+ RootSandboxLayout getRootView() {
return mRootView;
}
- View getLauncherView() {
- return mLauncherView;
- }
-
@Nullable TutorialHandAnimation getHandAnimation() {
return mHandCoachingAnimation;
}
diff --git a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
index 0bb0bbc..3157865 100644
--- a/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
+++ b/quickstep/src/com/android/quickstep/logging/SettingsChangeLogger.java
@@ -16,7 +16,13 @@
package com.android.quickstep.logging;
+import static com.android.launcher3.InvariantDeviceProfile.KEY_MIGRATION_SRC_HOTSEAT_COUNT;
import static com.android.launcher3.Utilities.getDevicePrefs;
+import static com.android.launcher3.Utilities.getPrefs;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_2;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_3;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_4;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_GRID_SIZE_5;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_SCREEN_SUGGESTIONS_DISABLED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_HOME_SCREEN_SUGGESTIONS_ENABLED;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_NOTIFICATION_DOT_DISABLED;
@@ -34,7 +40,6 @@
import com.android.launcher3.AutoInstallsLayout;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.logging.InstanceIdSequence;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
@@ -69,7 +74,7 @@
mLoggablePrefs = loadPrefKeys(context);
mNavMode = SysUINavigationMode.INSTANCE.get(context).addModeChangeListener(this);
- Utilities.getPrefs(context).registerOnSharedPreferenceChangeListener(this);
+ getPrefs(context).registerOnSharedPreferenceChangeListener(this);
getDevicePrefs(context).registerOnSharedPreferenceChangeListener(this);
SecureSettingsObserver dotsObserver =
@@ -125,7 +130,8 @@
@Override
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
- if (LAST_PREDICTION_ENABLED_STATE.equals(key) || mLoggablePrefs.containsKey(key)) {
+ if (LAST_PREDICTION_ENABLED_STATE.equals(key) || KEY_MIGRATION_SRC_HOTSEAT_COUNT.equals(key)
+ || mLoggablePrefs.containsKey(key)) {
dispatchUserEvent();
}
}
@@ -142,7 +148,28 @@
? LAUNCHER_HOME_SCREEN_SUGGESTIONS_ENABLED
: LAUNCHER_HOME_SCREEN_SUGGESTIONS_DISABLED);
- SharedPreferences prefs = Utilities.getPrefs(mContext);
+ SharedPreferences prefs = getPrefs(mContext);
+ StatsLogManager.LauncherEvent gridSizeChangedEvent = null;
+ switch (prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, -1)) {
+ case 5:
+ gridSizeChangedEvent = LAUNCHER_GRID_SIZE_5;
+ break;
+ case 4:
+ gridSizeChangedEvent = LAUNCHER_GRID_SIZE_4;
+ break;
+ case 3:
+ gridSizeChangedEvent = LAUNCHER_GRID_SIZE_3;
+ break;
+ case 2:
+ gridSizeChangedEvent = LAUNCHER_GRID_SIZE_2;
+ break;
+ default:
+ // Ignore illegal input.
+ break;
+ }
+ if (gridSizeChangedEvent != null) {
+ logger.log(gridSizeChangedEvent);
+ }
mLoggablePrefs.forEach((key, lp) -> logger.log(() ->
prefs.getBoolean(key, lp.defaultValue) ? lp.eventIdOn : lp.eventIdOff));
}
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 3230348..1b55496 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -36,6 +36,7 @@
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -418,15 +419,21 @@
if (freezeTaskList) {
ActivityOptionsCompat.setFreezeRecentTasksList(opts);
}
- ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(mTask.key,
- opts, (success) -> {
- if (resultCallback != null && !success) {
- // If the call to start activity failed, then post the result
- // immediately, otherwise, wait for the animation start callback
- // from the activity options above
- resultCallbackHandler.post(() -> resultCallback.accept(false));
- }
- }, resultCallbackHandler);
+ UI_HELPER_EXECUTOR.execute(
+ () -> ActivityManagerWrapper.getInstance().startActivityFromRecentsAsync(
+ mTask.key,
+ opts,
+ (success) -> {
+ if (resultCallback != null && !success) {
+ // If the call to start activity failed, then post the
+ // result
+ // immediately, otherwise, wait for the animation start
+ // callback
+ // from the activity options above
+ resultCallbackHandler.post(
+ () -> resultCallback.accept(false));
+ }
+ }, resultCallbackHandler));
}
}
}
diff --git a/res/values/config.xml b/res/values/config.xml
index 46b8c23..41d1a12 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -111,6 +111,7 @@
<!-- QSB IDs. DO not change -->
<item type="id" name="search_container_workspace" />
<item type="id" name="search_container_all_apps" />
+ <item type="id" name="search_container_hotseat" />
<!-- Recents -->
<item type="id" name="overview_panel"/>
diff --git a/robolectric_tests/config/robolectric.properties b/robolectric_tests/config/robolectric.properties
index a8e0cb3..4e811f3 100644
--- a/robolectric_tests/config/robolectric.properties
+++ b/robolectric_tests/config/robolectric.properties
@@ -1,15 +1,10 @@
sdk=29
shadows= \
- com.android.launcher3.shadows.LShadowApplicationPackageManager \
com.android.launcher3.shadows.LShadowAppPredictionManager \
com.android.launcher3.shadows.LShadowAppWidgetManager \
com.android.launcher3.shadows.LShadowBackupManager \
- com.android.launcher3.shadows.LShadowBitmap \
com.android.launcher3.shadows.LShadowDisplay \
com.android.launcher3.shadows.LShadowLauncherApps \
- com.android.launcher3.shadows.LShadowTypeface \
- com.android.launcher3.shadows.LShadowUserManager \
- com.android.launcher3.shadows.LShadowWallpaperManager \
com.android.launcher3.shadows.ShadowDeviceFlag \
com.android.launcher3.shadows.ShadowLooperExecutor \
com.android.launcher3.shadows.ShadowMainThreadInitializedObject \
diff --git a/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java b/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
index 90313ab..8baf5a3 100644
--- a/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
+++ b/robolectric_tests/src/com/android/launcher3/model/BackupRestoreTest.java
@@ -41,7 +41,6 @@
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.provider.RestoreDbTask;
import com.android.launcher3.shadows.LShadowBackupManager;
-import com.android.launcher3.shadows.LShadowUserManager;
import com.android.launcher3.util.LauncherModelHelper;
import org.junit.Before;
@@ -51,6 +50,7 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.LooperMode;
import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowUserManager;
/**
* Tests to verify backup and restore flow.
@@ -68,7 +68,7 @@
private static final int FLAG_SYSTEM = 0x00000800;
private static final int FLAG_PROFILE = 0x00001000;
- private LShadowUserManager mUserManager;
+ private ShadowUserManager mUserManager;
private BackupManager mBackupManager;
private LauncherModelHelper mModelHelper;
private SQLiteDatabase mDb;
diff --git a/robolectric_tests/src/com/android/launcher3/shadows/LShadowApplicationPackageManager.java b/robolectric_tests/src/com/android/launcher3/shadows/LShadowApplicationPackageManager.java
deleted file mode 100644
index da8b919..0000000
--- a/robolectric_tests/src/com/android/launcher3/shadows/LShadowApplicationPackageManager.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2020 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.shadows;
-
-import android.os.Process;
-import android.os.UserHandle;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowApplicationPackageManager;
-
-/**
- * Shadow for {@link ShadowApplicationPackageManager} which create mock predictors
- */
-@Implements(className = "android.app.ApplicationPackageManager")
-public class LShadowApplicationPackageManager extends ShadowApplicationPackageManager {
-
- @Implementation
- public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
- return Process.myUserHandle().equals(user) ? label : "Work " + label;
- }
-}
diff --git a/robolectric_tests/src/com/android/launcher3/shadows/LShadowBitmap.java b/robolectric_tests/src/com/android/launcher3/shadows/LShadowBitmap.java
deleted file mode 100644
index abd90bb..0000000
--- a/robolectric_tests/src/com/android/launcher3/shadows/LShadowBitmap.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2019 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.shadows;
-
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowBitmap;
-
-/**
- * Extension of {@link ShadowBitmap} with missing shadow methods
- */
-@Implements(value = Bitmap.class)
-public class LShadowBitmap extends ShadowBitmap {
-
- @Implementation
- protected Bitmap extractAlpha(Paint paint, int[] offsetXY) {
- return extractAlpha();
- }
-}
diff --git a/robolectric_tests/src/com/android/launcher3/shadows/LShadowTypeface.java b/robolectric_tests/src/com/android/launcher3/shadows/LShadowTypeface.java
deleted file mode 100644
index 0e7c1de..0000000
--- a/robolectric_tests/src/com/android/launcher3/shadows/LShadowTypeface.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2020 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.shadows;
-
-import android.graphics.Typeface;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowTypeface;
-
-/**
- * Extension of {@link ShadowTypeface} with missing shadow methods
- */
-@Implements(Typeface.class)
-public class LShadowTypeface extends ShadowTypeface {
-
- @Implementation
- public static Typeface create(Typeface family, int weight, boolean italic) {
- int style = italic ? Typeface.ITALIC : Typeface.NORMAL;
- if (weight >= 400) {
- style |= Typeface.BOLD;
- }
- return create(family, style);
- }
-}
diff --git a/robolectric_tests/src/com/android/launcher3/shadows/LShadowUserManager.java b/robolectric_tests/src/com/android/launcher3/shadows/LShadowUserManager.java
deleted file mode 100644
index edf8edb..0000000
--- a/robolectric_tests/src/com/android/launcher3/shadows/LShadowUserManager.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 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.shadows;
-
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.SparseBooleanArray;
-
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowUserManager;
-
-/**
- * Extension of {@link ShadowUserManager} with missing shadow methods
- */
-@Implements(value = UserManager.class)
-public class LShadowUserManager extends ShadowUserManager {
-
- private final SparseBooleanArray mQuietUsers = new SparseBooleanArray();
- private final SparseBooleanArray mLockedUsers = new SparseBooleanArray();
-
- @Implementation
- protected boolean isQuietModeEnabled(UserHandle userHandle) {
- return mQuietUsers.get(userHandle.hashCode());
- }
-
- public void setQuietModeEnabled(UserHandle userHandle, boolean enabled) {
- mQuietUsers.put(userHandle.hashCode(), enabled);
- }
-
- @Implementation
- protected boolean isUserUnlocked(UserHandle userHandle) {
- return !mLockedUsers.get(userHandle.hashCode());
- }
-
- public void setUserLocked(UserHandle userHandle, boolean enabled) {
- mLockedUsers.put(userHandle.hashCode(), enabled);
- }
-}
diff --git a/robolectric_tests/src/com/android/launcher3/shadows/LShadowWallpaperManager.java b/robolectric_tests/src/com/android/launcher3/shadows/LShadowWallpaperManager.java
deleted file mode 100644
index d60251c..0000000
--- a/robolectric_tests/src/com/android/launcher3/shadows/LShadowWallpaperManager.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2019 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.shadows;
-
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-
-import android.app.WallpaperManager;
-import android.content.Context;
-
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.shadows.ShadowUserManager;
-import org.robolectric.shadows.ShadowWallpaperManager;
-
-/**
- * Extension of {@link ShadowUserManager} with missing shadow methods
- */
-@Implements(WallpaperManager.class)
-public class LShadowWallpaperManager extends ShadowWallpaperManager {
-
- @Implementation
- protected static WallpaperManager getInstance(Context context) {
- return context.getSystemService(WallpaperManager.class);
- }
-
- /**
- * Remove this once the fix for
- * https://github.com/robolectric/robolectric/issues/5285
- * is available
- */
- public static void initializeMock() {
- WallpaperManager wm = mock(WallpaperManager.class);
- ShadowApplication shadowApplication = Shadows.shadowOf(RuntimeEnvironment.application);
- shadowApplication.setSystemService(Context.WALLPAPER_SERVICE, wm);
- doReturn(0).when(wm).getDesiredMinimumWidth();
- doReturn(0).when(wm).getDesiredMinimumHeight();
- }
-}
diff --git a/robolectric_tests/src/com/android/launcher3/util/LauncherTestApplication.java b/robolectric_tests/src/com/android/launcher3/util/LauncherTestApplication.java
index 6dd4df8..efac150 100644
--- a/robolectric_tests/src/com/android/launcher3/util/LauncherTestApplication.java
+++ b/robolectric_tests/src/com/android/launcher3/util/LauncherTestApplication.java
@@ -19,7 +19,6 @@
import android.app.Application;
-import com.android.launcher3.shadows.LShadowWallpaperManager;
import com.android.launcher3.shadows.ShadowMainThreadInitializedObject;
import com.android.launcher3.shadows.ShadowOverrides;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
@@ -37,9 +36,6 @@
// Disable plugins
PluginManagerWrapper.INSTANCE.initializeForTesting(mock(PluginManagerWrapper.class));
-
- // Initialize mock wallpaper manager
- LShadowWallpaperManager.initializeMock();
}
@Override
diff --git a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
index 8bf027d..b85c648 100644
--- a/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
+++ b/src/com/android/launcher3/AppWidgetsRestoredReceiver.java
@@ -106,7 +106,8 @@
}
}
// attempt to update widget id in backup table as well
- new ContentWriter(context, ContentWriter.CommitParams.backupCommitParams(where, args))
+ new ContentWriter(context, ContentWriter.CommitParams.backupCommitParams(
+ "appWidgetId=? and profileId=?", args))
.put(LauncherSettings.Favorites.APPWIDGET_ID, newWidgetIds[i])
.put(LauncherSettings.Favorites.RESTORED, state)
.commit();
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index 0d90602..52f0a4a 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -42,7 +42,6 @@
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;
@@ -108,20 +107,10 @@
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/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index e4bdb39..4f4f2a7 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -27,6 +27,8 @@
import androidx.annotation.Nullable;
+import com.android.launcher3.config.FeatureFlags;
+
import java.util.function.Consumer;
/**
@@ -38,7 +40,8 @@
private boolean mHasVerticalHotseat;
private Workspace mWorkspace;
private boolean mSendTouchToWorkspace;
- @Nullable private Consumer<Boolean> mOnVisibilityAggregatedCallback;
+ @Nullable
+ private Consumer<Boolean> mOnVisibilityAggregatedCallback;
public Hotseat(Context context) {
this(context, null);
@@ -73,8 +76,9 @@
if (hasVerticalHotseat) {
setGridSize(1, idp.numHotseatIcons);
} else {
- setGridSize(idp.numHotseatIcons, 1);
+ setGridSize(idp.numHotseatIcons, FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 2 : 1);
}
+ showInlineQsb();
}
@Override
@@ -97,7 +101,11 @@
lp.height = grid.hotseatBarSizePx + insets.bottom;
}
Rect padding = grid.getHotseatLayoutPadding();
- setPadding(padding.left, padding.top, padding.right, padding.bottom);
+ int paddingBottom = padding.bottom;
+ if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && !grid.isVerticalBarLayout()) {
+ paddingBottom -= grid.hotseatBarBottomPaddingPx;
+ }
+ setPadding(padding.left, padding.top, padding.right, paddingBottom);
setLayoutParams(lp);
InsettableFrameLayout.dispatchInsets(this, insets);
@@ -148,4 +156,8 @@
public void setOnVisibilityAggregatedCallback(@Nullable Consumer<Boolean> callback) {
mOnVisibilityAggregatedCallback = callback;
}
+
+ protected void showInlineQsb() {
+ //Does nothing
+ }
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 058eca8..ea98157 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -18,6 +18,7 @@
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.View.IMPORTANT_FOR_ACCESSIBILITY_NO;
import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
@@ -221,6 +222,8 @@
static final boolean DEBUG_STRICT_MODE = false;
+ private static final boolean ENABLE_ACTIVITY_CROSSFADE = false;
+
private static final int REQUEST_CREATE_SHORTCUT = 1;
private static final int REQUEST_CREATE_APPWIDGET = 5;
@@ -1134,7 +1137,11 @@
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 */);
}
@@ -1373,14 +1380,18 @@
@Override
public Object onRetainNonConfigurationInstance() {
+ NonConfigInstance instance = new NonConfigInstance();
+ instance.config = new Configuration(mOldConfig);
+
int width = mDragLayer.getWidth();
int height = mDragLayer.getHeight();
- if (width <= 0 || height <= 0) {
- return null;
+ // TODO: b/172467144 Remove hardcoded ENABLE_ACTIVITY_CROSSFADE.
+ if (ENABLE_ACTIVITY_CROSSFADE && width > 0 && height > 0) {
+ instance.snapshot =
+ BitmapRenderer.createHardwareBitmap(width, height, mDragLayer::draw);
}
-
- return BitmapRenderer.createHardwareBitmap(width, height, mDragLayer::draw);
+ return instance;
}
public AllAppsTransitionController getAllAppsController() {
@@ -1974,7 +1985,6 @@
return result;
}
- @Override
public void addOnResumeCallback(OnResumeCallback callback) {
mOnResumeCallbacks.add(callback);
}
@@ -2340,9 +2350,7 @@
if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) {
// Verify that we own the widget
if (appWidgetInfo == null) {
- FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId
- + ",title=" + item.title
- + ",providerName=" + item.providerName.toShortString());
+ FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId);
getModelWriter().deleteWidgetInfo(item, getAppWidgetHost());
return null;
}
@@ -2786,15 +2794,14 @@
* updates.
*/
private void crossFadeWithPreviousAppearance() {
- Bitmap previousAppearanceBitmap = (Bitmap) getLastNonConfigurationInstance();
+ NonConfigInstance lastInstance = (NonConfigInstance) getLastNonConfigurationInstance();
- if (previousAppearanceBitmap == null) {
+ if (lastInstance == null || lastInstance.snapshot == null) {
return;
}
ImageView crossFadeHelper = new ImageView(this);
-
- crossFadeHelper.setImageBitmap(previousAppearanceBitmap);
+ crossFadeHelper.setImageBitmap(lastInstance.snapshot);
crossFadeHelper.setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
InsettableFrameLayout.LayoutParams layoutParams = new InsettableFrameLayout.LayoutParams(
@@ -2814,4 +2821,9 @@
.withEndAction(() -> getRootView().removeView(crossFadeHelper))
.start();
}
+
+ private static class NonConfigInstance {
+ public Configuration config;
+ public Bitmap snapshot;
+ }
}
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 6af248c..aeed16a 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -85,7 +85,6 @@
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
-import java.util.stream.Collectors;
public class LauncherProvider extends ContentProvider {
private static final String TAG = "LauncherProvider";
@@ -932,11 +931,6 @@
final IntSet validWidgets = IntSet.wrap(LauncherDbUtils.queryIntArray(db,
Favorites.TABLE_NAME, Favorites.APPWIDGET_ID,
"itemType=" + Favorites.ITEM_TYPE_APPWIDGET, null, null));
- final String allWidgetIds = Arrays.stream(allWidgets).mapToObj(String::valueOf)
- .collect(Collectors.joining(","));
- final String validWidgetIds = validWidgets.getArray().toConcatString();
- FileLog.d(TAG, "All widget ids: " + allWidgetIds);
- FileLog.d(TAG, "Valid widget ids: " + validWidgetIds);
for (int widgetId : allWidgets) {
if (!validWidgets.contains(widgetId)) {
try {
diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java
index eba0ac9..79476fc 100644
--- a/src/com/android/launcher3/LauncherState.java
+++ b/src/com/android/launcher3/LauncherState.java
@@ -29,6 +29,7 @@
import android.content.Context;
import android.view.animation.Interpolator;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.states.HintState;
@@ -168,9 +169,9 @@
/**
* Returns an array of two elements.
- * The first specifies the scale for the overview
- * The second is the factor ([0, 1], 0 => center-screen; 1 => offscreen) by which overview
- * should be shifted horizontally.
+ * The first specifies the scale for the overview
+ * The second is the factor ([0, 1], 0 => center-screen; 1 => offscreen) by which overview
+ * should be shifted horizontally.
*/
public float[] getOverviewScaleAndOffset(Launcher launcher) {
return launcher.getNormalOverviewScaleAndOffset();
@@ -185,10 +186,12 @@
}
public int getVisibleElements(Launcher launcher) {
- if (launcher.getDeviceProfile().isVerticalBarLayout()) {
- return HOTSEAT_ICONS | VERTICAL_SWIPE_INDICATOR;
+ int flags = HOTSEAT_ICONS | VERTICAL_SWIPE_INDICATOR;
+ if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()
+ && !launcher.getDeviceProfile().isVerticalBarLayout()) {
+ flags |= HOTSEAT_SEARCH_BOX;
}
- return HOTSEAT_ICONS | HOTSEAT_SEARCH_BOX | VERTICAL_SWIPE_INDICATOR;
+ return flags;
}
/**
@@ -229,6 +232,7 @@
/**
* Returns the amount of blur and wallpaper zoom for this state with {@param isMultiWindowMode}.
+ *
* @see #getDepth(Context).
*/
public final float getDepth(Context context, boolean isMultiWindowMode) {
@@ -255,7 +259,7 @@
return new PageAlphaProvider(ACCEL_2) {
@Override
public float getPageAlpha(int pageIndex) {
- return pageIndex != centerPage ? 0 : 1f;
+ return pageIndex != centerPage ? 0 : 1f;
}
};
}
diff --git a/src/com/android/launcher3/ShortcutAndWidgetContainer.java b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
index 6326b7a..ee0c7bb 100644
--- a/src/com/android/launcher3/ShortcutAndWidgetContainer.java
+++ b/src/com/android/launcher3/ShortcutAndWidgetContainer.java
@@ -36,7 +36,8 @@
// return an (x, y) value from helper functions. Do NOT use them to maintain other state.
private final int[] mTmpCellXY = new int[2];
- @ContainerType private final int mContainerType;
+ @ContainerType
+ private final int mContainerType;
private final WallpaperManager mWallpaperManager;
private int mCellWidth;
@@ -44,7 +45,7 @@
private int mCountX;
- private ActivityContext mActivity;
+ private final ActivityContext mActivity;
private boolean mInvertIfRtl = false;
public ShortcutAndWidgetContainer(Context context, @ContainerType int containerType) {
@@ -79,7 +80,7 @@
int count = getChildCount();
int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
- int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
+ int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(widthSpecSize, heightSpecSize);
for (int i = 0; i < count; i++) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 5d5e017..558c6a8 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -548,6 +548,7 @@
if (focusedItem instanceof SearchAdapterItem) {
SearchTarget searchTarget = ((SearchAdapterItem) focusedItem).getSearchTarget();
SearchEventTracker.INSTANCE.get(getContext()).quickSelect(searchTarget);
+ return true;
}
if (focusedItem.appInfo != null) {
ItemInfo itemInfo = focusedItem.appInfo;
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index 000ccbb..bd2f04d 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -47,6 +47,7 @@
import com.android.launcher3.allapps.AlphabeticalAppsList;
import com.android.launcher3.allapps.SearchUiManager;
import com.android.launcher3.anim.PropertySetter;
+import com.android.launcher3.config.FeatureFlags;
import java.util.ArrayList;
import java.util.List;
@@ -215,7 +216,8 @@
@Override
public float getScrollRangeDelta(Rect insets) {
- if (mLauncher.getDeviceProfile().isVerticalBarLayout()) {
+ if (mLauncher.getDeviceProfile().isVerticalBarLayout()
+ || FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
return 0;
} else {
return insets.bottom + insets.top;
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 8e6c2a7..8f63c09 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -153,16 +153,17 @@
"ENABLE_OVERVIEW_CONTENT_PUSH", false, "Show Content Push button in Overview Actions");
public static final BooleanFlag ENABLE_DATABASE_RESTORE = getDebugFlag(
- "ENABLE_DATABASE_RESTORE", true,
+ "ENABLE_DATABASE_RESTORE", false,
"Enable database restore when new restore session is created");
public static final BooleanFlag ENABLE_SMARTSPACE_UNIVERSAL = getDebugFlag(
"ENABLE_SMARTSPACE_UNIVERSAL", false,
"Replace Smartspace with a version rendered by System UI.");
- public static final BooleanFlag ENABLE_SMARTSPACE_BLUECHIP = getDebugFlag(
- "ENABLE_SMARTSPACE_BLUECHIP", false,
- "Replace Smartspace with the Bluechip version. Ignored if ENABLE_SMARTSPACE_UNIVERSAL is enabled.");
+ public static final BooleanFlag ENABLE_SMARTSPACE_ENHANCED = getDebugFlag(
+ "ENABLE_SMARTSPACE_ENHANCED", false,
+ "Replace Smartspace with the enhanced version. "
+ + "Ignored if ENABLE_SMARTSPACE_UNIVERSAL is enabled.");
public static final BooleanFlag ENABLE_SYSTEM_VELOCITY_PROVIDER = getDebugFlag(
"ENABLE_SYSTEM_VELOCITY_PROVIDER", true,
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 0b445bc..2066cd3 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -332,6 +332,18 @@
@UiEvent(doc = "Notification dismissed by swiping right.")
LAUNCHER_NOTIFICATION_DISMISSED(652),
+
+ @UiEvent(doc = "Current grid size is changed to 5.")
+ LAUNCHER_GRID_SIZE_5(662),
+
+ @UiEvent(doc = "Current grid size is changed to 4.")
+ LAUNCHER_GRID_SIZE_4(663),
+
+ @UiEvent(doc = "Current grid size is changed to 3.")
+ LAUNCHER_GRID_SIZE_3(664),
+
+ @UiEvent(doc = "Current grid size is changed to 2.")
+ LAUNCHER_GRID_SIZE_2(665),
;
// ADD MORE
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index 80a684d..b108788 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -745,11 +745,7 @@
+ "span=" + appWidgetInfo.spanX + "x"
+ appWidgetInfo.spanY + " minSpan="
+ widgetProviderInfo.minSpanX + "x"
- + widgetProviderInfo.minSpanY
- + ", appWidgetInfo.provider="
- + appWidgetInfo.providerName.toShortString()
- + ", widgetProviderInfo.provider="
- + widgetProviderInfo.provider.toShortString());
+ + widgetProviderInfo.minSpanY);
continue;
}
if (!c.isOnWorkspaceOrHotseat()) {
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
index 2adf8ce..b496608 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDisplayLauncher.java
@@ -20,7 +20,6 @@
import android.app.ActivityOptions;
import android.content.Intent;
import android.os.Bundle;
-import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewAnimationUtils;
@@ -170,9 +169,7 @@
@Override
public ActivityOptions getActivityLaunchOptions(View v) {
- final Display display = getWindow().getDecorView().getDisplay();
- return display != null ? ActivityOptions.makeBasic().setLaunchDisplayId(
- display.getDisplayId()) : null;
+ return null;
}
@Override
diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java
index dbe5f42..601e117 100644
--- a/src/com/android/launcher3/statemanager/StatefulActivity.java
+++ b/src/com/android/launcher3/statemanager/StatefulActivity.java
@@ -121,7 +121,9 @@
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/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index 6a83332..804fb3e 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -16,6 +16,8 @@
package com.android.launcher3.views;
+import static android.view.HapticFeedbackConstants.CLOCK_TICK;
+
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
@@ -288,6 +290,7 @@
if (!sectionName.equals(mPopupSectionName)) {
mPopupSectionName = sectionName;
mPopupView.setText(sectionName);
+ performHapticFeedback(CLOCK_TICK);
}
animatePopupVisibility(!sectionName.isEmpty());
mLastTouchY = boundedY;
diff --git a/src/com/android/launcher3/views/SearchResultIcon.java b/src/com/android/launcher3/views/SearchResultIcon.java
index 51c741b..9bcfb8c 100644
--- a/src/com/android/launcher3/views/SearchResultIcon.java
+++ b/src/com/android/launcher3/views/SearchResultIcon.java
@@ -111,6 +111,7 @@
public void applySearchTarget(SearchTarget searchTarget) {
mSearchTarget = searchTarget;
SearchEventTracker.getInstance(getContext()).registerWeakHandler(mSearchTarget, this);
+ setVisibility(VISIBLE);
switch (searchTarget.getItemType()) {
case TARGET_TYPE_APP:
case TARGET_TYPE_HERO_APP:
@@ -131,6 +132,10 @@
private void prepareUsingApp(ComponentName componentName, UserHandle userHandle) {
AllAppsStore appsStore = mLauncher.getAppsView().getAppsStore();
AppInfo appInfo = appsStore.getApp(new ComponentKey(componentName, userHandle));
+ if (appInfo == null) {
+ setVisibility(GONE);
+ return;
+ }
applyFromApplicationInfo(appInfo);
notifyItemInfoChanged(appInfo);
}
diff --git a/src/com/android/launcher3/views/ThumbnailSearchResultView.java b/src/com/android/launcher3/views/ThumbnailSearchResultView.java
index f213f22..573d48f 100644
--- a/src/com/android/launcher3/views/ThumbnailSearchResultView.java
+++ b/src/com/android/launcher3/views/ThumbnailSearchResultView.java
@@ -88,9 +88,15 @@
bitmap = ((BitmapDrawable) target.getRemoteAction().getIcon()
.loadDrawable(getContext())).getBitmap();
// crop
- bitmap = Bitmap.createBitmap(bitmap, 0,
- bitmap.getHeight() / 2 - bitmap.getWidth() / 2,
- bitmap.getWidth(), bitmap.getWidth());
+ if (bitmap.getWidth() < bitmap.getHeight()) {
+ bitmap = Bitmap.createBitmap(bitmap, 0,
+ bitmap.getHeight() / 2 - bitmap.getWidth() / 2,
+ bitmap.getWidth(), bitmap.getWidth());
+ } else {
+ bitmap = Bitmap.createBitmap(bitmap, bitmap.getWidth() / 2 - bitmap.getHeight() / 2,
+ 0,
+ bitmap.getHeight(), bitmap.getHeight());
+ }
setTag(itemInfo);
} else {
bitmap = (Bitmap) target.getExtras().getParcelable("bitmap");
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index bc6356f..f243f27 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -98,7 +98,7 @@
<activity
android:name="com.android.launcher3.testcomponent.TestLauncherActivity"
android:clearTaskOnLaunch="true"
- android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize|uiMode"
+ android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"
android:enabled="false"
android:label="Test launcher"
android:launchMode="singleTask"
diff --git a/tests/src/com/android/launcher3/ui/WorkTabTest.java b/tests/src/com/android/launcher3/ui/WorkTabTest.java
index df0770d..1e1cf04 100644
--- a/tests/src/com/android/launcher3/ui/WorkTabTest.java
+++ b/tests/src/com/android/launcher3/ui/WorkTabTest.java
@@ -45,6 +45,7 @@
import java.util.List;
import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
@LargeTest
@RunWith(AndroidJUnit4.class)
@@ -71,7 +72,8 @@
@After
public void removeWorkProfile() throws Exception {
- Log.d(TestProtocol.WORK_PROFILE_REMOVED, "(teardown) removing uid" + mProfileUserId);
+ Log.d(TestProtocol.WORK_PROFILE_REMOVED, "(teardown) removing uid" + mProfileUserId,
+ new Exception());
mDevice.executeShellCommand("pm remove-user " + mProfileUserId);
}
@@ -142,12 +144,16 @@
"work profile status (" + mProfileUserId + ") :"
+ launcher.getAppsView().isWorkTabVisible()));
+ AtomicInteger attempt = new AtomicInteger(0);
// verify work edu is seen next
- waitForLauncherCondition("Launcher did not show the next edu screen", l ->
- ((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage() == WORK_PAGE
- && ((TextView) workEduView.findViewById(
- R.id.content_text)).getText().equals(
- l.getResources().getString(R.string.work_profile_edu_work_apps)));
+ waitForLauncherCondition("Launcher did not show the next edu screen", l -> {
+ Log.d(TestProtocol.WORK_PROFILE_REMOVED,
+ "running test attempt" + attempt.getAndIncrement());
+ return ((AllAppsPagedView) l.getAppsView().getContentView()).getCurrentPage()
+ == WORK_PAGE && ((TextView) workEduView.findViewById(
+ R.id.content_text)).getText().equals(
+ l.getResources().getString(R.string.work_profile_edu_work_apps));
+ });
}
@Test
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 22833ec..3c89cfd 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -105,6 +105,7 @@
static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");
static final Pattern EVENT_TOUCH_UP_TIS = getTouchEventPatternTIS("ACTION_UP");
private final String mLauncherPackage;
+ private final boolean mIsLauncher3;
// Types for launcher containers that the user is interacting with. "Background" is a
// pseudo-container corresponding to inactive launcher covered by another app.
@@ -205,6 +206,7 @@
public LauncherInstrumentation(Instrumentation instrumentation) {
mInstrumentation = instrumentation;
mDevice = UiDevice.getInstance(instrumentation);
+ mIsLauncher3 = "com.android.launcher3".equals(getLauncherPackageName());
// Launcher should run in test harness so that custom accessibility protocol between
// Launcher and TAPL is enabled. In-process tests enable this protocol with a direct call
@@ -1396,7 +1398,7 @@
}
boolean isLauncher3() {
- return "com.android.launcher3".equals(getLauncherPackageName());
+ return mIsLauncher3;
}
void expectEvent(String sequence, Pattern expected) {