SystemServicesProxy.java revision 65c294036bd3a01af0755519d37ef7e9f64b9fb9
1a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung/*
2a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * Copyright (C) 2014 The Android Open Source Project
3a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung *
4a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * Licensed under the Apache License, Version 2.0 (the "License");
5a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * you may not use this file except in compliance with the License.
6a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * You may obtain a copy of the License at
7a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung *
8a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung *      http://www.apache.org/licenses/LICENSE-2.0
9a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung *
10a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * Unless required by applicable law or agreed to in writing, software
11a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * distributed under the License is distributed on an "AS IS" BASIS,
12a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * See the License for the specific language governing permissions and
14a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * limitations under the License.
15a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung */
16a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
17ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungpackage com.android.systemui.recents.misc;
18a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
19a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.app.ActivityManager;
201f24c7e37bc794057a156a730c7e4b53b01212edWinson Chungimport android.app.ActivityManagerNative;
21a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.app.ActivityOptions;
224f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasaniimport android.app.AppGlobals;
23d16c565a607de754379fe699a4def21bd0e3de2fWinson Chungimport android.app.IActivityContainer;
241f24c7e37bc794057a156a730c7e4b53b01212edWinson Chungimport android.app.IActivityManager;
25740c3ac782675d190941b2ab1905e56f246c1b11Winson Chungimport android.app.ITaskStackListener;
26ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chungimport android.app.SearchManager;
27f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.appwidget.AppWidgetHost;
28f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.appwidget.AppWidgetManager;
29f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.appwidget.AppWidgetProviderInfo;
30a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.content.ComponentName;
3156e09b42a0f1670970872bef611a8036904ad6bfJason Monkimport android.content.ContentResolver;
32a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.content.Context;
33a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.content.Intent;
34a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.content.pm.ActivityInfo;
354f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasaniimport android.content.pm.IPackageManager;
36a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.content.pm.PackageManager;
37bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chungimport android.content.pm.ResolveInfo;
3885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chungimport android.content.res.Resources;
39a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.graphics.Bitmap;
40ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport android.graphics.BitmapFactory;
41b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chungimport android.graphics.Canvas;
42b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chungimport android.graphics.Color;
43b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chungimport android.graphics.Paint;
44dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chungimport android.graphics.Point;
45b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chungimport android.graphics.PorterDuff;
46b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chungimport android.graphics.PorterDuffXfermode;
47ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport android.graphics.Rect;
48a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.graphics.drawable.ColorDrawable;
49a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport android.graphics.drawable.Drawable;
50ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chungimport android.os.Bundle;
51ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport android.os.ParcelFileDescriptor;
524f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasaniimport android.os.RemoteException;
53d16c565a607de754379fe699a4def21bd0e3de2fWinson Chungimport android.os.SystemProperties;
544f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasaniimport android.os.UserHandle;
5556e09b42a0f1670970872bef611a8036904ad6bfJason Monkimport android.provider.Settings;
56b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chungimport android.util.Log;
57f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.util.Pair;
58d16c565a607de754379fe699a4def21bd0e3de2fWinson Chungimport android.util.SparseArray;
59d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport android.view.Display;
60d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport android.view.DisplayInfo;
61d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport android.view.SurfaceControl;
62d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport android.view.WindowManager;
63ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chungimport android.view.accessibility.AccessibilityManager;
644e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chungimport com.android.systemui.R;
65ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.Constants;
662cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chungimport com.android.systemui.recents.Recents;
67a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
68ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.io.IOException;
69a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport java.util.ArrayList;
70d16c565a607de754379fe699a4def21bd0e3de2fWinson Chungimport java.util.Collections;
71d16c565a607de754379fe699a4def21bd0e3de2fWinson Chungimport java.util.Comparator;
72918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chungimport java.util.Iterator;
73a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport java.util.List;
745e3e5d8945249cfeb8bd59de112be88954ba62bfWinson Chungimport java.util.Random;
752cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chungimport java.util.concurrent.atomic.AtomicBoolean;
76a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
77a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung/**
78a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * Acts as a shim around the real system services that we need to access data from, and provides
79a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * a point of injection when testing UI.
80a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung */
81a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungpublic class SystemServicesProxy {
82b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung    final static String TAG = "SystemServicesProxy";
83b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung
84aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn    final static BitmapFactory.Options sBitmapOptions;
85aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn
86ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung    AccessibilityManager mAccm;
87a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    ActivityManager mAm;
881f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung    IActivityManager mIam;
89f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    AppWidgetManager mAwm;
90a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    PackageManager mPm;
914f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    IPackageManager mIpm;
92ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung    SearchManager mSm;
93d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    WindowManager mWm;
94d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    Display mDisplay;
95918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung    String mRecentsPackage;
96da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung    ComponentName mAssistComponent;
97a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
98a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    Bitmap mDummyIcon;
9985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    int mDummyThumbnailWidth;
10085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    int mDummyThumbnailHeight;
101b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung    Paint mBgProtectionPaint;
102b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung    Canvas mBgProtectionCanvas;
103a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
104aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn    static {
105aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn        sBitmapOptions = new BitmapFactory.Options();
106aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn        sBitmapOptions.inMutable = true;
107aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn    }
108aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn
109a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Private constructor */
110a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public SystemServicesProxy(Context context) {
111ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung        mAccm = AccessibilityManager.getInstance(context);
112a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
1131f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung        mIam = ActivityManagerNative.getDefault();
114f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        mAwm = AppWidgetManager.getInstance(context);
115a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        mPm = context.getPackageManager();
1164f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        mIpm = AppGlobals.getPackageManager();
117ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung        mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
118d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
119d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mDisplay = mWm.getDefaultDisplay();
120918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        mRecentsPackage = context.getPackageName();
121a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
12285cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Get the dummy thumbnail width/heights
12385cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        Resources res = context.getResources();
12485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        int wId = com.android.internal.R.dimen.thumbnail_width;
12585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        int hId = com.android.internal.R.dimen.thumbnail_height;
12685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        mDummyThumbnailWidth = res.getDimensionPixelSize(wId);
12785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        mDummyThumbnailHeight = res.getDimensionPixelSize(hId);
12885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
129b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        // Create the protection paints
130b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        mBgProtectionPaint = new Paint();
131b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        mBgProtectionPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
132b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        mBgProtectionPaint.setColor(0xFFffffff);
133b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        mBgProtectionCanvas = new Canvas();
134b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung
135da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        // Resolve the assist intent
136da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        Intent assist = mSm.getAssistIntent(context, false);
137da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        if (assist != null) {
138da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung            mAssistComponent = assist.getComponent();
139da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        }
140da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung
141a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
142a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            // Create a dummy icon
1432f2ca08baa072376b3dfd60506625496aa05903fWinson Chung            mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
1446736905dc0e10689f7c63f6da43b31325caf966aWinson Chung            mDummyIcon.eraseColor(0xFF999999);
145a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
146a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
147a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
148a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns a list of the recents tasks */
1499cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung    public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId,
1509cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung            boolean isTopTaskHome) {
151a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return null;
152a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
153a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then create some recent tasks
154a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
155a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            ArrayList<ActivityManager.RecentTaskInfo> tasks =
156a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                    new ArrayList<ActivityManager.RecentTaskInfo>();
157918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            int count = Math.min(numLatestTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
158a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            for (int i = 0; i < count; i++) {
159a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                // Create a dummy component name
160a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
161a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                ComponentName cn = new ComponentName("com.android.test" + packageIndex,
162a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                        "com.android.test" + i + ".Activity");
163a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                String description = "" + i + " - " +
164a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                        Long.toString(Math.abs(new Random().nextLong()), 36);
165a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                // Create the recent task info
166a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
167a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                rti.id = rti.persistentId = i;
168a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                rti.baseIntent = new Intent();
169a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                rti.baseIntent.setComponent(cn);
170a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                rti.description = description;
171ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung                rti.firstActiveTime = rti.lastActiveTime = i;
1725e3e5d8945249cfeb8bd59de112be88954ba62bfWinson Chung                if (i % 2 == 0) {
173a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                    rti.taskDescription = new ActivityManager.TaskDescription(description,
17410f8139d3b8dd7cd08a2fc688285b3b74a34f0dbWinson Chung                        Bitmap.createBitmap(mDummyIcon),
17510f8139d3b8dd7cd08a2fc688285b3b74a34f0dbWinson Chung                        0xFF000000 | (0xFFFFFF & new Random().nextInt()));
176a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                } else {
177a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                    rti.taskDescription = new ActivityManager.TaskDescription();
1785e3e5d8945249cfeb8bd59de112be88954ba62bfWinson Chung                }
179a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                tasks.add(rti);
180a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            }
181a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return tasks;
182a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
183a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
184918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        // Remove home/recents/excluded tasks
185918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        int minNumTasksToQuery = 10;
186918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
187918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        List<ActivityManager.RecentTaskInfo> tasks = mAm.getRecentTasksForUser(numTasksToQuery,
188a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung                ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
189a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                ActivityManager.RECENT_IGNORE_UNAVAILABLE |
190918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                ActivityManager.RECENT_INCLUDE_PROFILES |
191918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                ActivityManager.RECENT_WITH_EXCLUDED, userId);
1924298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung
1934298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung        // Break early if we can't get a valid set of tasks
1944298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung        if (tasks == null) {
1954298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung            return new ArrayList<ActivityManager.RecentTaskInfo>();
1964298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung        }
1974298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung
198918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        boolean isFirstValidTask = true;
199918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
200918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        while (iter.hasNext()) {
201918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            ActivityManager.RecentTaskInfo t = iter.next();
202918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung
203918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            // NOTE: The order of these checks happens in the expected order of the traversal of the
204918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            // tasks
205918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung
206918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            // Check the first non-recents task, include this task even if it is marked as excluded
2079cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung            // from recents if we are currently in the app.  In other words, only remove excluded
2089cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung            // tasks if it is not the first active task.
209918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
210918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                    == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
2119cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung            if (isExcluded && (isTopTaskHome || !isFirstValidTask)) {
212918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                iter.remove();
213918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                continue;
214918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            }
215918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            isFirstValidTask = false;
216918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        }
217918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung
218918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        return tasks.subList(0, Math.min(tasks.size(), numLatestTasks));
219a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
220a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
221a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns a list of the running tasks */
2222cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    private List<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) {
223a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return null;
224a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        return mAm.getRunningTasks(numTasks);
225a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
226a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
2272cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    /** Returns the top task. */
2282cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    public ActivityManager.RunningTaskInfo getTopMostTask() {
2292cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        List<ActivityManager.RunningTaskInfo> tasks = getRunningTasks(1);
23065c294036bd3a01af0755519d37ef7e9f64b9fb9Winson Chung        if (tasks != null && !tasks.isEmpty()) {
2312cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            return tasks.get(0);
2322cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        }
2332cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        return null;
2342cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    }
2352cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung
2362cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    /** Returns whether the recents is currently running */
2372cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    public boolean isRecentsTopMost(ActivityManager.RunningTaskInfo topTask,
2382cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            AtomicBoolean isHomeTopMost) {
2392cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        if (topTask != null) {
2402cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            ComponentName topActivity = topTask.topActivity;
2412cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung
2422cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            // Check if the front most activity is recents
2432cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            if (topActivity.getPackageName().equals(Recents.sRecentsPackage) &&
2442cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                    topActivity.getClassName().equals(Recents.sRecentsActivity)) {
2452cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                if (isHomeTopMost != null) {
2462cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                    isHomeTopMost.set(false);
2472cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                }
2482cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                return true;
2492cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            }
2502cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung
2512cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            if (isHomeTopMost != null) {
2522cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                isHomeTopMost.set(isInHomeStack(topTask.id));
2532cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            }
2542cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        }
2552cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        return false;
2562cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    }
2572cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung
258ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne    /** Get the bounds of a stack / task. */
259ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne    public Rect getTaskBounds(int stackId) {
260ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne        ActivityManager.StackInfo info = getAllStackInfos().get(stackId);
261ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne        if (info != null)
2628aa7d161a11965cd75eace74e1bcf15421bbea18Skuhne          return info.bounds;
263ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne        return new Rect();
264d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
265d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
266ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne    /** Resize a given task. */
267ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne    public void resizeTask(int taskId, Rect bounds) {
268d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        if (mIam == null) return;
269d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
270d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        try {
271ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne            mIam.resizeTask(taskId, bounds);
272d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        } catch (RemoteException e) {
273d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            e.printStackTrace();
274d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        }
275d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
276d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
277d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    /** Returns the stack info for all stacks. */
278d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    public SparseArray<ActivityManager.StackInfo> getAllStackInfos() {
279d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        if (mIam == null) return new SparseArray<ActivityManager.StackInfo>();
280d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
281d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        try {
282d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            SparseArray<ActivityManager.StackInfo> stacks =
283d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung                    new SparseArray<ActivityManager.StackInfo>();
284d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            List<ActivityManager.StackInfo> infos = mIam.getAllStackInfos();
285d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            int stackCount = infos.size();
286d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            for (int i = 0; i < stackCount; i++) {
287d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung                ActivityManager.StackInfo info = infos.get(i);
288d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung                stacks.put(info.stackId, info);
289d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            }
290d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            return stacks;
291d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        } catch (RemoteException e) {
292d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            e.printStackTrace();
293d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            return new SparseArray<ActivityManager.StackInfo>();
294d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        }
295d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
296d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
297d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    /** Returns the focused stack id. */
298d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    public int getFocusedStack() {
299d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        if (mIam == null) return -1;
300d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
301d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        try {
302d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            return mIam.getFocusedStackId();
303d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        } catch (RemoteException e) {
304d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            e.printStackTrace();
305d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            return -1;
306d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        }
307d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
308d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
309a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns whether the specified task is in the home stack */
310a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public boolean isInHomeStack(int taskId) {
311a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return false;
312a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
313a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then just return false
314a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
315a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return false;
316a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
317a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
318a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        return mAm.isInHomeStack(taskId);
319a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
320a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
321a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns the top task thumbnail for the given task id */
322a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public Bitmap getTaskThumbnail(int taskId) {
323a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return null;
324a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
325a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then just return a dummy thumbnail
326a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
32785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            Bitmap thumbnail = Bitmap.createBitmap(mDummyThumbnailWidth, mDummyThumbnailHeight,
32885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    Bitmap.Config.ARGB_8888);
3296736905dc0e10689f7c63f6da43b31325caf966aWinson Chung            thumbnail.eraseColor(0xff333333);
330a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return thumbnail;
331a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
332a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
333ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        Bitmap thumbnail = SystemServicesProxy.getThumbnail(mAm, taskId);
334b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        if (thumbnail != null) {
335a91c293be26b2deb5434eb827a800fa0c80dc92cWinson Chung            thumbnail.setHasAlpha(false);
336b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            // We use a dumb heuristic for now, if the thumbnail is purely transparent in the top
337b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            // left pixel, then assume the whole thumbnail is transparent. Generally, proper
338b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            // screenshots are always composed onto a bitmap that has no alpha.
339b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            if (Color.alpha(thumbnail.getPixel(0, 0)) == 0) {
340b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                mBgProtectionCanvas.setBitmap(thumbnail);
341b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                mBgProtectionCanvas.drawRect(0, 0, thumbnail.getWidth(), thumbnail.getHeight(),
342b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                        mBgProtectionPaint);
343b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                mBgProtectionCanvas.setBitmap(null);
344b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                Log.e(TAG, "Invalid screenshot detected from getTaskThumbnail()");
345b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            }
346b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        }
347b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        return thumbnail;
348a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
349a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
350ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    /**
351ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     * Returns a task thumbnail from the activity manager
352ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     */
353ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    public static Bitmap getThumbnail(ActivityManager activityManager, int taskId) {
354ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        ActivityManager.TaskThumbnail taskThumbnail = activityManager.getTaskThumbnail(taskId);
35585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        if (taskThumbnail == null) return null;
35685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
357ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        Bitmap thumbnail = taskThumbnail.mainThumbnail;
358ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        ParcelFileDescriptor descriptor = taskThumbnail.thumbnailFileDescriptor;
359ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        if (thumbnail == null && descriptor != null) {
360aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn            thumbnail = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor(),
361aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn                    null, sBitmapOptions);
362ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        }
363ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        if (descriptor != null) {
364ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            try {
365ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung                descriptor.close();
366ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            } catch (IOException e) {
367ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            }
368ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        }
369ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        return thumbnail;
370ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    }
371ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
372d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    /** Moves a task to the front with the specified activity options. */
373a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public void moveTaskToFront(int taskId, ActivityOptions opts) {
374a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return;
375a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
376a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
377a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (opts != null) {
378a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME,
379a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                    opts.toBundle());
380a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        } else {
381a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME);
382a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
383a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
384a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
385d54b578e47fb410c776bb3a4272c2c523153f657Wale Ogunwale    /** Removes the task */
386d54b578e47fb410c776bb3a4272c2c523153f657Wale Ogunwale    public void removeTask(int taskId) {
387a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return;
388a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
389a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
390d54b578e47fb410c776bb3a4272c2c523153f657Wale Ogunwale        // Remove the task.
391d54b578e47fb410c776bb3a4272c2c523153f657Wale Ogunwale        mAm.removeTask(taskId);
392a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
393a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
3944f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    /**
3954f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     * Returns the activity info for a given component name.
396d54b578e47fb410c776bb3a4272c2c523153f657Wale Ogunwale     *
397f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     * @param cn The component name of the activity.
3984f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     * @param userId The userId of the user that this is for.
3994f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     */
4004f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
4014f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        if (mIpm == null) return null;
402814086db674d8eb298541b7e601e29c5c68e2074Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return new ActivityInfo();
403a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
404a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        try {
4054f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani            return mIpm.getActivityInfo(cn, PackageManager.GET_META_DATA, userId);
4064f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        } catch (RemoteException e) {
407a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            e.printStackTrace();
408a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return null;
409a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
410a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
411a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
412f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    /**
413f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     * Returns the activity info for a given component name.
414f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     *
415f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     * @param cn The component name of the activity.
416f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     */
417f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    public ActivityInfo getActivityInfo(ComponentName cn) {
418f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        if (mPm == null) return null;
419814086db674d8eb298541b7e601e29c5c68e2074Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return new ActivityInfo();
420f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
421f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        try {
422f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
423f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        } catch (PackageManager.NameNotFoundException e) {
424f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            e.printStackTrace();
425f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            return null;
426f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
427f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
428f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
429a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns the activity label */
430a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public String getActivityLabel(ActivityInfo info) {
431a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mPm == null) return null;
432a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
433a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then return a mock label
434a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
435a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return "Recent Task";
436a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
437a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
438a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        return info.loadLabel(mPm).toString();
439a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
440a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
441b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    /** Returns the application label */
442b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    public String getApplicationLabel(Intent baseIntent, int userId) {
443b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        if (mPm == null) return null;
444b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
445b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        // If we are mocking, then return a mock label
446b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
447b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz            return "Recent Task";
448b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        }
449b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
450b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        ResolveInfo ri = mPm.resolveActivityAsUser(baseIntent, 0, userId);
451b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        CharSequence label = (ri != null) ? ri.loadLabel(mPm) : null;
452b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        return (label != null) ? label.toString() : null;
453b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    }
454b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
455b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    /** Returns the content description for a given task */
456b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    public String getContentDescription(Intent baseIntent, int userId, String activityLabel,
457b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz            Resources res) {
458b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        String applicationLabel = getApplicationLabel(baseIntent, userId);
459b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        if (applicationLabel == null) {
460b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz            return getBadgedLabel(activityLabel, userId);
461b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        }
462b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
463b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        return applicationLabel.equals(activityLabel) ? badgedApplicationLabel
464b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz                : res.getString(R.string.accessibility_recents_task_header,
465b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz                        badgedApplicationLabel, activityLabel);
466b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    }
467b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
4684f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    /**
4694f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     * Returns the activity icon for the ActivityInfo for a user, badging if
4704f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     * necessary.
4714f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     */
4724f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    public Drawable getActivityIcon(ActivityInfo info, int userId) {
473c7d62f02b8acfd0a6b31f8544ec2c07e780fe4bbSvetoslav        if (mPm == null) return null;
474a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
475a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then return a mock label
476a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
4772f2ca08baa072376b3dfd60506625496aa05903fWinson Chung            return new ColorDrawable(0xFF666666);
478a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
479a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
4804f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        Drawable icon = info.loadIcon(mPm);
4816507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee        return getBadgedIcon(icon, userId);
4826507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee    }
4836507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee
4846507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee    /**
4856507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee     * Returns the given icon for a user, badging if necessary.
4866507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee     */
4876507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee    public Drawable getBadgedIcon(Drawable icon, int userId) {
4884f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        if (userId != UserHandle.myUserId()) {
489fdf169cbea5c59c6f74c25c6c529d8a19c6cb78cAmith Yamasani            icon = mPm.getUserBadgedIcon(icon, new UserHandle(userId));
4904f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        }
4914f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        return icon;
492a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
493ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung
494b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    /**
495b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz     * Returns the given label for a user, badging if necessary.
496b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz     */
497b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    public String getBadgedLabel(String label, int userId) {
498b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        if (userId != UserHandle.myUserId()) {
499b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz            label = mPm.getUserBadgedLabel(label, new UserHandle(userId)).toString();
500b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        }
501b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        return label;
502b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    }
503b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
504bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    /** Returns the package name of the home activity. */
505bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    public String getHomeActivityPackageName() {
506bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (mPm == null) return null;
507bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
508bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung
509bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
510bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        ComponentName defaultHomeActivity = mPm.getHomeActivities(homeActivities);
511bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (defaultHomeActivity != null) {
512bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung            return defaultHomeActivity.getPackageName();
513bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        } else if (homeActivities.size() == 1) {
514bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung            ResolveInfo info = homeActivities.get(0);
515bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung            if (info.activityInfo != null) {
516bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung                return info.activityInfo.packageName;
517bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung            }
518bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        }
519bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        return null;
520bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    }
521bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung
5222002cf5b463737e7f615f1469cb20d324c283544Winson Chung    /**
5232002cf5b463737e7f615f1469cb20d324c283544Winson Chung     * Returns whether the foreground user is the owner.
5242002cf5b463737e7f615f1469cb20d324c283544Winson Chung     */
5252002cf5b463737e7f615f1469cb20d324c283544Winson Chung    public boolean isForegroundUserOwner() {
5262002cf5b463737e7f615f1469cb20d324c283544Winson Chung        if (mAm == null) return false;
5272002cf5b463737e7f615f1469cb20d324c283544Winson Chung
5282002cf5b463737e7f615f1469cb20d324c283544Winson Chung        return mAm.getCurrentUser() == UserHandle.USER_OWNER;
5292002cf5b463737e7f615f1469cb20d324c283544Winson Chung    }
5302002cf5b463737e7f615f1469cb20d324c283544Winson Chung
531ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung    /**
532bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung     * Resolves and returns the first Recents widget from the same package as the global
533bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung     * assist activity.
534ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung     */
535bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    public AppWidgetProviderInfo resolveSearchAppWidget() {
536f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        if (mAwm == null) return null;
537da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        if (mAssistComponent == null) return null;
538ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung
539da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        // Find the first Recents widget from the same package as the global assist activity
540da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders(
541ee0b12161ab8563378e33e9d694d15ed1a757a26Winson Chung                AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
542f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        for (AppWidgetProviderInfo info : widgets) {
543da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung            if (info.provider.getPackageName().equals(mAssistComponent.getPackageName())) {
544bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung                return info;
545f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            }
546f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
547bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        return null;
548bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    }
549bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung
550bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    /**
551bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung     * Resolves and binds the search app widget that is to appear in the recents.
552bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung     */
553bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    public Pair<Integer, AppWidgetProviderInfo> bindSearchAppWidget(AppWidgetHost host) {
554bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (mAwm == null) return null;
555bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (mAssistComponent == null) return null;
556bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung
557bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        // Find the first Recents widget from the same package as the global assist activity
558bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        AppWidgetProviderInfo searchWidgetInfo = resolveSearchAppWidget();
559f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
560f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        // Return early if there is no search widget
561f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        if (searchWidgetInfo == null) return null;
562f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
563f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        // Allocate a new widget id and try and bind the app widget (if that fails, then just skip)
564f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        int searchWidgetId = host.allocateAppWidgetId();
565f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        Bundle opts = new Bundle();
566f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
567ee0b12161ab8563378e33e9d694d15ed1a757a26Winson Chung                AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
568f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, searchWidgetInfo.provider, opts)) {
569044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung            host.deleteAppWidgetId(searchWidgetId);
570f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            return null;
571f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
572f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        return new Pair<Integer, AppWidgetProviderInfo>(searchWidgetId, searchWidgetInfo);
573f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
574f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
575f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    /**
576f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     * Returns the app widget info for the specified app widget id.
577f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     */
578f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
579f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        if (mAwm == null) return null;
580f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
581f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        return mAwm.getAppWidgetInfo(appWidgetId);
582f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
583f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
584f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    /**
585f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     * Destroys the specified app widget.
586f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     */
587f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    public void unbindSearchAppWidget(AppWidgetHost host, int appWidgetId) {
588f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        if (mAwm == null) return;
589f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
590f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        // Delete the app widget
591f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        host.deleteAppWidgetId(appWidgetId);
592ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung    }
593d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
594d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    /**
595ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung     * Returns whether touch exploration is currently enabled.
596ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung     */
597ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung    public boolean isTouchExplorationEnabled() {
598ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung        if (mAccm == null) return false;
599ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung
600ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung        return mAccm.isEnabled() && mAccm.isTouchExplorationEnabled();
601ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung    }
602ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung
603ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung    /**
60456e09b42a0f1670970872bef611a8036904ad6bfJason Monk     * Returns a global setting.
60556e09b42a0f1670970872bef611a8036904ad6bfJason Monk     */
60656e09b42a0f1670970872bef611a8036904ad6bfJason Monk    public int getGlobalSetting(Context context, String setting) {
60756e09b42a0f1670970872bef611a8036904ad6bfJason Monk        ContentResolver cr = context.getContentResolver();
60856e09b42a0f1670970872bef611a8036904ad6bfJason Monk        return Settings.Global.getInt(cr, setting, 0);
60956e09b42a0f1670970872bef611a8036904ad6bfJason Monk    }
61056e09b42a0f1670970872bef611a8036904ad6bfJason Monk
61156e09b42a0f1670970872bef611a8036904ad6bfJason Monk    /**
61256e09b42a0f1670970872bef611a8036904ad6bfJason Monk     * Returns a system setting.
61356e09b42a0f1670970872bef611a8036904ad6bfJason Monk     */
61456e09b42a0f1670970872bef611a8036904ad6bfJason Monk    public int getSystemSetting(Context context, String setting) {
61556e09b42a0f1670970872bef611a8036904ad6bfJason Monk        ContentResolver cr = context.getContentResolver();
61656e09b42a0f1670970872bef611a8036904ad6bfJason Monk        return Settings.System.getInt(cr, setting, 0);
61756e09b42a0f1670970872bef611a8036904ad6bfJason Monk    }
61856e09b42a0f1670970872bef611a8036904ad6bfJason Monk
61956e09b42a0f1670970872bef611a8036904ad6bfJason Monk    /**
620d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung     * Returns a system property.
621d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung     */
622d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    public String getSystemProperty(String key) {
623d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        return SystemProperties.get(key);
624d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
625d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
626d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    /**
627ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     * Returns the window rect.
628ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     */
629ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    public Rect getWindowRect() {
630ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        Rect windowRect = new Rect();
631ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        if (mWm == null) return windowRect;
632ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
633dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        Point p = new Point();
634dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        mWm.getDefaultDisplay().getRealSize(p);
635dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        windowRect.set(0, 0, p.x, p.y);
636ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        return windowRect;
637ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    }
638ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
639ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    /**
640d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung     * Takes a screenshot of the current surface.
641d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung     */
642d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    public Bitmap takeScreenshot() {
643d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        DisplayInfo di = new DisplayInfo();
644d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mDisplay.getDisplayInfo(di);
645d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        return SurfaceControl.screenshot(di.getNaturalWidth(), di.getNaturalHeight());
646d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    }
647ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
648ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    /**
649ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     * Takes a screenshot of the current app.
650ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     */
651ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    public Bitmap takeAppScreenshot() {
652ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        return takeScreenshot();
653ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    }
654dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner
6554e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung    /** Starts an activity from recents. */
6564e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung    public boolean startActivityFromRecents(Context context, int taskId, String taskName,
6574e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung            ActivityOptions options) {
658dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner        if (mIam != null) {
659dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner            try {
660dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner                mIam.startActivityFromRecents(taskId, options == null ? null : options.toBundle());
6614e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung                return true;
6624e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung            } catch (Exception e) {
6634e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung                Console.logError(context,
6644e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung                        context.getString(R.string.recents_launch_error_message, taskName));
665dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner            }
666dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner        }
6674e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung        return false;
668dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner    }
669044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung
670044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung    /** Starts an in-place animation on the front most application windows. */
671044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung    public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts) {
672044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung        if (mIam == null) return;
673044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung
674044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung        try {
675044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung            mIam.startInPlaceAnimationOnFrontMostApplication(opts);
676044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung        } catch (Exception e) {
677044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung            e.printStackTrace();
678044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung        }
679044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung    }
680740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung
681740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung    /** Registers a task stack listener with the system. */
682740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung    public void registerTaskStackListener(ITaskStackListener listener) {
683740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        if (mIam == null) return;
684740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung
685740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        try {
686740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung            mIam.registerTaskStackListener(listener);
687740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        } catch (Exception e) {
688740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung            e.printStackTrace();
689740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        }
690740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung    }
691a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung}
692