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;
51c35e670d5386eb6388eb4e65746b950265312e7aWinson Chungimport android.os.Handler;
52c35e670d5386eb6388eb4e65746b950265312e7aWinson Chungimport android.os.HandlerThread;
53ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport android.os.ParcelFileDescriptor;
544f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasaniimport android.os.RemoteException;
55d16c565a607de754379fe699a4def21bd0e3de2fWinson Chungimport android.os.SystemProperties;
564f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasaniimport android.os.UserHandle;
57165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggiimport android.os.UserManager;
5856e09b42a0f1670970872bef611a8036904ad6bfJason Monkimport android.provider.Settings;
59b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chungimport android.util.Log;
60e1e20e11a758ee82753e8052773664823ca74746Winson Chungimport android.util.MutableBoolean;
61f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chungimport android.util.Pair;
62d16c565a607de754379fe699a4def21bd0e3de2fWinson Chungimport android.util.SparseArray;
63d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport android.view.Display;
64d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport android.view.DisplayInfo;
65d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport android.view.SurfaceControl;
66d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chungimport android.view.WindowManager;
67ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chungimport android.view.accessibility.AccessibilityManager;
68165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi
69165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggiimport com.android.internal.app.AssistUtils;
70af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chungimport com.android.systemui.Prefs;
714e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chungimport com.android.systemui.R;
72ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport com.android.systemui.recents.Constants;
732cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chungimport com.android.systemui.recents.Recents;
74af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chungimport com.android.systemui.recents.RecentsAppWidgetHost;
75a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
76ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chungimport java.io.IOException;
77a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport java.util.ArrayList;
78918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chungimport java.util.Iterator;
79a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungimport java.util.List;
805e3e5d8945249cfeb8bd59de112be88954ba62bfWinson Chungimport java.util.Random;
81a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
82a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung/**
83a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * Acts as a shim around the real system services that we need to access data from, and provides
84a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung * a point of injection when testing UI.
85a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung */
86a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chungpublic class SystemServicesProxy {
87b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung    final static String TAG = "SystemServicesProxy";
88b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung
89aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn    final static BitmapFactory.Options sBitmapOptions;
90c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung    final static HandlerThread sBgThread;
91c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung
92c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung    static {
93c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung        sBgThread = new HandlerThread("Recents-SystemServicesProxy",
94c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung                android.os.Process.THREAD_PRIORITY_BACKGROUND);
95c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung        sBgThread.start();
96c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung        sBitmapOptions = new BitmapFactory.Options();
97c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung        sBitmapOptions.inMutable = true;
98c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung    }
99aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn
100ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung    AccessibilityManager mAccm;
101a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    ActivityManager mAm;
1021f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung    IActivityManager mIam;
103f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    AppWidgetManager mAwm;
104a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    PackageManager mPm;
1054f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    IPackageManager mIpm;
106165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi    AssistUtils mAssistUtils;
107d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    WindowManager mWm;
108d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    Display mDisplay;
109918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung    String mRecentsPackage;
110da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung    ComponentName mAssistComponent;
111a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
112c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung    Handler mBgThreadHandler;
113c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung
114a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    Bitmap mDummyIcon;
11585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    int mDummyThumbnailWidth;
11685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung    int mDummyThumbnailHeight;
117b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung    Paint mBgProtectionPaint;
118b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung    Canvas mBgProtectionCanvas;
119a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
120a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Private constructor */
121a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public SystemServicesProxy(Context context) {
122ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung        mAccm = AccessibilityManager.getInstance(context);
123a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
1241f24c7e37bc794057a156a730c7e4b53b01212edWinson Chung        mIam = ActivityManagerNative.getDefault();
125f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        mAwm = AppWidgetManager.getInstance(context);
126a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        mPm = context.getPackageManager();
1274f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        mIpm = AppGlobals.getPackageManager();
128165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi        mAssistUtils = new AssistUtils(context);
129d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mWm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
130d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung        mDisplay = mWm.getDefaultDisplay();
131918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        mRecentsPackage = context.getPackageName();
132c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung        mBgThreadHandler = new Handler(sBgThread.getLooper());
133a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
13485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        // Get the dummy thumbnail width/heights
13585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        Resources res = context.getResources();
13685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        int wId = com.android.internal.R.dimen.thumbnail_width;
13785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        int hId = com.android.internal.R.dimen.thumbnail_height;
13885cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        mDummyThumbnailWidth = res.getDimensionPixelSize(wId);
13985cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        mDummyThumbnailHeight = res.getDimensionPixelSize(hId);
14085cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
141b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        // Create the protection paints
142b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        mBgProtectionPaint = new Paint();
143b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        mBgProtectionPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_ATOP));
144b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        mBgProtectionPaint.setColor(0xFFffffff);
145b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        mBgProtectionCanvas = new Canvas();
146b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung
147da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        // Resolve the assist intent
148165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi        mAssistComponent = mAssistUtils.getAssistComponentForUser(UserHandle.myUserId());
149da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung
150a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
151a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            // Create a dummy icon
1522f2ca08baa072376b3dfd60506625496aa05903fWinson Chung            mDummyIcon = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
1536736905dc0e10689f7c63f6da43b31325caf966aWinson Chung            mDummyIcon.eraseColor(0xFF999999);
154a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
155a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
156a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
157a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns a list of the recents tasks */
1589cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung    public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId,
1599cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung            boolean isTopTaskHome) {
160a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return null;
161a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
162a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then create some recent tasks
163a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
164a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            ArrayList<ActivityManager.RecentTaskInfo> tasks =
165a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                    new ArrayList<ActivityManager.RecentTaskInfo>();
166918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            int count = Math.min(numLatestTasks, Constants.DebugFlags.App.SystemServicesProxyMockTaskCount);
167a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            for (int i = 0; i < count; i++) {
168a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                // Create a dummy component name
169a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                int packageIndex = i % Constants.DebugFlags.App.SystemServicesProxyMockPackageCount;
170a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                ComponentName cn = new ComponentName("com.android.test" + packageIndex,
171a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                        "com.android.test" + i + ".Activity");
172a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                String description = "" + i + " - " +
173a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                        Long.toString(Math.abs(new Random().nextLong()), 36);
174a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                // Create the recent task info
175a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                ActivityManager.RecentTaskInfo rti = new ActivityManager.RecentTaskInfo();
176a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                rti.id = rti.persistentId = i;
177a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                rti.baseIntent = new Intent();
178a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                rti.baseIntent.setComponent(cn);
179a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                rti.description = description;
180ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung                rti.firstActiveTime = rti.lastActiveTime = i;
1815e3e5d8945249cfeb8bd59de112be88954ba62bfWinson Chung                if (i % 2 == 0) {
182a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                    rti.taskDescription = new ActivityManager.TaskDescription(description,
18310f8139d3b8dd7cd08a2fc688285b3b74a34f0dbWinson Chung                        Bitmap.createBitmap(mDummyIcon),
18410f8139d3b8dd7cd08a2fc688285b3b74a34f0dbWinson Chung                        0xFF000000 | (0xFFFFFF & new Random().nextInt()));
185a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                } else {
186a449dc033b79775b8945d9cc5a035a6deb145065Winson Chung                    rti.taskDescription = new ActivityManager.TaskDescription();
1875e3e5d8945249cfeb8bd59de112be88954ba62bfWinson Chung                }
188a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                tasks.add(rti);
189a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            }
190a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return tasks;
191a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
192a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
193918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        // Remove home/recents/excluded tasks
194918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        int minNumTasksToQuery = 10;
195918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        int numTasksToQuery = Math.max(minNumTasksToQuery, numLatestTasks);
196918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        List<ActivityManager.RecentTaskInfo> tasks = mAm.getRecentTasksForUser(numTasksToQuery,
197a4ccb86ddc8f9f486aee25fb836f4aff97bf7679Winson Chung                ActivityManager.RECENT_IGNORE_HOME_STACK_TASKS |
198a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                ActivityManager.RECENT_IGNORE_UNAVAILABLE |
199918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                ActivityManager.RECENT_INCLUDE_PROFILES |
200918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                ActivityManager.RECENT_WITH_EXCLUDED, userId);
2014298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung
2024298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung        // Break early if we can't get a valid set of tasks
2034298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung        if (tasks == null) {
204e1e20e11a758ee82753e8052773664823ca74746Winson Chung            return new ArrayList<>();
2054298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung        }
2064298b43592966b9b620866bb3da1ab3f9ed2e668Winson Chung
207918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        boolean isFirstValidTask = true;
208918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
209918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        while (iter.hasNext()) {
210918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            ActivityManager.RecentTaskInfo t = iter.next();
211918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung
212918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            // NOTE: The order of these checks happens in the expected order of the traversal of the
213918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            // tasks
214918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung
215918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            // Check the first non-recents task, include this task even if it is marked as excluded
2169cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung            // from recents if we are currently in the app.  In other words, only remove excluded
2179cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung            // tasks if it is not the first active task.
218918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
219918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                    == Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
2209cb5c4e3854aa7f2ddab707920b688c3108cbc85Winson Chung            if (isExcluded && (isTopTaskHome || !isFirstValidTask)) {
221918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                iter.remove();
222918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung                continue;
223918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            }
224918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung            isFirstValidTask = false;
225918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        }
226918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung
227918c0723a169cef46b8bf59c06fd3bb8021d0defWinson Chung        return tasks.subList(0, Math.min(tasks.size(), numLatestTasks));
228a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
229a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
230a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns a list of the running tasks */
2312cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    private List<ActivityManager.RunningTaskInfo> getRunningTasks(int numTasks) {
232a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return null;
233a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        return mAm.getRunningTasks(numTasks);
234a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
235a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
2362cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    /** Returns the top task. */
2372cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    public ActivityManager.RunningTaskInfo getTopMostTask() {
2382cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        List<ActivityManager.RunningTaskInfo> tasks = getRunningTasks(1);
23965c294036bd3a01af0755519d37ef7e9f64b9fb9Winson Chung        if (tasks != null && !tasks.isEmpty()) {
2402cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            return tasks.get(0);
2412cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        }
2422cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        return null;
2432cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    }
2442cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung
2452cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    /** Returns whether the recents is currently running */
2462cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    public boolean isRecentsTopMost(ActivityManager.RunningTaskInfo topTask,
247e1e20e11a758ee82753e8052773664823ca74746Winson Chung            MutableBoolean isHomeTopMost) {
2482cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        if (topTask != null) {
2492cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            ComponentName topActivity = topTask.topActivity;
2502cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung
2512cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            // Check if the front most activity is recents
2522cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            if (topActivity.getPackageName().equals(Recents.sRecentsPackage) &&
2532cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                    topActivity.getClassName().equals(Recents.sRecentsActivity)) {
2542cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                if (isHomeTopMost != null) {
255e1e20e11a758ee82753e8052773664823ca74746Winson Chung                    isHomeTopMost.value = false;
2562cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                }
2572cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung                return true;
2582cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            }
2592cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung
2602cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            if (isHomeTopMost != null) {
261e1e20e11a758ee82753e8052773664823ca74746Winson Chung                isHomeTopMost.value = isInHomeStack(topTask.id);
2622cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung            }
2632cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        }
2642cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung        return false;
2652cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung    }
2662cf8b221fca18dbee3703388ae7970491c86ec7fWinson Chung
267ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne    /** Get the bounds of a stack / task. */
268ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne    public Rect getTaskBounds(int stackId) {
269ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne        ActivityManager.StackInfo info = getAllStackInfos().get(stackId);
270ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne        if (info != null)
2718aa7d161a11965cd75eace74e1bcf15421bbea18Skuhne          return info.bounds;
272ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne        return new Rect();
273d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
274d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
275ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne    /** Resize a given task. */
276ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne    public void resizeTask(int taskId, Rect bounds) {
277d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        if (mIam == null) return;
278d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
279d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        try {
280ece738b5bc532d90bbdc42d0b5b63701c773a6f9Skuhne            mIam.resizeTask(taskId, bounds);
281d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        } catch (RemoteException e) {
282d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            e.printStackTrace();
283d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        }
284d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
285d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
286d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    /** Returns the stack info for all stacks. */
287d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    public SparseArray<ActivityManager.StackInfo> getAllStackInfos() {
288d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        if (mIam == null) return new SparseArray<ActivityManager.StackInfo>();
289d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
290d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        try {
291d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            SparseArray<ActivityManager.StackInfo> stacks =
292d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung                    new SparseArray<ActivityManager.StackInfo>();
293d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            List<ActivityManager.StackInfo> infos = mIam.getAllStackInfos();
294d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            int stackCount = infos.size();
295d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            for (int i = 0; i < stackCount; i++) {
296d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung                ActivityManager.StackInfo info = infos.get(i);
297d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung                stacks.put(info.stackId, info);
298d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            }
299d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            return stacks;
300d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        } catch (RemoteException e) {
301d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            e.printStackTrace();
302d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            return new SparseArray<ActivityManager.StackInfo>();
303d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        }
304d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
305d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
306d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    /** Returns the focused stack id. */
307d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    public int getFocusedStack() {
308d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        if (mIam == null) return -1;
309d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
310d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        try {
311d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            return mIam.getFocusedStackId();
312d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        } catch (RemoteException e) {
313d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            e.printStackTrace();
314d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung            return -1;
315d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        }
316d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
317d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
318a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns whether the specified task is in the home stack */
319a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public boolean isInHomeStack(int taskId) {
320a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return false;
321a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
322a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then just return false
323a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
324a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return false;
325a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
326a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
327a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        return mAm.isInHomeStack(taskId);
328a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
329a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
330a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns the top task thumbnail for the given task id */
331a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public Bitmap getTaskThumbnail(int taskId) {
332a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return null;
333a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
334a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then just return a dummy thumbnail
335a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
33685cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung            Bitmap thumbnail = Bitmap.createBitmap(mDummyThumbnailWidth, mDummyThumbnailHeight,
33785cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung                    Bitmap.Config.ARGB_8888);
3386736905dc0e10689f7c63f6da43b31325caf966aWinson Chung            thumbnail.eraseColor(0xff333333);
339a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return thumbnail;
340a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
341a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
342ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        Bitmap thumbnail = SystemServicesProxy.getThumbnail(mAm, taskId);
343b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        if (thumbnail != null) {
344a91c293be26b2deb5434eb827a800fa0c80dc92cWinson Chung            thumbnail.setHasAlpha(false);
345b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            // We use a dumb heuristic for now, if the thumbnail is purely transparent in the top
346b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            // left pixel, then assume the whole thumbnail is transparent. Generally, proper
347b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            // screenshots are always composed onto a bitmap that has no alpha.
348b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            if (Color.alpha(thumbnail.getPixel(0, 0)) == 0) {
349b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                mBgProtectionCanvas.setBitmap(thumbnail);
350b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                mBgProtectionCanvas.drawRect(0, 0, thumbnail.getWidth(), thumbnail.getHeight(),
351b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                        mBgProtectionPaint);
352b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                mBgProtectionCanvas.setBitmap(null);
353b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung                Log.e(TAG, "Invalid screenshot detected from getTaskThumbnail()");
354b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung            }
355b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        }
356b5ddfc375616bf7dbe9f4ff85ad124f02cc5990fWinson Chung        return thumbnail;
357a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
358a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
359ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    /**
360ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     * Returns a task thumbnail from the activity manager
361ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     */
362ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    public static Bitmap getThumbnail(ActivityManager activityManager, int taskId) {
363ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        ActivityManager.TaskThumbnail taskThumbnail = activityManager.getTaskThumbnail(taskId);
36485cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung        if (taskThumbnail == null) return null;
36585cfec811e35025dbde54f4dc09fe0e1337c36b8Winson Chung
366ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        Bitmap thumbnail = taskThumbnail.mainThumbnail;
367ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        ParcelFileDescriptor descriptor = taskThumbnail.thumbnailFileDescriptor;
368ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        if (thumbnail == null && descriptor != null) {
369aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn            thumbnail = BitmapFactory.decodeFileDescriptor(descriptor.getFileDescriptor(),
370aec68bb89fe614181a20eb97340149406218ce2fDianne Hackborn                    null, sBitmapOptions);
371ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        }
372ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        if (descriptor != null) {
373ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            try {
374ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung                descriptor.close();
375ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            } catch (IOException e) {
376ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung            }
377ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        }
378ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        return thumbnail;
379ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    }
380ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
381d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    /** Moves a task to the front with the specified activity options. */
382a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public void moveTaskToFront(int taskId, ActivityOptions opts) {
383a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return;
384a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
385a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
386a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (opts != null) {
387a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME,
388a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung                    opts.toBundle());
389a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        } else {
390a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            mAm.moveTaskToFront(taskId, ActivityManager.MOVE_TASK_WITH_HOME);
391a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
392a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
393a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
394d54b578e47fb410c776bb3a4272c2c523153f657Wale Ogunwale    /** Removes the task */
395c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung    public void removeTask(final int taskId) {
396a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mAm == null) return;
397a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return;
398a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
399d54b578e47fb410c776bb3a4272c2c523153f657Wale Ogunwale        // Remove the task.
400c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung        mBgThreadHandler.post(new Runnable() {
401c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung            @Override
402c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung            public void run() {
403c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung                mAm.removeTask(taskId);
404c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung            }
405c35e670d5386eb6388eb4e65746b950265312e7aWinson Chung        });
406a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
407a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
4084f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    /**
4094f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     * Returns the activity info for a given component name.
410d54b578e47fb410c776bb3a4272c2c523153f657Wale Ogunwale     *
411f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     * @param cn The component name of the activity.
4124f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     * @param userId The userId of the user that this is for.
4134f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     */
4144f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
4154f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        if (mIpm == null) return null;
416814086db674d8eb298541b7e601e29c5c68e2074Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return new ActivityInfo();
417a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
418a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        try {
4194f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani            return mIpm.getActivityInfo(cn, PackageManager.GET_META_DATA, userId);
4204f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        } catch (RemoteException e) {
421a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            e.printStackTrace();
422a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return null;
423a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
424a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
425a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
426f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    /**
427f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     * Returns the activity info for a given component name.
428f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     *
429f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     * @param cn The component name of the activity.
430f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung     */
431f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    public ActivityInfo getActivityInfo(ComponentName cn) {
432f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        if (mPm == null) return null;
433814086db674d8eb298541b7e601e29c5c68e2074Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return new ActivityInfo();
434f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
435f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        try {
436f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
437f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        } catch (PackageManager.NameNotFoundException e) {
438f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            e.printStackTrace();
439f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            return null;
440f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
441f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung    }
442f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung
443a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    /** Returns the activity label */
444a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    public String getActivityLabel(ActivityInfo info) {
445a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (mPm == null) return null;
446a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
447a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then return a mock label
448a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
449a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung            return "Recent Task";
450a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
451a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
452a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        return info.loadLabel(mPm).toString();
453a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
454a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
455b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    /** Returns the application label */
456b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    public String getApplicationLabel(Intent baseIntent, int userId) {
457b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        if (mPm == null) return null;
458b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
459b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        // If we are mocking, then return a mock label
460b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
461b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz            return "Recent Task";
462b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        }
463b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
464b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        ResolveInfo ri = mPm.resolveActivityAsUser(baseIntent, 0, userId);
465b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        CharSequence label = (ri != null) ? ri.loadLabel(mPm) : null;
466b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        return (label != null) ? label.toString() : null;
467b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    }
468b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
469b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    /** Returns the content description for a given task */
470b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    public String getContentDescription(Intent baseIntent, int userId, String activityLabel,
471b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz            Resources res) {
472b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        String applicationLabel = getApplicationLabel(baseIntent, userId);
473b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        if (applicationLabel == null) {
474b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz            return getBadgedLabel(activityLabel, userId);
475b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        }
476b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
477b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        return applicationLabel.equals(activityLabel) ? badgedApplicationLabel
478b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz                : res.getString(R.string.accessibility_recents_task_header,
479b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz                        badgedApplicationLabel, activityLabel);
480b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    }
481b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
4824f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    /**
4834f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     * Returns the activity icon for the ActivityInfo for a user, badging if
4844f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     * necessary.
4854f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani     */
4864f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani    public Drawable getActivityIcon(ActivityInfo info, int userId) {
487c7d62f02b8acfd0a6b31f8544ec2c07e780fe4bbSvetoslav        if (mPm == null) return null;
488a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
489a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        // If we are mocking, then return a mock label
490a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
4912f2ca08baa072376b3dfd60506625496aa05903fWinson Chung            return new ColorDrawable(0xFF666666);
492a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung        }
493a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung
4944f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        Drawable icon = info.loadIcon(mPm);
4956507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee        return getBadgedIcon(icon, userId);
4966507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee    }
4976507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee
4986507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee    /**
4996507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee     * Returns the given icon for a user, badging if necessary.
5006507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee     */
5016507f2e03a90244e08fb62f9b55653ba3230d0b7Robin Lee    public Drawable getBadgedIcon(Drawable icon, int userId) {
5024f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        if (userId != UserHandle.myUserId()) {
503fdf169cbea5c59c6f74c25c6c529d8a19c6cb78cAmith Yamasani            icon = mPm.getUserBadgedIcon(icon, new UserHandle(userId));
5044f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        }
5054f0a49e6b9ad1b00972dbe8a751263aa6c482538Amith Yamasani        return icon;
506a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung    }
507ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung
508b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    /**
509b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz     * Returns the given label for a user, badging if necessary.
510b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz     */
511b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    public String getBadgedLabel(String label, int userId) {
512b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        if (userId != UserHandle.myUserId()) {
513b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz            label = mPm.getUserBadgedLabel(label, new UserHandle(userId)).toString();
514b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        }
515b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz        return label;
516b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz    }
517b7a42fda313b6e5d5e82591ea9fb5d1b30acfc55Benjamin Franz
518bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    /** Returns the package name of the home activity. */
519bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    public String getHomeActivityPackageName() {
520bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (mPm == null) return null;
521bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
522bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung
523bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        ArrayList<ResolveInfo> homeActivities = new ArrayList<ResolveInfo>();
524bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        ComponentName defaultHomeActivity = mPm.getHomeActivities(homeActivities);
525bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (defaultHomeActivity != null) {
526bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung            return defaultHomeActivity.getPackageName();
527bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        } else if (homeActivities.size() == 1) {
528bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung            ResolveInfo info = homeActivities.get(0);
529bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung            if (info.activityInfo != null) {
530bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung                return info.activityInfo.packageName;
531bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung            }
532bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        }
533bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        return null;
534bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    }
535bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung
5362002cf5b463737e7f615f1469cb20d324c283544Winson Chung    /**
5372002cf5b463737e7f615f1469cb20d324c283544Winson Chung     * Returns whether the foreground user is the owner.
5382002cf5b463737e7f615f1469cb20d324c283544Winson Chung     */
5392002cf5b463737e7f615f1469cb20d324c283544Winson Chung    public boolean isForegroundUserOwner() {
5402002cf5b463737e7f615f1469cb20d324c283544Winson Chung        if (mAm == null) return false;
5412002cf5b463737e7f615f1469cb20d324c283544Winson Chung
5422002cf5b463737e7f615f1469cb20d324c283544Winson Chung        return mAm.getCurrentUser() == UserHandle.USER_OWNER;
5432002cf5b463737e7f615f1469cb20d324c283544Winson Chung    }
5442002cf5b463737e7f615f1469cb20d324c283544Winson Chung
545ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung    /**
546af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung     * Returns the current search widget id.
547ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung     */
548af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung    public int getSearchAppWidgetId(Context context) {
549af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        return Prefs.getInt(context, Prefs.Key.SEARCH_APP_WIDGET_ID, -1);
550af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung    }
551af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung
552af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung    /**
553af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung     * Returns the current search widget info, binding a new one if necessary.
554af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung     */
555af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung    public AppWidgetProviderInfo getOrBindSearchAppWidget(Context context, AppWidgetHost host) {
556af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        int searchWidgetId = Prefs.getInt(context, Prefs.Key.SEARCH_APP_WIDGET_ID, -1);
557af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        AppWidgetProviderInfo searchWidgetInfo = mAwm.getAppWidgetInfo(searchWidgetId);
558af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        AppWidgetProviderInfo resolvedSearchWidgetInfo = resolveSearchAppWidget();
559af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung
560af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        // Return the search widget info if it hasn't changed
561af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        if (searchWidgetInfo != null && resolvedSearchWidgetInfo != null &&
562af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung                searchWidgetInfo.provider.equals(resolvedSearchWidgetInfo.provider)) {
563af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung            if (Prefs.getString(context, Prefs.Key.SEARCH_APP_WIDGET_PACKAGE, null) == null) {
564af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung                Prefs.putString(context, Prefs.Key.SEARCH_APP_WIDGET_PACKAGE,
565af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung                        searchWidgetInfo.provider.getPackageName());
566af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung            }
567af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung            return searchWidgetInfo;
568af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        }
569af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung
570af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        // Delete the old widget
571af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        if (searchWidgetId != -1) {
572af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung            host.deleteAppWidgetId(searchWidgetId);
573af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        }
574af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung
575af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        // And rebind a new search widget
576af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        if (resolvedSearchWidgetInfo != null) {
577af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung            Pair<Integer, AppWidgetProviderInfo> widgetInfo = bindSearchAppWidget(host,
578af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung                    resolvedSearchWidgetInfo);
579af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung            if (widgetInfo != null) {
580af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung                Prefs.putInt(context, Prefs.Key.SEARCH_APP_WIDGET_ID, widgetInfo.first);
581af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung                Prefs.putString(context, Prefs.Key.SEARCH_APP_WIDGET_PACKAGE,
582af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung                        widgetInfo.second.provider.getPackageName());
583af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung                return widgetInfo.second;
584af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung            }
585af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        }
586af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung
587af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        // If we fall through here, then there is no resolved search widget, so clear the state
588af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        Prefs.remove(context, Prefs.Key.SEARCH_APP_WIDGET_ID);
589af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        Prefs.remove(context, Prefs.Key.SEARCH_APP_WIDGET_PACKAGE);
590af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        return null;
591af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung    }
592ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung
593af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung    /**
594af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung     * Returns the first Recents widget from the same package as the global assist activity.
595af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung     */
596af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung    private AppWidgetProviderInfo resolveSearchAppWidget() {
597165ce066b701ba0153000f0692bfc7032655d17dJorim Jaggi        if (mAssistComponent == null) return null;
598da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung        List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders(
599ee0b12161ab8563378e33e9d694d15ed1a757a26Winson Chung                AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
600f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        for (AppWidgetProviderInfo info : widgets) {
601da5b84c8d38d8322b5bb7d22653625bb51734a4eWinson Chung            if (info.provider.getPackageName().equals(mAssistComponent.getPackageName())) {
602bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung                return info;
603f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            }
604f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
605bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        return null;
606bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    }
607bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung
608bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung    /**
609bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung     * Resolves and binds the search app widget that is to appear in the recents.
610bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung     */
611af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung    private Pair<Integer, AppWidgetProviderInfo> bindSearchAppWidget(AppWidgetHost host,
612af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung            AppWidgetProviderInfo resolvedSearchWidgetInfo) {
613bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (mAwm == null) return null;
614bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung        if (mAssistComponent == null) return null;
615bf8871db617d76ee66c5cf803f0bafa5e93998e9Winson Chung
616f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        // Allocate a new widget id and try and bind the app widget (if that fails, then just skip)
617f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        int searchWidgetId = host.allocateAppWidgetId();
618f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        Bundle opts = new Bundle();
619f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
620ee0b12161ab8563378e33e9d694d15ed1a757a26Winson Chung                AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
621af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, resolvedSearchWidgetInfo.provider, opts)) {
622044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung            host.deleteAppWidgetId(searchWidgetId);
623f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung            return null;
624f7bca430d9356c26d6df222d2c90bc7668262f6bWinson Chung        }
625af3bb6936786a8c14ac01da3d81d196d17b68b96Winson Chung        return new Pair<>(searchWidgetId, resolvedSearchWidgetInfo);
626ecd9b3031c9a322bd69380eae2810d53839e8f64Winson Chung    }
627d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung
628d42a6cfe2bf632222617450a1ed340268e82f06cWinson Chung    /**
629ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung     * Returns whether touch exploration is currently enabled.
630ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung     */
631ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung    public boolean isTouchExplorationEnabled() {
632ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung        if (mAccm == null) return false;
633ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung
634ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung        return mAccm.isEnabled() && mAccm.isTouchExplorationEnabled();
635ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung    }
636ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung
637ee44595bd53c4f3f6a2eeb664ea96a268636c041Winson Chung    /**
63856e09b42a0f1670970872bef611a8036904ad6bfJason Monk     * Returns a global setting.
63956e09b42a0f1670970872bef611a8036904ad6bfJason Monk     */
64056e09b42a0f1670970872bef611a8036904ad6bfJason Monk    public int getGlobalSetting(Context context, String setting) {
64156e09b42a0f1670970872bef611a8036904ad6bfJason Monk        ContentResolver cr = context.getContentResolver();
64256e09b42a0f1670970872bef611a8036904ad6bfJason Monk        return Settings.Global.getInt(cr, setting, 0);
64356e09b42a0f1670970872bef611a8036904ad6bfJason Monk    }
64456e09b42a0f1670970872bef611a8036904ad6bfJason Monk
64556e09b42a0f1670970872bef611a8036904ad6bfJason Monk    /**
64656e09b42a0f1670970872bef611a8036904ad6bfJason Monk     * Returns a system setting.
64756e09b42a0f1670970872bef611a8036904ad6bfJason Monk     */
64856e09b42a0f1670970872bef611a8036904ad6bfJason Monk    public int getSystemSetting(Context context, String setting) {
64956e09b42a0f1670970872bef611a8036904ad6bfJason Monk        ContentResolver cr = context.getContentResolver();
65056e09b42a0f1670970872bef611a8036904ad6bfJason Monk        return Settings.System.getInt(cr, setting, 0);
65156e09b42a0f1670970872bef611a8036904ad6bfJason Monk    }
65256e09b42a0f1670970872bef611a8036904ad6bfJason Monk
65356e09b42a0f1670970872bef611a8036904ad6bfJason Monk    /**
654d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung     * Returns a system property.
655d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung     */
656d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    public String getSystemProperty(String key) {
657d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung        return SystemProperties.get(key);
658d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    }
659d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung
660d16c565a607de754379fe699a4def21bd0e3de2fWinson Chung    /**
661ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     * Returns the window rect.
662ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung     */
663ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    public Rect getWindowRect() {
664ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        Rect windowRect = new Rect();
665ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        if (mWm == null) return windowRect;
666ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
667dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        Point p = new Point();
668dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        mWm.getDefaultDisplay().getRealSize(p);
669dcfa7976fa836ae90bb4a579892a18a0abf35b3cWinson Chung        windowRect.set(0, 0, p.x, p.y);
670ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung        return windowRect;
671ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung    }
672ffa2ec664479bff6b4b61d4c349d9db2cb37ca16Winson Chung
6734e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung    /** Starts an activity from recents. */
6744e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung    public boolean startActivityFromRecents(Context context, int taskId, String taskName,
6754e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung            ActivityOptions options) {
676dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner        if (mIam != null) {
677dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner            try {
678dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner                mIam.startActivityFromRecents(taskId, options == null ? null : options.toBundle());
6794e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung                return true;
6804e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung            } catch (Exception e) {
6814e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung                Console.logError(context,
6824e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung                        context.getString(R.string.recents_launch_error_message, taskName));
683dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner            }
684dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner        }
6854e96eb709d2f1b6b1cd233c8a99f6706fde70bb1Winson Chung        return false;
686dc00cbe2c15eef5141656311a6d05c753d7c6db6Craig Mautner    }
687044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung
688044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung    /** Starts an in-place animation on the front most application windows. */
689044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung    public void startInPlaceAnimationOnFrontMostApplication(ActivityOptions opts) {
690044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung        if (mIam == null) return;
691044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung
692044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung        try {
693044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung            mIam.startInPlaceAnimationOnFrontMostApplication(opts);
694044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung        } catch (Exception e) {
695044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung            e.printStackTrace();
696044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung        }
697044d52934e57a337665f707aa4be1d423ee3fb29Winson Chung    }
698740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung
699740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung    /** Registers a task stack listener with the system. */
700740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung    public void registerTaskStackListener(ITaskStackListener listener) {
701740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        if (mIam == null) return;
702740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung
703740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        try {
704740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung            mIam.registerTaskStackListener(listener);
705740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        } catch (Exception e) {
706740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung            e.printStackTrace();
707740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung        }
708740c3ac782675d190941b2ab1905e56f246c1b11Winson Chung    }
709a10370fc2eb8eb95631592160c5f6281b9d75722Winson Chung}
710