diff options
| author | 2017-05-13 23:16:44 +0200 | |
|---|---|---|
| committer | 2017-05-17 14:16:57 +0200 | |
| commit | ef496ea80dfcc468bd051b9379f61e8fe141814d (patch) | |
| tree | d1fb03074edd96f218d90798f91b015d039a1898 | |
| parent | 9363d33262631651e39c4882a13a06ee4319c4fd (diff) | |
Optimize App -> Recents
- Use same strategy to draw thumbnail bitmap by moving
startActivity off from the main thread and start caching the future
when AM is busy executing startActivity.
- Move some binder calls off the main thread.
- Add some trace points for better analysis in the future.
- Make toggleRecentApps asynchronous so we don't have to wait on
the next app-vsync - it's totally not needed.
Test: com.android.apptransition.tests.LatencyTests
Fixes: 32668632
Change-Id: Id6483e26e9d6c1e319bceaa8268da976cedfbca3
Merged-In: I15db41f2e821779972ab3b430033c70aa1dfd907
8 files changed, 106 insertions, 65 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java index 4eb07484a65b..dbf07247d610 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java @@ -204,8 +204,8 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD Recents.getSystemServices().removeTask(task.persistentId); } } - Settings.Secure.putLongForUser(RecentsActivity.this.getContentResolver(), - Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, currentTime, currentUser); + Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync( + currentTime, currentUser); // Clear the last PiP task time, it's an edge case and we'd rather it // not relaunch the PiP task if the user double taps diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java index cde865eec118..e229c90e7827 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java +++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java @@ -35,15 +35,18 @@ import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.SystemClock; -import android.os.UserHandle; import android.util.Log; import android.util.MutableBoolean; +import android.util.Pair; import android.view.AppTransitionAnimationSpec; import android.view.LayoutInflater; import android.view.ViewConfiguration; import android.view.WindowManager; import android.widget.Toast; + +import com.google.android.collect.Lists; + import com.android.internal.logging.MetricsLogger; import com.android.internal.policy.DockedDividerUtils; import com.android.systemui.R; @@ -74,6 +77,8 @@ import com.android.systemui.recents.model.RecentsTaskLoader; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.TaskGrouping; import com.android.systemui.recents.model.TaskStack; +import com.android.systemui.recents.views.RecentsTransitionHelper; +import com.android.systemui.recents.views.RecentsTransitionHelper.AppTransitionAnimationSpecsFuture; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm; import com.android.systemui.recents.views.TaskStackLayoutAlgorithm.VisibilityReport; import com.android.systemui.recents.views.TaskStackView; @@ -671,7 +676,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener windowRect.bottom -= systemInsets.bottom; systemInsets.bottom = 0; } - calculateWindowStableInsets(systemInsets, windowRect); + calculateWindowStableInsets(systemInsets, windowRect, displayRect); windowRect.offsetTo(0, 0); synchronized (mDummyStackView) { @@ -761,8 +766,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener * Given the stable insets and the rect for our window, calculates the insets that affect our * window. */ - private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect) { - Rect displayRect = Recents.getSystemServices().getDisplayRect(); + private void calculateWindowStableInsets(Rect inOutInsets, Rect windowRect, Rect displayRect) { // Display rect without insets - available app space Rect appRect = new Rect(displayRect); @@ -812,8 +816,9 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener /** * Creates the activity options for an app->recents transition. */ - private ActivityOptions getThumbnailTransitionActivityOptions( - ActivityManager.RunningTaskInfo runningTask, Rect windowOverrideRect) { + private Pair<ActivityOptions, AppTransitionAnimationSpecsFuture> + getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo runningTask, + Rect windowOverrideRect) { if (runningTask != null && runningTask.stackId == FREEFORM_WORKSPACE_STACK_ID) { ArrayList<AppTransitionAnimationSpec> specs = new ArrayList<>(); ArrayList<Task> tasks; @@ -844,23 +849,27 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener } AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()]; specs.toArray(specsArray); - return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, - specsArray, mHandler, null, this); + return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, + specsArray, mHandler, null, this), null); } else { // Update the destination rect Task toTask = new Task(); TaskViewTransform toTransform = getThumbnailTransitionTransform(mDummyStackView, toTask, windowOverrideRect); - Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform, - mThumbTransitionBitmapCache); - if (thumbnail != null) { - RectF toTaskRect = toTransform.rect; - return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView, - thumbnail, (int) toTaskRect.left, (int) toTaskRect.top, - (int) toTaskRect.width(), (int) toTaskRect.height(), mHandler, null); - } - // If both the screenshot and thumbnail fails, then just fall back to the default transition - return getUnknownTransitionActivityOptions(); + + RectF toTaskRect = toTransform.rect; + AppTransitionAnimationSpecsFuture future = + new RecentsTransitionHelper(mContext).getAppTransitionFuture( + () -> { + Rect rect = new Rect(); + toTaskRect.round(rect); + Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform, + mThumbTransitionBitmapCache); + return Lists.newArrayList(new AppTransitionAnimationSpec( + toTask.key.id, thumbnail, rect)); + }); + return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext, + mHandler, future.getFuture(), null, false /* scaleUp */), future); } } @@ -986,30 +995,31 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener launchState.launchedNumVisibleThumbnails = stackVr.numVisibleThumbnails; if (!animate) { - startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1)); + startRecentsActivity(ActivityOptions.makeCustomAnimation(mContext, -1, -1), + null /* future */); return; } - ActivityOptions opts; + Pair<ActivityOptions, AppTransitionAnimationSpecsFuture> pair; if (isBlacklisted) { - opts = getUnknownTransitionActivityOptions(); + pair = new Pair<>(getUnknownTransitionActivityOptions(), null); } else if (useThumbnailTransition) { // Try starting with a thumbnail transition - opts = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect); + pair = getThumbnailTransitionActivityOptions(runningTask, windowOverrideRect); } else { // If there is no thumbnail transition, but is launching from home into recents, then // use a quick home transition - opts = hasRecentTasks - ? getHomeTransitionActivityOptions() - : getUnknownTransitionActivityOptions(); + pair = new Pair<>(hasRecentTasks + ? getHomeTransitionActivityOptions() + : getUnknownTransitionActivityOptions(), null); } - startRecentsActivity(opts); + startRecentsActivity(pair.first, pair.second); mLastToggleTime = SystemClock.elapsedRealtime(); } private Rect getWindowRectOverride(int growTarget) { if (growTarget == DividerView.INVALID_RECENTS_GROW_TARGET) { - return null; + return SystemServicesProxy.getInstance(mContext).getWindowRect(); } Rect result = new Rect(); Rect displayRect = Recents.getSystemServices().getDisplayRect(); @@ -1022,21 +1032,21 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener /** * Starts the recents activity. */ - private void startRecentsActivity(ActivityOptions opts) { + private void startRecentsActivity(ActivityOptions opts, + final AppTransitionAnimationSpecsFuture future) { Intent intent = new Intent(); intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS | Intent.FLAG_ACTIVITY_TASK_ON_HOME); - + Recents.getSystemServices().startActivityAsUserAsync(intent, opts); HidePipMenuEvent hideMenuEvent = new HidePipMenuEvent(); hideMenuEvent.addPostAnimationCallback(() -> { - if (opts != null) { - mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT); - } else { - mContext.startActivityAsUser(intent, UserHandle.CURRENT); - } + Recents.getSystemServices().startActivityAsUserAsync(intent, opts); EventBus.getDefault().send(new RecentsActivityStartingEvent()); + if (future != null) { + future.precacheSpecs(); + } }); EventBus.getDefault().send(hideMenuEvent); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java index f85fb34a9749..37dc3275878c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java @@ -58,20 +58,22 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.IRemoteCallback; -import android.os.Looper; import android.os.Message; import android.os.ParcelFileDescriptor; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.provider.Settings.Secure; +import android.service.dreams.DreamService; +import android.service.dreams.IDreamManager; import android.util.ArraySet; import android.util.IconDrawableFactory; import android.util.Log; import android.util.MutableBoolean; -import android.view.AppTransitionAnimationSpec; import android.view.Display; import android.view.IAppTransitionAnimationSpecsFuture; import android.view.IDockedStackListener; @@ -91,7 +93,6 @@ import com.android.systemui.recents.RecentsDebugFlags; import com.android.systemui.recents.RecentsImpl; import com.android.systemui.recents.model.Task; import com.android.systemui.recents.model.ThumbnailData; -import com.android.systemui.recents.views.RecentsTransitionHelper.AnimationSpecComposer; import java.io.IOException; import java.util.ArrayList; @@ -130,6 +131,8 @@ public class SystemServicesProxy { PackageManager mPm; IconDrawableFactory mDrawableFactory; IPackageManager mIpm; + private final IDreamManager mDreamManager; + private final Context mContext; AssistUtils mAssistUtils; WindowManager mWm; IWindowManager mIwm; @@ -285,6 +288,7 @@ public class SystemServicesProxy { /** Private constructor */ private SystemServicesProxy(Context context) { + mContext = context.getApplicationContext(); mAccm = AccessibilityManager.getInstance(context); mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); mIam = ActivityManager.getService(); @@ -296,6 +300,8 @@ public class SystemServicesProxy { mIwm = WindowManagerGlobal.getWindowManagerService(); mKgm = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); mUm = UserManager.get(context); + mDreamManager = IDreamManager.Stub.asInterface( + ServiceManager.checkService(DreamService.DREAM_SERVICE)); mDisplay = mWm.getDefaultDisplay(); mRecentsPackage = context.getPackageName(); mHasFreeformWorkspaceSupport = @@ -1127,6 +1133,11 @@ public class SystemServicesProxy { } } + public void startActivityAsUserAsync(Intent intent, ActivityOptions opts) { + mOnewayExecutor.submit(() -> mContext.startActivityAsUser(intent, + opts != null ? opts.toBundle() : null, UserHandle.CURRENT)); + } + /** Starts an activity from recents. */ public void startActivityFromRecents(Context context, Task.TaskKey taskKey, String taskName, ActivityOptions options, int stackId, @@ -1283,6 +1294,33 @@ public class SystemServicesProxy { } } + public boolean isDreaming() { + try { + return mDreamManager.isDreaming(); + } catch (RemoteException e) { + Log.e(TAG, "Failed to query dream manager.", e); + } + return false; + } + + public void awakenDreamsAsync() { + mOnewayExecutor.submit(() -> { + try { + mDreamManager.awaken(); + } catch (RemoteException e) { + e.printStackTrace(); + } + }); + } + + public void updateOverviewLastStackActiveTimeAsync(long newLastStackActiveTime, + int currentUserId) { + mOnewayExecutor.submit(() -> { + Settings.Secure.putLongForUser(mContext.getContentResolver(), + Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId); + }); + } + public interface StartActivityFromRecentsResultListener { void onStartActivityResult(boolean succeeded); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java index 7ee090643000..17bb386407a4 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java @@ -218,8 +218,8 @@ public class RecentsTaskLoadPlan { affiliatedTasks.put(taskKey.id, taskKey); } if (newLastStackActiveTime != -1) { - Settings.Secure.putLongForUser(mContext.getContentResolver(), - Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, newLastStackActiveTime, currentUserId); + Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync( + newLastStackActiveTime, currentUserId); } // Initialize the stacks @@ -316,9 +316,8 @@ public class RecentsTaskLoadPlan { for (int i = 0; i < users.size(); i++) { int userId = users.get(i).id; if (userId != currentUserId) { - Settings.Secure.putLongForUser(mContext.getContentResolver(), - Secure.OVERVIEW_LAST_STACK_ACTIVE_TIME, legacyLastStackActiveTime, - userId); + Recents.getSystemServices().updateOverviewLastStackActiveTimeAsync( + legacyLastStackActiveTime, userId); } } return legacyLastStackActiveTime; diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java index 97a9659c70fb..c5a292f2da26 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java +++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java @@ -28,6 +28,7 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; +import android.os.Trace; import android.util.Log; import android.util.LruCache; @@ -351,7 +352,12 @@ public class RecentsTaskLoader { /** Preloads recents tasks using the specified plan to store the output. */ public synchronized void preloadTasks(RecentsTaskLoadPlan plan, int runningTaskId, boolean includeFrontMostExcludedTask) { - plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask); + try { + Trace.beginSection("preloadPlan"); + plan.preloadPlan(this, runningTaskId, includeFrontMostExcludedTask); + } finally { + Trace.endSection(); + } } /** Begins loading the heavy task data according to the specified options. */ diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java index 24a2927dbd79..0c7703663810 100644 --- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java +++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java @@ -1169,7 +1169,7 @@ public class DividerView extends FrameLayout implements OnTouchListener, } public final void onBusEvent(RecentsActivityStartingEvent recentsActivityStartingEvent) { - if (mGrowRecents && getWindowManagerProxy().getDockSide() == WindowManager.DOCKED_TOP + if (mGrowRecents && mDockSide == WindowManager.DOCKED_TOP && getSnapAlgorithm().getMiddleTarget() != getSnapAlgorithm().getLastSplitTarget() && getCurrentPosition() == getSnapAlgorithm().getLastSplitTarget().position) { mState.growAfterRecentsDrawn = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java index be221bb67b17..bf89b010b8db 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java @@ -279,7 +279,9 @@ public class CommandQueue extends IStatusBar.Stub { public void toggleRecentApps() { synchronized (mLock) { mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS); - mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null).sendToTarget(); + Message msg = mHandler.obtainMessage(MSG_TOGGLE_RECENT_APPS, 0, 0, null); + msg.setAsynchronous(true); + msg.sendToTarget(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index fc73c0f24cbf..01bcd61952ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -149,6 +149,7 @@ import com.android.systemui.recents.ScreenPinningRequest; import com.android.systemui.recents.events.EventBus; import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent; import com.android.systemui.recents.events.activity.UndockingTaskEvent; +import com.android.systemui.recents.misc.SystemServicesProxy; import com.android.systemui.stackdivider.Divider; import com.android.systemui.stackdivider.WindowManagerProxy; import com.android.systemui.statusbar.ActivatableNotificationView; @@ -220,8 +221,6 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.os.Build; import android.os.Handler; -import android.service.dreams.DreamService; -import android.service.dreams.IDreamManager; import android.service.notification.NotificationListenerService; import android.service.vr.IVrManager; import android.service.vr.IVrStateCallbacks; @@ -778,8 +777,6 @@ public class StatusBar extends SystemUI implements DemoMode, mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); - mDreamManager = IDreamManager.Stub.asInterface( - ServiceManager.checkService(DreamService.DREAM_SERVICE)); mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class); @@ -1532,13 +1529,7 @@ public class StatusBar extends SystemUI implements DemoMode, } void awakenDreams() { - if (mDreamManager != null) { - try { - mDreamManager.awaken(); - } catch (RemoteException e) { - // fine, stay asleep then - } - } + SystemServicesProxy.getInstance(mContext).awakenDreamsAsync(); } public UserHandle getCurrentUserHandle() { @@ -5173,7 +5164,6 @@ public class StatusBar extends SystemUI implements DemoMode, protected boolean mDisableNotificationAlerts = false; protected DevicePolicyManager mDevicePolicyManager; - protected IDreamManager mDreamManager; protected PowerManager mPowerManager; protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; @@ -6816,12 +6806,8 @@ public class StatusBar extends SystemUI implements DemoMode, return false; } - boolean inUse = mPowerManager.isScreenOn(); - try { - inUse = inUse && !mDreamManager.isDreaming(); - } catch (RemoteException e) { - Log.d(TAG, "failed to query dream manager", e); - } + boolean inUse = mPowerManager.isScreenOn() + && !SystemServicesProxy.getInstance(mContext).isDreaming(); if (!inUse && !isDozing()) { if (DEBUG) { |