From 17c72fbb603bcb3ae6d4dd52ae9219050e072004 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 14 Oct 2019 14:06:38 -0700 Subject: [PATCH 01/17] Unifying various tracing calls Change-Id: Iedf6662ad1d7281b850bdc43b3a1e373ce535ac6 --- .../quickstep/TouchInteractionService.java | 11 +- .../WindowTransformSwipeHandler.java | 27 +-- .../OtherActivityInputConsumer.java | 16 +- .../quickstep/views/LauncherRecentsView.java | 4 +- .../uioverrides/DejankBinderTracker.java | 159 ------------- .../StartLauncherViaGestureTests.java | 4 +- .../launcher3/BaseDraggingActivity.java | 8 +- src/com/android/launcher3/Launcher.java | 224 +++++++++--------- .../android/launcher3/model/LoaderTask.java | 41 ++-- .../util/MainThreadInitializedObject.java | 5 +- .../launcher3/util/RaceConditionTracker.java | 61 ----- .../android/launcher3/util/TraceHelper.java | 101 ++++---- .../uioverrides/DejankBinderTracker.java | 57 ----- tests/Android.mk | 1 - .../util/RaceConditionReproducer.java | 32 ++- .../util/RaceConditionReproducerTest.java | 78 +++--- .../launcher3/util/TraceHelperForTest.java | 100 ++++++++ 17 files changed, 367 insertions(+), 562 deletions(-) delete mode 100644 quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java delete mode 100644 src/com/android/launcher3/util/RaceConditionTracker.java delete mode 100644 src_ui_overrides/com/android/launcher3/uioverrides/DejankBinderTracker.java create mode 100644 tests/src/com/android/launcher3/util/TraceHelperForTest.java diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 4b7ae6f426..d4e59c23d8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -60,7 +60,7 @@ import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.provider.RestoreDbTask; import com.android.launcher3.testing.TestProtocol; -import com.android.launcher3.uioverrides.DejankBinderTracker; +import com.android.launcher3.util.TraceHelper; import com.android.quickstep.SysUINavigationMode.Mode; import com.android.quickstep.SysUINavigationMode.NavigationModeChangeListener; import com.android.quickstep.inputconsumers.AccessibilityInputConsumer; @@ -401,7 +401,6 @@ public class TouchInteractionService extends Service implements } private void onInputEvent(InputEvent ev) { - DejankBinderTracker.allowBinderTrackingInTests(); if (TestProtocol.sDebugTracing) { Log.d(TestProtocol.NO_BACKGROUND_TO_OVERVIEW_TAG, "onInputEvent " + ev); } @@ -410,6 +409,7 @@ public class TouchInteractionService extends Service implements return; } + TraceHelper.INSTANCE.beginFlagsOverride(TraceHelper.FLAG_ALLOW_BINDER_TRACKING); MotionEvent event = (MotionEvent) ev; if (event.getAction() == ACTION_DOWN) { GestureState newGestureState = new GestureState( @@ -438,7 +438,7 @@ public class TouchInteractionService extends Service implements ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked()); mUncheckedConsumer.onMotionEvent(event); - DejankBinderTracker.disallowBinderTrackingInTests(); + TraceHelper.INSTANCE.endFlagsOverride(); } private InputConsumer newConsumer(GestureState gestureState, boolean useSharedState, @@ -490,7 +490,7 @@ public class TouchInteractionService extends Service implements private InputConsumer newBaseConsumer(GestureState gestureState, boolean useSharedState, MotionEvent event) { - RunningTaskInfo runningTaskInfo = DejankBinderTracker.whitelistIpcs( + RunningTaskInfo runningTaskInfo = TraceHelper.whitelistIpcs("getRunningTask.0", () -> mAM.getRunningTask(0)); if (!useSharedState) { sSwipeSharedState.clearAllState(false /* finishAnimation */); @@ -504,7 +504,8 @@ public class TouchInteractionService extends Service implements if (isExcludedAssistant(runningTaskInfo)) { // In the case where we are in the excluded assistant state, ignore it and treat the // running activity as the task behind the assistant - runningTaskInfo = DejankBinderTracker.whitelistIpcs( + + runningTaskInfo = TraceHelper.whitelistIpcs("getRunningTask.assistant", () -> mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT)); if (!ActivityManagerWrapper.isHomeTask(runningTaskInfo)) { final ComponentName homeComponent = diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index e3b12cb79c..8dd1fffe96 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -23,8 +23,6 @@ import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS; import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs; -import static com.android.launcher3.util.RaceConditionTracker.ENTER; -import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW; import static com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState.HIDE; import static com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState.PEEK; @@ -65,11 +63,9 @@ import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.logging.UserEventDispatcher; -import com.android.launcher3.uioverrides.DejankBinderTracker; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction; import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; -import com.android.launcher3.util.RaceConditionTracker; import com.android.launcher3.util.TraceHelper; import com.android.quickstep.BaseActivityInterface.AnimationFactory; import com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState; @@ -371,13 +367,13 @@ public class WindowTransformSwipeHandler if (mWasLauncherAlreadyVisible) { mStateCallback.setState(STATE_LAUNCHER_DRAWN); } else { - TraceHelper.beginSection("WTS-init"); + TraceHelper.INSTANCE.beginSection("WTS-init"); View dragLayer = activity.getDragLayer(); dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() { @Override public void onDraw() { - TraceHelper.endSection("WTS-init", "Launcher frame is drawn"); + TraceHelper.INSTANCE.endSection(); dragLayer.post(() -> dragLayer.getViewTreeObserver().removeOnDrawListener(this)); if (activity != mActivity) { @@ -420,13 +416,13 @@ public class WindowTransformSwipeHandler private void initializeLauncherAnimationController() { buildAnimationController(); - DejankBinderTracker.whitelistIpcs(() -> { - // Only used in debug builds - if (LatencyTrackerCompat.isEnabled(mContext)) { - LatencyTrackerCompat.logToggleRecents( - (int) (mLauncherFrameDrawnTime - mTouchTimeMs)); - } - }); + TraceHelper.INSTANCE.beginSection("logToggleRecents", TraceHelper.FLAG_IGNORE_BINDERS); + // Only used in debug builds + if (LatencyTrackerCompat.isEnabled(mContext)) { + LatencyTrackerCompat.logToggleRecents( + (int) (mLauncherFrameDrawnTime - mTouchTimeMs)); + } + TraceHelper.INSTANCE.endSection(); // This method is only called when STATE_GESTURE_STARTED is set, so we can enable the // high-res thumbnail loader here once we are sure that we will end up in an overview state @@ -1148,9 +1144,10 @@ public class WindowTransformSwipeHandler } if (!finishTransitionPosted) { // If we haven't posted a draw callback, set the state immediately. - RaceConditionTracker.onEvent(SCREENSHOT_CAPTURED_EVT, ENTER); + TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT, + TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS); setStateOnUiThread(STATE_SCREENSHOT_CAPTURED); - RaceConditionTracker.onEvent(SCREENSHOT_CAPTURED_EVT, EXIT); + TraceHelper.INSTANCE.endSection(); } } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index fbedc0f812..d231d51be3 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -25,8 +25,7 @@ import static android.view.MotionEvent.INVALID_POINTER_ID; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; import static com.android.launcher3.Utilities.squaredHypot; -import static com.android.launcher3.util.RaceConditionTracker.ENTER; -import static com.android.launcher3.util.RaceConditionTracker.EXIT; +import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS; import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync; import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; @@ -48,13 +47,13 @@ import androidx.annotation.UiThread; import com.android.launcher3.R; import com.android.launcher3.util.Preconditions; -import com.android.launcher3.util.RaceConditionTracker; import com.android.launcher3.util.TraceHelper; import com.android.quickstep.BaseActivityInterface; import com.android.quickstep.BaseSwipeUpHandler; import com.android.quickstep.BaseSwipeUpHandler.Factory; import com.android.quickstep.GestureState; import com.android.quickstep.InputConsumer; +import com.android.quickstep.RecentsAnimationCallbacks; import com.android.quickstep.RecentsAnimationDeviceState; import com.android.quickstep.SwipeSharedState; import com.android.quickstep.SysUINavigationMode; @@ -63,7 +62,6 @@ import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.CachedEventDispatcher; import com.android.quickstep.util.MotionPauseDetector; import com.android.quickstep.util.NavBarPosition; -import com.android.quickstep.RecentsAnimationCallbacks; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputMonitorCompat; @@ -200,8 +198,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC switch (ev.getActionMasked()) { case ACTION_DOWN: { - RaceConditionTracker.onEvent(DOWN_EVT, ENTER); - TraceHelper.beginSection("TouchInt"); + TraceHelper.INSTANCE.beginSection(DOWN_EVT, FLAG_CHECK_FOR_RACE_CONDITIONS); mActivePointerId = ev.getPointerId(0); mDownPos.set(ev.getX(), ev.getY()); mLastPos.set(mDownPos); @@ -212,7 +209,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC startTouchTrackingForWindowAnimation(ev.getEventTime(), false); } - RaceConditionTracker.onEvent(DOWN_EVT, EXIT); + TraceHelper.INSTANCE.endSection(); break; } case ACTION_POINTER_DOWN: { @@ -358,8 +355,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC * the animation can still be running. */ private void finishTouchTracking(MotionEvent ev) { - RaceConditionTracker.onEvent(UP_EVT, ENTER); - TraceHelper.endSection("TouchInt"); + TraceHelper.INSTANCE.beginSection(UP_EVT, FLAG_CHECK_FOR_RACE_CONDITIONS); if (mPassedWindowMoveSlop && mInteractionHandler != null) { if (ev.getActionMasked() == ACTION_CANCEL) { @@ -393,7 +389,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mVelocityTracker.recycle(); mVelocityTracker = null; mMotionPauseDetector.clear(); - RaceConditionTracker.onEvent(UP_EVT, EXIT); + TraceHelper.INSTANCE.endSection(); } @Override diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java index 1545ec5110..0655c733ba 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java @@ -46,8 +46,8 @@ import com.android.launcher3.R; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.appprediction.PredictionUiStateManager; import com.android.launcher3.appprediction.PredictionUiStateManager.Client; -import com.android.launcher3.uioverrides.DejankBinderTracker; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; +import com.android.launcher3.util.TraceHelper; import com.android.launcher3.views.ScrimView; import com.android.quickstep.SysUINavigationMode; import com.android.quickstep.util.AppWindowAnimationHelper; @@ -221,7 +221,7 @@ public class LauncherRecentsView extends RecentsView implements StateL @Override public boolean shouldUseMultiWindowTaskSizeStrategy() { - return DejankBinderTracker.whitelistIpcs(() -> mActivity.isInMultiWindowMode()); + return TraceHelper.whitelistIpcs("isInMultiWindowMode", mActivity::isInMultiWindowMode); } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java b/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java deleted file mode 100644 index d8aa235823..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java +++ /dev/null @@ -1,159 +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.uioverrides; - -import static android.os.IBinder.FLAG_ONEWAY; - -import android.os.Binder; -import android.os.Build; -import android.os.IBinder; -import android.os.Looper; -import android.os.RemoteException; -import android.util.Log; - -import androidx.annotation.MainThread; - -import java.util.HashSet; -import java.util.Locale; -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -/** - * A binder proxy transaction listener for tracking non-whitelisted binder calls. - */ -public class DejankBinderTracker implements Binder.ProxyTransactListener { - private static final String TAG = "DejankBinderTracker"; - - private static final Object sLock = new Object(); - private static final HashSet sWhitelistedFrameworkClasses = new HashSet<>(); - static { - // Common IPCs that are ok to block the main thread. - sWhitelistedFrameworkClasses.add("android.view.IWindowSession"); - sWhitelistedFrameworkClasses.add("android.os.IPowerManager"); - } - private static boolean sTemporarilyIgnoreTracking = false; - - // Used by the client to limit binder tracking to specific regions - private static boolean sTrackingAllowed = false; - - private BiConsumer mUnexpectedTransactionCallback; - private boolean mIsTracking = false; - - /** - * Temporarily ignore blocking binder calls for the duration of this {@link Runnable}. - */ - @MainThread - public static void whitelistIpcs(Runnable runnable) { - sTemporarilyIgnoreTracking = true; - runnable.run(); - sTemporarilyIgnoreTracking = false; - } - - /** - * Temporarily ignore blocking binder calls for the duration of this {@link Supplier}. - */ - @MainThread - public static T whitelistIpcs(Supplier supplier) { - sTemporarilyIgnoreTracking = true; - T value = supplier.get(); - sTemporarilyIgnoreTracking = false; - return value; - } - - /** - * Enables binder tracking during a test. - */ - @MainThread - public static void allowBinderTrackingInTests() { - sTrackingAllowed = true; - } - - /** - * Disables binder tracking during a test. - */ - @MainThread - public static void disallowBinderTrackingInTests() { - sTrackingAllowed = false; - } - - public DejankBinderTracker(BiConsumer unexpectedTransactionCallback) { - mUnexpectedTransactionCallback = unexpectedTransactionCallback; - } - - @MainThread - public void startTracking() { - if (!Build.TYPE.toLowerCase(Locale.ROOT).contains("debug") - && !Build.TYPE.toLowerCase(Locale.ROOT).equals("eng")) { - Log.wtf(TAG, "Unexpected use of binder tracker in non-debug build", new Exception()); - return; - } - if (mIsTracking) { - return; - } - mIsTracking = true; - Binder.setProxyTransactListener(this); - } - - @MainThread - public void stopTracking() { - if (!mIsTracking) { - return; - } - mIsTracking = false; - Binder.setProxyTransactListener(null); - } - - // Override the hidden Binder#onTransactStarted method - public synchronized Object onTransactStarted(IBinder binder, int transactionCode, int flags) { - if (!mIsTracking - || !sTrackingAllowed - || sTemporarilyIgnoreTracking - || (flags & FLAG_ONEWAY) == FLAG_ONEWAY - || !isMainThread()) { - return null; - } - - String descriptor; - try { - descriptor = binder.getInterfaceDescriptor(); - if (sWhitelistedFrameworkClasses.contains(descriptor)) { - return null; - } - } catch (RemoteException e) { - e.printStackTrace(); - descriptor = binder.getClass().getSimpleName(); - } - - mUnexpectedTransactionCallback.accept(descriptor, transactionCode); - return null; - } - - @Override - public Object onTransactStarted(IBinder binder, int transactionCode) { - // Do nothing - return null; - } - - @Override - public void onTransactEnded(Object session) { - // Do nothing - } - - public static boolean isMainThread() { - return Thread.currentThread() == Looper.getMainLooper().getThread(); - } -} diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java index 2111e2ca27..1d920f96c8 100644 --- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java +++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java @@ -16,8 +16,8 @@ package com.android.quickstep; -import static com.android.launcher3.util.RaceConditionTracker.enterEvt; -import static com.android.launcher3.util.RaceConditionTracker.exitEvt; +import static com.android.launcher3.util.RaceConditionReproducer.enterEvt; +import static com.android.launcher3.util.RaceConditionReproducer.exitEvt; import android.content.Intent; diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java index 00a06ae633..d24de8e30c 100644 --- a/src/com/android/launcher3/BaseDraggingActivity.java +++ b/src/com/android/launcher3/BaseDraggingActivity.java @@ -36,11 +36,11 @@ import androidx.annotation.Nullable; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.shortcuts.DeepShortcutManager; -import com.android.launcher3.uioverrides.DejankBinderTracker; import com.android.launcher3.uioverrides.DisplayRotationListener; import com.android.launcher3.uioverrides.WallpaperColorInfo; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.Themes; +import com.android.launcher3.util.TraceHelper; /** * Extension of BaseActivity allowing support for drag-n-drop @@ -66,8 +66,10 @@ public abstract class BaseDraggingActivity extends BaseActivity @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mIsSafeModeEnabled = DejankBinderTracker.whitelistIpcs(() -> - getPackageManager().isSafeMode()); + + + mIsSafeModeEnabled = TraceHelper.whitelistIpcs("isSafeMode", + () -> getPackageManager().isSafeMode()); mRotationListener = new DisplayRotationListener(this, this::onDeviceRotationChanged); // Update theme diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index c92d917155..a19ba21a48 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -32,8 +32,6 @@ import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOA import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.logging.LoggerUtils.newTarget; import static com.android.launcher3.states.RotationHelper.REQUEST_NONE; -import static com.android.launcher3.util.RaceConditionTracker.ENTER; -import static com.android.launcher3.util.RaceConditionTracker.EXIT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -115,7 +113,6 @@ import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.qsb.QsbContainerView; import com.android.launcher3.states.RotationHelper; import com.android.launcher3.touch.ItemClickHandler; -import com.android.launcher3.uioverrides.DejankBinderTracker; import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; import com.android.launcher3.userevent.nano.LauncherLogProto; @@ -132,7 +129,6 @@ import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.PendingRequestArgs; -import com.android.launcher3.util.RaceConditionTracker; import com.android.launcher3.util.ShortcutUtil; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; @@ -214,9 +210,11 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, private static final String RUNTIME_STATE_PENDING_ACTIVITY_RESULT = "launcher.activity_result"; // Type: SparseArray private static final String RUNTIME_STATE_WIDGET_PANEL = "launcher.widget_panel"; + public static final String ON_CREATE_EVT = "Launcher.onCreate"; - private static final String ON_START_EVT = "Launcher.onStart"; - private static final String ON_RESUME_EVT = "Launcher.onResume"; + public static final String ON_START_EVT = "Launcher.onStart"; + public static final String ON_RESUME_EVT = "Launcher.onResume"; + public static final String ON_NEW_INTENT_EVT = "Launcher.onNewIntent"; private LauncherStateManager mStateManager; @@ -313,8 +311,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onCreate(Bundle savedInstanceState) { - DejankBinderTracker.allowBinderTrackingInTests(); - RaceConditionTracker.onEvent(ON_CREATE_EVT, ENTER); + TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT, TraceHelper.FLAG_UI_EVENT); if (DEBUG_STRICT_MODE) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() @@ -329,10 +326,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, .penaltyDeath() .build()); } - TraceHelper.beginSection("Launcher-onCreate"); super.onCreate(savedInstanceState); - TraceHelper.partitionSection("Launcher-onCreate", "super call"); LauncherAppState app = LauncherAppState.getInstance(this); mOldConfig = new Configuration(getResources().getConfiguration()); @@ -414,8 +409,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mRotationHelper.initialize(); - TraceHelper.endSection("Launcher-onCreate"); - RaceConditionTracker.onEvent(ON_CREATE_EVT, EXIT); mStateManager.addStateListener(new LauncherStateManager.StateListener() { @Override public void onStateTransitionStart(LauncherState toState) { @@ -435,7 +428,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, } } }); - DejankBinderTracker.disallowBinderTrackingInTests(); + + TraceHelper.INSTANCE.endSection(); } protected LauncherOverlayManager getDefaultOverlay() { @@ -940,16 +934,14 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onStart() { - DejankBinderTracker.allowBinderTrackingInTests(); - RaceConditionTracker.onEvent(ON_START_EVT, ENTER); + TraceHelper.INSTANCE.beginSection(ON_START_EVT, TraceHelper.FLAG_UI_EVENT); super.onStart(); if (!mDeferOverlayCallbacks) { mOverlayManager.onActivityStarted(this); } mAppWidgetHost.setListenIfResumed(true); - RaceConditionTracker.onEvent(ON_START_EVT, EXIT); - DejankBinderTracker.disallowBinderTrackingInTests(); + TraceHelper.INSTANCE.endSection(); } private void handleDeferredResume() { @@ -1044,11 +1036,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onResume() { - DejankBinderTracker.allowBinderTrackingInTests(); - RaceConditionTracker.onEvent(ON_RESUME_EVT, ENTER); - TraceHelper.beginSection("ON_RESUME"); + TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT, TraceHelper.FLAG_UI_EVENT); super.onResume(); - TraceHelper.partitionSection("ON_RESUME", "superCall"); mHandler.removeCallbacks(mHandleDeferredResume); Utilities.postAsyncCallback(mHandler, mHandleDeferredResume); @@ -1068,9 +1057,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mOverlayManager.onActivityResumed(this); } - TraceHelper.endSection("ON_RESUME"); - RaceConditionTracker.onEvent(ON_RESUME_EVT, EXIT); - DejankBinderTracker.disallowBinderTrackingInTests(); + TraceHelper.INSTANCE.endSection(); } @Override @@ -1429,7 +1416,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onNewIntent(Intent intent) { - TraceHelper.beginSection("NEW_INTENT"); + TraceHelper.INSTANCE.beginSection(ON_NEW_INTENT_EVT); super.onNewIntent(intent); boolean alreadyOnHome = hasWindowFocus() && ((intent.getFlags() & @@ -1481,7 +1468,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mOverlayManager.hideOverlay(isStarted() && !isForceInvisible()); } - TraceHelper.endSection("NEW_INTENT"); + TraceHelper.INSTANCE.endSection(); } @Override @@ -1984,7 +1971,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, * Implementation of the method from LauncherModel.Callbacks. */ public void startBinding() { - TraceHelper.beginSection("startBinding"); + TraceHelper.INSTANCE.beginSection("startBinding"); // Floating panels (except the full widget sheet) are associated with individual icons. If // we are starting a fresh bind, close all such panels as all the icons are about // to go away. @@ -2002,7 +1989,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, if (mHotseat != null) { mHotseat.resetLayout(getWallpaperDeviceProfile().isVerticalBarLayout()); } - TraceHelper.endSection("startBinding"); + TraceHelper.INSTANCE.endSection(); } @Override @@ -2195,112 +2182,113 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, return null; } } - + final AppWidgetHostView view; if (mIsSafeModeEnabled) { - PendingAppWidgetHostView view = - new PendingAppWidgetHostView(this, item, mIconCache, true); + view = new PendingAppWidgetHostView(this, item, mIconCache, true); prepareAppWidget(view, item); return view; } - TraceHelper.beginSection("BIND_WIDGET"); + TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId); - final LauncherAppWidgetProviderInfo appWidgetInfo; + try { + final LauncherAppWidgetProviderInfo appWidgetInfo; - if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) { - // If the provider is not ready, bind as a pending widget. - appWidgetInfo = null; - } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) { - // The widget id is not valid. Try to find the widget based on the provider info. - appWidgetInfo = mAppWidgetManager.findProvider(item.providerName, item.user); - } else { - appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(item.appWidgetId); - } - - // If the provider is ready, but the width is not yet restored, try to restore it. - if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) && - (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) { - if (appWidgetInfo == null) { - Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId - + " belongs to component " + item.providerName - + ", as the provider is null"); - getModelWriter().deleteItemFromDatabase(item); - return null; + if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY)) { + // If the provider is not ready, bind as a pending widget. + appWidgetInfo = null; + } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) { + // The widget id is not valid. Try to find the widget based on the provider info. + appWidgetInfo = mAppWidgetManager.findProvider(item.providerName, item.user); + } else { + appWidgetInfo = mAppWidgetManager.getLauncherAppWidgetInfo(item.appWidgetId); } - // If we do not have a valid id, try to bind an id. - if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) { - if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) { - // Id has not been allocated yet. Allocate a new id. - item.appWidgetId = mAppWidgetHost.allocateAppWidgetId(); - item.restoreStatus |= LauncherAppWidgetInfo.FLAG_ID_ALLOCATED; + // If the provider is ready, but the width is not yet restored, try to restore it. + if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY) + && (item.restoreStatus != LauncherAppWidgetInfo.RESTORE_COMPLETED)) { + if (appWidgetInfo == null) { + Log.d(TAG, "Removing restored widget: id=" + item.appWidgetId + + " belongs to component " + item.providerName + + ", as the provider is null"); + getModelWriter().deleteItemFromDatabase(item); + return null; + } - // Also try to bind the widget. If the bind fails, the user will be shown - // a click to setup UI, which will ask for the bind permission. - PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(appWidgetInfo); - pendingInfo.spanX = item.spanX; - pendingInfo.spanY = item.spanY; - pendingInfo.minSpanX = item.minSpanX; - pendingInfo.minSpanY = item.minSpanY; - Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this, - pendingInfo); + // If we do not have a valid id, try to bind an id. + if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_NOT_VALID)) { + if (!item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_ID_ALLOCATED)) { + // Id has not been allocated yet. Allocate a new id. + item.appWidgetId = mAppWidgetHost.allocateAppWidgetId(); + item.restoreStatus |= LauncherAppWidgetInfo.FLAG_ID_ALLOCATED; - boolean isDirectConfig = - item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG); - if (isDirectConfig && item.bindOptions != null) { - Bundle newOptions = item.bindOptions.getExtras(); - if (options != null) { - newOptions.putAll(options); + // Also try to bind the widget. If the bind fails, the user will be shown + // a click to setup UI, which will ask for the bind permission. + PendingAddWidgetInfo pendingInfo = new PendingAddWidgetInfo(appWidgetInfo); + pendingInfo.spanX = item.spanX; + pendingInfo.spanY = item.spanY; + pendingInfo.minSpanX = item.minSpanX; + pendingInfo.minSpanY = item.minSpanY; + Bundle options = WidgetHostViewLoader.getDefaultOptionsForWidget(this, + pendingInfo); + + boolean isDirectConfig = + item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG); + if (isDirectConfig && item.bindOptions != null) { + Bundle newOptions = item.bindOptions.getExtras(); + if (options != null) { + newOptions.putAll(options); + } + options = newOptions; } - options = newOptions; + boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed( + item.appWidgetId, appWidgetInfo, options); + + // We tried to bind once. If we were not able to bind, we would need to + // go through the permission dialog, which means we cannot skip the config + // activity. + item.bindOptions = null; + item.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG; + + // Bind succeeded + if (success) { + // If the widget has a configure activity, it is still needs to set it + // up, otherwise the widget is ready to go. + item.restoreStatus = (appWidgetInfo.configure == null) || isDirectConfig + ? LauncherAppWidgetInfo.RESTORE_COMPLETED + : LauncherAppWidgetInfo.FLAG_UI_NOT_READY; + } + + getModelWriter().updateItemInDatabase(item); } - boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed( - item.appWidgetId, appWidgetInfo, options); - - // We tried to bind once. If we were not able to bind, we would need to - // go through the permission dialog, which means we cannot skip the config - // activity. - item.bindOptions = null; - item.restoreStatus &= ~LauncherAppWidgetInfo.FLAG_DIRECT_CONFIG; - - // Bind succeeded - if (success) { - // If the widget has a configure activity, it is still needs to set it up, - // otherwise the widget is ready to go. - item.restoreStatus = (appWidgetInfo.configure == null) || isDirectConfig - ? LauncherAppWidgetInfo.RESTORE_COMPLETED - : LauncherAppWidgetInfo.FLAG_UI_NOT_READY; - } - + } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY) + && (appWidgetInfo.configure == null)) { + // The widget was marked as UI not ready, but there is no configure activity to + // update the UI. + item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED; getModelWriter().updateItemInDatabase(item); } - } else if (item.hasRestoreFlag(LauncherAppWidgetInfo.FLAG_UI_NOT_READY) - && (appWidgetInfo.configure == null)) { - // The widget was marked as UI not ready, but there is no configure activity to - // update the UI. - item.restoreStatus = LauncherAppWidgetInfo.RESTORE_COMPLETED; - getModelWriter().updateItemInDatabase(item); - } - } - - final AppWidgetHostView view; - if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) { - // Verify that we own the widget - if (appWidgetInfo == null) { - FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId); - getModelWriter().deleteWidgetInfo(item, getAppWidgetHost()); - return null; } - item.minSpanX = appWidgetInfo.minSpanX; - item.minSpanY = appWidgetInfo.minSpanY; - view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo); - } else { - view = new PendingAppWidgetHostView(this, item, mIconCache, false); - } - prepareAppWidget(view, item); + if (item.restoreStatus == LauncherAppWidgetInfo.RESTORE_COMPLETED) { + // Verify that we own the widget + if (appWidgetInfo == null) { + FileLog.e(TAG, "Removing invalid widget: id=" + item.appWidgetId); + getModelWriter().deleteWidgetInfo(item, getAppWidgetHost()); + return null; + } + + item.minSpanX = appWidgetInfo.minSpanX; + item.minSpanY = appWidgetInfo.minSpanY; + view = mAppWidgetHost.createView(this, item.appWidgetId, appWidgetInfo); + } else { + view = new PendingAppWidgetHostView(this, item, mIconCache, false); + } + prepareAppWidget(view, item); + } finally { + TraceHelper.INSTANCE.endSection(); + } - TraceHelper.endSection("BIND_WIDGET", "id=" + item.appWidgetId); return view; } @@ -2378,7 +2366,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, * Implementation of the method from LauncherModel.Callbacks. */ public void finishBindingItems(int pageBoundFirst) { - TraceHelper.beginSection("finishBindingItems"); + TraceHelper.INSTANCE.beginSection("finishBindingItems"); mWorkspace.restoreInstanceStateForRemainingPages(); setWorkspaceLoading(false); @@ -2402,7 +2390,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mDeviceProfile.inv.numFolderColumns * mDeviceProfile.inv.numFolderRows); getViewCache().setCacheSize(R.layout.folder_page, 2); - TraceHelper.endSection("finishBindingItems"); + TraceHelper.INSTANCE.endSection(); } private boolean canRunNewAppsAnimation() { diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index a29b7e1370..2d4a816338 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -40,6 +40,7 @@ import android.text.TextUtils; import android.util.Log; import android.util.LongSparseArray; import android.util.MutableInt; +import android.util.TimingLogger; import com.android.launcher3.AppInfo; import com.android.launcher3.FolderInfo; @@ -169,82 +170,84 @@ public class LoaderTask implements Runnable { } } - TraceHelper.beginSection(TAG); + TraceHelper.INSTANCE.beginSection(TAG); + TimingLogger logger = new TimingLogger(TAG, "run"); try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { - TraceHelper.partitionSection(TAG, "step 1.1: loading workspace"); loadWorkspace(); + logger.addSplit("loadWorkspace"); verifyNotStopped(); - TraceHelper.partitionSection(TAG, "step 1.2: bind workspace workspace"); mResults.bindWorkspace(); + logger.addSplit("bindWorkspace"); // Notify the installer packages of packages with active installs on the first screen. - TraceHelper.partitionSection(TAG, "step 1.3: send first screen broadcast"); sendFirstScreenActiveInstallsBroadcast(); + logger.addSplit("sendFirstScreenActiveInstallsBroadcast"); // Take a break - TraceHelper.partitionSection(TAG, "step 1 completed, wait for idle"); waitForIdle(); + logger.addSplit("step 1 complete"); verifyNotStopped(); // second step - TraceHelper.partitionSection(TAG, "step 2.1: loading all apps"); List allActivityList = loadAllApps(); + logger.addSplit("loadAllApps"); - TraceHelper.partitionSection(TAG, "step 2.2: Binding all apps"); verifyNotStopped(); mResults.bindAllApps(); + logger.addSplit("bindAllApps"); verifyNotStopped(); - TraceHelper.partitionSection(TAG, "step 2.3: Update icon cache"); IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler(); setIgnorePackages(updateHandler); updateHandler.updateIcons(allActivityList, LauncherActivityCachingLogic.newInstance(mApp.getContext()), mApp.getModel()::onPackageIconsUpdated); + logger.addSplit("update icon cache"); // Take a break - TraceHelper.partitionSection(TAG, "step 2 completed, wait for idle"); waitForIdle(); + logger.addSplit("step 2 complete"); verifyNotStopped(); // third step - TraceHelper.partitionSection(TAG, "step 3.1: loading deep shortcuts"); loadDeepShortcuts(); + logger.addSplit("loadDeepShortcuts"); verifyNotStopped(); - TraceHelper.partitionSection(TAG, "step 3.2: bind deep shortcuts"); mResults.bindDeepShortcuts(); + logger.addSplit("bindDeepShortcuts"); // Take a break - TraceHelper.partitionSection(TAG, "step 3 completed, wait for idle"); waitForIdle(); + logger.addSplit("step 3 complete"); verifyNotStopped(); // fourth step - TraceHelper.partitionSection(TAG, "step 4.1: loading widgets"); List allWidgetsList = mBgDataModel.widgetsModel.update(mApp, null); + logger.addSplit("load widgets"); verifyNotStopped(); - TraceHelper.partitionSection(TAG, "step 4.2: Binding widgets"); mResults.bindWidgets(); - + logger.addSplit("bindWidgets"); verifyNotStopped(); - TraceHelper.partitionSection(TAG, "step 4.3: save widgets in icon cache"); updateHandler.updateIcons(allWidgetsList, new ComponentCachingLogic( mApp.getContext(), true), mApp.getModel()::onWidgetLabelsUpdated); + logger.addSplit("save widgets in icon cache"); verifyNotStopped(); - TraceHelper.partitionSection(TAG, "step 5: Finish icon cache update"); updateHandler.finish(); + logger.addSplit("finish icon update"); transaction.commit(); } catch (CancellationException e) { // Loader stopped, ignore - TraceHelper.partitionSection(TAG, "Cancelled"); + logger.addSplit("Cancelled"); + } finally { + logger.dumpToLog(); } - TraceHelper.endSection(TAG); + TraceHelper.INSTANCE.endSection(); } public synchronized void stopLocked() { diff --git a/src/com/android/launcher3/util/MainThreadInitializedObject.java b/src/com/android/launcher3/util/MainThreadInitializedObject.java index cf4e8c796b..520a9edd57 100644 --- a/src/com/android/launcher3/util/MainThreadInitializedObject.java +++ b/src/com/android/launcher3/util/MainThreadInitializedObject.java @@ -22,7 +22,6 @@ import android.os.Looper; import androidx.annotation.VisibleForTesting; -import com.android.launcher3.uioverrides.DejankBinderTracker; import com.android.launcher3.util.ResourceBasedOverride.Overrides; import java.util.concurrent.ExecutionException; @@ -42,8 +41,8 @@ public class MainThreadInitializedObject { public T get(Context context) { if (mValue == null) { if (Looper.myLooper() == Looper.getMainLooper()) { - mValue = DejankBinderTracker.whitelistIpcs(() -> - mProvider.get(context.getApplicationContext())); + mValue = TraceHelper.whitelistIpcs("main.thread.object", + () -> mProvider.get(context.getApplicationContext())); } else { try { return MAIN_EXECUTOR.submit(() -> get(context)).get(); diff --git a/src/com/android/launcher3/util/RaceConditionTracker.java b/src/com/android/launcher3/util/RaceConditionTracker.java deleted file mode 100644 index 6954d0e27f..0000000000 --- a/src/com/android/launcher3/util/RaceConditionTracker.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2018 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.util; - -/** - * Event tracker for reliably reproducing race conditions in tests. - * The app should call onEvent() for events that the test will try to reproduce in all possible - * orders. - */ -public class RaceConditionTracker { - public final static boolean ENTER = true; - public final static boolean EXIT = false; - static final String ENTER_POSTFIX = "enter"; - static final String EXIT_POSTFIX = "exit"; - - public interface EventProcessor { - void onEvent(String eventName); - } - - private static EventProcessor sEventProcessor; - - static void setEventProcessor(EventProcessor eventProcessor) { - sEventProcessor = eventProcessor; - } - - public static void onEvent(String eventName) { - if (sEventProcessor != null) sEventProcessor.onEvent(eventName); - } - - public static void onEvent(String eventName, boolean isEnter) { - if (sEventProcessor != null) { - sEventProcessor.onEvent(enterExitEvt(eventName, isEnter)); - } - } - - public static String enterExitEvt(String eventName, boolean isEnter) { - return eventName + ":" + (isEnter ? ENTER_POSTFIX : EXIT_POSTFIX); - } - - public static String enterEvt(String eventName) { - return enterExitEvt(eventName, ENTER); - } - - public static String exitEvt(String eventName) { - return enterExitEvt(eventName, EXIT); - } -} diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java index c24bb67813..073fb6a61d 100644 --- a/src/com/android/launcher3/util/TraceHelper.java +++ b/src/com/android/launcher3/util/TraceHelper.java @@ -15,19 +15,14 @@ */ package com.android.launcher3.util; -import static android.util.Log.VERBOSE; -import static android.util.Log.isLoggable; - -import android.os.SystemClock; import android.os.Trace; -import android.util.ArrayMap; -import android.util.Log; -import android.util.MutableLong; -import com.android.launcher3.config.FeatureFlags; +import androidx.annotation.MainThread; + +import java.util.function.Supplier; /** - * A wrapper around {@link Trace} with some utility information. + * A wrapper around {@link Trace} to allow better testing. * * To enable any tracing log, execute the following command: * $ adb shell setprop log.tag.LAUNCHER_TRACE VERBOSE @@ -35,65 +30,51 @@ import com.android.launcher3.config.FeatureFlags; */ public class TraceHelper { - private static final boolean ENABLED = isLoggable("LAUNCHER_TRACE", VERBOSE); + // Track binder class for this trace + public static final int FLAG_ALLOW_BINDER_TRACKING = 1 << 0; - private static final boolean SYSTEM_TRACE = ENABLED; - private static final ArrayMap sUpTimes = ENABLED ? new ArrayMap<>() : null; + // Temporarily ignore blocking binder calls for this trace. + public static final int FLAG_IGNORE_BINDERS = 1 << 1; - public static void beginSection(String sectionName) { - if (ENABLED) { - synchronized (sUpTimes) { - MutableLong time = sUpTimes.get(sectionName); - if (time == null) { - time = new MutableLong(isLoggable(sectionName, VERBOSE) ? 0 : -1); - sUpTimes.put(sectionName, time); - } - if (time.value >= 0) { - if (SYSTEM_TRACE) { - Trace.beginSection(sectionName); - } - time.value = SystemClock.uptimeMillis(); - } - } - } + public static final int FLAG_CHECK_FOR_RACE_CONDITIONS = 1 << 2; + + public static final int FLAG_UI_EVENT = + FLAG_ALLOW_BINDER_TRACKING | FLAG_CHECK_FOR_RACE_CONDITIONS; + + /** + * Static instance of Trace helper, overridden in tests. + */ + public static TraceHelper INSTANCE = new TraceHelper(); + + public void beginSection(String sectionName) { + beginSection(sectionName, 0); } - public static void partitionSection(String sectionName, String partition) { - if (ENABLED) { - synchronized (sUpTimes) { - MutableLong time = sUpTimes.get(sectionName); - if (time != null && time.value >= 0) { - - if (SYSTEM_TRACE) { - Trace.endSection(); - Trace.beginSection(sectionName); - } - - long now = SystemClock.uptimeMillis(); - Log.d(sectionName, partition + " : " + (now - time.value)); - time.value = now; - } - } - } + public void beginSection(String sectionName, int flags) { + Trace.beginSection(sectionName); } - public static void endSection(String sectionName) { - if (ENABLED) { - endSection(sectionName, "End"); - } + public void endSection() { + Trace.endSection(); } - public static void endSection(String sectionName, String msg) { - if (ENABLED) { - synchronized (sUpTimes) { - MutableLong time = sUpTimes.get(sectionName); - if (time != null && time.value >= 0) { - if (SYSTEM_TRACE) { - Trace.endSection(); - } - Log.d(sectionName, msg + " : " + (SystemClock.uptimeMillis() - time.value)); - } - } + /** + * Similar to {@link #beginSection} but doesn't add a trace section. + */ + public void beginFlagsOverride(int flags) { } + + public void endFlagsOverride() { } + + /** + * Temporarily ignore blocking binder calls for the duration of this {@link Supplier}. + */ + @MainThread + public static T whitelistIpcs(String rpcName, Supplier supplier) { + INSTANCE.beginSection(rpcName, FLAG_IGNORE_BINDERS); + try { + return supplier.get(); + } finally { + INSTANCE.endSection(); } } } diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/DejankBinderTracker.java b/src_ui_overrides/com/android/launcher3/uioverrides/DejankBinderTracker.java deleted file mode 100644 index 47f6ac6f75..0000000000 --- a/src_ui_overrides/com/android/launcher3/uioverrides/DejankBinderTracker.java +++ /dev/null @@ -1,57 +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.uioverrides; - -import android.os.IBinder; - -import java.util.function.BiConsumer; -import java.util.function.Supplier; - -/** - * A binder proxy transaction listener for tracking non-whitelisted binder calls. - */ -public class DejankBinderTracker { - public static void whitelistIpcs(Runnable runnable) {} - - public static T whitelistIpcs(Supplier supplier) { - return null; - } - - public static void allowBinderTrackingInTests() {} - - public static void disallowBinderTrackingInTests() {} - - public DejankBinderTracker(BiConsumer unexpectedTransactionCallback) { } - - public void startTracking() {} - - public void stopTracking() {} - - public Object onTransactStarted(IBinder binder, int transactionCode, int flags) { - return null; - } - - public Object onTransactStarted(IBinder binder, int transactionCode) { - return null; - } - - public void onTransactEnded(Object session) {} - - public static boolean isMainThread() { - return true; - } -} diff --git a/tests/Android.mk b/tests/Android.mk index b5c1dae612..31a996084c 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -30,7 +30,6 @@ else LOCAL_STATIC_JAVA_LIBRARIES += SystemUISharedLib LOCAL_SRC_FILES := $(call all-java-files-under, tapl) \ - ../quickstep/src/com/android/launcher3/uioverrides/DejankBinderTracker.java \ ../src/com/android/launcher3/ResourceUtils.java \ ../src/com/android/launcher3/util/SecureSettingsObserver.java \ ../src/com/android/launcher3/testing/TestProtocol.java diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java index 8f89173203..ed2ec7b40a 100644 --- a/tests/src/com/android/launcher3/util/RaceConditionReproducer.java +++ b/tests/src/com/android/launcher3/util/RaceConditionReproducer.java @@ -17,8 +17,6 @@ package com.android.launcher3.util; import static com.android.launcher3.util.Executors.createAndStartNewLooper; -import static com.android.launcher3.util.RaceConditionTracker.ENTER_POSTFIX; -import static com.android.launcher3.util.RaceConditionTracker.EXIT_POSTFIX; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -64,15 +62,30 @@ import java.util.concurrent.TimeUnit; * * When we register event XXX:enter, we hold all other events until we register XXX:exit. */ -public class RaceConditionReproducer implements RaceConditionTracker.EventProcessor { +public class RaceConditionReproducer { private static final String TAG = "RaceConditionReproducer"; + + private static final boolean ENTER = true; + private static final boolean EXIT = false; + private static final String ENTER_POSTFIX = "enter"; + private static final String EXIT_POSTFIX = "exit"; + private static final long SHORT_TIMEOUT_MS = 2000; private static final long LONG_TIMEOUT_MS = 60000; // Handler used to resume postponed events. - private static final Handler POSTPONED_EVENT_RESUME_HANDLER = createEventResumeHandler(); + private static final Handler POSTPONED_EVENT_RESUME_HANDLER = + new Handler(createAndStartNewLooper("RaceConditionEventResumer")); - private static Handler createEventResumeHandler() { - return new Handler(createAndStartNewLooper("RaceConditionEventResumer")); + public static String enterExitEvt(String eventName, boolean isEnter) { + return eventName + ":" + (isEnter ? ENTER_POSTFIX : EXIT_POSTFIX); + } + + public static String enterEvt(String eventName) { + return enterExitEvt(eventName, ENTER); + } + + public static String exitEvt(String eventName) { + return enterExitEvt(eventName, EXIT); } /** @@ -209,7 +222,8 @@ public class RaceConditionReproducer implements RaceConditionTracker.EventProces parseReproString(mReproString) : generateSequenceToFollowLocked(); Log.e(TAG, "---- Start of iteration; state:\n" + dumpStateLocked()); checkIfCompletedSequenceToFollowLocked(); - RaceConditionTracker.setEventProcessor(this); + + TraceHelperForTest.setRaceConditionReproducer(this); } /** @@ -218,7 +232,8 @@ public class RaceConditionReproducer implements RaceConditionTracker.EventProces * Returns whether we need more iterations. */ public synchronized boolean finishIteration() { - RaceConditionTracker.setEventProcessor(null); + TraceHelperForTest.setRaceConditionReproducer(null); + runResumeAllEventsCallbackLocked(); assertTrue("Non-empty postponed events", mPostponedEvents.isEmpty()); assertTrue("Last registered event is :enter", lastEventAsEnter() == null); @@ -243,7 +258,6 @@ public class RaceConditionReproducer implements RaceConditionTracker.EventProces /** * Called when the app issues an event. */ - @Override public void onEvent(String event) { final Semaphore waitObject = tryRegisterEvent(event); if (waitObject != null) { diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java index 3fc268e60b..d156d1f017 100644 --- a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java +++ b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue; import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; @@ -37,17 +38,24 @@ public class RaceConditionReproducerTest { return res; } - private static void run3_3_TestAction() throws InterruptedException { + RaceConditionReproducer eventProcessor; + + @Before + public void setup() { + eventProcessor = new RaceConditionReproducer(); + } + + private void run3_3_TestAction() throws InterruptedException { Thread tb = new Thread(() -> { - RaceConditionTracker.onEvent("B1"); - RaceConditionTracker.onEvent("B2"); - RaceConditionTracker.onEvent("B3"); + eventProcessor.onEvent("B1"); + eventProcessor.onEvent("B2"); + eventProcessor.onEvent("B3"); }); tb.start(); - RaceConditionTracker.onEvent("A1"); - RaceConditionTracker.onEvent("A2"); - RaceConditionTracker.onEvent("A3"); + eventProcessor.onEvent("A1"); + eventProcessor.onEvent("A2"); + eventProcessor.onEvent("A3"); tb.join(); } @@ -56,7 +64,6 @@ public class RaceConditionReproducerTest { @Ignore // The test is too long for continuous testing. // 2 threads, 3 events each. public void test3_3() throws Exception { - final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(); boolean sawTheValidSequence = false; for (; ; ) { @@ -80,25 +87,24 @@ public class RaceConditionReproducerTest { @Ignore // The test is too long for continuous testing. // 2 threads, 3 events, including enter-exit pairs each. public void test3_3_enter_exit() throws Exception { - final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(); boolean sawTheValidSequence = false; for (; ; ) { eventProcessor.startIteration(); Thread tb = new Thread(() -> { - RaceConditionTracker.onEvent("B1:enter"); - RaceConditionTracker.onEvent("B1:exit"); - RaceConditionTracker.onEvent("B2"); - RaceConditionTracker.onEvent("B3:enter"); - RaceConditionTracker.onEvent("B3:exit"); + eventProcessor.onEvent("B1:enter"); + eventProcessor.onEvent("B1:exit"); + eventProcessor.onEvent("B2"); + eventProcessor.onEvent("B3:enter"); + eventProcessor.onEvent("B3:exit"); }); tb.start(); - RaceConditionTracker.onEvent("A1"); - RaceConditionTracker.onEvent("A2:enter"); - RaceConditionTracker.onEvent("A2:exit"); - RaceConditionTracker.onEvent("A3:enter"); - RaceConditionTracker.onEvent("A3:exit"); + eventProcessor.onEvent("A1"); + eventProcessor.onEvent("A2:enter"); + eventProcessor.onEvent("A2:exit"); + eventProcessor.onEvent("A3:enter"); + eventProcessor.onEvent("A3:exit"); tb.join(); final boolean needMoreIterations = eventProcessor.finishIteration(); @@ -134,23 +140,21 @@ public class RaceConditionReproducerTest { @Ignore // The test is too long for continuous testing. // 2 threads with 2 events; 1 thread with 1 event. public void test2_1_2() throws Exception { - final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(); - for (; ; ) { eventProcessor.startIteration(); Thread tb = new Thread(() -> { - RaceConditionTracker.onEvent("B1"); - RaceConditionTracker.onEvent("B2"); + eventProcessor.onEvent("B1"); + eventProcessor.onEvent("B2"); }); tb.start(); Thread tc = new Thread(() -> { - RaceConditionTracker.onEvent("C1"); + eventProcessor.onEvent("C1"); }); tc.start(); - RaceConditionTracker.onEvent("A1"); - RaceConditionTracker.onEvent("A2"); + eventProcessor.onEvent("A1"); + eventProcessor.onEvent("A2"); tb.join(); tc.join(); @@ -167,28 +171,26 @@ public class RaceConditionReproducerTest { @Ignore // The test is too long for continuous testing. // 2 threads with 2 events; 1 thread with 1 event. Includes enter-exit pairs. public void test2_1_2_enter_exit() throws Exception { - final RaceConditionReproducer eventProcessor = new RaceConditionReproducer(); - for (; ; ) { eventProcessor.startIteration(); Thread tb = new Thread(() -> { - RaceConditionTracker.onEvent("B1:enter"); - RaceConditionTracker.onEvent("B1:exit"); - RaceConditionTracker.onEvent("B2:enter"); - RaceConditionTracker.onEvent("B2:exit"); + eventProcessor.onEvent("B1:enter"); + eventProcessor.onEvent("B1:exit"); + eventProcessor.onEvent("B2:enter"); + eventProcessor.onEvent("B2:exit"); }); tb.start(); Thread tc = new Thread(() -> { - RaceConditionTracker.onEvent("C1:enter"); - RaceConditionTracker.onEvent("C1:exit"); + eventProcessor.onEvent("C1:enter"); + eventProcessor.onEvent("C1:exit"); }); tc.start(); - RaceConditionTracker.onEvent("A1:enter"); - RaceConditionTracker.onEvent("A1:exit"); - RaceConditionTracker.onEvent("A2:enter"); - RaceConditionTracker.onEvent("A2:exit"); + eventProcessor.onEvent("A1:enter"); + eventProcessor.onEvent("A1:exit"); + eventProcessor.onEvent("A2:enter"); + eventProcessor.onEvent("A2:exit"); tb.join(); tc.join(); diff --git a/tests/src/com/android/launcher3/util/TraceHelperForTest.java b/tests/src/com/android/launcher3/util/TraceHelperForTest.java new file mode 100644 index 0000000000..9125f5fc35 --- /dev/null +++ b/tests/src/com/android/launcher3/util/TraceHelperForTest.java @@ -0,0 +1,100 @@ +/** + * 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.util; + +import java.util.LinkedList; +import java.util.function.IntConsumer; + +public class TraceHelperForTest extends TraceHelper { + + private static final TraceHelperForTest INSTANCE_FOR_TEST = new TraceHelperForTest(); + + private final ThreadLocal> mStack = + ThreadLocal.withInitial(LinkedList::new); + + private RaceConditionReproducer mRaceConditionReproducer; + private IntConsumer mFlagsChangeListener; + + public static void setRaceConditionReproducer(RaceConditionReproducer reproducer) { + TraceHelper.INSTANCE = INSTANCE_FOR_TEST; + INSTANCE_FOR_TEST.mRaceConditionReproducer = reproducer; + } + + public static void setFlagsChangeListener(IntConsumer listener) { + TraceHelper.INSTANCE = INSTANCE_FOR_TEST; + INSTANCE_FOR_TEST.mFlagsChangeListener = listener; + } + + private TraceHelperForTest() { } + + @Override + public void beginSection(String sectionName, int flags) { + LinkedList stack = mStack.get(); + stack.add(new TraceInfo(sectionName, flags)); + + if ((flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0 + && mRaceConditionReproducer != null) { + mRaceConditionReproducer.onEvent(RaceConditionReproducer.enterEvt(sectionName)); + } + updateBinderTracking(stack); + + super.beginSection(sectionName, flags); + } + + @Override + public void endSection() { + LinkedList stack = mStack.get(); + TraceInfo info = stack.pollLast(); + if ((info.flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0 + && mRaceConditionReproducer != null) { + mRaceConditionReproducer.onEvent(RaceConditionReproducer.exitEvt(info.sectionName)); + } + updateBinderTracking(stack); + + super.endSection(); + } + + @Override + public void beginFlagsOverride(int flags) { + LinkedList stack = mStack.get(); + stack.push(new TraceInfo(null, flags)); + updateBinderTracking(stack); + super.beginFlagsOverride(flags); + } + + @Override + public void endFlagsOverride() { + super.endFlagsOverride(); + updateBinderTracking(mStack.get()); + } + + private void updateBinderTracking(LinkedList stack) { + if (mFlagsChangeListener != null) { + mFlagsChangeListener.accept(stack.stream() + .mapToInt(s -> s.flags).reduce(0, (a, b) -> a | b)); + } + } + + private static class TraceInfo { + public final String sectionName; + public final int flags; + + TraceInfo(String sectionName, int flags) { + this.sectionName = sectionName; + this.flags = flags; + } + } +} From 68e01dda46f1dabfbe7ea8252b29f9381326e481 Mon Sep 17 00:00:00 2001 From: Andy Wickham Date: Mon, 14 Oct 2019 15:31:34 -0700 Subject: [PATCH 02/17] Fades out Assistant when entering Overview. This makes the transition smoother, since the Assistant goes away at the end of it. Note this only applies to the transition while an app other than Launcher is live. Before: https://drive.google.com/open?id=18SOWTtTUzt19TReAYnofQLIShJ2I-odP After: https://drive.google.com/open?id=1hqsikXSlCnSvNg0ZQYHxP-OIbS5yt9aW Bug: 136282913 Change-Id: Ia53c2407c82725c776f27b0d6e80a34554b4a303 Tested: Manually --- .../quickstep/util/AppWindowAnimationHelper.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java index 5eee897350..24e7f0ecea 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/AppWindowAnimationHelper.java @@ -35,10 +35,11 @@ import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.DeviceProfile; import com.android.launcher3.LauncherState; import com.android.launcher3.R; +import com.android.launcher3.Utilities; +import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.RemoteAnimationTargets; import com.android.quickstep.SystemUiProxy; -import com.android.launcher3.Utilities; -import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskThumbnailView; import com.android.quickstep.views.TaskView; @@ -200,6 +201,11 @@ public class AppWindowAnimationHelper { } mCurrentCornerRadius = cornerRadius; } + // Fade out Assistant overlay. + if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT + && app.isNotInRecents) { + alpha = 1 - Interpolators.DEACCEL_2_5.getInterpolation(progress); + } } else if (params.targetSet.hasRecents) { // If home has a different target then recents, reverse anim the // home target. From b9f25e631bb823c5cb06de0364ad6a7b0405eb7b Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Mon, 14 Oct 2019 13:24:24 -0700 Subject: [PATCH 03/17] include error log to debug the issue custom shortcut not working Bug: 141568904 Change-Id: I7e6b9aa4c3e1314aee18cbea81efa881b574923c --- src/com/android/launcher3/Launcher.java | 9 ++++++++- src/com/android/launcher3/testing/TestProtocol.java | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index a19ba21a48..2951d891dd 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -32,6 +32,7 @@ import static com.android.launcher3.dragndrop.DragLayer.ALPHA_INDEX_LAUNCHER_LOA import static com.android.launcher3.logging.LoggerUtils.newContainerTarget; import static com.android.launcher3.logging.LoggerUtils.newTarget; import static com.android.launcher3.states.RotationHelper.REQUEST_NONE; +import static com.android.launcher3.testing.TestProtocol.CRASH_ADD_CUSTOM_SHORTCUT; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -112,6 +113,7 @@ import com.android.launcher3.popup.PopupContainerWithArrow; import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.qsb.QsbContainerView; import com.android.launcher3.states.RotationHelper; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.touch.ItemClickHandler; import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; @@ -1207,8 +1209,13 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, */ private void completeAddShortcut(Intent data, int container, int screenId, int cellX, int cellY, PendingRequestArgs args) { - if (args.getRequestCode() != REQUEST_CREATE_SHORTCUT + if (data == null + || args.getRequestCode() != REQUEST_CREATE_SHORTCUT || args.getPendingIntent().getComponent() == null) { + if (data == null && TestProtocol.sDebugTracing) { + Log.d(CRASH_ADD_CUSTOM_SHORTCUT, + "Failed to add custom shortcut: Intent is null, args = " + args); + } return; } diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java index faf0ff6c45..923c466d2e 100644 --- a/src/com/android/launcher3/testing/TestProtocol.java +++ b/src/com/android/launcher3/testing/TestProtocol.java @@ -86,4 +86,5 @@ public final class TestProtocol { public static final String APP_NOT_DISABLED = "b/139891609"; public static final String NO_CONTEXT_MENU = "b/141770616"; public static final String LAUNCHER_DIDNT_INITIALIZE = "b/142514365"; + public static final String CRASH_ADD_CUSTOM_SHORTCUT = "b/141568904"; } From fb578e4528855c8a82f0478b1eab9393c4711821 Mon Sep 17 00:00:00 2001 From: Andy Wickham Date: Tue, 24 Sep 2019 12:51:36 -0700 Subject: [PATCH 04/17] Fades out Assistant when entering Overview. This makes the transition smoother, since the Assistant goes away at the end of it. Note this only applies to the transition while an app other than Launcher is live. Before: https://drive.google.com/open?id=18SOWTtTUzt19TReAYnofQLIShJ2I-odP After: https://drive.google.com/open?id=1hqsikXSlCnSvNg0ZQYHxP-OIbS5yt9aW Bug: 136282913 Change-Id: Ia53c2407c82725c776f27b0d6e80a34554b4a303 Merged-In: Ia53c2407c82725c776f27b0d6e80a34554b4a303 Tested: Manually --- .../com/android/quickstep/util/ClipAnimationHelper.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java index cae273a164..fa3be9c125 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java @@ -37,6 +37,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.LauncherState; import com.android.launcher3.R; import com.android.launcher3.Utilities; +import com.android.launcher3.anim.Interpolators; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.RecentsModel; import com.android.quickstep.views.RecentsView; @@ -50,8 +51,6 @@ import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat. import com.android.systemui.shared.system.TransactionCompat; import com.android.systemui.shared.system.WindowManagerWrapper; -import java.util.function.BiFunction; - /** * Utility class to handle window clip animation */ @@ -213,6 +212,11 @@ public class ClipAnimationHelper { } mCurrentCornerRadius = cornerRadius; } + // Fade out Assistant overlay. + if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_ASSISTANT + && app.isNotInRecents) { + alpha = 1 - Interpolators.DEACCEL_2_5.getInterpolation(progress); + } } else if (targetSet.hasRecents) { // If home has a different target then recents, reverse anim the // home target. From 54e0c9e49c75a5b07921ad273a10946a95994445 Mon Sep 17 00:00:00 2001 From: vadimt Date: Mon, 14 Oct 2019 18:39:10 -0700 Subject: [PATCH 05/17] Tracing to determine why the model doesn't load Bug: 142514365 Change-Id: I30ecaec5a5d0868db10157c61a2a8d7dd12872ca --- src/com/android/launcher3/LauncherModel.java | 11 +++++++++++ src/com/android/launcher3/model/LoaderTask.java | 13 +++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index b22d137b2f..fc2e953b00 100644 --- a/src/com/android/launcher3/LauncherModel.java +++ b/src/com/android/launcher3/LauncherModel.java @@ -326,6 +326,9 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi public void stopLoader() { synchronized (mLock) { LoaderTask oldTask = mLoaderTask; + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, "LauncherModel.stopLoader"); + } mLoaderTask = null; if (oldTask != null) { oldTask.stopLocked(); @@ -337,6 +340,10 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi synchronized (mLock) { stopLoader(); mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, sBgDataModel, results); + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, + "LauncherModel.startLoaderForResults " + mLoaderTask); + } // Always post the loader task, instead of running directly (even on same thread) so // that we exit any nested synchronized blocks @@ -438,6 +445,10 @@ public class LauncherModel extends LauncherApps.Callback implements InstallSessi public void close() { synchronized (mLock) { // If we are still the last one to be scheduled, remove ourselves. + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, + "LauncherModel.close " + mLoaderTask + ", " + mTask); + } if (mLoaderTask == mTask) { mLoaderTask = null; } diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 2d4a816338..497b99df6c 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -71,6 +71,7 @@ import com.android.launcher3.provider.ImportDataTask; import com.android.launcher3.qsb.QsbContainerView; import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.shortcuts.ShortcutKey; +import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IOUtils; import com.android.launcher3.util.LooperIdleLock; @@ -163,12 +164,20 @@ public class LoaderTask implements Runnable { } public void run() { + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, + "LoaderTask1 " + this); + } synchronized (this) { // Skip fast if we are already stopped. if (mStopped) { return; } } + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, + "LoaderTask2 " + this); + } TraceHelper.INSTANCE.beginSection(TAG); TimingLogger logger = new TimingLogger(TAG, "run"); @@ -240,6 +249,10 @@ public class LoaderTask implements Runnable { updateHandler.finish(); logger.addSplit("finish icon update"); + if (TestProtocol.sDebugTracing) { + Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, + "LoaderTask3 " + this); + } transaction.commit(); } catch (CancellationException e) { // Loader stopped, ignore From 28dc8de660be05800bfb21c5f4c7f709a5c9cb1f Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Tue, 1 Oct 2019 18:12:20 +0000 Subject: [PATCH 06/17] Revert "Revert "Revert "Revert "cache shourtcut image"""" This reverts commit 52908c9adc3a27ffb90b398fa4bc97d71e9af184. Reason for revert: roll-forward and fixes the crash due to access icon cache on main thread Bug: 141568904 Change-Id: I1274db349c4f508d9cf59735b5f15180bb0ec033 --- .../launcher3/icons/cache/CachingLogic.java | 8 +++ .../icons/cache/IconCacheUpdateHandler.java | 4 +- .../android/launcher3/icons/IconCache.java | 12 ++++ .../launcher3/icons/LauncherIcons.java | 10 ++- .../launcher3/icons/ShortcutCachingLogic.java | 72 +++++++++++++++++++ .../android/launcher3/model/LoaderTask.java | 24 +++++-- 6 files changed, 118 insertions(+), 12 deletions(-) create mode 100644 src/com/android/launcher3/icons/ShortcutCachingLogic.java diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java index e40a9c2c96..3aa783a14c 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java +++ b/iconloaderlib/src/com/android/launcher3/icons/cache/CachingLogic.java @@ -17,6 +17,7 @@ package com.android.launcher3.icons.cache; import android.content.ComponentName; import android.content.Context; +import android.content.pm.PackageInfo; import android.os.LocaleList; import android.os.UserHandle; @@ -42,6 +43,13 @@ public interface CachingLogic { return null; } + /** + * Returns the timestamp the entry was last updated in cache. + */ + default long getLastUpdatedTime(T object, PackageInfo info) { + return info.lastUpdateTime; + } + /** * Returns true the object should be added to mem cache; otherwise returns false. */ diff --git a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java index 8224966d87..bcdbce5e29 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java +++ b/iconloaderlib/src/com/android/launcher3/icons/cache/IconCacheUpdateHandler.java @@ -171,7 +171,8 @@ public class IconCacheUpdateHandler { long updateTime = c.getLong(indexLastUpdate); int version = c.getInt(indexVersion); T app = componentMap.remove(component); - if (version == info.versionCode && updateTime == info.lastUpdateTime + if (version == info.versionCode + && updateTime == cachingLogic.getLastUpdatedTime(app, info) && TextUtils.equals(c.getString(systemStateIndex), mIconCache.getIconSystemState(info.packageName))) { @@ -231,7 +232,6 @@ public class IconCacheUpdateHandler { } } - /** * A runnable that updates invalid icons and adds missing icons in the DB for the provided * LauncherActivityInfo list. Items are updated/added one at a time, so that the diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java index 9886f53863..ad01f9fa6a 100644 --- a/src/com/android/launcher3/icons/IconCache.java +++ b/src/com/android/launcher3/icons/IconCache.java @@ -28,6 +28,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.pm.ShortcutInfo; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Process; @@ -50,6 +51,7 @@ import com.android.launcher3.icons.cache.BaseIconCache; import com.android.launcher3.icons.cache.CachingLogic; import com.android.launcher3.icons.cache.HandlerRunnable; import com.android.launcher3.model.PackageItemInfo; +import com.android.launcher3.shortcuts.ShortcutKey; import com.android.launcher3.util.InstantAppResolver; import com.android.launcher3.util.PackageUserKey; import com.android.launcher3.util.Preconditions; @@ -65,6 +67,7 @@ public class IconCache extends BaseIconCache { private final CachingLogic mComponentWithLabelCachingLogic; private final CachingLogic mLauncherActivityInfoCachingLogic; + private final CachingLogic mShortcutCachingLogic; private final LauncherApps mLauncherApps; private final UserManagerCompat mUserManager; @@ -78,6 +81,7 @@ public class IconCache extends BaseIconCache { inv.fillResIconDpi, inv.iconBitmapSize, true /* inMemoryCache */); mComponentWithLabelCachingLogic = new ComponentCachingLogic(context, false); mLauncherActivityInfoCachingLogic = LauncherActivityCachingLogic.newInstance(context); + mShortcutCachingLogic = new ShortcutCachingLogic(); mLauncherApps = mContext.getSystemService(LauncherApps.class); mUserManager = UserManagerCompat.getInstance(mContext); mInstantAppResolver = InstantAppResolver.newInstance(mContext); @@ -175,6 +179,14 @@ public class IconCache extends BaseIconCache { getTitleAndIcon(info, () -> activityInfo, false, useLowResIcon); } + /** + * Fill in info with the icon and label for deep shortcut. + */ + public synchronized CacheEntry getDeepShortcutTitleAndIcon(ShortcutInfo info) { + return cacheLocked(ShortcutKey.fromInfo(info).componentName, info.getUserHandle(), + () -> info, mShortcutCachingLogic, false, false); + } + /** * Fill in {@param info} with the icon and label. If the * corresponding activity is not found, it reverts to the package icon. diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java index adc92c46c4..c6949afc37 100644 --- a/src/com/android/launcher3/icons/LauncherIcons.java +++ b/src/com/android/launcher3/icons/LauncherIcons.java @@ -21,7 +21,6 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ShortcutInfo; import android.graphics.Bitmap; -import android.graphics.drawable.Drawable; import android.os.Process; import androidx.annotation.Nullable; @@ -33,8 +32,8 @@ import com.android.launcher3.ItemInfoWithIcon; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.graphics.IconShape; +import com.android.launcher3.icons.cache.BaseIconCache; import com.android.launcher3.model.PackageItemInfo; -import com.android.launcher3.shortcuts.DeepShortcutManager; import com.android.launcher3.util.Themes; import java.util.function.Supplier; @@ -126,13 +125,12 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable { public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged, @Nullable Supplier fallbackIconProvider) { - Drawable unbadgedDrawable = DeepShortcutManager.getInstance(mContext) - .getShortcutIconDrawable(shortcutInfo, mFillResIconDpi); IconCache cache = LauncherAppState.getInstance(mContext).getIconCache(); + BaseIconCache.CacheEntry entry = cache.getDeepShortcutTitleAndIcon(shortcutInfo); final Bitmap unbadgedBitmap; - if (unbadgedDrawable != null) { - unbadgedBitmap = createScaledBitmapWithoutShadow(unbadgedDrawable, 0); + if (entry.icon != null) { + unbadgedBitmap = entry.icon; } else { if (fallbackIconProvider != null) { // Fallback icons are already badged and with appropriate shadow diff --git a/src/com/android/launcher3/icons/ShortcutCachingLogic.java b/src/com/android/launcher3/icons/ShortcutCachingLogic.java new file mode 100644 index 0000000000..5d696fd6f3 --- /dev/null +++ b/src/com/android/launcher3/icons/ShortcutCachingLogic.java @@ -0,0 +1,72 @@ +/* + * 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.icons; + +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.ShortcutInfo; +import android.graphics.drawable.Drawable; +import android.os.UserHandle; + +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.icons.cache.CachingLogic; +import com.android.launcher3.shortcuts.DeepShortcutManager; +import com.android.launcher3.shortcuts.ShortcutKey; + +/** + * Caching logic for shortcuts. + */ +public class ShortcutCachingLogic implements CachingLogic { + + @Override + public ComponentName getComponent(ShortcutInfo info) { + return ShortcutKey.fromInfo(info).componentName; + } + + @Override + public UserHandle getUser(ShortcutInfo info) { + return info.getUserHandle(); + } + + @Override + public CharSequence getLabel(ShortcutInfo info) { + return info.getShortLabel(); + } + + @Override + public void loadIcon(Context context, ShortcutInfo info, BitmapInfo target) { + LauncherIcons li = LauncherIcons.obtain(context); + Drawable unbadgedDrawable = DeepShortcutManager.getInstance(context) + .getShortcutIconDrawable(info, LauncherAppState.getIDP(context).fillResIconDpi); + if (unbadgedDrawable != null) { + target.icon = li.createScaledBitmapWithoutShadow(unbadgedDrawable, 0); + } + li.recycle(); + } + + @Override + public long getLastUpdatedTime(ShortcutInfo shortcutInfo, PackageInfo info) { + if (shortcutInfo == null) return info.lastUpdateTime; + return Math.max(shortcutInfo.getLastChangedTimestamp(), info.lastUpdateTime); + } + + @Override + public boolean addToMemCache() { + return false; + } +} diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 497b99df6c..3673102bfe 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -63,6 +63,7 @@ import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic; import com.android.launcher3.icons.IconCache; import com.android.launcher3.icons.LauncherActivityCachingLogic; import com.android.launcher3.icons.LauncherIcons; +import com.android.launcher3.icons.ShortcutCachingLogic; import com.android.launcher3.icons.cache.IconCacheUpdateHandler; import com.android.launcher3.logging.FileLog; import com.android.launcher3.pm.PackageInstallInfo; @@ -182,7 +183,8 @@ public class LoaderTask implements Runnable { TraceHelper.INSTANCE.beginSection(TAG); TimingLogger logger = new TimingLogger(TAG, "run"); try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { - loadWorkspace(); + List allShortcuts = new ArrayList<>(); + loadWorkspace(allShortcuts); logger.addSplit("loadWorkspace"); verifyNotStopped(); @@ -214,19 +216,29 @@ public class LoaderTask implements Runnable { mApp.getModel()::onPackageIconsUpdated); logger.addSplit("update icon cache"); + verifyNotStopped(); + logger.addSplit("save shortcuts in icon cache"); + updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(), + mApp.getModel()::onPackageIconsUpdated); + // Take a break waitForIdle(); logger.addSplit("step 2 complete"); verifyNotStopped(); // third step - loadDeepShortcuts(); + List allDeepShortcuts = loadDeepShortcuts(); logger.addSplit("loadDeepShortcuts"); verifyNotStopped(); mResults.bindDeepShortcuts(); logger.addSplit("bindDeepShortcuts"); + verifyNotStopped(); + logger.addSplit("save deep shortcuts in icon cache"); + updateHandler.updateIcons(allDeepShortcuts, + new ShortcutCachingLogic(), (pkgs, user) -> { }); + // Take a break waitForIdle(); logger.addSplit("step 3 complete"); @@ -268,7 +280,7 @@ public class LoaderTask implements Runnable { this.notify(); } - private void loadWorkspace() { + private void loadWorkspace(List allDeepShortcuts) { final Context context = mApp.getContext(); final ContentResolver contentResolver = context.getContentResolver(); final PackageManagerHelper pmHelper = new PackageManagerHelper(context); @@ -523,6 +535,7 @@ public class LoaderTask implements Runnable { info.runtimeStatusFlags |= FLAG_DISABLED_SUSPENDED; } intent = info.intent; + allDeepShortcuts.add(pinnedShortcut); } else { // Create a shortcut info in disabled mode for now. info = c.loadSimpleWorkspaceItem(); @@ -871,7 +884,8 @@ public class LoaderTask implements Runnable { return allActivityList; } - private void loadDeepShortcuts() { + private List loadDeepShortcuts() { + List allShortcuts = new ArrayList<>(); mBgDataModel.deepShortcutMap.clear(); mBgDataModel.hasShortcutHostPermission = mShortcutManager.hasHostPermission(); if (mBgDataModel.hasShortcutHostPermission) { @@ -879,10 +893,12 @@ public class LoaderTask implements Runnable { if (mUserManager.isUserUnlocked(user)) { List shortcuts = mShortcutManager.queryForAllShortcuts(user); + allShortcuts.addAll(shortcuts); mBgDataModel.updateDeepShortcutCounts(null, user, shortcuts); } } } + return allShortcuts; } public static boolean isValidProvider(AppWidgetProviderInfo provider) { From 4ec390e490dfb1503909853eb55df85f79e9813a Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Tue, 1 Oct 2019 14:28:05 -0700 Subject: [PATCH 07/17] fetch and update shortcut icons in background thread Bug: 141568904 Test: Manually verified use cases from following call-site (with and without delay) LauncherAppsCompatVO 1. (Custom Shortcut) Long click on google maps -> widgets -> drag driving mode to workspace. 2. Open chrome -> add to home screen -> add -> add automatically. InstallShortcutReceiver Removed the line that trigger above flow for android O and above, then open chrome -> add to home screen -> add -> add automatically. ShortcutDragPreviewProvider qdb -> long press on suggested app that has deep shortcut -> drag to workspace. Change-Id: I59a4d004913a8df697af1fcfe0a080b6da01eefd --- .../launcher3/InstallShortcutReceiver.java | 5 ++-- .../launcher3/icons/LauncherIcons.java | 28 ++++++++++++----- .../launcher3/pm/PinRequestHelper.java | 9 ++---- .../ShortcutDragPreviewProvider.java | 21 ++++++------- .../android/launcher3/util/ShortcutUtil.java | 30 +++++++++++++++++++ 5 files changed, 66 insertions(+), 27 deletions(-) diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index 8ebf46442f..0b79dd2835 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -17,6 +17,7 @@ package com.android.launcher3; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import static com.android.launcher3.util.ShortcutUtil.fetchAndUpdateShortcutIconAsync; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; @@ -482,9 +483,7 @@ public class InstallShortcutReceiver extends BroadcastReceiver { return Pair.create(si, null); } else if (shortcutInfo != null) { WorkspaceItemInfo itemInfo = new WorkspaceItemInfo(shortcutInfo, mContext); - LauncherIcons li = LauncherIcons.obtain(mContext); - itemInfo.applyFrom(li.createShortcutIcon(shortcutInfo)); - li.recycle(); + fetchAndUpdateShortcutIconAsync(mContext, itemInfo, shortcutInfo, true); return Pair.create(itemInfo, shortcutInfo); } else if (providerInfo != null) { LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo diff --git a/src/com/android/launcher3/icons/LauncherIcons.java b/src/com/android/launcher3/icons/LauncherIcons.java index c6949afc37..0f5d2903ce 100644 --- a/src/com/android/launcher3/icons/LauncherIcons.java +++ b/src/com/android/launcher3/icons/LauncherIcons.java @@ -24,6 +24,7 @@ import android.graphics.Bitmap; import android.os.Process; import androidx.annotation.Nullable; +import androidx.annotation.WorkerThread; import com.android.launcher3.AppInfo; import com.android.launcher3.FastBitmapDrawable; @@ -32,7 +33,6 @@ import com.android.launcher3.ItemInfoWithIcon; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.graphics.IconShape; -import com.android.launcher3.icons.cache.BaseIconCache; import com.android.launcher3.model.PackageItemInfo; import com.android.launcher3.util.Themes; @@ -114,23 +114,37 @@ public class LauncherIcons extends BaseIconFactory implements AutoCloseable { } // below methods should also migrate to BaseIconFactory - + @WorkerThread public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo) { return createShortcutIcon(shortcutInfo, true /* badged */); } + @WorkerThread public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged) { return createShortcutIcon(shortcutInfo, badged, null); } - public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, - boolean badged, @Nullable Supplier fallbackIconProvider) { + @WorkerThread + public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged, + @Nullable Supplier fallbackIconProvider) { + return createShortcutIcon(shortcutInfo, badged, true, fallbackIconProvider); + } + + @WorkerThread + public BitmapInfo createShortcutIcon(ShortcutInfo shortcutInfo, boolean badged, + boolean useCache, @Nullable Supplier fallbackIconProvider) { IconCache cache = LauncherAppState.getInstance(mContext).getIconCache(); - BaseIconCache.CacheEntry entry = cache.getDeepShortcutTitleAndIcon(shortcutInfo); + final BitmapInfo bitmapInfo; + if (useCache) { + bitmapInfo = cache.getDeepShortcutTitleAndIcon(shortcutInfo); + } else { + bitmapInfo = new BitmapInfo(); + new ShortcutCachingLogic().loadIcon(mContext, shortcutInfo, bitmapInfo); + } final Bitmap unbadgedBitmap; - if (entry.icon != null) { - unbadgedBitmap = entry.icon; + if (bitmapInfo.icon != null) { + unbadgedBitmap = bitmapInfo.icon; } else { if (fallbackIconProvider != null) { // Fallback icons are already badged and with appropriate shadow diff --git a/src/com/android/launcher3/pm/PinRequestHelper.java b/src/com/android/launcher3/pm/PinRequestHelper.java index 68ea6c43ad..5b6b56d858 100644 --- a/src/com/android/launcher3/pm/PinRequestHelper.java +++ b/src/com/android/launcher3/pm/PinRequestHelper.java @@ -17,6 +17,7 @@ package com.android.launcher3.pm; import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; +import static com.android.launcher3.util.ShortcutUtil.fetchAndUpdateShortcutIconAsync; import android.annotation.TargetApi; import android.content.Context; @@ -29,9 +30,7 @@ import android.os.Parcelable; import androidx.annotation.Nullable; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.WorkspaceItemInfo; -import com.android.launcher3.icons.LauncherIcons; public class PinRequestHelper { @@ -81,11 +80,7 @@ public class PinRequestHelper { ShortcutInfo si = request.getShortcutInfo(); WorkspaceItemInfo info = new WorkspaceItemInfo(si, context); // Apply the unbadged icon and fetch the actual icon asynchronously. - LauncherIcons li = LauncherIcons.obtain(context); - info.applyFrom(li.createShortcutIcon(si, false /* badged */)); - li.recycle(); - LauncherAppState.getInstance(context).getModel() - .updateAndBindWorkspaceItem(info, si); + fetchAndUpdateShortcutIconAsync(context, info, si, false); return info; } else { return null; diff --git a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java index ee97641109..408ced20e2 100644 --- a/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java +++ b/src/com/android/launcher3/shortcuts/ShortcutDragPreviewProvider.java @@ -26,6 +26,7 @@ import android.view.View; import com.android.launcher3.Launcher; import com.android.launcher3.Utilities; import com.android.launcher3.graphics.DragPreviewProvider; +import com.android.launcher3.icons.BitmapRenderer; /** * Extension of {@link DragPreviewProvider} which generates bitmaps scaled to the default icon size. @@ -39,22 +40,22 @@ public class ShortcutDragPreviewProvider extends DragPreviewProvider { mPositionShift = shift; } + @Override public Bitmap createDragBitmap() { + int size = Launcher.getLauncher(mView.getContext()).getDeviceProfile().iconSizePx; + return BitmapRenderer.createHardwareBitmap( + size + blurSizeOutline, + size + blurSizeOutline, + (c) -> drawDragViewOnBackground(c, size)); + } + + private void drawDragViewOnBackground(Canvas canvas, float size) { Drawable d = mView.getBackground(); Rect bounds = getDrawableBounds(d); - - int size = Launcher.getLauncher(mView.getContext()).getDeviceProfile().iconSizePx; - final Bitmap b = Bitmap.createBitmap( - size + blurSizeOutline, - size + blurSizeOutline, - Bitmap.Config.ARGB_8888); - - Canvas canvas = new Canvas(b); canvas.translate(blurSizeOutline / 2, blurSizeOutline / 2); - canvas.scale(((float) size) / bounds.width(), ((float) size) / bounds.height(), 0, 0); + canvas.scale(size / bounds.width(), size / bounds.height(), 0, 0); canvas.translate(bounds.left, bounds.top); d.draw(canvas); - return b; } @Override diff --git a/src/com/android/launcher3/util/ShortcutUtil.java b/src/com/android/launcher3/util/ShortcutUtil.java index 49c97daf35..a69cd6c085 100644 --- a/src/com/android/launcher3/util/ShortcutUtil.java +++ b/src/com/android/launcher3/util/ShortcutUtil.java @@ -15,10 +15,20 @@ */ package com.android.launcher3.util; +import static com.android.launcher3.util.Executors.MODEL_EXECUTOR; + +import android.content.Context; +import android.content.pm.ShortcutInfo; + +import androidx.annotation.NonNull; + import com.android.launcher3.ItemInfo; +import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherSettings; import com.android.launcher3.Utilities; import com.android.launcher3.WorkspaceItemInfo; +import com.android.launcher3.icons.BitmapInfo; +import com.android.launcher3.icons.LauncherIcons; import com.android.launcher3.model.WidgetsModel; import com.android.launcher3.shortcuts.ShortcutKey; @@ -61,6 +71,26 @@ public class ShortcutUtil { && info instanceof WorkspaceItemInfo; } + /** + * Fetch the shortcut icon in background, then update the UI. + */ + public static void fetchAndUpdateShortcutIconAsync( + @NonNull Context context, @NonNull WorkspaceItemInfo info, @NonNull ShortcutInfo si, + boolean badged) { + if (info.iconBitmap == null) { + // use low res icon as placeholder while the actual icon is being fetched. + info.iconBitmap = BitmapInfo.LOW_RES_ICON; + info.iconColor = Themes.getColorAccent(context); + } + MODEL_EXECUTOR.execute(() -> { + LauncherIcons li = LauncherIcons.obtain(context); + BitmapInfo bitmapInfo = li.createShortcutIcon(si, badged, true, null); + info.applyFrom(bitmapInfo); + li.recycle(); + LauncherAppState.getInstance(context).getModel().updateAndBindWorkspaceItem(info, si); + }); + } + private static boolean isActive(ItemInfo info) { boolean isLoading = info instanceof WorkspaceItemInfo && ((WorkspaceItemInfo) info).hasPromiseIconUi(); From 6c484bc9bf332d9ac8e73f2d577e25365616d4b5 Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 15 Oct 2019 10:55:58 -0700 Subject: [PATCH 08/17] More logging for a lab-only bug Bug: 142514365 Change-Id: I9936415fc4f3bfd4676d607f2dfff44070409c0c --- src/com/android/launcher3/model/LoaderTask.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 3673102bfe..5582363ad5 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -181,7 +181,16 @@ public class LoaderTask implements Runnable { } TraceHelper.INSTANCE.beginSection(TAG); - TimingLogger logger = new TimingLogger(TAG, "run"); + TimingLogger logger = TestProtocol.sDebugTracing ? + new TimingLogger(TAG, "run") { + @Override + public void addSplit(String splitLabel) { + super.addSplit(splitLabel); + Log.d(TestProtocol.LAUNCHER_DIDNT_INITIALIZE, + "LoaderTask.addSplit " + splitLabel); + } + } + : new TimingLogger(TAG, "run"); try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) { List allShortcuts = new ArrayList<>(); loadWorkspace(allShortcuts); From 14b919e2fde5fe2f5d1a3db13998042d3fabc960 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 15 Oct 2019 11:35:15 -0700 Subject: [PATCH 09/17] Fix mSubtractDisplacement when recatching Previously we correctly set mSubtractDisplacement when re-catching during the SETTLING state, but then immediately overrode it to be +/-mTouchSlop. Test: Swipe up to all apps, catch it by touching down during the transition, ensure there's no jump when starting to move again. Change-Id: I5d543e8a8b027b68bafb26b752e70862f6ae0777 --- src/com/android/launcher3/touch/SwipeDetector.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/com/android/launcher3/touch/SwipeDetector.java b/src/com/android/launcher3/touch/SwipeDetector.java index d0edfd87de..c38ca24d92 100644 --- a/src/com/android/launcher3/touch/SwipeDetector.java +++ b/src/com/android/launcher3/touch/SwipeDetector.java @@ -330,8 +330,7 @@ public class SwipeDetector { private void initializeDragging() { if (mState == ScrollState.SETTLING && mIgnoreSlopWhenSettling) { mSubtractDisplacement = 0; - } - if (mDisplacement > 0) { + } else if (mDisplacement > 0) { mSubtractDisplacement = mTouchSlop; } else { mSubtractDisplacement = -mTouchSlop; From 657d3f8ca7f6ea92b42edfaf7ede534eca0e21bd Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 15 Oct 2019 12:06:06 -0700 Subject: [PATCH 10/17] Changing the taskAffinity for LockScreenRecentsActivity so that other activities do not get started in this task Bug: 138473688 Change-Id: I63b72236496a818d08ccb14e02e4fbf698a0cc49 --- quickstep/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index 546548036e..826a27553c 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -88,6 +88,7 @@ From 91ac68284e0c0f027f16c442f92e630530f7233f Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 15 Oct 2019 12:06:06 -0700 Subject: [PATCH 11/17] Changing the taskAffinity for LockScreenRecentsActivity so that other activities do not get started in this task Bug: 138473688 Change-Id: I63b72236496a818d08ccb14e02e4fbf698a0cc49 (cherry picked from commit 657d3f8ca7f6ea92b42edfaf7ede534eca0e21bd) --- quickstep/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml index 546548036e..826a27553c 100644 --- a/quickstep/AndroidManifest.xml +++ b/quickstep/AndroidManifest.xml @@ -88,6 +88,7 @@ From b3d3ca87dd6d0d317a0058efc66d119bd4f96c6e Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Tue, 15 Oct 2019 14:23:27 -0700 Subject: [PATCH 12/17] temporarily disable a regression test to unblock merging to master The test case testDragCustomShortcut was created initially to prevent future regression on custom shortcut (b/141568904), which was caused by ag/9342399. Some times after ag/9342399 was reverted on ub-launcher3-master, a different error is causing custom shortcut to not working intermittently (b/141528961). Since this is different from b/141568904, it should not be a blocker to merging to master. Bug: 141568904 Change-Id: Ia11e1ae44d0ef86c16876c002954aa662f1edbc8 --- tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index 709822bbbf..e7a5de0817 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -349,6 +349,7 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { * Custom shortcuts are replaced by deep shortcuts after api 25. */ @Test + @Ignore("Temporarily disabled to unblock merging to master") @PortraitLandscape public void testDragCustomShortcut() { mLauncher.getWorkspace().openAllWidgets() From 4565739fb7f422c8e29d79b99214fc19c70afab0 Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 15 Oct 2019 17:06:41 -0700 Subject: [PATCH 13/17] Increasing wait time for loading model to 60s Bug: 142514365 Change-Id: I15e0ff8e2a721f7ffdefdf2eb02e114212dded3b --- .../com/android/launcher3/tapl/LauncherInstrumentation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 484cbb61c3..321f727e7c 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -497,7 +497,7 @@ public final class LauncherInstrumentation { } public void waitForLauncherInitialized() { - for (int i = 0; i < 100; ++i) { + for (int i = 0; i < 600; ++i) { if (getTestInfo( TestProtocol.REQUEST_IS_LAUNCHER_INITIALIZED). getBoolean(TestProtocol.TEST_INFO_RESPONSE_FIELD)) { From a0f77c4449753490adca6863cbf97c509e70e17a Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Tue, 15 Oct 2019 15:24:39 -0700 Subject: [PATCH 14/17] Fix quick switch test gesture in landscape 2-button mode It should swipe from the bottom right to top right when the nav bar is on the right, rather than from the bottom left to bottom right. For now, disable testQuickSwitchFromApp() because it seems to have other failures as well. Bug: 140252765 Change-Id: I1f4989f3ea5456c18bb9cbf42ea4b157cee500d7 --- .../android/quickstep/TaplTestsQuickstep.java | 1 + .../android/launcher3/tapl/Background.java | 28 ++++++++++++++----- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java index 41f4a82175..d270d762d9 100644 --- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java +++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java @@ -248,6 +248,7 @@ public class TaplTestsQuickstep extends AbstractQuickStepTest { @Test @NavigationModeSwitch @PortraitLandscape + @Ignore("Temporarily disabled b/140252765") public void testQuickSwitchFromApp() throws Exception { startAppFast(getAppPackageName()); startTestActivity(2); diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java index 0dd3e775c5..db3d846a09 100644 --- a/tests/tapl/com/android/launcher3/tapl/Background.java +++ b/tests/tapl/com/android/launcher3/tapl/Background.java @@ -132,15 +132,29 @@ public class Background extends LauncherInstrumentation.VisibleContainer { } protected void quickSwitchToPreviousApp(int expectedState) { + boolean transposeInLandscape = false; switch (mLauncher.getNavigationModel()) { - case ZERO_BUTTON: + case TWO_BUTTON: + transposeInLandscape = true; // Fall through, zero button and two button modes behave the same. - case TWO_BUTTON: { - // Swipe from the bottom left to the bottom right of the screen. - final int startX = 0; - final int startY = getSwipeStartY(); - final int endX = mLauncher.getDevice().getDisplayWidth(); - final int endY = startY; + case ZERO_BUTTON: { + final int startX; + final int startY; + final int endX; + final int endY; + if (mLauncher.getDevice().isNaturalOrientation() || !transposeInLandscape) { + // Swipe from the bottom left to the bottom right of the screen. + startX = 0; + startY = getSwipeStartY(); + endX = mLauncher.getDevice().getDisplayWidth(); + endY = startY; + } else { + // Swipe from the bottom right to the top right of the screen. + startX = getSwipeStartX(); + startY = mLauncher.getRealDisplaySize().y - 1; + endX = startX; + endY = 0; + } mLauncher.swipeToState(startX, startY, endX, endY, 20, expectedState); break; } From 36d7be7fc933bd1a8cdd3ef30dc67570845afe78 Mon Sep 17 00:00:00 2001 From: vadimt Date: Tue, 15 Oct 2019 18:34:58 -0700 Subject: [PATCH 15/17] Implementing test stability attribute Change-Id: I5d78a19039ab2bcdb217886fdaca29e3df412780 --- .../launcher3/ui/TaplTestsLauncher3.java | 9 --- .../util/rule/TestStabilityRule.java | 60 ++++++++++++++----- 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java index e7a5de0817..5e87612f43 100644 --- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java +++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java @@ -24,8 +24,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import android.util.Log; - import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; @@ -38,7 +36,6 @@ import com.android.launcher3.tapl.AppIconMenu; import com.android.launcher3.tapl.AppIconMenuItem; import com.android.launcher3.tapl.Widgets; import com.android.launcher3.tapl.Workspace; -import com.android.launcher3.util.rule.TestStabilityRule.Stability; import com.android.launcher3.views.OptionsPopupView; import com.android.launcher3.widget.WidgetsFullSheet; import com.android.launcher3.widget.WidgetsRecyclerView; @@ -362,10 +359,4 @@ public class TaplTestsLauncher3 extends AbstractLauncherUiTest { public static String getAppPackageName() { return getInstrumentation().getContext().getPackageName(); } - - @Test - @Stability - public void testTestStabilityAttribute() { - Log.d("TestStabilityRule", "Hello world!"); - } } diff --git a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java index d7f41bf041..69bf01d40c 100644 --- a/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java +++ b/tests/src/com/android/launcher3/util/rule/TestStabilityRule.java @@ -17,6 +17,7 @@ package com.android.launcher3.util.rule; import static androidx.test.InstrumentationRegistry.getInstrumentation; +import android.content.pm.PackageManager; import android.os.Build; import android.util.Log; @@ -50,20 +51,33 @@ public class TestStabilityRule implements TestRule { + "(?[0-9]+)" + ")$"); + public static final int LOCAL = 0x1; + public static final int UNBUNDLED_PRESUBMIT = 0x2; + public static final int UNBUNDLED_POSTSUBMIT = 0x4; + public static final int PLATFORM_PRESUBMIT = 0x8; + public static final int PLATFORM_POSTSUBMIT = 0x10; + + private static final int RUN_FLAFOR = getRunFlavor(); + @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Stability { + int flavors(); } @Override public Statement apply(Statement base, Description description) { - if (description.getAnnotation(Stability.class) != null) { + final Stability stability = description.getAnnotation(Stability.class); + if (stability != null) { return new Statement() { @Override public void evaluate() throws Throwable { - getRunFlavor(); - - base.evaluate(); + if ((stability.flavors() & RUN_FLAFOR) != 0) { + Log.d(TAG, "Running " + description.getDisplayName()); + base.evaluate(); + } else { + Log.d(TAG, "Skipping " + description.getDisplayName()); + } } }; } else { @@ -71,49 +85,63 @@ public class TestStabilityRule implements TestRule { } } - private static void getRunFlavor() throws Exception { - final String launcherVersion = getInstrumentation(). - getContext(). - getPackageManager(). - getPackageInfo( - UiDevice.getInstance(getInstrumentation()). - getLauncherPackageName(), - 0). - versionName; + private static int getRunFlavor() { + final String launcherVersion; + try { + launcherVersion = getInstrumentation(). + getContext(). + getPackageManager(). + getPackageInfo( + UiDevice.getInstance(getInstrumentation()). + getLauncherPackageName(), + 0). + versionName; + } catch (PackageManager.NameNotFoundException e) { + throw new RuntimeException(e); + } final Matcher launcherBuildMatcher = LAUNCHER_BUILD.matcher(launcherVersion); if (!launcherBuildMatcher.find()) { - Log.e(TAG, "Match not found"); + throw new AssertionError("Launcher build match not found"); } final String platformVersion = Build.VERSION.INCREMENTAL; final Matcher platformBuildMatcher = PLATFORM_BUILD.matcher(platformVersion); if (!platformBuildMatcher.find()) { - Log.e(TAG, "Match not found"); + throw new AssertionError("Platform build match not found"); } Log.d(TAG, "Launcher: " + launcherVersion + ", platform: " + platformVersion); + final int runFlavor; + if (launcherBuildMatcher.group("local") != null && ( platformBuildMatcher.group("commandLine") != null || platformBuildMatcher.group("postsubmit") != null)) { Log.d(TAG, "LOCAL RUN"); + runFlavor = LOCAL; } else if (launcherBuildMatcher.group("presubmit") != null && platformBuildMatcher.group("postsubmit") != null) { Log.d(TAG, "UNBUNDLED PRESUBMIT"); + runFlavor = UNBUNDLED_PRESUBMIT; } else if (launcherBuildMatcher.group("postsubmit") != null && platformBuildMatcher.group("postsubmit") != null) { Log.d(TAG, "UNBUNDLED POSTSUBMIT"); + runFlavor = UNBUNDLED_POSTSUBMIT; } else if (launcherBuildMatcher.group("platform") != null && platformBuildMatcher.group("presubmit") != null) { Log.d(TAG, "PLATFORM PRESUBMIT"); + runFlavor = PLATFORM_PRESUBMIT; } else if (launcherBuildMatcher.group("platform") != null && platformBuildMatcher.group("postsubmit") != null) { Log.d(TAG, "PLATFORM POSTSUBMIT"); + runFlavor = PLATFORM_POSTSUBMIT; } else { - Log.e(TAG, "ERROR3"); + throw new AssertionError("Unrecognized run flavor"); } + + return runFlavor; } } From bffbd7521dbaf6483a4a3f50a578dbcd3f56f69e Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Tue, 15 Oct 2019 14:32:04 -0700 Subject: [PATCH 16/17] Cleaning up properly after RaceConditionReproducerTest Change-Id: I43362fbc63789d3ce3468266a5189a9f9d209d00 --- .../launcher3/util/RaceConditionReproducerTest.java | 10 +++++++--- .../com/android/launcher3/util/TraceHelperForTest.java | 5 +++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java index d156d1f017..59f21734f4 100644 --- a/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java +++ b/tests/src/com/android/launcher3/util/RaceConditionReproducerTest.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertTrue; import androidx.test.filters.LargeTest; import androidx.test.runner.AndroidJUnit4; +import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -45,6 +46,11 @@ public class RaceConditionReproducerTest { eventProcessor = new RaceConditionReproducer(); } + @After + public void tearDown() { + TraceHelperForTest.cleanup(); + } + private void run3_3_TestAction() throws InterruptedException { Thread tb = new Thread(() -> { eventProcessor.onEvent("B1"); @@ -125,9 +131,7 @@ public class RaceConditionReproducerTest { @Test // 2 threads, 3 events each; reproducing a particular event sequence. public void test3_3_ReproMode() throws Exception { - final RaceConditionReproducer eventProcessor = new RaceConditionReproducer( - SOME_VALID_SEQUENCE_3_3); - + eventProcessor = new RaceConditionReproducer(SOME_VALID_SEQUENCE_3_3); eventProcessor.startIteration(); run3_3_TestAction(); assertTrue(!eventProcessor.finishIteration()); diff --git a/tests/src/com/android/launcher3/util/TraceHelperForTest.java b/tests/src/com/android/launcher3/util/TraceHelperForTest.java index 9125f5fc35..2fcd757c52 100644 --- a/tests/src/com/android/launcher3/util/TraceHelperForTest.java +++ b/tests/src/com/android/launcher3/util/TraceHelperForTest.java @@ -33,6 +33,11 @@ public class TraceHelperForTest extends TraceHelper { INSTANCE_FOR_TEST.mRaceConditionReproducer = reproducer; } + public static void cleanup() { + INSTANCE_FOR_TEST.mRaceConditionReproducer = null; + INSTANCE_FOR_TEST.mFlagsChangeListener = null; + } + public static void setFlagsChangeListener(IntConsumer listener) { TraceHelper.INSTANCE = INSTANCE_FOR_TEST; INSTANCE_FOR_TEST.mFlagsChangeListener = listener; From 5cc62c7d0b01bd229e3f47ade9ae45aaef472d49 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 16 Oct 2019 11:32:41 -0700 Subject: [PATCH 17/17] Fix a couple trace issues - Adding trace tokens since we can be starting/ending traces out of order - Fixing issue with draw hitting twice causing the trace stack to be popped twice - Fix issue with endFlagOverrides not removing from the stack Bug: 142803200 Change-Id: I8649b94249910a352f00f2f2c2459c355d2bab00 --- .../quickstep/TouchInteractionService.java | 5 +-- .../WindowTransformSwipeHandler.java | 19 +++++++---- .../OtherActivityInputConsumer.java | 10 +++--- src/com/android/launcher3/Launcher.java | 31 +++++++++-------- .../android/launcher3/model/LoaderTask.java | 4 +-- .../android/launcher3/util/TraceHelper.java | 25 +++++++++----- .../launcher3/util/TraceHelperForTest.java | 33 ++++++++++++------- 7 files changed, 80 insertions(+), 47 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 556f4818d2..0eafb44a53 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -417,7 +417,8 @@ public class TouchInteractionService extends Service implements return; } - TraceHelper.INSTANCE.beginFlagsOverride(TraceHelper.FLAG_ALLOW_BINDER_TRACKING); + Object traceToken = TraceHelper.INSTANCE.beginFlagsOverride( + TraceHelper.FLAG_ALLOW_BINDER_TRACKING); MotionEvent event = (MotionEvent) ev; if (event.getAction() == ACTION_DOWN) { GestureState newGestureState = new GestureState( @@ -446,7 +447,7 @@ public class TouchInteractionService extends Service implements ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked()); mUncheckedConsumer.onMotionEvent(event); - TraceHelper.INSTANCE.endFlagsOverride(); + TraceHelper.INSTANCE.endFlagsOverride(traceToken); } private InputConsumer newConsumer(GestureState gestureState, boolean useSharedState, diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index 8dd1fffe96..1168758dfa 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -367,13 +367,19 @@ public class WindowTransformSwipeHandler if (mWasLauncherAlreadyVisible) { mStateCallback.setState(STATE_LAUNCHER_DRAWN); } else { - TraceHelper.INSTANCE.beginSection("WTS-init"); + Object traceToken = TraceHelper.INSTANCE.beginSection("WTS-init"); View dragLayer = activity.getDragLayer(); dragLayer.getViewTreeObserver().addOnDrawListener(new OnDrawListener() { + boolean mHandled = false; @Override public void onDraw() { - TraceHelper.INSTANCE.endSection(); + if (mHandled) { + return; + } + mHandled = true; + + TraceHelper.INSTANCE.endSection(traceToken); dragLayer.post(() -> dragLayer.getViewTreeObserver().removeOnDrawListener(this)); if (activity != mActivity) { @@ -416,13 +422,14 @@ public class WindowTransformSwipeHandler private void initializeLauncherAnimationController() { buildAnimationController(); - TraceHelper.INSTANCE.beginSection("logToggleRecents", TraceHelper.FLAG_IGNORE_BINDERS); + Object traceToken = TraceHelper.INSTANCE.beginSection("logToggleRecents", + TraceHelper.FLAG_IGNORE_BINDERS); // Only used in debug builds if (LatencyTrackerCompat.isEnabled(mContext)) { LatencyTrackerCompat.logToggleRecents( (int) (mLauncherFrameDrawnTime - mTouchTimeMs)); } - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); // This method is only called when STATE_GESTURE_STARTED is set, so we can enable the // high-res thumbnail loader here once we are sure that we will end up in an overview state @@ -1144,10 +1151,10 @@ public class WindowTransformSwipeHandler } if (!finishTransitionPosted) { // If we haven't posted a draw callback, set the state immediately. - TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT, + Object traceToken = TraceHelper.INSTANCE.beginSection(SCREENSHOT_CAPTURED_EVT, TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS); setStateOnUiThread(STATE_SCREENSHOT_CAPTURED); - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java index d231d51be3..02f4c4032d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/OtherActivityInputConsumer.java @@ -198,7 +198,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC switch (ev.getActionMasked()) { case ACTION_DOWN: { - TraceHelper.INSTANCE.beginSection(DOWN_EVT, FLAG_CHECK_FOR_RACE_CONDITIONS); + Object traceToken = TraceHelper.INSTANCE.beginSection(DOWN_EVT, + FLAG_CHECK_FOR_RACE_CONDITIONS); mActivePointerId = ev.getPointerId(0); mDownPos.set(ev.getX(), ev.getY()); mLastPos.set(mDownPos); @@ -209,7 +210,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC startTouchTrackingForWindowAnimation(ev.getEventTime(), false); } - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); break; } case ACTION_POINTER_DOWN: { @@ -355,7 +356,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC * the animation can still be running. */ private void finishTouchTracking(MotionEvent ev) { - TraceHelper.INSTANCE.beginSection(UP_EVT, FLAG_CHECK_FOR_RACE_CONDITIONS); + Object traceToken = TraceHelper.INSTANCE.beginSection(UP_EVT, + FLAG_CHECK_FOR_RACE_CONDITIONS); if (mPassedWindowMoveSlop && mInteractionHandler != null) { if (ev.getActionMasked() == ACTION_CANCEL) { @@ -389,7 +391,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC mVelocityTracker.recycle(); mVelocityTracker = null; mMotionPauseDetector.clear(); - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } @Override diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 2951d891dd..4b4d7939e6 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -313,7 +313,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onCreate(Bundle savedInstanceState) { - TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT, TraceHelper.FLAG_UI_EVENT); + Object traceToken = TraceHelper.INSTANCE.beginSection(ON_CREATE_EVT, + TraceHelper.FLAG_UI_EVENT); if (DEBUG_STRICT_MODE) { StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() .detectDiskReads() @@ -431,7 +432,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, } }); - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } protected LauncherOverlayManager getDefaultOverlay() { @@ -936,14 +937,15 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onStart() { - TraceHelper.INSTANCE.beginSection(ON_START_EVT, TraceHelper.FLAG_UI_EVENT); + Object traceToken = TraceHelper.INSTANCE.beginSection(ON_START_EVT, + TraceHelper.FLAG_UI_EVENT); super.onStart(); if (!mDeferOverlayCallbacks) { mOverlayManager.onActivityStarted(this); } mAppWidgetHost.setListenIfResumed(true); - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } private void handleDeferredResume() { @@ -1038,7 +1040,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onResume() { - TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT, TraceHelper.FLAG_UI_EVENT); + Object traceToken = TraceHelper.INSTANCE.beginSection(ON_RESUME_EVT, + TraceHelper.FLAG_UI_EVENT); super.onResume(); mHandler.removeCallbacks(mHandleDeferredResume); @@ -1059,7 +1062,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mOverlayManager.onActivityResumed(this); } - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } @Override @@ -1423,7 +1426,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onNewIntent(Intent intent) { - TraceHelper.INSTANCE.beginSection(ON_NEW_INTENT_EVT); + Object traceToken = TraceHelper.INSTANCE.beginSection(ON_NEW_INTENT_EVT); super.onNewIntent(intent); boolean alreadyOnHome = hasWindowFocus() && ((intent.getFlags() & @@ -1475,7 +1478,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mOverlayManager.hideOverlay(isStarted() && !isForceInvisible()); } - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } @Override @@ -1978,7 +1981,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, * Implementation of the method from LauncherModel.Callbacks. */ public void startBinding() { - TraceHelper.INSTANCE.beginSection("startBinding"); + Object traceToken = TraceHelper.INSTANCE.beginSection("startBinding"); // Floating panels (except the full widget sheet) are associated with individual icons. If // we are starting a fresh bind, close all such panels as all the icons are about // to go away. @@ -1996,7 +1999,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, if (mHotseat != null) { mHotseat.resetLayout(getWallpaperDeviceProfile().isVerticalBarLayout()); } - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } @Override @@ -2196,7 +2199,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, return view; } - TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId); + Object traceToken = TraceHelper.INSTANCE.beginSection("BIND_WIDGET_id=" + item.appWidgetId); try { final LauncherAppWidgetProviderInfo appWidgetInfo; @@ -2293,7 +2296,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, } prepareAppWidget(view, item); } finally { - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } return view; @@ -2373,7 +2376,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, * Implementation of the method from LauncherModel.Callbacks. */ public void finishBindingItems(int pageBoundFirst) { - TraceHelper.INSTANCE.beginSection("finishBindingItems"); + Object traceToken = TraceHelper.INSTANCE.beginSection("finishBindingItems"); mWorkspace.restoreInstanceStateForRemainingPages(); setWorkspaceLoading(false); @@ -2397,7 +2400,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mDeviceProfile.inv.numFolderColumns * mDeviceProfile.inv.numFolderRows); getViewCache().setCacheSize(R.layout.folder_page, 2); - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } private boolean canRunNewAppsAnimation() { diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 5582363ad5..81b701d716 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -180,7 +180,7 @@ public class LoaderTask implements Runnable { "LoaderTask2 " + this); } - TraceHelper.INSTANCE.beginSection(TAG); + Object traceToken = TraceHelper.INSTANCE.beginSection(TAG); TimingLogger logger = TestProtocol.sDebugTracing ? new TimingLogger(TAG, "run") { @Override @@ -281,7 +281,7 @@ public class LoaderTask implements Runnable { } finally { logger.dumpToLog(); } - TraceHelper.INSTANCE.endSection(); + TraceHelper.INSTANCE.endSection(traceToken); } public synchronized void stopLocked() { diff --git a/src/com/android/launcher3/util/TraceHelper.java b/src/com/android/launcher3/util/TraceHelper.java index 073fb6a61d..168227db6e 100644 --- a/src/com/android/launcher3/util/TraceHelper.java +++ b/src/com/android/launcher3/util/TraceHelper.java @@ -46,35 +46,44 @@ public class TraceHelper { */ public static TraceHelper INSTANCE = new TraceHelper(); - public void beginSection(String sectionName) { - beginSection(sectionName, 0); + /** + * @return a token to pass into {@link #endSection(Object)}. + */ + public Object beginSection(String sectionName) { + return beginSection(sectionName, 0); } - public void beginSection(String sectionName, int flags) { + public Object beginSection(String sectionName, int flags) { Trace.beginSection(sectionName); + return null; } - public void endSection() { + /** + * @param token the token returned from {@link #beginSection(String, int)} + */ + public void endSection(Object token) { Trace.endSection(); } /** * Similar to {@link #beginSection} but doesn't add a trace section. */ - public void beginFlagsOverride(int flags) { } + public Object beginFlagsOverride(int flags) { + return null; + } - public void endFlagsOverride() { } + public void endFlagsOverride(Object token) { } /** * Temporarily ignore blocking binder calls for the duration of this {@link Supplier}. */ @MainThread public static T whitelistIpcs(String rpcName, Supplier supplier) { - INSTANCE.beginSection(rpcName, FLAG_IGNORE_BINDERS); + Object traceToken = INSTANCE.beginSection(rpcName, FLAG_IGNORE_BINDERS); try { return supplier.get(); } finally { - INSTANCE.endSection(); + INSTANCE.endSection(traceToken); } } } diff --git a/tests/src/com/android/launcher3/util/TraceHelperForTest.java b/tests/src/com/android/launcher3/util/TraceHelperForTest.java index 9125f5fc35..61e9520e41 100644 --- a/tests/src/com/android/launcher3/util/TraceHelperForTest.java +++ b/tests/src/com/android/launcher3/util/TraceHelperForTest.java @@ -41,9 +41,10 @@ public class TraceHelperForTest extends TraceHelper { private TraceHelperForTest() { } @Override - public void beginSection(String sectionName, int flags) { + public Object beginSection(String sectionName, int flags) { LinkedList stack = mStack.get(); - stack.add(new TraceInfo(sectionName, flags)); + TraceInfo info = new TraceInfo(sectionName, flags); + stack.add(info); if ((flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0 && mRaceConditionReproducer != null) { @@ -52,39 +53,49 @@ public class TraceHelperForTest extends TraceHelper { updateBinderTracking(stack); super.beginSection(sectionName, flags); + return info; } @Override - public void endSection() { + public void endSection(Object token) { LinkedList stack = mStack.get(); - TraceInfo info = stack.pollLast(); + if (stack.size() == 0) { + new Throwable().printStackTrace(); + } + TraceInfo info = (TraceInfo) token; + stack.remove(info); if ((info.flags & TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS) != 0 && mRaceConditionReproducer != null) { mRaceConditionReproducer.onEvent(RaceConditionReproducer.exitEvt(info.sectionName)); } updateBinderTracking(stack); - super.endSection(); + super.endSection(token); } @Override - public void beginFlagsOverride(int flags) { + public Object beginFlagsOverride(int flags) { LinkedList stack = mStack.get(); - stack.push(new TraceInfo(null, flags)); + TraceInfo info = new TraceInfo(null, flags); + stack.add(info); updateBinderTracking(stack); super.beginFlagsOverride(flags); + return info; } @Override - public void endFlagsOverride() { - super.endFlagsOverride(); - updateBinderTracking(mStack.get()); + public void endFlagsOverride(Object token) { + super.endFlagsOverride(token); + LinkedList stack = mStack.get(); + TraceInfo info = (TraceInfo) token; + stack.remove(info); + updateBinderTracking(stack); } private void updateBinderTracking(LinkedList stack) { if (mFlagsChangeListener != null) { mFlagsChangeListener.accept(stack.stream() - .mapToInt(s -> s.flags).reduce(0, (a, b) -> a | b)); + .mapToInt(info -> info.flags).reduce(0, (a, b) -> a | b)); } }