summaryrefslogtreecommitdiffstats
path: root/packages/SystemUI/src
diff options
context:
space:
mode:
authorWinson Chung <winsonc@google.com>2014-03-18 12:21:24 -0700
committerWinson Chung <winsonc@google.com>2014-03-18 14:44:24 -0700
commit7048fea75c06324a748d49f25bc05be908cda9ff (patch)
tree614b97fe3f3fd0ab1cd24195e5efd7cd643aedef /packages/SystemUI/src
parent0535a9f7aa5d0f875b06845e9af5f6dbfc5c8a19 (diff)
downloadframeworks_base-7048fea75c06324a748d49f25bc05be908cda9ff.zip
frameworks_base-7048fea75c06324a748d49f25bc05be908cda9ff.tar.gz
frameworks_base-7048fea75c06324a748d49f25bc05be908cda9ff.tar.bz2
Moving alternate recents component logic into its own file.
- Adding min delay between toggles of recents - Merging changes to show related recents Change-Id: I2201a9f98417e26cdfb1c16cb0a2ef095d2cd5fc
Diffstat (limited to 'packages/SystemUI/src')
-rw-r--r--packages/SystemUI/src/com/android/systemui/recent/Recents.java334
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java376
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Console.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java3
5 files changed, 399 insertions, 320 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
index 56acf04..10b6d49 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -16,142 +16,54 @@
package com.android.systemui.recent;
-import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.content.ActivityNotFoundException;
-import android.content.ComponentName;
-import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ActivityInfo;
-import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
-import android.graphics.Matrix;
import android.graphics.Paint;
-import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.Messenger;
-import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
-import android.view.Surface;
-import android.view.SurfaceControl;
import android.view.View;
-import android.view.WindowManager;
import com.android.systemui.R;
import com.android.systemui.RecentsComponent;
import com.android.systemui.SystemUI;
-
-import java.util.List;
+import com.android.systemui.recents.AlternateRecentsComponent;
public class Recents extends SystemUI implements RecentsComponent {
- /** A handler for messages from the recents implementation */
- class RecentsMessageHandler extends Handler {
- @Override
- public void handleMessage(Message msg) {
- if (!mUseAlternateRecents) return;
- if (msg.what == MSG_UPDATE_FOR_CONFIGURATION) {
- Resources res = mContext.getResources();
- float statusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- mFirstTaskRect = (Rect) msg.getData().getParcelable("taskRect");
- mFirstTaskRect.offset(0, (int) statusBarHeight);
- }
- }
- }
-
- /** A service connection to the recents implementation */
- class RecentsServiceConnection implements ServiceConnection {
- @Override
- public void onServiceConnected(ComponentName className, IBinder service) {
- if (!mUseAlternateRecents) return;
-
- Log.d(TAG, "[RecentsComponent|ServiceConnection|onServiceConnected] toggleRecents: " +
- mToggleRecentsUponServiceBound);
- mService = new Messenger(service);
- mServiceIsBound = true;
-
- // Toggle recents if this service connection was triggered by hitting the recents button
- if (mToggleRecentsUponServiceBound) {
- startAlternateRecentsActivity();
- }
- mToggleRecentsUponServiceBound = false;
- }
-
- @Override
- public void onServiceDisconnected(ComponentName className) {
- if (!mUseAlternateRecents) return;
-
- Log.d(TAG, "[RecentsComponent|ServiceConnection|onServiceDisconnected]");
- mService = null;
- mServiceIsBound = false;
- }
- }
-
private static final String TAG = "Recents";
private static final boolean DEBUG = true;
- final static int MSG_UPDATE_FOR_CONFIGURATION = 0;
- final static int MSG_UPDATE_TASK_THUMBNAIL = 1;
- final static int MSG_PRELOAD_TASKS = 2;
- final static int MSG_CANCEL_PRELOAD_TASKS = 3;
- final static int MSG_CLOSE_RECENTS = 4;
- final static int MSG_TOGGLE_RECENTS = 5;
-
- final static String sToggleRecentsAction = "com.android.systemui.recents.SHOW_RECENTS";
- final static String sRecentsPackage = "com.android.systemui";
- final static String sRecentsActivity = "com.android.systemui.recents.RecentsActivity";
- final static String sRecentsService = "com.android.systemui.recents.RecentsService";
-
// Which recents to use
boolean mUseAlternateRecents;
-
- // Recents service binding
- Messenger mService = null;
- Messenger mMessenger;
- boolean mServiceIsBound = false;
- boolean mToggleRecentsUponServiceBound;
- RecentsServiceConnection mConnection = new RecentsServiceConnection();
-
- View mStatusBarView;
- Rect mFirstTaskRect = new Rect();
-
- public Recents() {
- mMessenger = new Messenger(new RecentsMessageHandler());
- }
+ AlternateRecentsComponent mAlternateRecents;
@Override
public void start() {
- mUseAlternateRecents =
- SystemProperties.getBoolean("persist.recents.use_alternate", false);
-
- putComponent(RecentsComponent.class, this);
-
+ mUseAlternateRecents = SystemProperties.getBoolean("persist.recents.use_alternate", false);
if (mUseAlternateRecents) {
- Log.d(TAG, "[RecentsComponent|start]");
-
- // Try to create a long-running connection to the recents service
- bindToRecentsService(false);
+ if (mAlternateRecents == null) {
+ mAlternateRecents = new AlternateRecentsComponent(mContext);
+ }
+ mAlternateRecents.onStart();
}
+
+ putComponent(RecentsComponent.class, this);
}
@Override
public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
if (mUseAlternateRecents) {
// Launch the alternate recents if required
- toggleAlternateRecents(display, layoutDirection, statusBarView);
+ mAlternateRecents.onToggleRecents(display, layoutDirection, statusBarView);
return;
}
@@ -298,222 +210,17 @@ public class Recents extends SystemUI implements RecentsComponent {
}
}
- /** Toggles the alternate recents activity */
- public void toggleAlternateRecents(Display display, int layoutDirection, View statusBarView) {
- if (!mUseAlternateRecents) return;
-
- Log.d(TAG, "[RecentsComponent|toggleRecents] serviceIsBound: " + mServiceIsBound);
- mStatusBarView = statusBarView;
- if (!mServiceIsBound) {
- // Try to create a long-running connection to the recents service before toggling
- // recents
- bindToRecentsService(true);
- return;
- }
-
- try {
- startAlternateRecentsActivity();
- } catch (ActivityNotFoundException e) {
- Log.e(TAG, "Failed to launch RecentAppsIntent", e);
- }
- }
-
@Override
protected void onConfigurationChanged(Configuration newConfig) {
- if (mServiceIsBound) {
- Resources res = mContext.getResources();
- int statusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- int navBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.navigation_bar_height);
- Rect rect = new Rect();
- WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- wm.getDefaultDisplay().getRectSize(rect);
-
- // Try and update the recents configuration
- try {
- Bundle data = new Bundle();
- data.putParcelable("windowRect", rect);
- data.putParcelable("systemInsets", new Rect(0, statusBarHeight, 0, 0));
- Message msg = Message.obtain(null, MSG_UPDATE_FOR_CONFIGURATION, 0, 0);
- msg.setData(data);
- msg.replyTo = mMessenger;
- mService.send(msg);
- } catch (RemoteException re) {
- re.printStackTrace();
- }
- }
- }
-
- /** Binds to the recents implementation */
- private void bindToRecentsService(boolean toggleRecentsUponConnection) {
- if (!mUseAlternateRecents) return;
-
- mToggleRecentsUponServiceBound = toggleRecentsUponConnection;
- Intent intent = new Intent();
- intent.setClassName(sRecentsPackage, sRecentsService);
- mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
- }
-
- /** Loads the first task thumbnail */
- Bitmap loadFirstTaskThumbnail() {
- ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
- ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
- UserHandle.CURRENT.getIdentifier());
- for (ActivityManager.RecentTaskInfo t : tasks) {
- // Skip tasks in the home stack
- if (am.isInHomeStack(t.persistentId)) {
- return null;
- }
-
- Bitmap thumbnail = am.getTaskTopThumbnail(t.persistentId);
- return thumbnail;
- }
- return null;
- }
-
- /** Returns whether there is a first task */
- boolean hasFirstTask() {
- ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
- ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
- UserHandle.CURRENT.getIdentifier());
- for (ActivityManager.RecentTaskInfo t : tasks) {
- // Skip tasks in the home stack
- if (am.isInHomeStack(t.persistentId)) {
- continue;
- }
-
- return true;
- }
- return false;
- }
-
- /** Converts from the device rotation to the degree */
- float getDegreesForRotation(int value) {
- switch (value) {
- case Surface.ROTATION_90:
- return 360f - 90f;
- case Surface.ROTATION_180:
- return 360f - 180f;
- case Surface.ROTATION_270:
- return 360f - 270f;
- }
- return 0f;
- }
-
- /** Takes a screenshot of the surface */
- Bitmap takeScreenshot(Display display) {
- DisplayMetrics dm = new DisplayMetrics();
- display.getRealMetrics(dm);
- float[] dims = {dm.widthPixels, dm.heightPixels};
- float degrees = getDegreesForRotation(display.getRotation());
- boolean requiresRotation = (degrees > 0);
- if (requiresRotation) {
- // Get the dimensions of the device in its native orientation
- Matrix m = new Matrix();
- m.preRotate(-degrees);
- m.mapPoints(dims);
- dims[0] = Math.abs(dims[0]);
- dims[1] = Math.abs(dims[1]);
- }
- return SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
- }
-
- /** Starts the recents activity */
- void startAlternateRecentsActivity() {
- // If Recents is the front most activity, then we should just communicate with it directly
- // to launch the first task or dismiss itself
- ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
- List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
- if (!tasks.isEmpty()) {
- ComponentName topActivity = tasks.get(0).topActivity;
- Log.d(TAG, "[RecentsComponent|topActivity] " + topActivity);
-
- // Check if the front most activity is recents
- if (topActivity.getPackageName().equals(sRecentsPackage) &&
- topActivity.getClassName().equals(sRecentsActivity)) {
- // Notify Recents to toggle itself
- try {
- Bundle data = new Bundle();
- Message msg = Message.obtain(null, MSG_TOGGLE_RECENTS, 0, 0);
- msg.setData(data);
- mService.send(msg);
- } catch (RemoteException re) {
- re.printStackTrace();
- }
- return;
- }
- }
-
- // XXX: If window transitions are currently happening, then we should eat up the event here
-
- // Otherwise, Recents is not the front-most activity and we should animate into it
- Rect taskRect = mFirstTaskRect;
- if (taskRect != null && taskRect.width() > 0 && taskRect.height() > 0 && hasFirstTask()) {
- // Loading from thumbnail
- Bitmap thumbnail;
- Bitmap firstThumbnail = loadFirstTaskThumbnail();
- if (firstThumbnail == null) {
- // Load the thumbnail from the screenshot
- WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
- Display display = wm.getDefaultDisplay();
- Bitmap screenshot = takeScreenshot(display);
- Resources res = mContext.getResources();
- int size = Math.min(screenshot.getWidth(), screenshot.getHeight());
- int statusBarHeight = res.getDimensionPixelSize(
- com.android.internal.R.dimen.status_bar_height);
- thumbnail = Bitmap.createBitmap(mFirstTaskRect.width(), mFirstTaskRect.height(),
- Bitmap.Config.ARGB_8888);
- Canvas c = new Canvas(thumbnail);
- c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size),
- new Rect(0, 0, mFirstTaskRect.width(), mFirstTaskRect.height()), null);
- c.setBitmap(null);
- // Recycle the old screenshot
- screenshot.recycle();
- } else {
- // Create the thumbnail
- thumbnail = Bitmap.createBitmap(mFirstTaskRect.width(), mFirstTaskRect.height(),
- Bitmap.Config.ARGB_8888);
- int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
- Canvas c = new Canvas(thumbnail);
- c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
- new Rect(0, 0, mFirstTaskRect.width(), mFirstTaskRect.height()), null);
- c.setBitmap(null);
- // Recycle the old thumbnail
- firstThumbnail.recycle();
- }
-
- ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
- thumbnail, mFirstTaskRect.left, mFirstTaskRect.top, null);
- startAlternateRecentsActivity(opts);
- } else {
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_from_launcher_enter,
- R.anim.recents_from_launcher_exit);
- startAlternateRecentsActivity(opts);
- }
- }
-
- /** Starts the recents activity */
- void startAlternateRecentsActivity(ActivityOptions opts) {
- Intent intent = new Intent(sToggleRecentsAction);
- intent.setClassName(sRecentsPackage, sRecentsActivity);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
- if (opts != null) {
- mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
- UserHandle.USER_CURRENT));
- } else {
- mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ if (mUseAlternateRecents) {
+ mAlternateRecents.onConfigurationChanged(newConfig);
}
}
@Override
public void preloadRecentTasksList() {
if (mUseAlternateRecents) {
- Log.d(TAG, "[RecentsComponent|preloadRecents]");
+ mAlternateRecents.onPreloadRecents();
} else {
Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
intent.setClassName("com.android.systemui",
@@ -527,7 +234,7 @@ public class Recents extends SystemUI implements RecentsComponent {
@Override
public void cancelPreloadingRecentTasksList() {
if (mUseAlternateRecents) {
- Log.d(TAG, "[RecentsComponent|cancelPreload]");
+ mAlternateRecents.onCancelPreloadingRecents();
} else {
Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
intent.setClassName("com.android.systemui",
@@ -541,18 +248,7 @@ public class Recents extends SystemUI implements RecentsComponent {
@Override
public void closeRecents() {
if (mUseAlternateRecents) {
- Log.d(TAG, "[RecentsComponent|closeRecents]");
- if (mServiceIsBound) {
- // Try and update the recents configuration
- try {
- Bundle data = new Bundle();
- Message msg = Message.obtain(null, MSG_CLOSE_RECENTS, 0, 0);
- msg.setData(data);
- mService.send(msg);
- } catch (RemoteException re) {
- re.printStackTrace();
- }
- }
+ mAlternateRecents.onCloseRecents();
} else {
Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
intent.setPackage("com.android.systemui");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
new file mode 100644
index 0000000..19a6b09
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -0,0 +1,376 @@
+/*
+ * Copyright (C) 2014 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.systemui.recents;
+
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.os.UserHandle;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.WindowManager;
+import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.SystemUI;
+
+import java.util.List;
+
+/** A proxy implementation for the recents component */
+public class AlternateRecentsComponent {
+
+ /** A handler for messages from the recents implementation */
+ class RecentsMessageHandler extends Handler {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_UPDATE_FOR_CONFIGURATION) {
+ Resources res = mContext.getResources();
+ float statusBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ mFirstTaskRect = (Rect) msg.getData().getParcelable("taskRect");
+ mFirstTaskRect.offset(0, (int) statusBarHeight);
+ }
+ }
+ }
+
+ /** A service connection to the recents implementation */
+ class RecentsServiceConnection implements ServiceConnection {
+ @Override
+ public void onServiceConnected(ComponentName className, IBinder service) {
+ Console.log(Constants.DebugFlags.App.RecentsComponent,
+ "[RecentsComponent|ServiceConnection|onServiceConnected]",
+ "toggleRecents: " + mToggleRecentsUponServiceBound);
+ mService = new Messenger(service);
+ mServiceIsBound = true;
+
+ // Toggle recents if this service connection was triggered by hitting the recents button
+ if (mToggleRecentsUponServiceBound) {
+ startAlternateRecentsActivity();
+ }
+ mToggleRecentsUponServiceBound = false;
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName className) {
+ Console.log(Constants.DebugFlags.App.RecentsComponent,
+ "[RecentsComponent|ServiceConnection|onServiceDisconnected]");
+ mService = null;
+ mServiceIsBound = false;
+ }
+ }
+
+ final static int MSG_UPDATE_FOR_CONFIGURATION = 0;
+ final static int MSG_UPDATE_TASK_THUMBNAIL = 1;
+ final static int MSG_PRELOAD_TASKS = 2;
+ final static int MSG_CANCEL_PRELOAD_TASKS = 3;
+ final static int MSG_CLOSE_RECENTS = 4;
+ final static int MSG_TOGGLE_RECENTS = 5;
+
+ final static int sMinToggleDelay = 475;
+
+ final static String sToggleRecentsAction = "com.android.systemui.recents.SHOW_RECENTS";
+ final static String sRecentsPackage = "com.android.systemui";
+ final static String sRecentsActivity = "com.android.systemui.recents.RecentsActivity";
+ final static String sRecentsService = "com.android.systemui.recents.RecentsService";
+
+ Context mContext;
+
+ // Recents service binding
+ Messenger mService = null;
+ Messenger mMessenger;
+ boolean mServiceIsBound = false;
+ boolean mToggleRecentsUponServiceBound;
+ RecentsServiceConnection mConnection = new RecentsServiceConnection();
+
+ View mStatusBarView;
+ Rect mFirstTaskRect = new Rect();
+ long mLastToggleTime;
+
+ public AlternateRecentsComponent(Context context) {
+ mContext = context;
+ mMessenger = new Messenger(new RecentsMessageHandler());
+ }
+
+ public void onStart() {
+ Console.log(Constants.DebugFlags.App.RecentsComponent, "[RecentsComponent|start]");
+
+ // Try to create a long-running connection to the recents service
+ bindToRecentsService(false);
+ }
+
+ /** Toggles the alternate recents activity */
+ public void onToggleRecents(Display display, int layoutDirection, View statusBarView) {
+ Console.log(Constants.DebugFlags.App.RecentsComponent, "[RecentsComponent|toggleRecents]",
+ "serviceIsBound: " + mServiceIsBound);
+ mStatusBarView = statusBarView;
+ if (!mServiceIsBound) {
+ // Try to create a long-running connection to the recents service before toggling
+ // recents
+ bindToRecentsService(true);
+ return;
+ }
+
+ try {
+ startAlternateRecentsActivity();
+ } catch (ActivityNotFoundException e) {
+ Console.logRawError("Failed to launch RecentAppsIntent", e);
+ }
+ }
+
+ public void onPreloadRecents() {
+ // Do nothing
+ }
+
+ public void onCancelPreloadingRecents() {
+ // Do nothing
+ }
+
+ public void onCloseRecents() {
+ Console.log(Constants.DebugFlags.App.RecentsComponent, "[RecentsComponent|closeRecents]");
+ if (mServiceIsBound) {
+ // Try and update the recents configuration
+ try {
+ Bundle data = new Bundle();
+ Message msg = Message.obtain(null, MSG_CLOSE_RECENTS, 0, 0);
+ msg.setData(data);
+ mService.send(msg);
+ } catch (RemoteException re) {
+ re.printStackTrace();
+ }
+ }
+ }
+
+ public void onConfigurationChanged(Configuration newConfig) {
+ if (mServiceIsBound) {
+ Resources res = mContext.getResources();
+ int statusBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ int navBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.navigation_bar_height);
+ Rect rect = new Rect();
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ wm.getDefaultDisplay().getRectSize(rect);
+
+ // Try and update the recents configuration
+ try {
+ Bundle data = new Bundle();
+ data.putParcelable("windowRect", rect);
+ data.putParcelable("systemInsets", new Rect(0, statusBarHeight, 0, 0));
+ Message msg = Message.obtain(null, MSG_UPDATE_FOR_CONFIGURATION, 0, 0);
+ msg.setData(data);
+ msg.replyTo = mMessenger;
+ mService.send(msg);
+ } catch (RemoteException re) {
+ re.printStackTrace();
+ }
+ }
+ }
+
+ /** Binds to the recents implementation */
+ private void bindToRecentsService(boolean toggleRecentsUponConnection) {
+ mToggleRecentsUponServiceBound = toggleRecentsUponConnection;
+ Intent intent = new Intent();
+ intent.setClassName(sRecentsPackage, sRecentsService);
+ mContext.bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+ }
+
+ /** Loads the first task thumbnail */
+ Bitmap loadFirstTaskThumbnail() {
+ ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
+ ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+ UserHandle.CURRENT.getIdentifier());
+ for (ActivityManager.RecentTaskInfo t : tasks) {
+ // Skip tasks in the home stack
+ if (am.isInHomeStack(t.persistentId)) {
+ return null;
+ }
+
+ Bitmap thumbnail = am.getTaskTopThumbnail(t.persistentId);
+ return thumbnail;
+ }
+ return null;
+ }
+
+ /** Returns whether there is a first task */
+ boolean hasFirstTask() {
+ ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(1,
+ ActivityManager.RECENT_IGNORE_UNAVAILABLE | ActivityManager.RECENT_INCLUDE_RELATED,
+ UserHandle.CURRENT.getIdentifier());
+ for (ActivityManager.RecentTaskInfo t : tasks) {
+ // Skip tasks in the home stack
+ if (am.isInHomeStack(t.persistentId)) {
+ continue;
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /** Converts from the device rotation to the degree */
+ float getDegreesForRotation(int value) {
+ switch (value) {
+ case Surface.ROTATION_90:
+ return 360f - 90f;
+ case Surface.ROTATION_180:
+ return 360f - 180f;
+ case Surface.ROTATION_270:
+ return 360f - 270f;
+ }
+ return 0f;
+ }
+
+ /** Takes a screenshot of the surface */
+ Bitmap takeScreenshot(Display display) {
+ DisplayMetrics dm = new DisplayMetrics();
+ display.getRealMetrics(dm);
+ float[] dims = {dm.widthPixels, dm.heightPixels};
+ float degrees = getDegreesForRotation(display.getRotation());
+ boolean requiresRotation = (degrees > 0);
+ if (requiresRotation) {
+ // Get the dimensions of the device in its native orientation
+ Matrix m = new Matrix();
+ m.preRotate(-degrees);
+ m.mapPoints(dims);
+ dims[0] = Math.abs(dims[0]);
+ dims[1] = Math.abs(dims[1]);
+ }
+ return SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
+ }
+
+ /** Starts the recents activity */
+ void startAlternateRecentsActivity() {
+ // If the user has toggled it too quickly, then just eat up the event here (it's better than
+ // showing a janky screenshot).
+ // NOTE: Ideally, the screenshot mechanism would take the window transform into account
+ if (System.currentTimeMillis() - mLastToggleTime < sMinToggleDelay) {
+ return;
+ }
+
+ // If Recents is the front most activity, then we should just communicate with it directly
+ // to launch the first task or dismiss itself
+ ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+ List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+ if (!tasks.isEmpty()) {
+ ComponentName topActivity = tasks.get(0).topActivity;
+
+ // Check if the front most activity is recents
+ if (topActivity.getPackageName().equals(sRecentsPackage) &&
+ topActivity.getClassName().equals(sRecentsActivity)) {
+ // Notify Recents to toggle itself
+ try {
+ Bundle data = new Bundle();
+ Message msg = Message.obtain(null, MSG_TOGGLE_RECENTS, 0, 0);
+ msg.setData(data);
+ mService.send(msg);
+ } catch (RemoteException re) {
+ re.printStackTrace();
+ }
+ mLastToggleTime = System.currentTimeMillis();
+ return;
+ }
+ }
+
+ // Otherwise, Recents is not the front-most activity and we should animate into it
+ Rect taskRect = mFirstTaskRect;
+ if (taskRect != null && taskRect.width() > 0 && taskRect.height() > 0 && hasFirstTask()) {
+ // Loading from thumbnail
+ Bitmap thumbnail;
+ Bitmap firstThumbnail = loadFirstTaskThumbnail();
+ if (firstThumbnail == null) {
+ // Load the thumbnail from the screenshot
+ WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+ Display display = wm.getDefaultDisplay();
+ Bitmap screenshot = takeScreenshot(display);
+ Resources res = mContext.getResources();
+ int size = Math.min(screenshot.getWidth(), screenshot.getHeight());
+ int statusBarHeight = res.getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_height);
+ thumbnail = Bitmap.createBitmap(mFirstTaskRect.width(), mFirstTaskRect.height(),
+ Bitmap.Config.ARGB_8888);
+ Canvas c = new Canvas(thumbnail);
+ c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size),
+ new Rect(0, 0, mFirstTaskRect.width(), mFirstTaskRect.height()), null);
+ c.setBitmap(null);
+ // Recycle the old screenshot
+ screenshot.recycle();
+ } else {
+ // Create the thumbnail
+ thumbnail = Bitmap.createBitmap(mFirstTaskRect.width(), mFirstTaskRect.height(),
+ Bitmap.Config.ARGB_8888);
+ int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
+ Canvas c = new Canvas(thumbnail);
+ c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
+ new Rect(0, 0, mFirstTaskRect.width(), mFirstTaskRect.height()), null);
+ c.setBitmap(null);
+ // Recycle the old thumbnail
+ firstThumbnail.recycle();
+ }
+
+ ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
+ thumbnail, mFirstTaskRect.left, mFirstTaskRect.top, null);
+ startAlternateRecentsActivity(opts);
+ } else {
+ ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
+ R.anim.recents_from_launcher_enter,
+ R.anim.recents_from_launcher_exit);
+ startAlternateRecentsActivity(opts);
+ }
+ mLastToggleTime = System.currentTimeMillis();
+ }
+
+ /** Starts the recents activity */
+ void startAlternateRecentsActivity(ActivityOptions opts) {
+ Intent intent = new Intent(sToggleRecentsAction);
+ intent.setClassName(sRecentsPackage, sRecentsActivity);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+ if (opts != null) {
+ mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
+ UserHandle.USER_CURRENT));
+ } else {
+ mContext.startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Console.java b/packages/SystemUI/src/com/android/systemui/recents/Console.java
index db95193..614c4e7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Console.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Console.java
@@ -67,6 +67,11 @@ public class Console {
Log.e("Recents", msg);
}
+ /** Logs a raw error */
+ public static void logRawError(String msg, Exception e) {
+ Log.e("Recents", msg, e);
+ }
+
/** Logs a divider bar */
public static void logDivider(boolean condition) {
if (condition) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index ede4ea8..59a591a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -32,6 +32,7 @@ public class Constants {
// This disables the bitmap and icon caches to
public static final boolean DisableBackgroundCache = false;
+ public static final boolean RecentsComponent = false;
public static final boolean TaskDataLoader = false;
public static final boolean SystemUIHandshake = false;
public static final boolean TimeSystemCalls = false;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 5f9162d..c5e325e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -340,7 +340,8 @@ public class RecentsTaskLoader {
// Get the recent tasks
List<ActivityManager.RecentTaskInfo> tasks = am.getRecentTasksForUser(25,
- ActivityManager.RECENT_IGNORE_UNAVAILABLE, UserHandle.CURRENT.getIdentifier());
+ ActivityManager.RECENT_IGNORE_UNAVAILABLE |
+ ActivityManager.RECENT_INCLUDE_RELATED, UserHandle.CURRENT.getIdentifier());
Collections.reverse(tasks);
Console.log(Constants.DebugFlags.App.TimeSystemCalls,
"[RecentsTaskLoader|getRecentTasks]",