Merge "Merge redfin/bramble support."

This commit is contained in:
Treehugger Robot 2020-10-19 23:20:08 +00:00 committed by Gerrit Code Review
commit 01e833073e
13 changed files with 182 additions and 135 deletions

View File

@ -156,8 +156,7 @@
<provider
android:name="com.android.launcher3.graphics.GridOptionsProvider"
android:authorities="${packageName}.grid_control"
android:exported="true"
android:enabled="false" />
android:exported="true" />
<!--
The settings activity. To extend point settings_fragment_name to appropriate fragment class

View File

@ -39,6 +39,7 @@ import com.android.launcher3.util.WindowBounds;
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.util.ActivityInitListener;
import com.android.quickstep.util.InputConsumerProxy;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.SurfaceTransactionApplier;
import com.android.quickstep.util.TransformParams;
@ -61,7 +62,7 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend
private static final String TAG = "BaseSwipeUpHandler";
protected final BaseActivityInterface<?, T> mActivityInterface;
protected final InputConsumerController mInputConsumer;
protected final InputConsumerProxy mInputConsumerProxy;
protected final ActivityInitListener mActivityInitListener;
@ -87,7 +88,8 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend
super(context, deviceState, gestureState, new TransformParams());
mActivityInterface = gestureState.getActivityInterface();
mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
mInputConsumer = inputConsumer;
mInputConsumerProxy =
new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler);
}
/**

View File

@ -850,11 +850,9 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
}
}
if (endTarget.isLauncher && mRecentsAnimationController != null) {
mRecentsAnimationController.enableInputProxy(mInputConsumer,
this::createNewInputProxyHandler);
if (endTarget.isLauncher) {
mInputConsumerProxy.enable();
}
if (endTarget == HOME) {
setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
@ -1181,6 +1179,7 @@ public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q exte
}
private void invalidateHandler() {
mInputConsumerProxy.destroy();
endRunningWindowAnim(false /* cancel */);
if (mGestureEndCallback != null) {

View File

@ -0,0 +1,118 @@
/*
* 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.quickstep.util;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
import android.util.Log;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import com.android.quickstep.InputConsumer;
import com.android.systemui.shared.system.InputConsumerController;
import java.util.function.Supplier;
/**
* Utility class which manages proxying input events from {@link InputConsumerController}
* to an {@link InputConsumer}
*/
public class InputConsumerProxy {
private static final String TAG = "InputConsumerProxy";
private final InputConsumerController mInputConsumerController;
private final Supplier<InputConsumer> mConsumerSupplier;
// The consumer is created lazily on demand.
private InputConsumer mInputConsumer;
private boolean mDestroyed = false;
private boolean mTouchInProgress = false;
private boolean mDestroyPending = false;
public InputConsumerProxy(InputConsumerController inputConsumerController,
Supplier<InputConsumer> consumerSupplier) {
mInputConsumerController = inputConsumerController;
mConsumerSupplier = consumerSupplier;
}
public void enable() {
if (mDestroyed) {
return;
}
mInputConsumerController.setInputListener(this::onInputConsumerEvent);
}
private boolean onInputConsumerEvent(InputEvent ev) {
if (ev instanceof MotionEvent) {
onInputConsumerMotionEvent((MotionEvent) ev);
} else if (ev instanceof KeyEvent) {
if (mInputConsumer == null) {
mInputConsumer = mConsumerSupplier.get();
}
mInputConsumer.onKeyEvent((KeyEvent) ev);
return true;
}
return false;
}
private boolean onInputConsumerMotionEvent(MotionEvent ev) {
int action = ev.getAction();
// Just to be safe, verify that ACTION_DOWN comes before any other action,
// and ignore any ACTION_DOWN after the first one (though that should not happen).
if (!mTouchInProgress && action != ACTION_DOWN) {
Log.w(TAG, "Received non-down motion before down motion: " + action);
return false;
}
if (mTouchInProgress && action == ACTION_DOWN) {
Log.w(TAG, "Received down motion while touch was already in progress");
return false;
}
if (action == ACTION_DOWN) {
mTouchInProgress = true;
if (mInputConsumer == null) {
mInputConsumer = mConsumerSupplier.get();
}
} else if (action == ACTION_CANCEL || action == ACTION_UP) {
// Finish any pending actions
mTouchInProgress = false;
if (mDestroyPending) {
destroy();
}
}
if (mInputConsumer != null) {
mInputConsumer.onMotionEvent(ev);
}
return true;
}
public void destroy() {
if (mTouchInProgress) {
mDestroyPending = true;
return;
}
mDestroyPending = false;
mDestroyed = true;
mInputConsumerController.setInputListener(null);
}
}

View File

@ -15,49 +15,30 @@
*/
package com.android.quickstep;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import android.os.SystemClock;
import android.util.Log;
import android.view.InputEvent;
import android.view.KeyEvent;
import android.view.MotionEvent;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import com.android.launcher3.util.Preconditions;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.Consumer;
import java.util.function.Supplier;
/**
* Wrapper around RecentsAnimationControllerCompat to help with some synchronization
*/
public class RecentsAnimationController {
private static final String TAG = "RecentsAnimationController";
private final RecentsAnimationControllerCompat mController;
private final Consumer<RecentsAnimationController> mOnFinishedListener;
private final boolean mAllowMinimizeSplitScreen;
private InputConsumerController mInputConsumerController;
private Supplier<InputConsumer> mInputProxySupplier;
private InputConsumer mInputConsumer;
private boolean mUseLauncherSysBarFlags = false;
private boolean mSplitScreenMinimized = false;
private boolean mTouchInProgress;
private boolean mDisableInputProxyPending;
public RecentsAnimationController(RecentsAnimationControllerCompat controller,
boolean allowMinimizeSplitScreen,
@ -136,12 +117,12 @@ public class RecentsAnimationController {
@UiThread
public void finishAnimationToHome() {
finishAndDisableInputProxy(true /* toRecents */, null, false /* sendUserLeaveHint */);
finishController(true /* toRecents */, null, false /* sendUserLeaveHint */);
}
@UiThread
public void finishAnimationToApp() {
finishAndDisableInputProxy(false /* toRecents */, null, false /* sendUserLeaveHint */);
finishController(false /* toRecents */, null, false /* sendUserLeaveHint */);
}
/** See {@link #finish(boolean, Runnable, boolean)} */
@ -160,18 +141,6 @@ public class RecentsAnimationController {
@UiThread
public void finish(boolean toRecents, Runnable onFinishComplete, boolean sendUserLeaveHint) {
Preconditions.assertUIThread();
if (toRecents && mTouchInProgress) {
// Finish the controller as requested, but don't disable input proxy yet.
mDisableInputProxyPending = true;
finishController(toRecents, onFinishComplete, sendUserLeaveHint);
} else {
finishAndDisableInputProxy(toRecents, onFinishComplete, sendUserLeaveHint);
}
}
private void finishAndDisableInputProxy(boolean toRecents, Runnable onFinishComplete,
boolean sendUserLeaveHint) {
disableInputProxy();
finishController(toRecents, onFinishComplete, sendUserLeaveHint);
}
@ -179,7 +148,6 @@ public class RecentsAnimationController {
public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) {
mOnFinishedListener.accept(this);
UI_HELPER_EXECUTOR.execute(() -> {
mController.setInputConsumerEnabled(false);
mController.finish(toRecents, sendUserLeaveHint);
if (callback != null) {
MAIN_EXECUTOR.execute(callback);
@ -197,75 +165,8 @@ public class RecentsAnimationController {
});
}
public void enableInputProxy(InputConsumerController inputConsumerController,
Supplier<InputConsumer> inputProxySupplier) {
mInputProxySupplier = inputProxySupplier;
mInputConsumerController = inputConsumerController;
mInputConsumerController.setInputListener(this::onInputConsumerEvent);
}
/** @return wrapper controller. */
public RecentsAnimationControllerCompat getController() {
return mController;
}
private void disableInputProxy() {
if (mInputConsumer != null && mTouchInProgress) {
long now = SystemClock.uptimeMillis();
MotionEvent dummyCancel = MotionEvent.obtain(now, now, ACTION_CANCEL, 0, 0, 0);
mInputConsumer.onMotionEvent(dummyCancel);
dummyCancel.recycle();
}
if (mInputConsumerController != null) {
mInputConsumerController.setInputListener(null);
}
mInputProxySupplier = null;
}
private boolean onInputConsumerEvent(InputEvent ev) {
if (ev instanceof MotionEvent) {
onInputConsumerMotionEvent((MotionEvent) ev);
} else if (ev instanceof KeyEvent) {
if (mInputConsumer == null) {
mInputConsumer = mInputProxySupplier.get();
}
mInputConsumer.onKeyEvent((KeyEvent) ev);
return true;
}
return false;
}
private boolean onInputConsumerMotionEvent(MotionEvent ev) {
int action = ev.getAction();
// Just to be safe, verify that ACTION_DOWN comes before any other action,
// and ignore any ACTION_DOWN after the first one (though that should not happen).
if (!mTouchInProgress && action != ACTION_DOWN) {
Log.w(TAG, "Received non-down motion before down motion: " + action);
return false;
}
if (mTouchInProgress && action == ACTION_DOWN) {
Log.w(TAG, "Received down motion while touch was already in progress");
return false;
}
if (action == ACTION_DOWN) {
mTouchInProgress = true;
if (mInputConsumer == null) {
mInputConsumer = mInputProxySupplier.get();
}
} else if (action == ACTION_CANCEL || action == ACTION_UP) {
// Finish any pending actions
mTouchInProgress = false;
if (mDisableInputProxyPending) {
mDisableInputProxyPending = false;
disableInputProxy();
}
}
if (mInputConsumer != null) {
mInputConsumer.onMotionEvent(ev);
}
return true;
}
}

View File

@ -110,7 +110,7 @@ public class LoaderCursorTest {
public void getAppShortcutInfo_dontAllowMissing_invalidComponent() {
initCursor(ITEM_TYPE_APPLICATION, "");
assertTrue(mLoaderCursor.moveToNext());
ComponentName cn = new ComponentName(mContext.getPackageName(), "placeholder-do");
ComponentName cn = new ComponentName(mContext.getPackageName(), "dummy-do");
assertNull(mLoaderCursor.getAppShortcutInfo(
new Intent().setComponent(cn), false /* allowMissingTarget */, true));
}

View File

@ -44,7 +44,7 @@ public class RestoreDbTaskTest {
@Test
public void testMigrateProfileId() throws Exception {
SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
// Add some mock data
// Add some dummy data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, i);
@ -64,7 +64,7 @@ public class RestoreDbTaskTest {
@Test
public void testChangeDefaultColumn() throws Exception {
SQLiteDatabase db = new MyDatabaseHelper(42).getWritableDatabase();
// Add some mock data
// Add some dummy data
for (int i = 0; i < 5; i++) {
ContentValues values = new ContentValues();
values.put(Favorites._ID, i);

View File

@ -241,9 +241,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
mFolderName.setSelectAllOnFocus(true);
mFolderName.setInputType(mFolderName.getInputType()
& ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
& ~InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
| InputType.TYPE_TEXT_FLAG_CAP_WORDS);
mFolderName.forceDisableSuggestions(!FeatureFlags.FOLDER_NAME_SUGGEST.get());
mFolderName.forceDisableSuggestions(true);
mFooter = findViewById(R.id.folder_footer);

View File

@ -28,6 +28,7 @@ import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.annotation.TargetApi;
import android.app.Fragment;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetProviderInfo;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
@ -56,6 +57,7 @@ import com.android.launcher3.Hotseat;
import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
@ -83,6 +85,7 @@ import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.UserCache;
import com.android.launcher3.uioverrides.PredictedAppIconInflater;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.IntArray;
import com.android.launcher3.util.MainThreadInitializedObject;
import com.android.launcher3.views.ActivityContext;
@ -339,14 +342,33 @@ public class LauncherPreviewRenderer {
addInScreenFromBind(folderIcon, info);
}
private void inflateAndAddWidgets(LauncherAppWidgetInfo info,
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) {
if (widgetProviderInfoMap == null) {
return;
}
AppWidgetProviderInfo providerInfo = widgetProviderInfoMap.get(
new ComponentKey(info.providerName, info.user));
if (providerInfo == null) {
return;
}
inflateAndAddWidgets(info, LauncherAppWidgetProviderInfo.fromProviderInfo(
getApplicationContext(), providerInfo));
}
private void inflateAndAddWidgets(LauncherAppWidgetInfo info, WidgetsModel widgetsModel) {
WidgetItem widgetItem = widgetsModel.getWidgetProviderInfoByProviderName(
info.providerName);
if (widgetItem == null) {
return;
}
inflateAndAddWidgets(info, widgetItem.widgetInfo);
}
private void inflateAndAddWidgets(LauncherAppWidgetInfo info,
LauncherAppWidgetProviderInfo providerInfo) {
AppWidgetHostView view = new AppWidgetHostView(mContext);
view.setAppWidget(-1, widgetItem.widgetInfo);
view.setAppWidget(-1, providerInfo);
view.updateAppWidget(null);
view.setTag(info);
addInScreenFromBind(view, info);
@ -433,8 +455,13 @@ public class LauncherPreviewRenderer {
switch (itemInfo.itemType) {
case Favorites.ITEM_TYPE_APPWIDGET:
case Favorites.ITEM_TYPE_CUSTOM_APPWIDGET:
inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
workspaceResult.mWidgetsModel);
if (mMigrated) {
inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
workspaceResult.mWidgetProvidersMap);
} else {
inflateAndAddWidgets((LauncherAppWidgetInfo) itemInfo,
workspaceResult.mWidgetsModel);
}
break;
default:
break;
@ -542,7 +569,7 @@ public class LauncherPreviewRenderer {
}
return new WorkspaceResult(mBgDataModel.workspaceItems, mBgDataModel.appWidgets,
mBgDataModel.cachedPredictedItems, mBgDataModel.widgetsModel);
mBgDataModel.cachedPredictedItems, mBgDataModel.widgetsModel, null);
}
}
@ -569,9 +596,8 @@ public class LauncherPreviewRenderer {
public WorkspaceResult call() throws Exception {
List<ShortcutInfo> allShortcuts = new ArrayList<>();
loadWorkspace(allShortcuts, LauncherSettings.Favorites.PREVIEW_CONTENT_URI);
mBgDataModel.widgetsModel.update(mApp, null);
return new WorkspaceResult(mBgDataModel.workspaceItems, mBgDataModel.appWidgets,
mBgDataModel.cachedPredictedItems, mBgDataModel.widgetsModel);
mBgDataModel.cachedPredictedItems, null, mWidgetProvidersMap);
}
}
@ -593,14 +619,17 @@ public class LauncherPreviewRenderer {
private final ArrayList<LauncherAppWidgetInfo> mAppWidgets;
private final ArrayList<AppInfo> mCachedPredictedItems;
private final WidgetsModel mWidgetsModel;
private final Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap;
private WorkspaceResult(ArrayList<ItemInfo> workspaceItems,
ArrayList<LauncherAppWidgetInfo> appWidgets,
ArrayList<AppInfo> cachedPredictedItems, WidgetsModel widgetsModel) {
ArrayList<AppInfo> cachedPredictedItems, WidgetsModel widgetsModel,
Map<ComponentKey, AppWidgetProviderInfo> widgetProviderInfoMap) {
mWorkspaceItems = workspaceItems;
mAppWidgets = appWidgets;
mCachedPredictedItems = cachedPredictedItems;
mWidgetsModel = widgetsModel;
mWidgetProvidersMap = widgetProviderInfoMap;
}
}
}

View File

@ -406,7 +406,7 @@ public class GridSizeMigrationTaskV2 {
* to speed up the search.
*/
private boolean findPlacement(DbEntry entry) {
for (int y = mNextStartY; y > 0; y--) {
for (int y = mNextStartY; y >= (mScreenId == 0 ? 1 /* smartspace */ : 0); y--) {
for (int x = mNextStartX; x < mTrgX; x++) {
boolean fits = mOccupied.isRegionVacant(x, y, entry.spanX, entry.spanY);
boolean minFits = mOccupied.isRegionVacant(x, y, entry.minSpanX,

View File

@ -126,6 +126,8 @@ public class LoaderTask implements Runnable {
private final UserManagerState mUserManagerState = new UserManagerState();
protected Map<ComponentKey, AppWidgetProviderInfo> mWidgetProvidersMap;
private boolean mStopped;
public LoaderTask(LauncherAppState app, AllAppsList bgAllAppsList, BgDataModel dataModel,
@ -342,8 +344,6 @@ public class LoaderTask implements Runnable {
contentResolver.query(contentUri, null, null, null, null), contentUri, mApp,
mUserManagerState);
Map<ComponentKey, AppWidgetProviderInfo> widgetProvidersMap = null;
try {
final int appWidgetIdIndex = c.getColumnIndexOrThrow(
LauncherSettings.Favorites.APPWIDGET_ID);
@ -650,10 +650,11 @@ public class LoaderTask implements Runnable {
final boolean wasProviderReady = !c.hasRestoreFlag(
LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY);
if (widgetProvidersMap == null) {
widgetProvidersMap = WidgetManagerHelper.getAllProvidersMap(context);
if (mWidgetProvidersMap == null) {
mWidgetProvidersMap = WidgetManagerHelper.getAllProvidersMap(
context);
}
final AppWidgetProviderInfo provider = widgetProvidersMap.get(
final AppWidgetProviderInfo provider = mWidgetProvidersMap.get(
new ComponentKey(component, c.user));
final boolean isProviderReady = isValidProvider(provider);

View File

@ -216,7 +216,7 @@ public class WorkspaceItemInfo extends ItemInfoWithIcon {
if (cn == null && (itemType == Favorites.ITEM_TYPE_SHORTCUT || hasStatusFlag(
FLAG_SUPPORTS_WEB_UI | FLAG_AUTOINSTALL_ICON | FLAG_RESTORED_ICON))) {
// Legacy shortcuts and promise icons with web UI may not have a componentName but just
// a packageName. In that case create a empty componentName instead of adding additional
// a packageName. In that case create a dummy componentName instead of adding additional
// check everywhere.
String pkg = intent.getPackage();
return pkg == null ? null : new ComponentName(pkg, IconCache.EMPTY_CLASS_NAME);

View File

@ -52,7 +52,6 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
private static final float MIN_SATUNATION = 0.7f;
private final Rect mRect = new Rect();
private View mDefaultView;
private OnClickListener mClickListener;
private final LauncherAppWidgetInfo mInfo;
private final int mStartState;
@ -111,12 +110,11 @@ public class PendingAppWidgetHostView extends LauncherAppWidgetHostView
@Override
protected View getDefaultView() {
if (mDefaultView == null) {
mDefaultView = mInflater.inflate(R.layout.appwidget_not_ready, this, false);
mDefaultView.setOnClickListener(this);
applyState();
}
return mDefaultView;
View defaultView = mInflater.inflate(R.layout.appwidget_not_ready, this, false);
defaultView.setOnClickListener(this);
applyState();
invalidate();
return defaultView;
}
@Override