blob: b27c4802e84c8938efa3ba3f66e34a042d063f34 [file] [log] [blame]
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package com.android.server.am;
18
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070019import static android.Manifest.permission.BIND_VOICE_INTERACTION;
20import static android.Manifest.permission.CHANGE_CONFIGURATION;
21import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
22import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070023import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070024import static android.Manifest.permission.READ_FRAME_BUFFER;
25import static android.Manifest.permission.REMOVE_TASKS;
26import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
27import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
Wale Ogunwale6767eae2018-05-03 15:52:51 -070028import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_CONTENT;
29import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_DATA;
30import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_RECEIVER_EXTRAS;
31import static android.app.ActivityTaskManagerInternal.ASSIST_KEY_STRUCTURE;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070032import static android.app.ActivityTaskManager.INVALID_STACK_ID;
33import static android.app.ActivityTaskManager.RESIZE_MODE_PRESERVE_WINDOW;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070034import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070035import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070036import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070037import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
38import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
39import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070040import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
41import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070042import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070043import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070044import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
Wale Ogunwaled0412b32018-05-08 09:25:50 -070045import static android.content.pm.PackageManager.PERMISSION_GRANTED;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070046import static android.os.Process.SYSTEM_UID;
47import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION;
48import static android.view.Display.DEFAULT_DISPLAY;
49import static android.view.Display.INVALID_DISPLAY;
Wale Ogunwaled0412b32018-05-08 09:25:50 -070050import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN;
Wale Ogunwale6767eae2018-05-03 15:52:51 -070051import static android.view.WindowManager.TRANSIT_NONE;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070052import static android.view.WindowManager.TRANSIT_TASK_IN_PLACE;
Wale Ogunwaled0412b32018-05-08 09:25:50 -070053import static android.view.WindowManager.TRANSIT_TASK_OPEN;
54import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070055import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ALL;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070056import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_CONFIGURATION;
57import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_FOCUS;
58import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_IMMERSIVE;
59import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
Wale Ogunwale6767eae2018-05-03 15:52:51 -070060import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_OOM_ADJ;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070061import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070062import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_SWITCH;
63import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_VISIBILITY;
64import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_FOCUS;
65import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_IMMERSIVE;
66import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070067import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070068import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_SWITCH;
69import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_VISIBILITY;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070070import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
71import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070072import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070073import static com.android.server.am.ActivityManagerService.ANIMATE;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070074import static com.android.server.am.ActivityManagerService.DISPATCH_SCREEN_KEYGUARD_MSG;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070075import static com.android.server.am.ActivityManagerService.STOCK_PM_FLAGS;
76import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070077import static com.android.server.am.ActivityStackSupervisor.DEFER_RESUME;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070078import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_ONLY;
79import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
80import static com.android.server.am.ActivityStackSupervisor.ON_TOP;
81import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
82import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
83import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
84import static com.android.server.am.TaskRecord.LOCK_TASK_AUTH_DONT_LOCK;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070085import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070086import static com.android.server.am.TaskRecord.REPARENT_LEAVE_STACK_IN_PLACE;
87import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
88import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070089
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070090import android.Manifest;
91import android.annotation.Nullable;
92import android.annotation.UserIdInt;
93import android.app.Activity;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070094import android.app.ActivityManager;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070095import android.app.ActivityOptions;
96import android.app.ActivityTaskManager;
Wale Ogunwale6767eae2018-05-03 15:52:51 -070097import android.app.ActivityTaskManagerInternal;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -070098import android.app.AppGlobals;
Wale Ogunwale65ebd952018-04-25 15:41:44 -070099import android.app.IActivityTaskManager;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700100import android.app.IApplicationThread;
101import android.app.IAssistDataReceiver;
102import android.app.ITaskStackListener;
103import android.app.PictureInPictureParams;
104import android.app.ProfilerInfo;
105import android.app.RemoteAction;
106import android.app.WaitResult;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700107import android.app.WindowConfiguration;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700108import android.app.admin.DevicePolicyCache;
109import android.app.assist.AssistContent;
110import android.app.assist.AssistStructure;
111import android.app.usage.UsageEvents;
112import android.content.ActivityNotFoundException;
113import android.content.ComponentName;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700114import android.content.Context;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700115import android.content.IIntentSender;
116import android.content.Intent;
117import android.content.pm.ActivityInfo;
118import android.content.pm.PackageManager;
119import android.content.pm.ParceledListSlice;
120import android.content.pm.ResolveInfo;
121import android.content.res.Configuration;
122import android.graphics.Bitmap;
123import android.graphics.Point;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700124import android.graphics.Rect;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700125import android.metrics.LogMaker;
126import android.net.Uri;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700127import android.os.Binder;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700128import android.os.Bundle;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700129import android.os.Handler;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700130import android.os.IBinder;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700131import android.os.Looper;
132import android.os.Message;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700133import android.os.PersistableBundle;
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700134import android.os.Process;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700135import android.os.RemoteException;
136import android.os.TransactionTooLargeException;
137import android.os.UserHandle;
138import android.provider.Settings;
139import android.service.voice.IVoiceInteractionSession;
140import android.service.voice.VoiceInteractionManagerInternal;
141import android.telecom.TelecomManager;
142import android.text.TextUtils;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700143import android.util.Slog;
144
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700145import android.util.SparseIntArray;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700146import android.util.proto.ProtoOutputStream;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700147import android.view.IRecentsAnimationRunner;
148import android.view.RemoteAnimationAdapter;
149import android.view.RemoteAnimationDefinition;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700150
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700151import com.android.internal.app.AssistUtils;
152import com.android.internal.app.IVoiceInteractor;
153import com.android.internal.logging.MetricsLogger;
154import com.android.internal.os.logging.MetricsLoggerWrapper;
155import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
156import com.android.internal.policy.IKeyguardDismissCallback;
157import com.android.internal.policy.KeyguardDismissCallback;
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700158import com.android.internal.util.Preconditions;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700159import com.android.server.LocalServices;
160import com.android.server.SystemService;
161import com.android.server.Watchdog;
162import com.android.server.vr.VrManagerInternal;
163import com.android.server.wm.PinnedStackWindowController;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700164import com.android.server.wm.WindowManagerService;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700165
166import java.io.File;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700167import java.io.PrintWriter;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700168import java.util.ArrayList;
169import java.util.List;
170
171/**
172 * System service for managing activities and their containers (task, stacks, displays,... ).
173 *
174 * {@hide}
175 */
176public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
177 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityTaskManagerService" : TAG_AM;
178 private static final String TAG_STACK = TAG + POSTFIX_STACK;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700179 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH;
180 private static final String TAG_IMMERSIVE = TAG + POSTFIX_IMMERSIVE;
181 private static final String TAG_FOCUS = TAG + POSTFIX_FOCUS;
182 private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY;
183 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700184
Wale Ogunwale16e505a2018-05-07 15:00:49 -0700185 Context mContext;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700186 H mH;
Wale Ogunwale16e505a2018-05-07 15:00:49 -0700187 ActivityManagerService mAm;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700188 /* Global service lock used by the package the owns this service. */
189 Object mGlobalLock;
Wale Ogunwale16e505a2018-05-07 15:00:49 -0700190 ActivityStackSupervisor mStackSupervisor;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700191 WindowManagerService mWindowManager;
Wale Ogunwale16e505a2018-05-07 15:00:49 -0700192 /** List of intents that were used to start the most recent tasks. */
193 private RecentTasks mRecentTasks;
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700194 /** State of external calls telling us if the device is awake or asleep. */
195 private boolean mKeyguardShown = false;
196
197 // Wrapper around VoiceInteractionServiceManager
198 private AssistUtils mAssistUtils;
199
200 // VoiceInteraction session ID that changes for each new request except when
201 // being called for multi-window assist in a single session.
202 private int mViSessionId = 1000;
203
204 // How long to wait in getAssistContextExtras for the activity and foreground services
205 // to respond with the result.
206 private static final int PENDING_ASSIST_EXTRAS_TIMEOUT = 500;
207
208 // How long top wait when going through the modern assist (which doesn't need to block
209 // on getting this result before starting to launch its UI).
210 private static final int PENDING_ASSIST_EXTRAS_LONG_TIMEOUT = 2000;
211
212 // How long to wait in getAutofillAssistStructure() for the activity to respond with the result.
213 private static final int PENDING_AUTOFILL_ASSIST_STRUCTURE_TIMEOUT = 2000;
214
215 private final ArrayList<PendingAssistExtras> mPendingAssistExtras = new ArrayList<>();
216
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700217 // Keeps track of the active voice interaction service component, notified from
218 // VoiceInteractionManagerService
219 ComponentName mActiveVoiceInteractionServiceComponent;
220
221 private VrController mVrController;
222 KeyguardController mKeyguardController;
223 private final ClientLifecycleManager mLifecycleManager;
224 private TaskChangeNotificationController mTaskChangeNotificationController;
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700225 /** The controller for all operations related to locktask. */
226 private LockTaskController mLockTaskController;
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700227 private ActivityStartController mActivityStartController;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700228
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700229 boolean mSuppressResizeConfigChanges;
230
231 private final UpdateConfigurationResult mTmpUpdateConfigurationResult =
232 new UpdateConfigurationResult();
233
234 static final class UpdateConfigurationResult {
235 // Configuration changes that were updated.
236 int changes;
237 // If the activity was relaunched to match the new configuration.
238 boolean activityRelaunched;
239
240 void reset() {
241 changes = 0;
242 activityRelaunched = false;
243 }
244 }
245
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700246 ActivityTaskManagerService(Context context) {
247 mContext = context;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700248 mLifecycleManager = new ClientLifecycleManager();
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700249 }
250
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700251 void onSystemReady() {
252 mAssistUtils = new AssistUtils(mContext);
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700253 mVrController.onSystemReady();
254 mRecentTasks.onSystemReadyLocked();
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700255 }
256
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700257 // TODO: Will be converted to WM lock once transition is complete.
258 void setActivityManagerService(ActivityManagerService am) {
259 mAm = am;
260 mGlobalLock = mAm;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700261 mH = new H(mAm.mHandlerThread.getLooper());
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700262 mStackSupervisor = mAm.mStackSupervisor;
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700263 mTaskChangeNotificationController =
264 new TaskChangeNotificationController(mAm, mStackSupervisor, mH);
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700265 mLockTaskController = new LockTaskController(mContext, mStackSupervisor, mH);
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700266 mActivityStartController = new ActivityStartController(mAm);
Wale Ogunwale16e505a2018-05-07 15:00:49 -0700267 mRecentTasks = createRecentTasks();
268 mStackSupervisor.setRecentTasks(mRecentTasks);
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700269 mVrController = new VrController(mAm);
270 mKeyguardController = mStackSupervisor.getKeyguardController();
271 }
272
273 void setWindowManager(WindowManagerService wm) {
274 mWindowManager = wm;
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700275 mLockTaskController.setWindowManager(wm);
Wale Ogunwale16e505a2018-05-07 15:00:49 -0700276 }
277
278 protected RecentTasks createRecentTasks() {
279 return new RecentTasks(this, mStackSupervisor);
280 }
281
282 RecentTasks getRecentTasks() {
283 return mRecentTasks;
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700284 }
285
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700286 ClientLifecycleManager getLifecycleManager() {
287 return mLifecycleManager;
288 }
289
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700290 ActivityStartController getActivityStartController() {
291 return mActivityStartController;
292 }
293
Wale Ogunwaled0412b32018-05-08 09:25:50 -0700294 TaskChangeNotificationController getTaskChangeNotificationController() {
295 return mTaskChangeNotificationController;
296 }
297
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700298 LockTaskController getLockTaskController() {
299 return mLockTaskController;
300 }
301
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700302 private void start() {
303 LocalServices.addService(ActivityTaskManagerInternal.class, new LocalService());
304 }
305
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700306 public static final class Lifecycle extends SystemService {
307 private final ActivityTaskManagerService mService;
308
309 public Lifecycle(Context context) {
310 super(context);
311 mService = new ActivityTaskManagerService(context);
312 }
313
314 @Override
315 public void onStart() {
316 publishBinderService(Context.ACTIVITY_TASK_SERVICE, mService);
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700317 mService.start();
Wale Ogunwale65ebd952018-04-25 15:41:44 -0700318 }
319
320 public ActivityTaskManagerService getService() {
321 return mService;
322 }
323 }
324
325 @Override
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700326 public final int startActivity(IApplicationThread caller, String callingPackage,
327 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
328 int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
329 return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
330 resultWho, requestCode, startFlags, profilerInfo, bOptions,
331 UserHandle.getCallingUserId());
332 }
333
334 @Override
335 public final int startActivities(IApplicationThread caller, String callingPackage,
336 Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions,
337 int userId) {
338 final String reason = "startActivities";
339 mAm.enforceNotIsolatedCaller(reason);
340 userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
341 Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
342 // TODO: Switch to user app stacks here.
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700343 return getActivityStartController().startActivities(caller, -1, callingPackage, intents,
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700344 resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId, reason);
345 }
346
347 @Override
348 public int startActivityAsUser(IApplicationThread caller, String callingPackage,
349 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
350 int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
351 return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
352 resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
353 true /*validateIncomingUser*/);
354 }
355
356 int startActivityAsUser(IApplicationThread caller, String callingPackage,
357 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
358 int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,
359 boolean validateIncomingUser) {
360 mAm.enforceNotIsolatedCaller("startActivityAsUser");
361
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700362 userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700363 Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
364
365 // TODO: Switch to user app stacks here.
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700366 return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700367 .setCaller(caller)
368 .setCallingPackage(callingPackage)
369 .setResolvedType(resolvedType)
370 .setResultTo(resultTo)
371 .setResultWho(resultWho)
372 .setRequestCode(requestCode)
373 .setStartFlags(startFlags)
374 .setProfilerInfo(profilerInfo)
375 .setActivityOptions(bOptions)
376 .setMayWait(userId)
377 .execute();
378
379 }
380
381 @Override
382 public int startActivityIntentSender(IApplicationThread caller, IIntentSender target,
383 IBinder whitelistToken, Intent fillInIntent, String resolvedType, IBinder resultTo,
384 String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle bOptions)
385 throws TransactionTooLargeException {
386 mAm.enforceNotIsolatedCaller("startActivityIntentSender");
387 // Refuse possible leaked file descriptors
388 if (fillInIntent != null && fillInIntent.hasFileDescriptors()) {
389 throw new IllegalArgumentException("File descriptors passed in Intent");
390 }
391
392 if (!(target instanceof PendingIntentRecord)) {
393 throw new IllegalArgumentException("Bad PendingIntent object");
394 }
395
396 PendingIntentRecord pir = (PendingIntentRecord)target;
397
398 synchronized (mGlobalLock) {
399 // If this is coming from the currently resumed activity, it is
400 // effectively saying that app switches are allowed at this point.
401 final ActivityStack stack = mAm.getFocusedStack();
402 if (stack.mResumedActivity != null &&
403 stack.mResumedActivity.info.applicationInfo.uid == Binder.getCallingUid()) {
404 mAm.mAppSwitchesAllowedTime = 0;
405 }
406 }
407 int ret = pir.sendInner(0, fillInIntent, resolvedType, whitelistToken, null, null,
408 resultTo, resultWho, requestCode, flagsMask, flagsValues, bOptions);
409 return ret;
410 }
411
412 @Override
413 public boolean startNextMatchingActivity(IBinder callingActivity, Intent intent,
414 Bundle bOptions) {
415 // Refuse possible leaked file descriptors
416 if (intent != null && intent.hasFileDescriptors()) {
417 throw new IllegalArgumentException("File descriptors passed in Intent");
418 }
419 SafeActivityOptions options = SafeActivityOptions.fromBundle(bOptions);
420
421 synchronized (mGlobalLock) {
422 final ActivityRecord r = ActivityRecord.isInStackLocked(callingActivity);
423 if (r == null) {
424 SafeActivityOptions.abort(options);
425 return false;
426 }
427 if (r.app == null || r.app.thread == null) {
428 // The caller is not running... d'oh!
429 SafeActivityOptions.abort(options);
430 return false;
431 }
432 intent = new Intent(intent);
433 // The caller is not allowed to change the data.
434 intent.setDataAndType(r.intent.getData(), r.intent.getType());
435 // And we are resetting to find the next component...
436 intent.setComponent(null);
437
438 final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
439
440 ActivityInfo aInfo = null;
441 try {
442 List<ResolveInfo> resolves =
443 AppGlobals.getPackageManager().queryIntentActivities(
444 intent, r.resolvedType,
445 PackageManager.MATCH_DEFAULT_ONLY | STOCK_PM_FLAGS,
446 UserHandle.getCallingUserId()).getList();
447
448 // Look for the original activity in the list...
449 final int N = resolves != null ? resolves.size() : 0;
450 for (int i=0; i<N; i++) {
451 ResolveInfo rInfo = resolves.get(i);
452 if (rInfo.activityInfo.packageName.equals(r.packageName)
453 && rInfo.activityInfo.name.equals(r.info.name)) {
454 // We found the current one... the next matching is
455 // after it.
456 i++;
457 if (i<N) {
458 aInfo = resolves.get(i).activityInfo;
459 }
460 if (debug) {
461 Slog.v(TAG, "Next matching activity: found current " + r.packageName
462 + "/" + r.info.name);
463 Slog.v(TAG, "Next matching activity: next is " + ((aInfo == null)
464 ? "null" : aInfo.packageName + "/" + aInfo.name));
465 }
466 break;
467 }
468 }
469 } catch (RemoteException e) {
470 }
471
472 if (aInfo == null) {
473 // Nobody who is next!
474 SafeActivityOptions.abort(options);
475 if (debug) Slog.d(TAG, "Next matching activity: nothing found");
476 return false;
477 }
478
479 intent.setComponent(new ComponentName(
480 aInfo.applicationInfo.packageName, aInfo.name));
481 intent.setFlags(intent.getFlags()&~(
482 Intent.FLAG_ACTIVITY_FORWARD_RESULT|
483 Intent.FLAG_ACTIVITY_CLEAR_TOP|
484 Intent.FLAG_ACTIVITY_MULTIPLE_TASK|
485 FLAG_ACTIVITY_NEW_TASK));
486
487 // Okay now we need to start the new activity, replacing the currently running activity.
488 // This is a little tricky because we want to start the new one as if the current one is
489 // finished, but not finish the current one first so that there is no flicker.
490 // And thus...
491 final boolean wasFinishing = r.finishing;
492 r.finishing = true;
493
494 // Propagate reply information over to the new activity.
495 final ActivityRecord resultTo = r.resultTo;
496 final String resultWho = r.resultWho;
497 final int requestCode = r.requestCode;
498 r.resultTo = null;
499 if (resultTo != null) {
500 resultTo.removeResultsLocked(r, resultWho, requestCode);
501 }
502
503 final long origId = Binder.clearCallingIdentity();
504 // TODO(b/64750076): Check if calling pid should really be -1.
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700505 final int res = getActivityStartController()
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700506 .obtainStarter(intent, "startNextMatchingActivity")
507 .setCaller(r.app.thread)
508 .setResolvedType(r.resolvedType)
509 .setActivityInfo(aInfo)
510 .setResultTo(resultTo != null ? resultTo.appToken : null)
511 .setResultWho(resultWho)
512 .setRequestCode(requestCode)
513 .setCallingPid(-1)
514 .setCallingUid(r.launchedFromUid)
515 .setCallingPackage(r.launchedFromPackage)
516 .setRealCallingPid(-1)
517 .setRealCallingUid(r.launchedFromUid)
518 .setActivityOptions(options)
519 .execute();
520 Binder.restoreCallingIdentity(origId);
521
522 r.finishing = wasFinishing;
523 if (res != ActivityManager.START_SUCCESS) {
524 return false;
525 }
526 return true;
527 }
528 }
529
530 @Override
531 public final WaitResult startActivityAndWait(IApplicationThread caller, String callingPackage,
532 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
533 int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
534 final WaitResult res = new WaitResult();
535 synchronized (mGlobalLock) {
536 mAm.enforceNotIsolatedCaller("startActivityAndWait");
537 userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
538 Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY,
539 "startActivityAndWait", null);
540 // TODO: Switch to user app stacks here.
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700541 getActivityStartController().obtainStarter(intent, "startActivityAndWait")
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700542 .setCaller(caller)
543 .setCallingPackage(callingPackage)
544 .setResolvedType(resolvedType)
545 .setResultTo(resultTo)
546 .setResultWho(resultWho)
547 .setRequestCode(requestCode)
548 .setStartFlags(startFlags)
549 .setActivityOptions(bOptions)
550 .setMayWait(userId)
551 .setProfilerInfo(profilerInfo)
552 .setWaitResult(res)
553 .execute();
554 }
555 return res;
556 }
557
558 @Override
559 public final int startActivityWithConfig(IApplicationThread caller, String callingPackage,
560 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
561 int startFlags, Configuration config, Bundle bOptions, int userId) {
562 synchronized (mGlobalLock) {
563 mAm.enforceNotIsolatedCaller("startActivityWithConfig");
564 userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
565 Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY,
566 "startActivityWithConfig", null);
567 // TODO: Switch to user app stacks here.
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700568 return getActivityStartController().obtainStarter(intent, "startActivityWithConfig")
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700569 .setCaller(caller)
570 .setCallingPackage(callingPackage)
571 .setResolvedType(resolvedType)
572 .setResultTo(resultTo)
573 .setResultWho(resultWho)
574 .setRequestCode(requestCode)
575 .setStartFlags(startFlags)
576 .setGlobalConfiguration(config)
577 .setActivityOptions(bOptions)
578 .setMayWait(userId)
579 .execute();
580 }
581 }
582
583 @Override
584 public final int startActivityAsCaller(IApplicationThread caller, String callingPackage,
585 Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
586 int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, boolean ignoreTargetSecurity,
587 int userId) {
588
589 // This is very dangerous -- it allows you to perform a start activity (including
590 // permission grants) as any app that may launch one of your own activities. So
591 // we will only allow this to be done from activities that are part of the core framework,
592 // and then only when they are running as the system.
593 final ActivityRecord sourceRecord;
594 final int targetUid;
595 final String targetPackage;
596 final boolean isResolver;
597 synchronized (mGlobalLock) {
598 if (resultTo == null) {
599 throw new SecurityException("Must be called from an activity");
600 }
601 sourceRecord = mStackSupervisor.isInAnyStackLocked(resultTo);
602 if (sourceRecord == null) {
603 throw new SecurityException("Called with bad activity token: " + resultTo);
604 }
605 if (!sourceRecord.info.packageName.equals("android")) {
606 throw new SecurityException(
607 "Must be called from an activity that is declared in the android package");
608 }
609 if (sourceRecord.app == null) {
610 throw new SecurityException("Called without a process attached to activity");
611 }
612 if (UserHandle.getAppId(sourceRecord.app.uid) != SYSTEM_UID) {
613 // This is still okay, as long as this activity is running under the
614 // uid of the original calling activity.
615 if (sourceRecord.app.uid != sourceRecord.launchedFromUid) {
616 throw new SecurityException(
617 "Calling activity in uid " + sourceRecord.app.uid
618 + " must be system uid or original calling uid "
619 + sourceRecord.launchedFromUid);
620 }
621 }
622 if (ignoreTargetSecurity) {
623 if (intent.getComponent() == null) {
624 throw new SecurityException(
625 "Component must be specified with ignoreTargetSecurity");
626 }
627 if (intent.getSelector() != null) {
628 throw new SecurityException(
629 "Selector not allowed with ignoreTargetSecurity");
630 }
631 }
632 targetUid = sourceRecord.launchedFromUid;
633 targetPackage = sourceRecord.launchedFromPackage;
634 isResolver = sourceRecord.isResolverOrChildActivity();
635 }
636
637 if (userId == UserHandle.USER_NULL) {
638 userId = UserHandle.getUserId(sourceRecord.app.uid);
639 }
640
641 // TODO: Switch to user app stacks here.
642 try {
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700643 return getActivityStartController().obtainStarter(intent, "startActivityAsCaller")
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700644 .setCallingUid(targetUid)
645 .setCallingPackage(targetPackage)
646 .setResolvedType(resolvedType)
647 .setResultTo(resultTo)
648 .setResultWho(resultWho)
649 .setRequestCode(requestCode)
650 .setStartFlags(startFlags)
651 .setActivityOptions(bOptions)
652 .setMayWait(userId)
653 .setIgnoreTargetSecurity(ignoreTargetSecurity)
654 .setFilterCallingUid(isResolver ? 0 /* system */ : targetUid)
655 .execute();
656 } catch (SecurityException e) {
657 // XXX need to figure out how to propagate to original app.
658 // A SecurityException here is generally actually a fault of the original
659 // calling activity (such as a fairly granting permissions), so propagate it
660 // back to them.
661 /*
662 StringBuilder msg = new StringBuilder();
663 msg.append("While launching");
664 msg.append(intent.toString());
665 msg.append(": ");
666 msg.append(e.getMessage());
667 */
668 throw e;
669 }
670 }
671
672 @Override
673 public int startVoiceActivity(String callingPackage, int callingPid, int callingUid,
674 Intent intent, String resolvedType, IVoiceInteractionSession session,
675 IVoiceInteractor interactor, int startFlags, ProfilerInfo profilerInfo,
676 Bundle bOptions, int userId) {
677 mAm.enforceCallingPermission(BIND_VOICE_INTERACTION, "startVoiceActivity()");
678 if (session == null || interactor == null) {
679 throw new NullPointerException("null session or interactor");
680 }
681 userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
682 ALLOW_FULL_ONLY, "startVoiceActivity", null);
683 // TODO: Switch to user app stacks here.
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700684 return getActivityStartController().obtainStarter(intent, "startVoiceActivity")
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700685 .setCallingUid(callingUid)
686 .setCallingPackage(callingPackage)
687 .setResolvedType(resolvedType)
688 .setVoiceSession(session)
689 .setVoiceInteractor(interactor)
690 .setStartFlags(startFlags)
691 .setProfilerInfo(profilerInfo)
692 .setActivityOptions(bOptions)
693 .setMayWait(userId)
694 .execute();
695 }
696
697 @Override
698 public int startAssistantActivity(String callingPackage, int callingPid, int callingUid,
699 Intent intent, String resolvedType, Bundle bOptions, int userId) {
700 mAm.enforceCallingPermission(BIND_VOICE_INTERACTION, "startAssistantActivity()");
701 userId = mAm.mUserController.handleIncomingUser(callingPid, callingUid, userId, false,
702 ALLOW_FULL_ONLY, "startAssistantActivity", null);
703
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700704 return getActivityStartController().obtainStarter(intent, "startAssistantActivity")
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700705 .setCallingUid(callingUid)
706 .setCallingPackage(callingPackage)
707 .setResolvedType(resolvedType)
708 .setActivityOptions(bOptions)
709 .setMayWait(userId)
710 .execute();
711 }
712
713 @Override
714 public void startRecentsActivity(Intent intent, IAssistDataReceiver assistDataReceiver,
715 IRecentsAnimationRunner recentsAnimationRunner) {
716 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "startRecentsActivity()");
717 final int callingPid = Binder.getCallingPid();
718 final long origId = Binder.clearCallingIdentity();
719 try {
720 synchronized (mGlobalLock) {
Wale Ogunwale16e505a2018-05-07 15:00:49 -0700721 final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
722 final int recentsUid = mRecentTasks.getRecentsComponentUid();
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700723
724 // Start a new recents animation
725 final RecentsAnimation anim = new RecentsAnimation(mAm, mStackSupervisor,
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -0700726 getActivityStartController(), mAm.mWindowManager, mAm.mUserController,
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700727 callingPid);
728 anim.startRecentsActivity(intent, recentsAnimationRunner, recentsComponent,
729 recentsUid, assistDataReceiver);
730 }
731 } finally {
732 Binder.restoreCallingIdentity(origId);
733 }
734 }
735
736 @Override
737 public final int startActivityFromRecents(int taskId, Bundle bOptions) {
738 mAm.enforceCallerIsRecentsOrHasPermission(START_TASKS_FROM_RECENTS,
739 "startActivityFromRecents()");
740
741 final int callingPid = Binder.getCallingPid();
742 final int callingUid = Binder.getCallingUid();
743 final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(bOptions);
744 final long origId = Binder.clearCallingIdentity();
745 try {
746 synchronized (mGlobalLock) {
747 return mStackSupervisor.startActivityFromRecents(callingPid, callingUid, taskId,
748 safeOptions);
749 }
750 } finally {
751 Binder.restoreCallingIdentity(origId);
752 }
753 }
754
755 /**
756 * This is the internal entry point for handling Activity.finish().
757 *
758 * @param token The Binder token referencing the Activity we want to finish.
759 * @param resultCode Result code, if any, from this Activity.
760 * @param resultData Result data (Intent), if any, from this Activity.
761 * @param finishTask Whether to finish the task associated with this Activity.
762 *
763 * @return Returns true if the activity successfully finished, or false if it is still running.
764 */
765 @Override
766 public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
767 int finishTask) {
768 // Refuse possible leaked file descriptors
769 if (resultData != null && resultData.hasFileDescriptors()) {
770 throw new IllegalArgumentException("File descriptors passed in Intent");
771 }
772
773 synchronized (mGlobalLock) {
774 ActivityRecord r = ActivityRecord.isInStackLocked(token);
775 if (r == null) {
776 return true;
777 }
778 // Keep track of the root activity of the task before we finish it
779 TaskRecord tr = r.getTask();
780 ActivityRecord rootR = tr.getRootActivity();
781 if (rootR == null) {
782 Slog.w(TAG, "Finishing task with all activities already finished");
783 }
784 // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can
785 // finish.
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700786 if (getLockTaskController().activityBlockedFromFinish(r)) {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700787 return false;
788 }
789
790 if (mAm.mController != null) {
791 // Find the first activity that is not finishing.
792 ActivityRecord next = r.getStack().topRunningActivityLocked(token, 0);
793 if (next != null) {
794 // ask watcher if this is allowed
795 boolean resumeOK = true;
796 try {
797 resumeOK = mAm.mController.activityResuming(next.packageName);
798 } catch (RemoteException e) {
799 mAm.mController = null;
800 Watchdog.getInstance().setActivityController(null);
801 }
802
803 if (!resumeOK) {
804 Slog.i(TAG, "Not finishing activity because controller resumed");
805 return false;
806 }
807 }
808 }
809 final long origId = Binder.clearCallingIdentity();
810 try {
811 boolean res;
812 final boolean finishWithRootActivity =
813 finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY;
814 if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY
815 || (finishWithRootActivity && r == rootR)) {
816 // If requested, remove the task that is associated to this activity only if it
817 // was the root activity in the task. The result code and data is ignored
818 // because we don't support returning them across task boundaries. Also, to
819 // keep backwards compatibility we remove the task from recents when finishing
820 // task with root activity.
821 res = mStackSupervisor.removeTaskByIdLocked(tr.taskId, false,
822 finishWithRootActivity, "finish-activity");
823 if (!res) {
824 Slog.i(TAG, "Removing task failed to finish activity");
825 }
826 } else {
827 res = tr.getStack().requestFinishActivityLocked(token, resultCode,
828 resultData, "app-request", true);
829 if (!res) {
830 Slog.i(TAG, "Failed to finish by app-request");
831 }
832 }
833 return res;
834 } finally {
835 Binder.restoreCallingIdentity(origId);
836 }
837 }
838 }
839
840 @Override
841 public boolean finishActivityAffinity(IBinder token) {
842 synchronized (mGlobalLock) {
843 final long origId = Binder.clearCallingIdentity();
844 try {
845 ActivityRecord r = ActivityRecord.isInStackLocked(token);
846 if (r == null) {
847 return false;
848 }
849
850 // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps
851 // can finish.
852 final TaskRecord task = r.getTask();
Wale Ogunwaled95c06b2018-05-08 10:35:38 -0700853 if (getLockTaskController().activityBlockedFromFinish(r)) {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -0700854 return false;
855 }
856 return task.getStack().finishActivityAffinityLocked(r);
857 } finally {
858 Binder.restoreCallingIdentity(origId);
859 }
860 }
861 }
862
863 @Override
864 public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) {
865 final long origId = Binder.clearCallingIdentity();
866 synchronized (mGlobalLock) {
867 ActivityStack stack = ActivityRecord.getStackLocked(token);
868 if (stack != null) {
869 ActivityRecord r =
870 mStackSupervisor.activityIdleInternalLocked(token, false /* fromTimeout */,
871 false /* processPausingActivities */, config);
872 if (stopProfiling) {
873 if ((mAm.mProfileProc == r.app) && mAm.mProfilerInfo != null) {
874 mAm.clearProfilerLocked();
875 }
876 }
877 }
878 }
879 Binder.restoreCallingIdentity(origId);
880 }
881
882 @Override
883 public final void activityResumed(IBinder token) {
884 final long origId = Binder.clearCallingIdentity();
885 synchronized (mGlobalLock) {
886 ActivityRecord.activityResumedLocked(token);
887 mAm.mWindowManager.notifyAppResumedFinished(token);
888 }
889 Binder.restoreCallingIdentity(origId);
890 }
891
892 @Override
893 public final void activityPaused(IBinder token) {
894 final long origId = Binder.clearCallingIdentity();
895 synchronized (mGlobalLock) {
896 ActivityStack stack = ActivityRecord.getStackLocked(token);
897 if (stack != null) {
898 stack.activityPausedLocked(token, false);
899 }
900 }
901 Binder.restoreCallingIdentity(origId);
902 }
903
904 @Override
905 public final void activityStopped(IBinder token, Bundle icicle,
906 PersistableBundle persistentState, CharSequence description) {
907 if (DEBUG_ALL) Slog.v(TAG, "Activity stopped: token=" + token);
908
909 // Refuse possible leaked file descriptors
910 if (icicle != null && icicle.hasFileDescriptors()) {
911 throw new IllegalArgumentException("File descriptors passed in Bundle");
912 }
913
914 final long origId = Binder.clearCallingIdentity();
915
916 synchronized (mGlobalLock) {
917 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
918 if (r != null) {
919 r.activityStoppedLocked(icicle, persistentState, description);
920 }
921 }
922
923 mAm.trimApplications();
924
925 Binder.restoreCallingIdentity(origId);
926 }
927
928 @Override
929 public final void activityDestroyed(IBinder token) {
930 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token);
931 synchronized (mGlobalLock) {
932 ActivityStack stack = ActivityRecord.getStackLocked(token);
933 if (stack != null) {
934 stack.activityDestroyedLocked(token, "activityDestroyed");
935 }
936 }
937 }
938
939 @Override
940 public final void activityRelaunched(IBinder token) {
941 final long origId = Binder.clearCallingIdentity();
942 synchronized (mGlobalLock) {
943 mStackSupervisor.activityRelaunchedLocked(token);
944 }
945 Binder.restoreCallingIdentity(origId);
946 }
947
948 public final void activitySlept(IBinder token) {
949 if (DEBUG_ALL) Slog.v(TAG, "Activity slept: token=" + token);
950
951 final long origId = Binder.clearCallingIdentity();
952
953 synchronized (mGlobalLock) {
954 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
955 if (r != null) {
956 mStackSupervisor.activitySleptLocked(r);
957 }
958 }
959
960 Binder.restoreCallingIdentity(origId);
961 }
962
963 @Override
964 public void setRequestedOrientation(IBinder token, int requestedOrientation) {
965 synchronized (mGlobalLock) {
966 ActivityRecord r = ActivityRecord.isInStackLocked(token);
967 if (r == null) {
968 return;
969 }
970 final long origId = Binder.clearCallingIdentity();
971 try {
972 r.setRequestedOrientation(requestedOrientation);
973 } finally {
974 Binder.restoreCallingIdentity(origId);
975 }
976 }
977 }
978
979 @Override
980 public int getRequestedOrientation(IBinder token) {
981 synchronized (mGlobalLock) {
982 ActivityRecord r = ActivityRecord.isInStackLocked(token);
983 if (r == null) {
984 return ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
985 }
986 return r.getRequestedOrientation();
987 }
988 }
989
990 @Override
991 public void setImmersive(IBinder token, boolean immersive) {
992 synchronized (mGlobalLock) {
993 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
994 if (r == null) {
995 throw new IllegalArgumentException();
996 }
997 r.immersive = immersive;
998
999 // update associated state if we're frontmost
1000 if (r == mStackSupervisor.getResumedActivityLocked()) {
1001 if (DEBUG_IMMERSIVE) Slog.d(TAG_IMMERSIVE, "Frontmost changed immersion: "+ r);
1002 mAm.applyUpdateLockStateLocked(r);
1003 }
1004 }
1005 }
1006
1007 @Override
1008 public boolean isImmersive(IBinder token) {
1009 synchronized (mGlobalLock) {
1010 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
1011 if (r == null) {
1012 throw new IllegalArgumentException();
1013 }
1014 return r.immersive;
1015 }
1016 }
1017
1018 @Override
1019 public boolean isTopActivityImmersive() {
1020 mAm.enforceNotIsolatedCaller("isTopActivityImmersive");
1021 synchronized (mGlobalLock) {
1022 final ActivityRecord r = mAm.getFocusedStack().topRunningActivityLocked();
1023 return (r != null) ? r.immersive : false;
1024 }
1025 }
1026
1027 @Override
1028 public void overridePendingTransition(IBinder token, String packageName,
1029 int enterAnim, int exitAnim) {
1030 synchronized (mGlobalLock) {
1031 ActivityRecord self = ActivityRecord.isInStackLocked(token);
1032 if (self == null) {
1033 return;
1034 }
1035
1036 final long origId = Binder.clearCallingIdentity();
1037
1038 if (self.isState(
1039 ActivityStack.ActivityState.RESUMED, ActivityStack.ActivityState.PAUSING)) {
1040 mAm.mWindowManager.overridePendingAppTransition(packageName,
1041 enterAnim, exitAnim, null);
1042 }
1043
1044 Binder.restoreCallingIdentity(origId);
1045 }
1046 }
1047
1048 @Override
1049 public int getFrontActivityScreenCompatMode() {
1050 mAm.enforceNotIsolatedCaller("getFrontActivityScreenCompatMode");
1051 synchronized (mGlobalLock) {
1052 return mAm.mCompatModePackages.getFrontActivityScreenCompatModeLocked();
1053 }
1054 }
1055
1056 @Override
1057 public void setFrontActivityScreenCompatMode(int mode) {
1058 mAm.enforceCallingPermission(android.Manifest.permission.SET_SCREEN_COMPATIBILITY,
1059 "setFrontActivityScreenCompatMode");
1060 synchronized (mGlobalLock) {
1061 mAm.mCompatModePackages.setFrontActivityScreenCompatModeLocked(mode);
1062 }
1063 }
1064
1065 @Override
1066 public int getLaunchedFromUid(IBinder activityToken) {
1067 ActivityRecord srec;
1068 synchronized (mGlobalLock) {
1069 srec = ActivityRecord.forTokenLocked(activityToken);
1070 }
1071 if (srec == null) {
1072 return -1;
1073 }
1074 return srec.launchedFromUid;
1075 }
1076
1077 @Override
1078 public String getLaunchedFromPackage(IBinder activityToken) {
1079 ActivityRecord srec;
1080 synchronized (mGlobalLock) {
1081 srec = ActivityRecord.forTokenLocked(activityToken);
1082 }
1083 if (srec == null) {
1084 return null;
1085 }
1086 return srec.launchedFromPackage;
1087 }
1088
1089 @Override
1090 public boolean convertFromTranslucent(IBinder token) {
1091 final long origId = Binder.clearCallingIdentity();
1092 try {
1093 synchronized (mGlobalLock) {
1094 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
1095 if (r == null) {
1096 return false;
1097 }
1098 final boolean translucentChanged = r.changeWindowTranslucency(true);
1099 if (translucentChanged) {
1100 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1101 }
1102 mAm.mWindowManager.setAppFullscreen(token, true);
1103 return translucentChanged;
1104 }
1105 } finally {
1106 Binder.restoreCallingIdentity(origId);
1107 }
1108 }
1109
1110 @Override
1111 public boolean convertToTranslucent(IBinder token, Bundle options) {
1112 SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options);
1113 final long origId = Binder.clearCallingIdentity();
1114 try {
1115 synchronized (mGlobalLock) {
1116 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
1117 if (r == null) {
1118 return false;
1119 }
1120 final TaskRecord task = r.getTask();
1121 int index = task.mActivities.lastIndexOf(r);
1122 if (index > 0) {
1123 ActivityRecord under = task.mActivities.get(index - 1);
1124 under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null;
1125 }
1126 final boolean translucentChanged = r.changeWindowTranslucency(false);
1127 if (translucentChanged) {
1128 r.getStack().convertActivityToTranslucent(r);
1129 }
1130 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1131 mAm.mWindowManager.setAppFullscreen(token, false);
1132 return translucentChanged;
1133 }
1134 } finally {
1135 Binder.restoreCallingIdentity(origId);
1136 }
1137 }
1138
1139 @Override
1140 public void notifyActivityDrawn(IBinder token) {
1141 if (DEBUG_VISIBILITY) Slog.d(TAG_VISIBILITY, "notifyActivityDrawn: token=" + token);
1142 synchronized (mGlobalLock) {
1143 ActivityRecord r = mStackSupervisor.isInAnyStackLocked(token);
1144 if (r != null) {
1145 r.getStack().notifyActivityDrawnLocked(r);
1146 }
1147 }
1148 }
1149
1150 @Override
1151 public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) {
1152 synchronized (mGlobalLock) {
1153 ActivityRecord r = ActivityRecord.isInStackLocked(token);
1154 if (r == null) {
1155 return;
1156 }
1157 r.reportFullyDrawnLocked(restoredFromBundle);
1158 }
1159 }
1160
1161 @Override
1162 public int getActivityDisplayId(IBinder activityToken) throws RemoteException {
1163 synchronized (mGlobalLock) {
1164 final ActivityStack stack = ActivityRecord.getStackLocked(activityToken);
1165 if (stack != null && stack.mDisplayId != INVALID_DISPLAY) {
1166 return stack.mDisplayId;
1167 }
1168 return DEFAULT_DISPLAY;
1169 }
1170 }
1171
1172 @Override
1173 public ActivityManager.StackInfo getFocusedStackInfo() throws RemoteException {
1174 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
1175 long ident = Binder.clearCallingIdentity();
1176 try {
1177 synchronized (mGlobalLock) {
1178 ActivityStack focusedStack = mAm.getFocusedStack();
1179 if (focusedStack != null) {
1180 return mStackSupervisor.getStackInfo(focusedStack.mStackId);
1181 }
1182 return null;
1183 }
1184 } finally {
1185 Binder.restoreCallingIdentity(ident);
1186 }
1187 }
1188
1189 @Override
1190 public void setFocusedStack(int stackId) {
1191 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "setFocusedStack()");
1192 if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedStack: stackId=" + stackId);
1193 final long callingId = Binder.clearCallingIdentity();
1194 try {
1195 synchronized (mGlobalLock) {
1196 final ActivityStack stack = mStackSupervisor.getStack(stackId);
1197 if (stack == null) {
1198 Slog.w(TAG, "setFocusedStack: No stack with id=" + stackId);
1199 return;
1200 }
1201 final ActivityRecord r = stack.topRunningActivityLocked();
1202 if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(
1203 r, "setFocusedStack")) {
1204 mStackSupervisor.resumeFocusedStackTopActivityLocked();
1205 }
1206 }
1207 } finally {
1208 Binder.restoreCallingIdentity(callingId);
1209 }
1210 }
1211
1212 @Override
1213 public void setFocusedTask(int taskId) {
1214 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "setFocusedTask()");
1215 if (DEBUG_FOCUS) Slog.d(TAG_FOCUS, "setFocusedTask: taskId=" + taskId);
1216 final long callingId = Binder.clearCallingIdentity();
1217 try {
1218 synchronized (mGlobalLock) {
1219 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
1220 if (task == null) {
1221 return;
1222 }
1223 final ActivityRecord r = task.topRunningActivityLocked();
1224 if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(r, "setFocusedTask")) {
1225 mStackSupervisor.resumeFocusedStackTopActivityLocked();
1226 }
1227 }
1228 } finally {
1229 Binder.restoreCallingIdentity(callingId);
1230 }
1231 }
1232
1233 @Override
1234 public boolean removeTask(int taskId) {
1235 mAm.enforceCallerIsRecentsOrHasPermission(REMOVE_TASKS, "removeTask()");
1236 synchronized (mGlobalLock) {
1237 final long ident = Binder.clearCallingIdentity();
1238 try {
1239 return mStackSupervisor.removeTaskByIdLocked(taskId, true, REMOVE_FROM_RECENTS,
1240 "remove-task");
1241 } finally {
1242 Binder.restoreCallingIdentity(ident);
1243 }
1244 }
1245 }
1246
1247 @Override
1248 public boolean shouldUpRecreateTask(IBinder token, String destAffinity) {
1249 synchronized (mGlobalLock) {
1250 final ActivityRecord srec = ActivityRecord.forTokenLocked(token);
1251 if (srec != null) {
1252 return srec.getStack().shouldUpRecreateTaskLocked(srec, destAffinity);
1253 }
1254 }
1255 return false;
1256 }
1257
1258 @Override
1259 public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
1260 Intent resultData) {
1261
1262 synchronized (mGlobalLock) {
1263 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1264 if (r != null) {
1265 return r.getStack().navigateUpToLocked(r, destIntent, resultCode, resultData);
1266 }
1267 return false;
1268 }
1269 }
1270
1271 /**
1272 * Attempts to move a task backwards in z-order (the order of activities within the task is
1273 * unchanged).
1274 *
1275 * There are several possible results of this call:
1276 * - if the task is locked, then we will show the lock toast
1277 * - if there is a task behind the provided task, then that task is made visible and resumed as
1278 * this task is moved to the back
1279 * - otherwise, if there are no other tasks in the stack:
1280 * - if this task is in the pinned stack, then we remove the stack completely, which will
1281 * have the effect of moving the task to the top or bottom of the fullscreen stack
1282 * (depending on whether it is visible)
1283 * - otherwise, we simply return home and hide this task
1284 *
1285 * @param token A reference to the activity we wish to move
1286 * @param nonRoot If false then this only works if the activity is the root
1287 * of a task; if true it will work for any activity in a task.
1288 * @return Returns true if the move completed, false if not.
1289 */
1290 @Override
1291 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) {
1292 mAm.enforceNotIsolatedCaller("moveActivityTaskToBack");
1293 synchronized (mGlobalLock) {
1294 final long origId = Binder.clearCallingIdentity();
1295 try {
1296 int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot);
1297 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
1298 if (task != null) {
1299 return ActivityRecord.getStackLocked(token).moveTaskToBackLocked(taskId);
1300 }
1301 } finally {
1302 Binder.restoreCallingIdentity(origId);
1303 }
1304 }
1305 return false;
1306 }
1307
1308 @Override
1309 public Rect getTaskBounds(int taskId) {
1310 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "getTaskBounds()");
1311 long ident = Binder.clearCallingIdentity();
1312 Rect rect = new Rect();
1313 try {
1314 synchronized (mGlobalLock) {
1315 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
1316 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
1317 if (task == null) {
1318 Slog.w(TAG, "getTaskBounds: taskId=" + taskId + " not found");
1319 return rect;
1320 }
1321 if (task.getStack() != null) {
1322 // Return the bounds from window manager since it will be adjusted for various
1323 // things like the presense of a docked stack for tasks that aren't resizeable.
1324 task.getWindowContainerBounds(rect);
1325 } else {
1326 // Task isn't in window manager yet since it isn't associated with a stack.
1327 // Return the persist value from activity manager
1328 if (!task.matchParentBounds()) {
1329 rect.set(task.getBounds());
1330 } else if (task.mLastNonFullscreenBounds != null) {
1331 rect.set(task.mLastNonFullscreenBounds);
1332 }
1333 }
1334 }
1335 } finally {
1336 Binder.restoreCallingIdentity(ident);
1337 }
1338 return rect;
1339 }
1340
1341 @Override
1342 public ActivityManager.TaskDescription getTaskDescription(int id) {
1343 synchronized (mGlobalLock) {
1344 mAm.enforceCallerIsRecentsOrHasPermission(
1345 MANAGE_ACTIVITY_STACKS, "getTaskDescription()");
1346 final TaskRecord tr = mStackSupervisor.anyTaskForIdLocked(id,
1347 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
1348 if (tr != null) {
1349 return tr.lastTaskDescription;
1350 }
1351 }
1352 return null;
1353 }
1354
1355 @Override
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001356 public void setTaskWindowingMode(int taskId, int windowingMode, boolean toTop) {
1357 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
1358 setTaskWindowingModeSplitScreenPrimary(taskId, SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT,
1359 toTop, ANIMATE, null /* initialBounds */, true /* showRecents */);
1360 return;
1361 }
1362 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setTaskWindowingMode()");
1363 synchronized (mGlobalLock) {
1364 final long ident = Binder.clearCallingIdentity();
1365 try {
1366 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
1367 if (task == null) {
1368 Slog.w(TAG, "setTaskWindowingMode: No task for id=" + taskId);
1369 return;
1370 }
1371
1372 if (DEBUG_STACK) Slog.d(TAG_STACK, "setTaskWindowingMode: moving task=" + taskId
1373 + " to windowingMode=" + windowingMode + " toTop=" + toTop);
1374
1375 if (!task.isActivityTypeStandardOrUndefined()) {
1376 throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move"
1377 + " non-standard task " + taskId + " to windowing mode="
1378 + windowingMode);
1379 }
1380
1381 final ActivityStack stack = task.getStack();
1382 if (toTop) {
1383 stack.moveToFront("setTaskWindowingMode", task);
1384 }
1385 stack.setWindowingMode(windowingMode);
1386 } finally {
1387 Binder.restoreCallingIdentity(ident);
1388 }
1389 }
1390 }
1391
1392 @Override
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001393 public String getCallingPackage(IBinder token) {
1394 synchronized (this) {
1395 ActivityRecord r = getCallingRecordLocked(token);
1396 return r != null ? r.info.packageName : null;
1397 }
1398 }
1399
1400 @Override
1401 public ComponentName getCallingActivity(IBinder token) {
1402 synchronized (this) {
1403 ActivityRecord r = getCallingRecordLocked(token);
1404 return r != null ? r.intent.getComponent() : null;
1405 }
1406 }
1407
1408 private ActivityRecord getCallingRecordLocked(IBinder token) {
1409 ActivityRecord r = ActivityRecord.isInStackLocked(token);
1410 if (r == null) {
1411 return null;
1412 }
1413 return r.resultTo;
1414 }
1415
1416 @Override
1417 public void unhandledBack() {
1418 mAm.enforceCallingPermission(android.Manifest.permission.FORCE_BACK, "unhandledBack()");
1419
1420 synchronized (mGlobalLock) {
1421 final long origId = Binder.clearCallingIdentity();
1422 try {
1423 mAm.getFocusedStack().unhandledBackLocked();
1424 } finally {
1425 Binder.restoreCallingIdentity(origId);
1426 }
1427 }
1428 }
1429
1430 /**
1431 * TODO: Add mController hook
1432 */
1433 @Override
1434 public void moveTaskToFront(int taskId, int flags, Bundle bOptions) {
1435 mAm.enforceCallingPermission(android.Manifest.permission.REORDER_TASKS, "moveTaskToFront()");
1436
1437 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
1438 synchronized (mGlobalLock) {
1439 moveTaskToFrontLocked(taskId, flags, SafeActivityOptions.fromBundle(bOptions),
1440 false /* fromRecents */);
1441 }
1442 }
1443
1444 void moveTaskToFrontLocked(int taskId, int flags, SafeActivityOptions options,
1445 boolean fromRecents) {
1446
1447 if (!mAm.checkAppSwitchAllowedLocked(Binder.getCallingPid(),
1448 Binder.getCallingUid(), -1, -1, "Task to front")) {
1449 SafeActivityOptions.abort(options);
1450 return;
1451 }
1452 final long origId = Binder.clearCallingIdentity();
1453 try {
1454 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
1455 if (task == null) {
1456 Slog.d(TAG, "Could not find task for id: "+ taskId);
1457 return;
1458 }
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07001459 if (getLockTaskController().isLockTaskModeViolation(task)) {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001460 Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
1461 return;
1462 }
1463 ActivityOptions realOptions = options != null
1464 ? options.getOptions(mStackSupervisor)
1465 : null;
1466 mStackSupervisor.findTaskToMoveToFront(task, flags, realOptions, "moveTaskToFront",
1467 false /* forceNonResizable */);
1468
1469 final ActivityRecord topActivity = task.getTopActivity();
1470 if (topActivity != null) {
1471
1472 // We are reshowing a task, use a starting window to hide the initial draw delay
1473 // so the transition can start earlier.
1474 topActivity.showStartingWindow(null /* prev */, false /* newTask */,
1475 true /* taskSwitch */, fromRecents);
1476 }
1477 } finally {
1478 Binder.restoreCallingIdentity(origId);
1479 }
1480 SafeActivityOptions.abort(options);
1481 }
1482
1483 @Override
1484 public int getTaskForActivity(IBinder token, boolean onlyRoot) {
1485 synchronized (mGlobalLock) {
1486 return ActivityRecord.getTaskForActivityLocked(token, onlyRoot);
1487 }
1488 }
1489
1490 @Override
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001491 public List<ActivityManager.RunningTaskInfo> getTasks(int maxNum) {
1492 return getFilteredTasks(maxNum, ACTIVITY_TYPE_UNDEFINED, WINDOWING_MODE_UNDEFINED);
1493 }
1494
1495 @Override
1496 public List<ActivityManager.RunningTaskInfo> getFilteredTasks(int maxNum,
1497 @WindowConfiguration.ActivityType int ignoreActivityType,
1498 @WindowConfiguration.WindowingMode int ignoreWindowingMode) {
1499 final int callingUid = Binder.getCallingUid();
1500 ArrayList<ActivityManager.RunningTaskInfo> list = new ArrayList<>();
1501
1502 synchronized (mGlobalLock) {
1503 if (DEBUG_ALL) Slog.v(TAG, "getTasks: max=" + maxNum);
1504
1505 final boolean allowed = mAm.isGetTasksAllowed("getTasks", Binder.getCallingPid(),
1506 callingUid);
1507 mStackSupervisor.getRunningTasks(maxNum, list, ignoreActivityType,
1508 ignoreWindowingMode, callingUid, allowed);
1509 }
1510
1511 return list;
1512 }
1513
1514 @Override
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001515 public final void finishSubActivity(IBinder token, String resultWho, int requestCode) {
1516 synchronized (mGlobalLock) {
1517 final long origId = Binder.clearCallingIdentity();
1518 ActivityRecord r = ActivityRecord.isInStackLocked(token);
1519 if (r != null) {
1520 r.getStack().finishSubActivityLocked(r, resultWho, requestCode);
1521 }
1522 Binder.restoreCallingIdentity(origId);
1523 }
1524 }
1525
1526 @Override
1527 public boolean willActivityBeVisible(IBinder token) {
1528 synchronized(this) {
1529 ActivityStack stack = ActivityRecord.getStackLocked(token);
1530 if (stack != null) {
1531 return stack.willActivityBeVisibleLocked(token);
1532 }
1533 return false;
1534 }
1535 }
1536
1537 @Override
Wale Ogunwale65ebd952018-04-25 15:41:44 -07001538 public void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1539 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "moveTaskToStack()");
1540 synchronized (mGlobalLock) {
1541 final long ident = Binder.clearCallingIdentity();
1542 try {
1543 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
1544 if (task == null) {
1545 Slog.w(TAG, "moveTaskToStack: No task for id=" + taskId);
1546 return;
1547 }
1548
1549 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToStack: moving task=" + taskId
1550 + " to stackId=" + stackId + " toTop=" + toTop);
1551
1552 final ActivityStack stack = mStackSupervisor.getStack(stackId);
1553 if (stack == null) {
1554 throw new IllegalStateException(
1555 "moveTaskToStack: No stack for stackId=" + stackId);
1556 }
1557 if (!stack.isActivityTypeStandardOrUndefined()) {
1558 throw new IllegalArgumentException("moveTaskToStack: Attempt to move task "
1559 + taskId + " to stack " + stackId);
1560 }
1561 if (stack.inSplitScreenPrimaryWindowingMode()) {
1562 mAm.mWindowManager.setDockedStackCreateState(
1563 SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
1564 }
1565 task.reparent(stack, toTop, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE, !DEFER_RESUME,
1566 "moveTaskToStack");
1567 } finally {
1568 Binder.restoreCallingIdentity(ident);
1569 }
1570 }
1571 }
1572
1573 @Override
1574 public void resizeStack(int stackId, Rect destBounds, boolean allowResizeInDockedMode,
1575 boolean preserveWindows, boolean animate, int animationDuration) {
1576 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeStack()");
1577
1578 final long ident = Binder.clearCallingIdentity();
1579 try {
1580 synchronized (mGlobalLock) {
1581 if (animate) {
1582 final PinnedActivityStack stack = mStackSupervisor.getStack(stackId);
1583 if (stack == null) {
1584 Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
1585 return;
1586 }
1587 if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
1588 throw new IllegalArgumentException("Stack: " + stackId
1589 + " doesn't support animated resize.");
1590 }
1591 stack.animateResizePinnedStack(null /* sourceHintBounds */, destBounds,
1592 animationDuration, false /* fromFullscreen */);
1593 } else {
1594 final ActivityStack stack = mStackSupervisor.getStack(stackId);
1595 if (stack == null) {
1596 Slog.w(TAG, "resizeStack: stackId " + stackId + " not found.");
1597 return;
1598 }
1599 mStackSupervisor.resizeStackLocked(stack, destBounds,
1600 null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
1601 preserveWindows, allowResizeInDockedMode, !DEFER_RESUME);
1602 }
1603 }
1604 } finally {
1605 Binder.restoreCallingIdentity(ident);
1606 }
1607 }
1608
1609 /**
1610 * Moves the specified task to the primary-split-screen stack.
1611 *
1612 * @param taskId Id of task to move.
1613 * @param createMode The mode the primary split screen stack should be created in if it doesn't
1614 * exist already. See
1615 * {@link android.app.ActivityTaskManager#SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT}
1616 * and
1617 * {@link android.app.ActivityTaskManager#SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT}
1618 * @param toTop If the task and stack should be moved to the top.
1619 * @param animate Whether we should play an animation for the moving the task.
1620 * @param initialBounds If the primary stack gets created, it will use these bounds for the
1621 * stack. Pass {@code null} to use default bounds.
1622 * @param showRecents If the recents activity should be shown on the other side of the task
1623 * going into split-screen mode.
1624 */
1625 @Override
1626 public boolean setTaskWindowingModeSplitScreenPrimary(int taskId, int createMode,
1627 boolean toTop, boolean animate, Rect initialBounds, boolean showRecents) {
1628 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
1629 "setTaskWindowingModeSplitScreenPrimary()");
1630 synchronized (mGlobalLock) {
1631 final long ident = Binder.clearCallingIdentity();
1632 try {
1633 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
1634 if (task == null) {
1635 Slog.w(TAG, "setTaskWindowingModeSplitScreenPrimary: No task for id=" + taskId);
1636 return false;
1637 }
1638 if (DEBUG_STACK) Slog.d(TAG_STACK,
1639 "setTaskWindowingModeSplitScreenPrimary: moving task=" + taskId
1640 + " to createMode=" + createMode + " toTop=" + toTop);
1641 if (!task.isActivityTypeStandardOrUndefined()) {
1642 throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move"
1643 + " non-standard task " + taskId + " to split-screen windowing mode");
1644 }
1645
1646 mAm.mWindowManager.setDockedStackCreateState(createMode, initialBounds);
1647 final int windowingMode = task.getWindowingMode();
1648 final ActivityStack stack = task.getStack();
1649 if (toTop) {
1650 stack.moveToFront("setTaskWindowingModeSplitScreenPrimary", task);
1651 }
1652 stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, animate, showRecents,
1653 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */);
1654 return windowingMode != task.getWindowingMode();
1655 } finally {
1656 Binder.restoreCallingIdentity(ident);
1657 }
1658 }
1659 }
1660
1661 /**
1662 * Removes stacks in the input windowing modes from the system if they are of activity type
1663 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
1664 */
1665 @Override
1666 public void removeStacksInWindowingModes(int[] windowingModes) {
1667 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
1668 "removeStacksInWindowingModes()");
1669
1670 synchronized (mGlobalLock) {
1671 final long ident = Binder.clearCallingIdentity();
1672 try {
1673 mStackSupervisor.removeStacksInWindowingModes(windowingModes);
1674 } finally {
1675 Binder.restoreCallingIdentity(ident);
1676 }
1677 }
1678 }
1679
1680 @Override
1681 public void removeStacksWithActivityTypes(int[] activityTypes) {
1682 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
1683 "removeStacksWithActivityTypes()");
1684
1685 synchronized (mGlobalLock) {
1686 final long ident = Binder.clearCallingIdentity();
1687 try {
1688 mStackSupervisor.removeStacksWithActivityTypes(activityTypes);
1689 } finally {
1690 Binder.restoreCallingIdentity(ident);
1691 }
1692 }
1693 }
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001694
1695 @Override
1696 public ParceledListSlice<ActivityManager.RecentTaskInfo> getRecentTasks(int maxNum, int flags,
1697 int userId) {
1698 final int callingUid = Binder.getCallingUid();
1699 userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(), callingUid, userId,
1700 false, ALLOW_FULL_ONLY, "getRecentTasks", null);
1701 final boolean allowed = mAm.isGetTasksAllowed("getRecentTasks", Binder.getCallingPid(),
1702 callingUid);
1703 final boolean detailed = mAm.checkCallingPermission(
1704 android.Manifest.permission.GET_DETAILED_TASKS)
1705 == PackageManager.PERMISSION_GRANTED;
1706
1707 synchronized (mGlobalLock) {
Wale Ogunwale16e505a2018-05-07 15:00:49 -07001708 return mRecentTasks.getRecentTasks(maxNum, flags, allowed, detailed, userId,
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001709 callingUid);
1710 }
1711 }
1712
1713 @Override
1714 public List<ActivityManager.StackInfo> getAllStackInfos() {
1715 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getAllStackInfos()");
1716 long ident = Binder.clearCallingIdentity();
1717 try {
1718 synchronized (mGlobalLock) {
1719 return mStackSupervisor.getAllStackInfosLocked();
1720 }
1721 } finally {
1722 Binder.restoreCallingIdentity(ident);
1723 }
1724 }
1725
1726 @Override
1727 public ActivityManager.StackInfo getStackInfo(int windowingMode, int activityType) {
1728 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "getStackInfo()");
1729 long ident = Binder.clearCallingIdentity();
1730 try {
1731 synchronized (mGlobalLock) {
1732 return mStackSupervisor.getStackInfo(windowingMode, activityType);
1733 }
1734 } finally {
1735 Binder.restoreCallingIdentity(ident);
1736 }
1737 }
1738
1739 @Override
1740 public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
1741 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "cancelRecentsAnimation()");
1742 final long callingUid = Binder.getCallingUid();
1743 final long origId = Binder.clearCallingIdentity();
1744 try {
1745 synchronized (mGlobalLock) {
1746 // Cancel the recents animation synchronously (do not hold the WM lock)
1747 mAm.mWindowManager.cancelRecentsAnimationSynchronously(restoreHomeStackPosition
1748 ? REORDER_MOVE_TO_ORIGINAL_POSITION
1749 : REORDER_KEEP_IN_PLACE, "cancelRecentsAnimation/uid=" + callingUid);
1750 }
1751 } finally {
1752 Binder.restoreCallingIdentity(origId);
1753 }
1754 }
1755
1756 @Override
1757 public void startLockTaskModeByToken(IBinder token) {
1758 synchronized (mGlobalLock) {
1759 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1760 if (r == null) {
1761 return;
1762 }
1763 startLockTaskModeLocked(r.getTask(), false /* isSystemCaller */);
1764 }
1765 }
1766
1767 @Override
1768 public void startSystemLockTaskMode(int taskId) throws RemoteException {
1769 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "startSystemLockTaskMode");
1770 // This makes inner call to look as if it was initiated by system.
1771 long ident = Binder.clearCallingIdentity();
1772 try {
1773 synchronized (mGlobalLock) {
1774 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
1775
1776 // When starting lock task mode the stack must be in front and focused
1777 task.getStack().moveToFront("startSystemLockTaskMode");
1778 startLockTaskModeLocked(task, true /* isSystemCaller */);
1779 }
1780 } finally {
1781 Binder.restoreCallingIdentity(ident);
1782 }
1783 }
1784
1785 @Override
1786 public void stopLockTaskModeByToken(IBinder token) {
1787 synchronized (mGlobalLock) {
1788 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
1789 if (r == null) {
1790 return;
1791 }
1792 stopLockTaskModeInternal(r.getTask(), false /* isSystemCaller */);
1793 }
1794 }
1795
1796 /**
1797 * This API should be called by SystemUI only when user perform certain action to dismiss
1798 * lock task mode. We should only dismiss pinned lock task mode in this case.
1799 */
1800 @Override
1801 public void stopSystemLockTaskMode() throws RemoteException {
1802 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "stopSystemLockTaskMode");
1803 stopLockTaskModeInternal(null, true /* isSystemCaller */);
1804 }
1805
1806 private void startLockTaskModeLocked(@Nullable TaskRecord task, boolean isSystemCaller) {
1807 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "startLockTaskModeLocked: " + task);
1808 if (task == null || task.mLockTaskAuth == LOCK_TASK_AUTH_DONT_LOCK) {
1809 return;
1810 }
1811
1812 final ActivityStack stack = mStackSupervisor.getFocusedStack();
1813 if (stack == null || task != stack.topTask()) {
1814 throw new IllegalArgumentException("Invalid task, not in foreground");
1815 }
1816
1817 // {@code isSystemCaller} is used to distinguish whether this request is initiated by the
1818 // system or a specific app.
1819 // * System-initiated requests will only start the pinned mode (screen pinning)
1820 // * App-initiated requests
1821 // - will put the device in fully locked mode (LockTask), if the app is whitelisted
1822 // - will start the pinned mode, otherwise
1823 final int callingUid = Binder.getCallingUid();
1824 long ident = Binder.clearCallingIdentity();
1825 try {
1826 // When a task is locked, dismiss the pinned stack if it exists
1827 mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
1828
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07001829 getLockTaskController().startLockTaskMode(task, isSystemCaller, callingUid);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001830 } finally {
1831 Binder.restoreCallingIdentity(ident);
1832 }
1833 }
1834
1835 private void stopLockTaskModeInternal(@Nullable TaskRecord task, boolean isSystemCaller) {
1836 final int callingUid = Binder.getCallingUid();
1837 long ident = Binder.clearCallingIdentity();
1838 try {
1839 synchronized (mGlobalLock) {
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07001840 getLockTaskController().stopLockTaskMode(task, isSystemCaller, callingUid);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001841 }
1842 // Launch in-call UI if a call is ongoing. This is necessary to allow stopping the lock
1843 // task and jumping straight into a call in the case of emergency call back.
1844 TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE);
1845 if (tm != null) {
1846 tm.showInCallScreen(false);
1847 }
1848 } finally {
1849 Binder.restoreCallingIdentity(ident);
1850 }
1851 }
1852
1853 @Override
1854 public boolean isInLockTaskMode() {
1855 return getLockTaskModeState() != LOCK_TASK_MODE_NONE;
1856 }
1857
1858 @Override
1859 public int getLockTaskModeState() {
1860 synchronized (mGlobalLock) {
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07001861 return getLockTaskController().getLockTaskModeState();
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001862 }
1863 }
1864
1865 @Override
1866 public void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) {
1867 synchronized (mGlobalLock) {
1868 ActivityRecord r = ActivityRecord.isInStackLocked(token);
1869 if (r != null) {
1870 r.setTaskDescription(td);
1871 final TaskRecord task = r.getTask();
1872 task.updateTaskDescription();
Wale Ogunwaled0412b32018-05-08 09:25:50 -07001873 mTaskChangeNotificationController.notifyTaskDescriptionChanged(task.taskId, td);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001874 }
1875 }
1876 }
1877
1878 @Override
1879 public Bundle getActivityOptions(IBinder token) {
1880 final long origId = Binder.clearCallingIdentity();
1881 try {
1882 synchronized (mGlobalLock) {
1883 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
1884 if (r != null) {
1885 final ActivityOptions activityOptions = r.takeOptionsLocked();
1886 return activityOptions == null ? null : activityOptions.toBundle();
1887 }
1888 return null;
1889 }
1890 } finally {
1891 Binder.restoreCallingIdentity(origId);
1892 }
1893 }
1894
1895 @Override
1896 public List<IBinder> getAppTasks(String callingPackage) {
1897 int callingUid = Binder.getCallingUid();
1898 long ident = Binder.clearCallingIdentity();
1899 try {
1900 synchronized (mGlobalLock) {
Wale Ogunwale16e505a2018-05-07 15:00:49 -07001901 return mRecentTasks.getAppTasksList(callingUid, callingPackage);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001902 }
1903 } finally {
1904 Binder.restoreCallingIdentity(ident);
1905 }
1906 }
1907
1908 @Override
1909 public void finishVoiceTask(IVoiceInteractionSession session) {
1910 synchronized (mGlobalLock) {
1911 final long origId = Binder.clearCallingIdentity();
1912 try {
1913 // TODO: VI Consider treating local voice interactions and voice tasks
1914 // differently here
1915 mStackSupervisor.finishVoiceTask(session);
1916 } finally {
1917 Binder.restoreCallingIdentity(origId);
1918 }
1919 }
1920
1921 }
1922
1923 @Override
1924 public boolean isTopOfTask(IBinder token) {
1925 synchronized (mGlobalLock) {
1926 ActivityRecord r = ActivityRecord.isInStackLocked(token);
1927 if (r == null) {
1928 throw new IllegalArgumentException();
1929 }
1930 return r.getTask().getTopActivity() == r;
1931 }
1932 }
1933
1934 @Override
1935 public void notifyLaunchTaskBehindComplete(IBinder token) {
1936 mStackSupervisor.scheduleLaunchTaskBehindComplete(token);
1937 }
1938
1939 @Override
1940 public void notifyEnterAnimationComplete(IBinder token) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07001941 mH.post(() -> {
1942 synchronized (mGlobalLock) {
1943 ActivityRecord r = ActivityRecord.forTokenLocked(token);
1944 if (r != null && r.app != null && r.app.thread != null) {
1945 try {
1946 r.app.thread.scheduleEnterAnimationComplete(r.appToken);
1947 } catch (RemoteException e) {
1948 }
1949 }
1950 }
1951
1952 });
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07001953 }
1954
1955 /** Called from an app when assist data is ready. */
1956 @Override
1957 public void reportAssistContextExtras(IBinder token, Bundle extras, AssistStructure structure,
1958 AssistContent content, Uri referrer) {
1959 PendingAssistExtras pae = (PendingAssistExtras)token;
1960 synchronized (pae) {
1961 pae.result = extras;
1962 pae.structure = structure;
1963 pae.content = content;
1964 if (referrer != null) {
1965 pae.extras.putParcelable(Intent.EXTRA_REFERRER, referrer);
1966 }
1967 if (structure != null) {
1968 structure.setHomeActivity(pae.isHome);
1969 }
1970 pae.haveResult = true;
1971 pae.notifyAll();
1972 if (pae.intent == null && pae.receiver == null) {
1973 // Caller is just waiting for the result.
1974 return;
1975 }
1976 }
1977 // We are now ready to launch the assist activity.
1978 IAssistDataReceiver sendReceiver = null;
1979 Bundle sendBundle = null;
1980 synchronized (mGlobalLock) {
1981 buildAssistBundleLocked(pae, extras);
1982 boolean exists = mPendingAssistExtras.remove(pae);
1983 mAm.mUiHandler.removeCallbacks(pae);
1984 if (!exists) {
1985 // Timed out.
1986 return;
1987 }
1988
1989 if ((sendReceiver=pae.receiver) != null) {
1990 // Caller wants result sent back to them.
1991 sendBundle = new Bundle();
1992 sendBundle.putBundle(ASSIST_KEY_DATA, pae.extras);
1993 sendBundle.putParcelable(ASSIST_KEY_STRUCTURE, pae.structure);
1994 sendBundle.putParcelable(ASSIST_KEY_CONTENT, pae.content);
1995 sendBundle.putBundle(ASSIST_KEY_RECEIVER_EXTRAS, pae.receiverExtras);
1996 }
1997 }
1998 if (sendReceiver != null) {
1999 try {
2000 sendReceiver.onHandleAssistData(sendBundle);
2001 } catch (RemoteException e) {
2002 }
2003 return;
2004 }
2005
2006 final long ident = Binder.clearCallingIdentity();
2007 try {
2008 if (TextUtils.equals(pae.intent.getAction(),
2009 android.service.voice.VoiceInteractionService.SERVICE_INTERFACE)) {
2010 pae.intent.putExtras(pae.extras);
2011 mContext.startServiceAsUser(pae.intent, new UserHandle(pae.userHandle));
2012 } else {
2013 pae.intent.replaceExtras(pae.extras);
2014 pae.intent.setFlags(FLAG_ACTIVITY_NEW_TASK
2015 | Intent.FLAG_ACTIVITY_SINGLE_TOP
2016 | Intent.FLAG_ACTIVITY_CLEAR_TOP);
2017 mAm.closeSystemDialogs("assist");
2018
2019 try {
2020 mContext.startActivityAsUser(pae.intent, new UserHandle(pae.userHandle));
2021 } catch (ActivityNotFoundException e) {
2022 Slog.w(TAG, "No activity to handle assist action.", e);
2023 }
2024 }
2025 } finally {
2026 Binder.restoreCallingIdentity(ident);
2027 }
2028 }
2029
2030 @Override
2031 public int addAppTask(IBinder activityToken, Intent intent,
2032 ActivityManager.TaskDescription description, Bitmap thumbnail) throws RemoteException {
2033 final int callingUid = Binder.getCallingUid();
2034 final long callingIdent = Binder.clearCallingIdentity();
2035
2036 try {
2037 synchronized (mGlobalLock) {
2038 ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
2039 if (r == null) {
2040 throw new IllegalArgumentException("Activity does not exist; token="
2041 + activityToken);
2042 }
2043 ComponentName comp = intent.getComponent();
2044 if (comp == null) {
2045 throw new IllegalArgumentException("Intent " + intent
2046 + " must specify explicit component");
2047 }
2048 if (thumbnail.getWidth() != mAm.mThumbnailWidth
2049 || thumbnail.getHeight() != mAm.mThumbnailHeight) {
2050 throw new IllegalArgumentException("Bad thumbnail size: got "
2051 + thumbnail.getWidth() + "x" + thumbnail.getHeight() + ", require "
2052 + mAm.mThumbnailWidth + "x" + mAm.mThumbnailHeight);
2053 }
2054 if (intent.getSelector() != null) {
2055 intent.setSelector(null);
2056 }
2057 if (intent.getSourceBounds() != null) {
2058 intent.setSourceBounds(null);
2059 }
2060 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_NEW_DOCUMENT) != 0) {
2061 if ((intent.getFlags()&Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS) == 0) {
2062 // The caller has added this as an auto-remove task... that makes no
2063 // sense, so turn off auto-remove.
2064 intent.addFlags(Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
2065 }
2066 }
2067 final ActivityInfo ainfo = AppGlobals.getPackageManager().getActivityInfo(comp,
2068 STOCK_PM_FLAGS, UserHandle.getUserId(callingUid));
2069 if (ainfo.applicationInfo.uid != callingUid) {
2070 throw new SecurityException(
2071 "Can't add task for another application: target uid="
2072 + ainfo.applicationInfo.uid + ", calling uid=" + callingUid);
2073 }
2074
2075 final ActivityStack stack = r.getStack();
2076 final TaskRecord task = stack.createTaskRecord(
2077 mStackSupervisor.getNextTaskIdForUserLocked(r.userId), ainfo, intent,
2078 null /* voiceSession */, null /* voiceInteractor */, !ON_TOP);
Wale Ogunwale16e505a2018-05-07 15:00:49 -07002079 if (!mRecentTasks.addToBottom(task)) {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002080 // The app has too many tasks already and we can't add any more
2081 stack.removeTask(task, "addAppTask", REMOVE_TASK_MODE_DESTROYING);
2082 return INVALID_TASK_ID;
2083 }
2084 task.lastTaskDescription.copyFrom(description);
2085
2086 // TODO: Send the thumbnail to WM to store it.
2087
2088 return task.taskId;
2089 }
2090 } finally {
2091 Binder.restoreCallingIdentity(callingIdent);
2092 }
2093 }
2094
2095 @Override
2096 public Point getAppTaskThumbnailSize() {
2097 synchronized (mGlobalLock) {
2098 return new Point(mAm.mThumbnailWidth, mAm.mThumbnailHeight);
2099 }
2100 }
2101
2102 @Override
2103 public void setTaskResizeable(int taskId, int resizeableMode) {
2104 synchronized (mGlobalLock) {
2105 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(
2106 taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
2107 if (task == null) {
2108 Slog.w(TAG, "setTaskResizeable: taskId=" + taskId + " not found");
2109 return;
2110 }
2111 task.setResizeMode(resizeableMode);
2112 }
2113 }
2114
2115 @Override
2116 public void resizeTask(int taskId, Rect bounds, int resizeMode) {
2117 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "resizeTask()");
2118 long ident = Binder.clearCallingIdentity();
2119 try {
2120 synchronized (mGlobalLock) {
2121 TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
2122 if (task == null) {
2123 Slog.w(TAG, "resizeTask: taskId=" + taskId + " not found");
2124 return;
2125 }
2126 // Place the task in the right stack if it isn't there already based on
2127 // the requested bounds.
2128 // The stack transition logic is:
2129 // - a null bounds on a freeform task moves that task to fullscreen
2130 // - a non-null bounds on a non-freeform (fullscreen OR docked) task moves
2131 // that task to freeform
2132 // - otherwise the task is not moved
2133 ActivityStack stack = task.getStack();
2134 if (!task.getWindowConfiguration().canResizeTask()) {
2135 throw new IllegalArgumentException("resizeTask not allowed on task=" + task);
2136 }
2137 if (bounds == null && stack.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
2138 stack = stack.getDisplay().getOrCreateStack(
2139 WINDOWING_MODE_FULLSCREEN, stack.getActivityType(), ON_TOP);
2140 } else if (bounds != null && stack.getWindowingMode() != WINDOWING_MODE_FREEFORM) {
2141 stack = stack.getDisplay().getOrCreateStack(
2142 WINDOWING_MODE_FREEFORM, stack.getActivityType(), ON_TOP);
2143 }
2144
2145 // Reparent the task to the right stack if necessary
2146 boolean preserveWindow = (resizeMode & RESIZE_MODE_PRESERVE_WINDOW) != 0;
2147 if (stack != task.getStack()) {
2148 // Defer resume until the task is resized below
2149 task.reparent(stack, ON_TOP, REPARENT_KEEP_STACK_AT_FRONT, ANIMATE,
2150 DEFER_RESUME, "resizeTask");
2151 preserveWindow = false;
2152 }
2153
2154 // After reparenting (which only resizes the task to the stack bounds), resize the
2155 // task to the actual bounds provided
2156 task.resize(bounds, resizeMode, preserveWindow, !DEFER_RESUME);
2157 }
2158 } finally {
2159 Binder.restoreCallingIdentity(ident);
2160 }
2161 }
2162
2163 @Override
2164 public boolean releaseActivityInstance(IBinder token) {
2165 synchronized (mGlobalLock) {
2166 final long origId = Binder.clearCallingIdentity();
2167 try {
2168 ActivityRecord r = ActivityRecord.isInStackLocked(token);
2169 if (r == null) {
2170 return false;
2171 }
2172 return r.getStack().safelyDestroyActivityLocked(r, "app-req");
2173 } finally {
2174 Binder.restoreCallingIdentity(origId);
2175 }
2176 }
2177 }
2178
2179 @Override
2180 public void releaseSomeActivities(IApplicationThread appInt) {
2181 synchronized (mGlobalLock) {
2182 final long origId = Binder.clearCallingIdentity();
2183 try {
2184 ProcessRecord app = mAm.getRecordForAppLocked(appInt);
2185 mStackSupervisor.releaseSomeActivitiesLocked(app, "low-mem");
2186 } finally {
2187 Binder.restoreCallingIdentity(origId);
2188 }
2189 }
2190 }
2191
2192 @Override
2193 public void setLockScreenShown(boolean keyguardShowing, boolean aodShowing,
2194 int secondaryDisplayShowing) {
2195 if (mAm.checkCallingPermission(android.Manifest.permission.DEVICE_POWER)
2196 != PackageManager.PERMISSION_GRANTED) {
2197 throw new SecurityException("Requires permission "
2198 + android.Manifest.permission.DEVICE_POWER);
2199 }
2200
2201 synchronized (mGlobalLock) {
2202 long ident = Binder.clearCallingIdentity();
2203 if (mKeyguardShown != keyguardShowing) {
2204 mKeyguardShown = keyguardShowing;
2205 reportCurKeyguardUsageEventLocked(keyguardShowing);
2206 }
2207 try {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002208 mKeyguardController.setKeyguardShown(keyguardShowing, aodShowing,
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002209 secondaryDisplayShowing);
2210 } finally {
2211 Binder.restoreCallingIdentity(ident);
2212 }
2213 }
2214
2215 mAm.mHandler.obtainMessage(DISPATCH_SCREEN_KEYGUARD_MSG, keyguardShowing ? 1 : 0, 0)
2216 .sendToTarget();
2217 }
2218
2219 @Override
2220 public Bitmap getTaskDescriptionIcon(String filePath, int userId) {
2221 userId = mAm.mUserController.handleIncomingUser(Binder.getCallingPid(),
2222 Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "getTaskDescriptionIcon", null);
2223
2224 final File passedIconFile = new File(filePath);
2225 final File legitIconFile = new File(TaskPersister.getUserImagesDir(userId),
2226 passedIconFile.getName());
2227 if (!legitIconFile.getPath().equals(filePath)
2228 || !filePath.contains(ActivityRecord.ACTIVITY_ICON_SUFFIX)) {
2229 throw new IllegalArgumentException("Bad file path: " + filePath
2230 + " passed for userId " + userId);
2231 }
Wale Ogunwale16e505a2018-05-07 15:00:49 -07002232 return mRecentTasks.getTaskDescriptionIcon(filePath);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002233 }
2234
2235 @Override
2236 public void startInPlaceAnimationOnFrontMostApplication(Bundle opts)
2237 throws RemoteException {
2238 final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(opts);
2239 final ActivityOptions activityOptions = safeOptions != null
2240 ? safeOptions.getOptions(mStackSupervisor)
2241 : null;
2242 if (activityOptions == null
2243 || activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE
2244 || activityOptions.getCustomInPlaceResId() == 0) {
2245 throw new IllegalArgumentException("Expected in-place ActivityOption " +
2246 "with valid animation");
2247 }
2248 mAm.mWindowManager.prepareAppTransition(TRANSIT_TASK_IN_PLACE, false);
2249 mAm.mWindowManager.overridePendingAppTransitionInPlace(activityOptions.getPackageName(),
2250 activityOptions.getCustomInPlaceResId());
2251 mAm.mWindowManager.executeAppTransition();
2252 }
2253
2254 @Override
2255 public void removeStack(int stackId) {
2256 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "removeStack()");
2257 synchronized (mGlobalLock) {
2258 final long ident = Binder.clearCallingIdentity();
2259 try {
2260 final ActivityStack stack = mStackSupervisor.getStack(stackId);
2261 if (stack == null) {
2262 Slog.w(TAG, "removeStack: No stack with id=" + stackId);
2263 return;
2264 }
2265 if (!stack.isActivityTypeStandardOrUndefined()) {
2266 throw new IllegalArgumentException(
2267 "Removing non-standard stack is not allowed.");
2268 }
2269 mStackSupervisor.removeStack(stack);
2270 } finally {
2271 Binder.restoreCallingIdentity(ident);
2272 }
2273 }
2274 }
2275
2276 @Override
2277 public void moveStackToDisplay(int stackId, int displayId) {
2278 mAm.enforceCallingPermission(INTERNAL_SYSTEM_WINDOW, "moveStackToDisplay()");
2279
2280 synchronized (mGlobalLock) {
2281 final long ident = Binder.clearCallingIdentity();
2282 try {
2283 if (DEBUG_STACK) Slog.d(TAG_STACK, "moveStackToDisplay: moving stackId=" + stackId
2284 + " to displayId=" + displayId);
2285 mStackSupervisor.moveStackToDisplayLocked(stackId, displayId, ON_TOP);
2286 } finally {
2287 Binder.restoreCallingIdentity(ident);
2288 }
2289 }
2290 }
2291
2292 @Override
2293 public int createStackOnDisplay(int displayId) {
2294 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "createStackOnDisplay()");
2295 synchronized (mGlobalLock) {
2296 final ActivityDisplay display =
2297 mStackSupervisor.getActivityDisplayOrCreateLocked(displayId);
2298 if (display == null) {
2299 return INVALID_STACK_ID;
2300 }
2301 // TODO(multi-display): Have the caller pass in the windowing mode and activity type.
2302 final ActivityStack stack = display.createStack(
2303 WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
2304 ON_TOP);
2305 return (stack != null) ? stack.mStackId : INVALID_STACK_ID;
2306 }
2307 }
2308
2309 @Override
2310 public void exitFreeformMode(IBinder token) {
2311 synchronized (mGlobalLock) {
2312 long ident = Binder.clearCallingIdentity();
2313 try {
2314 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2315 if (r == null) {
2316 throw new IllegalArgumentException(
2317 "exitFreeformMode: No activity record matching token=" + token);
2318 }
2319
2320 final ActivityStack stack = r.getStack();
2321 if (stack == null || !stack.inFreeformWindowingMode()) {
2322 throw new IllegalStateException(
2323 "exitFreeformMode: You can only go fullscreen from freeform.");
2324 }
2325
2326 stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
2327 } finally {
2328 Binder.restoreCallingIdentity(ident);
2329 }
2330 }
2331 }
2332
2333 /** Sets the task stack listener that gets callbacks when a task stack changes. */
2334 @Override
2335 public void registerTaskStackListener(ITaskStackListener listener) {
2336 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
2337 "registerTaskStackListener()");
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002338 mTaskChangeNotificationController.registerTaskStackListener(listener);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002339 }
2340
2341 /** Unregister a task stack listener so that it stops receiving callbacks. */
2342 @Override
2343 public void unregisterTaskStackListener(ITaskStackListener listener) {
2344 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
2345 "unregisterTaskStackListener()");
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002346 mTaskChangeNotificationController.unregisterTaskStackListener(listener);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002347 }
2348
2349 private void reportCurKeyguardUsageEventLocked(boolean keyguardShowing) {
2350 mAm.reportGlobalUsageEventLocked(keyguardShowing
2351 ? UsageEvents.Event.KEYGUARD_SHOWN
2352 : UsageEvents.Event.KEYGUARD_HIDDEN);
2353 }
2354
2355 @Override
2356 public boolean requestAssistContextExtras(int requestType, IAssistDataReceiver receiver,
2357 Bundle receiverExtras, IBinder activityToken, boolean focused, boolean newSessionId) {
2358 return enqueueAssistContext(requestType, null, null, receiver, receiverExtras,
2359 activityToken, focused, newSessionId, UserHandle.getCallingUserId(), null,
2360 PENDING_ASSIST_EXTRAS_LONG_TIMEOUT, 0) != null;
2361 }
2362
2363 @Override
2364 public boolean requestAutofillData(IAssistDataReceiver receiver, Bundle receiverExtras,
2365 IBinder activityToken, int flags) {
2366 return enqueueAssistContext(ActivityManager.ASSIST_CONTEXT_AUTOFILL, null, null,
2367 receiver, receiverExtras, activityToken, true, true, UserHandle.getCallingUserId(),
2368 null, PENDING_AUTOFILL_ASSIST_STRUCTURE_TIMEOUT, flags) != null;
2369 }
2370
2371 @Override
2372 public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
2373 Bundle args) {
2374 return enqueueAssistContext(requestType, intent, hint, null, null, null,
2375 true /* focused */, true /* newSessionId */, userHandle, args,
2376 PENDING_ASSIST_EXTRAS_TIMEOUT, 0) != null;
2377 }
2378
2379 @Override
2380 public Bundle getAssistContextExtras(int requestType) {
2381 PendingAssistExtras pae = enqueueAssistContext(requestType, null, null, null,
2382 null, null, true /* focused */, true /* newSessionId */,
2383 UserHandle.getCallingUserId(), null, PENDING_ASSIST_EXTRAS_TIMEOUT, 0);
2384 if (pae == null) {
2385 return null;
2386 }
2387 synchronized (pae) {
2388 while (!pae.haveResult) {
2389 try {
2390 pae.wait();
2391 } catch (InterruptedException e) {
2392 }
2393 }
2394 }
2395 synchronized (mGlobalLock) {
2396 buildAssistBundleLocked(pae, pae.result);
2397 mPendingAssistExtras.remove(pae);
2398 mAm.mUiHandler.removeCallbacks(pae);
2399 }
2400 return pae.extras;
2401 }
2402
2403 private PendingAssistExtras enqueueAssistContext(int requestType, Intent intent, String hint,
2404 IAssistDataReceiver receiver, Bundle receiverExtras, IBinder activityToken,
2405 boolean focused, boolean newSessionId, int userHandle, Bundle args, long timeout,
2406 int flags) {
2407 mAm.enforceCallingPermission(android.Manifest.permission.GET_TOP_ACTIVITY_INFO,
2408 "enqueueAssistContext()");
2409
2410 synchronized (mGlobalLock) {
2411 ActivityRecord activity = mAm.getFocusedStack().getTopActivity();
2412 if (activity == null) {
2413 Slog.w(TAG, "getAssistContextExtras failed: no top activity");
2414 return null;
2415 }
2416 if (activity.app == null || activity.app.thread == null) {
2417 Slog.w(TAG, "getAssistContextExtras failed: no process for " + activity);
2418 return null;
2419 }
2420 if (focused) {
2421 if (activityToken != null) {
2422 ActivityRecord caller = ActivityRecord.forTokenLocked(activityToken);
2423 if (activity != caller) {
2424 Slog.w(TAG, "enqueueAssistContext failed: caller " + caller
2425 + " is not current top " + activity);
2426 return null;
2427 }
2428 }
2429 } else {
2430 activity = ActivityRecord.forTokenLocked(activityToken);
2431 if (activity == null) {
2432 Slog.w(TAG, "enqueueAssistContext failed: activity for token=" + activityToken
2433 + " couldn't be found");
2434 return null;
2435 }
2436 if (activity.app == null || activity.app.thread == null) {
2437 Slog.w(TAG, "enqueueAssistContext failed: no process for " + activity);
2438 return null;
2439 }
2440 }
2441
2442 PendingAssistExtras pae;
2443 Bundle extras = new Bundle();
2444 if (args != null) {
2445 extras.putAll(args);
2446 }
2447 extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
2448 extras.putInt(Intent.EXTRA_ASSIST_UID, activity.app.uid);
2449
2450 pae = new PendingAssistExtras(activity, extras, intent, hint, receiver, receiverExtras,
2451 userHandle);
2452 pae.isHome = activity.isActivityTypeHome();
2453
2454 // Increment the sessionId if necessary
2455 if (newSessionId) {
2456 mViSessionId++;
2457 }
2458 try {
2459 activity.app.thread.requestAssistContextExtras(activity.appToken, pae, requestType,
2460 mViSessionId, flags);
2461 mPendingAssistExtras.add(pae);
2462 mAm.mUiHandler.postDelayed(pae, timeout);
2463 } catch (RemoteException e) {
2464 Slog.w(TAG, "getAssistContextExtras failed: crash calling " + activity);
2465 return null;
2466 }
2467 return pae;
2468 }
2469 }
2470
2471 private void buildAssistBundleLocked(PendingAssistExtras pae, Bundle result) {
2472 if (result != null) {
2473 pae.extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, result);
2474 }
2475 if (pae.hint != null) {
2476 pae.extras.putBoolean(pae.hint, true);
2477 }
2478 }
2479
2480 private void pendingAssistExtrasTimedOut(PendingAssistExtras pae) {
2481 IAssistDataReceiver receiver;
2482 synchronized (mGlobalLock) {
2483 mPendingAssistExtras.remove(pae);
2484 receiver = pae.receiver;
2485 }
2486 if (receiver != null) {
2487 // Caller wants result sent back to them.
2488 Bundle sendBundle = new Bundle();
2489 // At least return the receiver extras
2490 sendBundle.putBundle(ASSIST_KEY_RECEIVER_EXTRAS, pae.receiverExtras);
2491 try {
2492 pae.receiver.onHandleAssistData(sendBundle);
2493 } catch (RemoteException e) {
2494 }
2495 }
2496 }
2497
2498 public class PendingAssistExtras extends Binder implements Runnable {
2499 public final ActivityRecord activity;
2500 public boolean isHome;
2501 public final Bundle extras;
2502 public final Intent intent;
2503 public final String hint;
2504 public final IAssistDataReceiver receiver;
2505 public final int userHandle;
2506 public boolean haveResult = false;
2507 public Bundle result = null;
2508 public AssistStructure structure = null;
2509 public AssistContent content = null;
2510 public Bundle receiverExtras;
2511
2512 public PendingAssistExtras(ActivityRecord _activity, Bundle _extras, Intent _intent,
2513 String _hint, IAssistDataReceiver _receiver, Bundle _receiverExtras,
2514 int _userHandle) {
2515 activity = _activity;
2516 extras = _extras;
2517 intent = _intent;
2518 hint = _hint;
2519 receiver = _receiver;
2520 receiverExtras = _receiverExtras;
2521 userHandle = _userHandle;
2522 }
2523
2524 @Override
2525 public void run() {
2526 Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from " + activity);
2527 synchronized (this) {
2528 haveResult = true;
2529 notifyAll();
2530 }
2531 pendingAssistExtrasTimedOut(this);
2532 }
2533 }
2534
2535 @Override
2536 public boolean isAssistDataAllowedOnCurrentActivity() {
2537 int userId;
2538 synchronized (mGlobalLock) {
2539 final ActivityStack focusedStack = mAm.getFocusedStack();
2540 if (focusedStack == null || focusedStack.isActivityTypeAssistant()) {
2541 return false;
2542 }
2543
2544 final ActivityRecord activity = focusedStack.getTopActivity();
2545 if (activity == null) {
2546 return false;
2547 }
2548 userId = activity.userId;
2549 }
2550 return !DevicePolicyCache.getInstance().getScreenCaptureDisabled(userId);
2551 }
2552
2553 @Override
2554 public boolean showAssistFromActivity(IBinder token, Bundle args) {
2555 long ident = Binder.clearCallingIdentity();
2556 try {
2557 synchronized (mGlobalLock) {
2558 ActivityRecord caller = ActivityRecord.forTokenLocked(token);
2559 ActivityRecord top = mAm.getFocusedStack().getTopActivity();
2560 if (top != caller) {
2561 Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
2562 + " is not current top " + top);
2563 return false;
2564 }
2565 if (!top.nowVisible) {
2566 Slog.w(TAG, "showAssistFromActivity failed: caller " + caller
2567 + " is not visible");
2568 return false;
2569 }
2570 }
2571 return mAssistUtils.showSessionForActiveService(args, SHOW_SOURCE_APPLICATION, null,
2572 token);
2573 } finally {
2574 Binder.restoreCallingIdentity(ident);
2575 }
2576 }
2577
2578 @Override
2579 public boolean isRootVoiceInteraction(IBinder token) {
2580 synchronized (mGlobalLock) {
2581 ActivityRecord r = ActivityRecord.isInStackLocked(token);
2582 if (r == null) {
2583 return false;
2584 }
2585 return r.rootVoiceInteraction;
2586 }
2587 }
2588
2589 @Override
2590 public ComponentName getActivityClassForToken(IBinder token) {
2591 synchronized (mGlobalLock) {
2592 ActivityRecord r = ActivityRecord.isInStackLocked(token);
2593 if (r == null) {
2594 return null;
2595 }
2596 return r.intent.getComponent();
2597 }
2598 }
2599
2600 @Override
2601 public String getPackageForToken(IBinder token) {
2602 synchronized (mGlobalLock) {
2603 ActivityRecord r = ActivityRecord.isInStackLocked(token);
2604 if (r == null) {
2605 return null;
2606 }
2607 return r.packageName;
2608 }
2609 }
2610
2611 @Override
2612 public void showLockTaskEscapeMessage(IBinder token) {
2613 synchronized (mGlobalLock) {
2614 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2615 if (r == null) {
2616 return;
2617 }
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07002618 getLockTaskController().showLockTaskToast();
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002619 }
2620 }
2621
2622 @Override
2623 public void keyguardGoingAway(int flags) {
2624 mAm.enforceNotIsolatedCaller("keyguardGoingAway");
2625 final long token = Binder.clearCallingIdentity();
2626 try {
2627 synchronized (mGlobalLock) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002628 mKeyguardController.keyguardGoingAway(flags);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002629 }
2630 } finally {
2631 Binder.restoreCallingIdentity(token);
2632 }
2633 }
2634
2635 /**
2636 * Try to place task to provided position. The final position might be different depending on
2637 * current user and stacks state. The task will be moved to target stack if it's currently in
2638 * different stack.
2639 */
2640 @Override
2641 public void positionTaskInStack(int taskId, int stackId, int position) {
2642 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "positionTaskInStack()");
2643 synchronized (mGlobalLock) {
2644 long ident = Binder.clearCallingIdentity();
2645 try {
2646 if (DEBUG_STACK) Slog.d(TAG_STACK, "positionTaskInStack: positioning task="
2647 + taskId + " in stackId=" + stackId + " at position=" + position);
2648 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
2649 if (task == null) {
2650 throw new IllegalArgumentException("positionTaskInStack: no task for id="
2651 + taskId);
2652 }
2653
2654 final ActivityStack stack = mStackSupervisor.getStack(stackId);
2655
2656 if (stack == null) {
2657 throw new IllegalArgumentException("positionTaskInStack: no stack for id="
2658 + stackId);
2659 }
2660 if (!stack.isActivityTypeStandardOrUndefined()) {
2661 throw new IllegalArgumentException("positionTaskInStack: Attempt to change"
2662 + " the position of task " + taskId + " in/to non-standard stack");
2663 }
2664
2665 // TODO: Have the callers of this API call a separate reparent method if that is
2666 // what they intended to do vs. having this method also do reparenting.
2667 if (task.getStack() == stack) {
2668 // Change position in current stack.
2669 stack.positionChildAt(task, position);
2670 } else {
2671 // Reparent to new stack.
2672 task.reparent(stack, position, REPARENT_LEAVE_STACK_IN_PLACE, !ANIMATE,
2673 !DEFER_RESUME, "positionTaskInStack");
2674 }
2675 } finally {
2676 Binder.restoreCallingIdentity(ident);
2677 }
2678 }
2679 }
2680
2681 @Override
2682 public void reportSizeConfigurations(IBinder token, int[] horizontalSizeConfiguration,
2683 int[] verticalSizeConfigurations, int[] smallestSizeConfigurations) {
2684 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Report configuration: " + token + " "
2685 + horizontalSizeConfiguration + " " + verticalSizeConfigurations);
2686 synchronized (mGlobalLock) {
2687 ActivityRecord record = ActivityRecord.isInStackLocked(token);
2688 if (record == null) {
2689 throw new IllegalArgumentException("reportSizeConfigurations: ActivityRecord not "
2690 + "found for: " + token);
2691 }
2692 record.setSizeConfigurations(horizontalSizeConfiguration,
2693 verticalSizeConfigurations, smallestSizeConfigurations);
2694 }
2695 }
2696
2697 /**
2698 * Dismisses split-screen multi-window mode.
2699 * @param toTop If true the current primary split-screen stack will be placed or left on top.
2700 */
2701 @Override
2702 public void dismissSplitScreenMode(boolean toTop) {
2703 mAm.enforceCallerIsRecentsOrHasPermission(
2704 MANAGE_ACTIVITY_STACKS, "dismissSplitScreenMode()");
2705 final long ident = Binder.clearCallingIdentity();
2706 try {
2707 synchronized (mGlobalLock) {
2708 final ActivityStack stack =
2709 mStackSupervisor.getDefaultDisplay().getSplitScreenPrimaryStack();
2710 if (stack == null) {
2711 Slog.w(TAG, "dismissSplitScreenMode: primary split-screen stack not found.");
2712 return;
2713 }
2714
2715 if (toTop) {
2716 // Caller wants the current split-screen primary stack to be the top stack after
2717 // it goes fullscreen, so move it to the front.
2718 stack.moveToFront("dismissSplitScreenMode");
2719 } else if (mStackSupervisor.isFocusedStack(stack)) {
2720 // In this case the current split-screen primary stack shouldn't be the top
2721 // stack after it goes fullscreen, but it current has focus, so we move the
2722 // focus to the top-most split-screen secondary stack next to it.
2723 final ActivityStack otherStack = stack.getDisplay().getTopStackInWindowingMode(
2724 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
2725 if (otherStack != null) {
2726 otherStack.moveToFront("dismissSplitScreenMode_other");
2727 }
2728 }
2729
2730 stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
2731 }
2732 } finally {
2733 Binder.restoreCallingIdentity(ident);
2734 }
2735 }
2736
2737 /**
2738 * Dismisses Pip
2739 * @param animate True if the dismissal should be animated.
2740 * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
2741 * default animation duration should be used.
2742 */
2743 @Override
2744 public void dismissPip(boolean animate, int animationDuration) {
2745 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "dismissPip()");
2746 final long ident = Binder.clearCallingIdentity();
2747 try {
2748 synchronized (mGlobalLock) {
2749 final PinnedActivityStack stack =
2750 mStackSupervisor.getDefaultDisplay().getPinnedStack();
2751 if (stack == null) {
2752 Slog.w(TAG, "dismissPip: pinned stack not found.");
2753 return;
2754 }
2755 if (stack.getWindowingMode() != WINDOWING_MODE_PINNED) {
2756 throw new IllegalArgumentException("Stack: " + stack
2757 + " doesn't support animated resize.");
2758 }
2759 if (animate) {
2760 stack.animateResizePinnedStack(null /* sourceHintBounds */,
2761 null /* destBounds */, animationDuration, false /* fromFullscreen */);
2762 } else {
2763 mStackSupervisor.moveTasksToFullscreenStackLocked(stack, true /* onTop */);
2764 }
2765 }
2766 } finally {
2767 Binder.restoreCallingIdentity(ident);
2768 }
2769 }
2770
2771 @Override
2772 public void suppressResizeConfigChanges(boolean suppress) throws RemoteException {
2773 mAm.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, "suppressResizeConfigChanges()");
2774 synchronized (mGlobalLock) {
2775 mSuppressResizeConfigChanges = suppress;
2776 }
2777 }
2778
2779 /**
2780 * NOTE: For the pinned stack, this method is usually called after the bounds animation has
2781 * animated the stack to the fullscreen, but can also be called if we are relaunching an
2782 * activity and clearing the task at the same time.
2783 */
2784 @Override
2785 // TODO: API should just be about changing windowing modes...
2786 public void moveTasksToFullscreenStack(int fromStackId, boolean onTop) {
2787 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
2788 "moveTasksToFullscreenStack()");
2789 synchronized (mGlobalLock) {
2790 final long origId = Binder.clearCallingIdentity();
2791 try {
2792 final ActivityStack stack = mStackSupervisor.getStack(fromStackId);
2793 if (stack != null){
2794 if (!stack.isActivityTypeStandardOrUndefined()) {
2795 throw new IllegalArgumentException(
2796 "You can't move tasks from non-standard stacks.");
2797 }
2798 mStackSupervisor.moveTasksToFullscreenStackLocked(stack, onTop);
2799 }
2800 } finally {
2801 Binder.restoreCallingIdentity(origId);
2802 }
2803 }
2804 }
2805
2806 /**
2807 * Moves the top activity in the input stackId to the pinned stack.
2808 *
2809 * @param stackId Id of stack to move the top activity to pinned stack.
2810 * @param bounds Bounds to use for pinned stack.
2811 *
2812 * @return True if the top activity of the input stack was successfully moved to the pinned
2813 * stack.
2814 */
2815 @Override
2816 public boolean moveTopActivityToPinnedStack(int stackId, Rect bounds) {
2817 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
2818 "moveTopActivityToPinnedStack()");
2819 synchronized (mGlobalLock) {
2820 if (!mAm.mSupportsPictureInPicture) {
2821 throw new IllegalStateException("moveTopActivityToPinnedStack:"
2822 + "Device doesn't support picture-in-picture mode");
2823 }
2824
2825 long ident = Binder.clearCallingIdentity();
2826 try {
2827 return mStackSupervisor.moveTopStackActivityToPinnedStackLocked(stackId, bounds);
2828 } finally {
2829 Binder.restoreCallingIdentity(ident);
2830 }
2831 }
2832 }
2833
2834 @Override
2835 public boolean isInMultiWindowMode(IBinder token) {
2836 final long origId = Binder.clearCallingIdentity();
2837 try {
2838 synchronized (mGlobalLock) {
2839 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
2840 if (r == null) {
2841 return false;
2842 }
2843 // An activity is consider to be in multi-window mode if its task isn't fullscreen.
2844 return r.inMultiWindowMode();
2845 }
2846 } finally {
2847 Binder.restoreCallingIdentity(origId);
2848 }
2849 }
2850
2851 @Override
2852 public boolean isInPictureInPictureMode(IBinder token) {
2853 final long origId = Binder.clearCallingIdentity();
2854 try {
2855 synchronized (mGlobalLock) {
2856 return isInPictureInPictureMode(ActivityRecord.forTokenLocked(token));
2857 }
2858 } finally {
2859 Binder.restoreCallingIdentity(origId);
2860 }
2861 }
2862
2863 private boolean isInPictureInPictureMode(ActivityRecord r) {
2864 if (r == null || r.getStack() == null || !r.inPinnedWindowingMode()
2865 || r.getStack().isInStackLocked(r) == null) {
2866 return false;
2867 }
2868
2869 // If we are animating to fullscreen then we have already dispatched the PIP mode
2870 // changed, so we should reflect that check here as well.
2871 final PinnedActivityStack stack = r.getStack();
2872 final PinnedStackWindowController windowController = stack.getWindowContainerController();
2873 return !windowController.isAnimatingBoundsToFullscreen();
2874 }
2875
2876 @Override
2877 public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) {
2878 final long origId = Binder.clearCallingIdentity();
2879 try {
2880 synchronized (mGlobalLock) {
2881 final ActivityRecord r = ensureValidPictureInPictureActivityParamsLocked(
2882 "enterPictureInPictureMode", token, params);
2883
2884 // If the activity is already in picture in picture mode, then just return early
2885 if (isInPictureInPictureMode(r)) {
2886 return true;
2887 }
2888
2889 // Activity supports picture-in-picture, now check that we can enter PiP at this
2890 // point, if it is
2891 if (!r.checkEnterPictureInPictureState("enterPictureInPictureMode",
2892 false /* beforeStopping */)) {
2893 return false;
2894 }
2895
2896 final Runnable enterPipRunnable = () -> {
Wale Ogunwalef276a6f2018-06-15 08:26:07 -07002897 synchronized (mGlobalLock) {
2898 // Only update the saved args from the args that are set
2899 r.pictureInPictureArgs.copyOnlySet(params);
2900 final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
2901 final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
2902 // Adjust the source bounds by the insets for the transition down
2903 final Rect sourceBounds = new Rect(
2904 r.pictureInPictureArgs.getSourceRectHint());
2905 mStackSupervisor.moveActivityToPinnedStackLocked(
2906 r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
2907 final PinnedActivityStack stack = r.getStack();
2908 stack.setPictureInPictureAspectRatio(aspectRatio);
2909 stack.setPictureInPictureActions(actions);
2910 MetricsLoggerWrapper.logPictureInPictureEnter(mContext, r.appInfo.uid,
2911 r.shortComponentName, r.supportsEnterPipOnTaskSwitch);
2912 logPictureInPictureArgs(params);
2913 }
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002914 };
2915
Wale Ogunwaled0412b32018-05-08 09:25:50 -07002916 if (isKeyguardLocked()) {
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002917 // If the keyguard is showing or occluded, then try and dismiss it before
2918 // entering picture-in-picture (this will prompt the user to authenticate if the
2919 // device is currently locked).
2920 dismissKeyguard(token, new KeyguardDismissCallback() {
2921 @Override
2922 public void onDismissSucceeded() throws RemoteException {
2923 mAm.mHandler.post(enterPipRunnable);
2924 }
2925 }, null /* message */);
2926 } else {
2927 // Enter picture in picture immediately otherwise
2928 enterPipRunnable.run();
2929 }
2930 return true;
2931 }
2932 } finally {
2933 Binder.restoreCallingIdentity(origId);
2934 }
2935 }
2936
2937 @Override
2938 public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) {
2939 final long origId = Binder.clearCallingIdentity();
2940 try {
2941 synchronized (mGlobalLock) {
2942 final ActivityRecord r = ensureValidPictureInPictureActivityParamsLocked(
2943 "setPictureInPictureParams", token, params);
2944
2945 // Only update the saved args from the args that are set
2946 r.pictureInPictureArgs.copyOnlySet(params);
2947 if (r.inPinnedWindowingMode()) {
2948 // If the activity is already in picture-in-picture, update the pinned stack now
2949 // if it is not already expanding to fullscreen. Otherwise, the arguments will
2950 // be used the next time the activity enters PiP
2951 final PinnedActivityStack stack = r.getStack();
2952 if (!stack.isAnimatingBoundsToFullscreen()) {
2953 stack.setPictureInPictureAspectRatio(
2954 r.pictureInPictureArgs.getAspectRatio());
2955 stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
2956 }
2957 }
2958 logPictureInPictureArgs(params);
2959 }
2960 } finally {
2961 Binder.restoreCallingIdentity(origId);
2962 }
2963 }
2964
2965 @Override
2966 public int getMaxNumPictureInPictureActions(IBinder token) {
2967 // Currently, this is a static constant, but later, we may change this to be dependent on
2968 // the context of the activity
2969 return 3;
2970 }
2971
2972 private void logPictureInPictureArgs(PictureInPictureParams params) {
2973 if (params.hasSetActions()) {
2974 MetricsLogger.histogram(mContext, "tron_varz_picture_in_picture_actions_count",
2975 params.getActions().size());
2976 }
2977 if (params.hasSetAspectRatio()) {
2978 LogMaker lm = new LogMaker(MetricsEvent.ACTION_PICTURE_IN_PICTURE_ASPECT_RATIO_CHANGED);
2979 lm.addTaggedData(MetricsEvent.PICTURE_IN_PICTURE_ASPECT_RATIO, params.getAspectRatio());
2980 MetricsLogger.action(lm);
2981 }
2982 }
2983
2984 /**
2985 * Checks the state of the system and the activity associated with the given {@param token} to
2986 * verify that picture-in-picture is supported for that activity.
2987 *
2988 * @return the activity record for the given {@param token} if all the checks pass.
2989 */
2990 private ActivityRecord ensureValidPictureInPictureActivityParamsLocked(String caller,
2991 IBinder token, PictureInPictureParams params) {
2992 if (!mAm.mSupportsPictureInPicture) {
2993 throw new IllegalStateException(caller
2994 + ": Device doesn't support picture-in-picture mode.");
2995 }
2996
2997 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2998 if (r == null) {
2999 throw new IllegalStateException(caller
3000 + ": Can't find activity for token=" + token);
3001 }
3002
3003 if (!r.supportsPictureInPicture()) {
3004 throw new IllegalStateException(caller
3005 + ": Current activity does not support picture-in-picture.");
3006 }
3007
3008 if (params.hasSetAspectRatio()
3009 && !mAm.mWindowManager.isValidPictureInPictureAspectRatio(r.getStack().mDisplayId,
3010 params.getAspectRatio())) {
3011 final float minAspectRatio = mContext.getResources().getFloat(
3012 com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
3013 final float maxAspectRatio = mContext.getResources().getFloat(
3014 com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
3015 throw new IllegalArgumentException(String.format(caller
3016 + ": Aspect ratio is too extreme (must be between %f and %f).",
3017 minAspectRatio, maxAspectRatio));
3018 }
3019
3020 // Truncate the number of actions if necessary
3021 params.truncateActions(getMaxNumPictureInPictureActions(token));
3022
3023 return r;
3024 }
3025
3026 @Override
3027 public IBinder getUriPermissionOwnerForActivity(IBinder activityToken) {
3028 mAm.enforceNotIsolatedCaller("getUriPermissionOwnerForActivity");
3029 synchronized (mGlobalLock) {
3030 ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
3031 if (r == null) {
3032 throw new IllegalArgumentException("Activity does not exist; token="
3033 + activityToken);
3034 }
3035 return r.getUriPermissionsLocked().getExternalTokenLocked();
3036 }
3037 }
3038
3039 @Override
3040 public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
3041 Rect tempDockedTaskInsetBounds,
3042 Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) {
3043 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeDockedStack()");
3044 long ident = Binder.clearCallingIdentity();
3045 try {
3046 synchronized (mGlobalLock) {
3047 mStackSupervisor.resizeDockedStackLocked(dockedBounds, tempDockedTaskBounds,
3048 tempDockedTaskInsetBounds, tempOtherTaskBounds, tempOtherTaskInsetBounds,
3049 PRESERVE_WINDOWS);
3050 }
3051 } finally {
3052 Binder.restoreCallingIdentity(ident);
3053 }
3054 }
3055
3056 @Override
3057 public void setSplitScreenResizing(boolean resizing) {
3058 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setSplitScreenResizing()");
3059 final long ident = Binder.clearCallingIdentity();
3060 try {
3061 synchronized (mGlobalLock) {
3062 mStackSupervisor.setSplitScreenResizing(resizing);
3063 }
3064 } finally {
3065 Binder.restoreCallingIdentity(ident);
3066 }
3067 }
3068
3069 @Override
3070 public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
3071 mAm.enforceSystemHasVrFeature();
3072
3073 final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
3074
3075 ActivityRecord r;
3076 synchronized (mGlobalLock) {
3077 r = ActivityRecord.isInStackLocked(token);
3078 }
3079
3080 if (r == null) {
3081 throw new IllegalArgumentException();
3082 }
3083
3084 int err;
3085 if ((err = vrService.hasVrPackage(packageName, r.userId)) !=
3086 VrManagerInternal.NO_ERROR) {
3087 return err;
3088 }
3089
3090 // Clear the binder calling uid since this path may call moveToTask().
3091 final long callingId = Binder.clearCallingIdentity();
3092 try {
3093 synchronized (mGlobalLock) {
3094 r.requestedVrComponent = (enabled) ? packageName : null;
3095
3096 // Update associated state if this activity is currently focused
3097 if (r == mStackSupervisor.getResumedActivityLocked()) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07003098 applyUpdateVrModeLocked(r);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07003099 }
3100 return 0;
3101 }
3102 } finally {
3103 Binder.restoreCallingIdentity(callingId);
3104 }
3105 }
3106
3107 @Override
3108 public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
3109 Slog.i(TAG, "Activity tried to startLocalVoiceInteraction");
3110 synchronized (mGlobalLock) {
3111 ActivityRecord activity = mAm.getFocusedStack().getTopActivity();
3112 if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
3113 throw new SecurityException("Only focused activity can call startVoiceInteraction");
3114 }
3115 if (mAm.mRunningVoice != null || activity.getTask().voiceSession != null
3116 || activity.voiceSession != null) {
3117 Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
3118 return;
3119 }
3120 if (activity.pendingVoiceInteractionStart) {
3121 Slog.w(TAG, "Pending start of voice interaction already.");
3122 return;
3123 }
3124 activity.pendingVoiceInteractionStart = true;
3125 }
3126 LocalServices.getService(VoiceInteractionManagerInternal.class)
3127 .startLocalVoiceInteraction(callingActivity, options);
3128 }
3129
3130 @Override
3131 public void stopLocalVoiceInteraction(IBinder callingActivity) {
3132 LocalServices.getService(VoiceInteractionManagerInternal.class)
3133 .stopLocalVoiceInteraction(callingActivity);
3134 }
3135
3136 @Override
3137 public boolean supportsLocalVoiceInteraction() {
3138 return LocalServices.getService(VoiceInteractionManagerInternal.class)
3139 .supportsLocalVoiceInteraction();
3140 }
3141
3142 /** Notifies all listeners when the pinned stack animation starts. */
3143 @Override
3144 public void notifyPinnedStackAnimationStarted() {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07003145 mTaskChangeNotificationController.notifyPinnedStackAnimationStarted();
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07003146 }
3147
3148 /** Notifies all listeners when the pinned stack animation ends. */
3149 @Override
3150 public void notifyPinnedStackAnimationEnded() {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07003151 mTaskChangeNotificationController.notifyPinnedStackAnimationEnded();
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07003152 }
3153
3154 @Override
3155 public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
3156 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizePinnedStack()");
3157 final long ident = Binder.clearCallingIdentity();
3158 try {
3159 synchronized (mGlobalLock) {
3160 mStackSupervisor.resizePinnedStackLocked(pinnedBounds, tempPinnedTaskBounds);
3161 }
3162 } finally {
3163 Binder.restoreCallingIdentity(ident);
3164 }
3165 }
3166
3167 @Override
3168 public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId) {
3169 mAm.enforceCallingPermission(CHANGE_CONFIGURATION, "updateDisplayOverrideConfiguration()");
3170
3171 synchronized (mGlobalLock) {
3172 // Check if display is initialized in AM.
3173 if (!mStackSupervisor.isDisplayAdded(displayId)) {
3174 // Call might come when display is not yet added or has already been removed.
3175 if (DEBUG_CONFIGURATION) {
3176 Slog.w(TAG, "Trying to update display configuration for non-existing displayId="
3177 + displayId);
3178 }
3179 return false;
3180 }
3181
3182 if (values == null && mAm.mWindowManager != null) {
3183 // sentinel: fetch the current configuration from the window manager
3184 values = mAm.mWindowManager.computeNewConfiguration(displayId);
3185 }
3186
3187 if (mAm.mWindowManager != null) {
3188 // Update OOM levels based on display size.
3189 mAm.mProcessList.applyDisplaySize(mAm.mWindowManager);
3190 }
3191
3192 final long origId = Binder.clearCallingIdentity();
3193 try {
3194 if (values != null) {
3195 Settings.System.clearConfiguration(values);
3196 }
3197 mAm.updateDisplayOverrideConfigurationLocked(values, null /* starting */,
3198 false /* deferResume */, displayId, mTmpUpdateConfigurationResult);
3199 return mTmpUpdateConfigurationResult.changes != 0;
3200 } finally {
3201 Binder.restoreCallingIdentity(origId);
3202 }
3203 }
3204 }
3205
3206 @Override
3207 public boolean updateConfiguration(Configuration values) {
3208 mAm.enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()");
3209
3210 synchronized (mGlobalLock) {
3211 if (values == null && mAm.mWindowManager != null) {
3212 // sentinel: fetch the current configuration from the window manager
3213 values = mAm.mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
3214 }
3215
3216 if (mAm.mWindowManager != null) {
3217 // Update OOM levels based on display size.
3218 mAm.mProcessList.applyDisplaySize(mAm.mWindowManager);
3219 }
3220
3221 final long origId = Binder.clearCallingIdentity();
3222 try {
3223 if (values != null) {
3224 Settings.System.clearConfiguration(values);
3225 }
3226 mAm.updateConfigurationLocked(values, null, false, false /* persistent */,
3227 UserHandle.USER_NULL, false /* deferResume */,
3228 mTmpUpdateConfigurationResult);
3229 return mTmpUpdateConfigurationResult.changes != 0;
3230 } finally {
3231 Binder.restoreCallingIdentity(origId);
3232 }
3233 }
3234 }
3235
3236 @Override
3237 public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback,
3238 CharSequence message) {
3239 if (message != null) {
3240 mAm.enforceCallingPermission(
3241 Manifest.permission.SHOW_KEYGUARD_MESSAGE, "dismissKeyguard()");
3242 }
3243 final long callingId = Binder.clearCallingIdentity();
3244 try {
3245 synchronized (mGlobalLock) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07003246 mKeyguardController.dismissKeyguard(token, callback, message);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07003247 }
3248 } finally {
3249 Binder.restoreCallingIdentity(callingId);
3250 }
3251 }
3252
3253 @Override
3254 public void cancelTaskWindowTransition(int taskId) {
3255 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
3256 "cancelTaskWindowTransition()");
3257 final long ident = Binder.clearCallingIdentity();
3258 try {
3259 synchronized (mGlobalLock) {
3260 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
3261 MATCH_TASK_IN_STACKS_ONLY);
3262 if (task == null) {
3263 Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
3264 return;
3265 }
3266 task.cancelWindowTransition();
3267 }
3268 } finally {
3269 Binder.restoreCallingIdentity(ident);
3270 }
3271 }
3272
3273 @Override
3274 public ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean reducedResolution) {
3275 mAm.enforceCallerIsRecentsOrHasPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
3276 final long ident = Binder.clearCallingIdentity();
3277 try {
3278 final TaskRecord task;
3279 synchronized (mGlobalLock) {
3280 task = mStackSupervisor.anyTaskForIdLocked(taskId,
3281 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
3282 if (task == null) {
3283 Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found");
3284 return null;
3285 }
3286 }
3287 // Don't call this while holding the lock as this operation might hit the disk.
3288 return task.getSnapshot(reducedResolution);
3289 } finally {
3290 Binder.restoreCallingIdentity(ident);
3291 }
3292 }
3293
3294 @Override
3295 public void setDisablePreviewScreenshots(IBinder token, boolean disable) {
3296 synchronized (mGlobalLock) {
3297 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
3298 if (r == null) {
3299 Slog.w(TAG, "setDisablePreviewScreenshots: Unable to find activity for token="
3300 + token);
3301 return;
3302 }
3303 final long origId = Binder.clearCallingIdentity();
3304 try {
3305 r.setDisablePreviewScreenshots(disable);
3306 } finally {
3307 Binder.restoreCallingIdentity(origId);
3308 }
3309 }
3310 }
3311
3312 /** Return the user id of the last resumed activity. */
3313 @Override
3314 public @UserIdInt
3315 int getLastResumedActivityUserId() {
3316 mAm.enforceCallingPermission(
3317 Manifest.permission.INTERACT_ACROSS_USERS_FULL, "getLastResumedActivityUserId()");
3318 synchronized (mGlobalLock) {
3319 if (mAm.mLastResumedActivity == null) {
3320 return mAm.mUserController.getCurrentUserId();
3321 }
3322 return mAm.mLastResumedActivity.userId;
3323 }
3324 }
3325
3326 @Override
3327 public void updateLockTaskFeatures(int userId, int flags) {
3328 final int callingUid = Binder.getCallingUid();
3329 if (callingUid != 0 && callingUid != SYSTEM_UID) {
3330 mAm.enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
3331 "updateLockTaskFeatures()");
3332 }
3333 synchronized (mGlobalLock) {
3334 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Allowing features " + userId + ":0x" +
3335 Integer.toHexString(flags));
Wale Ogunwaled95c06b2018-05-08 10:35:38 -07003336 getLockTaskController().updateLockTaskFeatures(userId, flags);
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07003337 }
3338 }
3339
3340 @Override
3341 public void setShowWhenLocked(IBinder token, boolean showWhenLocked) {
3342 synchronized (mGlobalLock) {
3343 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
3344 if (r == null) {
3345 return;
3346 }
3347 final long origId = Binder.clearCallingIdentity();
3348 try {
3349 r.setShowWhenLocked(showWhenLocked);
3350 } finally {
3351 Binder.restoreCallingIdentity(origId);
3352 }
3353 }
3354 }
3355
3356 @Override
3357 public void setTurnScreenOn(IBinder token, boolean turnScreenOn) {
3358 synchronized (mGlobalLock) {
3359 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
3360 if (r == null) {
3361 return;
3362 }
3363 final long origId = Binder.clearCallingIdentity();
3364 try {
3365 r.setTurnScreenOn(turnScreenOn);
3366 } finally {
3367 Binder.restoreCallingIdentity(origId);
3368 }
3369 }
3370 }
3371
3372 @Override
3373 public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) {
3374 mAm.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
3375 "registerRemoteAnimations");
3376 definition.setCallingPid(Binder.getCallingPid());
3377 synchronized (mGlobalLock) {
3378 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
3379 if (r == null) {
3380 return;
3381 }
3382 final long origId = Binder.clearCallingIdentity();
3383 try {
3384 r.registerRemoteAnimations(definition);
3385 } finally {
3386 Binder.restoreCallingIdentity(origId);
3387 }
3388 }
3389 }
3390
3391 @Override
3392 public void registerRemoteAnimationForNextActivityStart(String packageName,
3393 RemoteAnimationAdapter adapter) {
3394 mAm.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
3395 "registerRemoteAnimationForNextActivityStart");
3396 adapter.setCallingPid(Binder.getCallingPid());
3397 synchronized (mGlobalLock) {
3398 final long origId = Binder.clearCallingIdentity();
3399 try {
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -07003400 getActivityStartController().registerRemoteAnimationForNextActivityStart(
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07003401 packageName, adapter);
3402 } finally {
3403 Binder.restoreCallingIdentity(origId);
3404 }
3405 }
3406 }
3407
3408 /** @see android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning */
3409 @Override
3410 public void alwaysShowUnsupportedCompileSdkWarning(ComponentName activity) {
3411 synchronized (mGlobalLock) {
3412 final long origId = Binder.clearCallingIdentity();
3413 try {
3414 mAm.mAppWarnings.alwaysShowUnsupportedCompileSdkWarning(activity);
3415 } finally {
3416 Binder.restoreCallingIdentity(origId);
3417 }
3418 }
3419 }
Wale Ogunwale6767eae2018-05-03 15:52:51 -07003420
Wale Ogunwaled0412b32018-05-08 09:25:50 -07003421 @Override
3422 public void setVrThread(int tid) {
3423 mAm.enforceSystemHasVrFeature();
3424 synchronized (mGlobalLock) {
3425 synchronized (mAm.mPidsSelfLocked) {
3426 final int pid = Binder.getCallingPid();
3427 final ProcessRecord proc = mAm.mPidsSelfLocked.get(pid);
3428 mVrController.setVrThreadLocked(tid, pid, proc);
3429 }
3430 }
3431 }
3432
3433 @Override
3434 public void setPersistentVrThread(int tid) {
3435 if (mAm.checkCallingPermission(Manifest.permission.RESTRICTED_VR_ACCESS)
3436 != PERMISSION_GRANTED) {
3437 final String msg = "Permission Denial: setPersistentVrThread() from pid="
3438 + Binder.getCallingPid()
3439 + ", uid=" + Binder.getCallingUid()
3440 + " requires " + Manifest.permission.RESTRICTED_VR_ACCESS;
3441 Slog.w(TAG, msg);
3442 throw new SecurityException(msg);
3443 }
3444 mAm.enforceSystemHasVrFeature();
3445 synchronized (mGlobalLock) {
3446 synchronized (mAm.mPidsSelfLocked) {
3447 final int pid = Binder.getCallingPid();
3448 final ProcessRecord proc = mAm.mPidsSelfLocked.get(pid);
3449 mVrController.setPersistentVrThreadLocked(tid, pid, proc);
3450 }
3451 }
3452 }
3453
3454 /**
3455 * @return whether the system should disable UI modes incompatible with VR mode.
3456 */
3457 boolean shouldDisableNonVrUiLocked() {
3458 return mVrController.shouldDisableNonVrUiLocked();
3459 }
3460
3461 void applyUpdateVrModeLocked(ActivityRecord r) {
3462 // VR apps are expected to run in a main display. If an app is turning on VR for
3463 // itself, but lives in a dynamic stack, then make sure that it is moved to the main
3464 // fullscreen stack before enabling VR Mode.
3465 // TODO: The goal of this code is to keep the VR app on the main display. When the
3466 // stack implementation changes in the future, keep in mind that the use of the fullscreen
3467 // stack is a means to move the activity to the main display and a moveActivityToDisplay()
3468 // option would be a better choice here.
3469 if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
3470 Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
3471 + " to main stack for VR");
3472 final ActivityStack stack = mStackSupervisor.getDefaultDisplay().getOrCreateStack(
3473 WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
3474 moveTaskToStack(r.getTask().taskId, stack.mStackId, true /* toTop */);
3475 }
3476 mH.post(() -> {
3477 if (!mVrController.onVrModeChanged(r)) {
3478 return;
3479 }
3480 synchronized (mGlobalLock) {
3481 final boolean disableNonVrUi = mVrController.shouldDisableNonVrUiLocked();
3482 mWindowManager.disableNonVrUi(disableNonVrUi);
3483 if (disableNonVrUi) {
3484 // If we are in a VR mode where Picture-in-Picture mode is unsupported,
3485 // then remove the pinned stack.
3486 mStackSupervisor.removeStacksInWindowingModes(WINDOWING_MODE_PINNED);
3487 }
3488 }
3489 });
3490 }
3491
3492 /** Pokes the task persister. */
3493 void notifyTaskPersisterLocked(TaskRecord task, boolean flush) {
3494 mRecentTasks.notifyTaskPersisterLocked(task, flush);
3495 }
3496
3497 void onTopProcChangedLocked(ProcessRecord proc) {
3498 mVrController.onTopProcChangedLocked(proc);
3499 }
3500
3501 boolean isKeyguardLocked() {
3502 return mKeyguardController.isKeyguardLocked();
3503 }
3504
3505 boolean isNextTransitionForward() {
3506 int transit = mWindowManager.getPendingAppTransition();
3507 return transit == TRANSIT_ACTIVITY_OPEN
3508 || transit == TRANSIT_TASK_OPEN
3509 || transit == TRANSIT_TASK_TO_FRONT;
3510 }
3511
3512 void dumpVrControllerLocked(PrintWriter pw) {
3513 pw.println(" mVrController=" + mVrController);
3514 }
3515
3516 void writeVrControllerToProto(ProtoOutputStream proto, long fieldId) {
3517 mVrController.writeToProto(proto, fieldId);
3518 }
3519
3520 final class H extends Handler {
3521 public H(Looper looper) {
3522 super(looper, null, true);
3523 }
3524 }
3525
Wale Ogunwale6767eae2018-05-03 15:52:51 -07003526 final class LocalService extends ActivityTaskManagerInternal {
3527 @Override
3528 public SleepToken acquireSleepToken(String tag, int displayId) {
3529 Preconditions.checkNotNull(tag);
3530 return mAm.acquireSleepToken(tag, displayId);
3531 }
3532
3533 @Override
3534 public ComponentName getHomeActivityForUser(int userId) {
3535 synchronized (mGlobalLock) {
3536 ActivityRecord homeActivity = mStackSupervisor.getHomeActivityForUser(userId);
3537 return homeActivity == null ? null : homeActivity.realActivity;
3538 }
3539 }
3540
3541 @Override
3542 public void onLocalVoiceInteractionStarted(IBinder activity,
3543 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor) {
3544 synchronized (mGlobalLock) {
3545 mAm.onLocalVoiceInteractionStartedLocked(activity, voiceSession, voiceInteractor);
3546 }
3547 }
3548
3549 @Override
3550 public void notifyAppTransitionStarting(SparseIntArray reasons, long timestamp) {
3551 synchronized (mGlobalLock) {
3552 mStackSupervisor.getActivityMetricsLogger().notifyTransitionStarting(
3553 reasons, timestamp);
3554 }
3555 }
3556
3557 @Override
3558 public void notifyAppTransitionFinished() {
3559 synchronized (mGlobalLock) {
3560 mStackSupervisor.notifyAppTransitionDone();
3561 }
3562 }
3563
3564 @Override
3565 public void notifyAppTransitionCancelled() {
3566 synchronized (mGlobalLock) {
3567 mStackSupervisor.notifyAppTransitionDone();
3568 }
3569 }
3570
3571 @Override
3572 public List<IBinder> getTopVisibleActivities() {
3573 synchronized (mGlobalLock) {
3574 return mStackSupervisor.getTopVisibleActivities();
3575 }
3576 }
3577
3578 @Override
3579 public void notifyDockedStackMinimizedChanged(boolean minimized) {
3580 synchronized (mGlobalLock) {
3581 mStackSupervisor.setDockedStackMinimized(minimized);
3582 }
3583 }
3584
3585 @Override
3586 public int startActivitiesAsPackage(String packageName, int userId, Intent[] intents,
3587 Bundle bOptions) {
3588 Preconditions.checkNotNull(intents, "intents");
3589 final String[] resolvedTypes = new String[intents.length];
3590
3591 // UID of the package on user userId.
3592 // "= 0" is needed because otherwise catch(RemoteException) would make it look like
3593 // packageUid may not be initialized.
3594 int packageUid = 0;
3595 final long ident = Binder.clearCallingIdentity();
3596
3597 try {
3598 for (int i = 0; i < intents.length; i++) {
3599 resolvedTypes[i] =
3600 intents[i].resolveTypeIfNeeded(mContext.getContentResolver());
3601 }
3602
3603 packageUid = AppGlobals.getPackageManager().getPackageUid(
3604 packageName, PackageManager.MATCH_DEBUG_TRIAGED_MISSING, userId);
3605 } catch (RemoteException e) {
3606 // Shouldn't happen.
3607 } finally {
3608 Binder.restoreCallingIdentity(ident);
3609 }
3610
3611 synchronized (mGlobalLock) {
Wale Ogunwale5fa8a8c2018-05-08 13:43:21 -07003612 return getActivityStartController().startActivitiesInPackage(
Wale Ogunwale6767eae2018-05-03 15:52:51 -07003613 packageUid, packageName,
3614 intents, resolvedTypes, null /* resultTo */,
3615 SafeActivityOptions.fromBundle(bOptions), userId,
3616 false /* validateIncomingUser */);
3617 }
3618 }
3619
3620 @Override
3621 public int startActivityAsUser(IApplicationThread caller, String callerPacakge,
3622 Intent intent, Bundle options, int userId) {
3623 return ActivityTaskManagerService.this.startActivityAsUser(
3624 caller, callerPacakge, intent,
3625 intent.resolveTypeIfNeeded(mContext.getContentResolver()),
3626 null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, options, userId,
3627 false /*validateIncomingUser*/);
3628 }
3629
3630 @Override
3631 public void notifyKeyguardFlagsChanged(@Nullable Runnable callback) {
3632 synchronized (mGlobalLock) {
3633
3634 // We might change the visibilities here, so prepare an empty app transition which
3635 // might be overridden later if we actually change visibilities.
3636 final boolean wasTransitionSet =
3637 mAm.mWindowManager.getPendingAppTransition() != TRANSIT_NONE;
3638 if (!wasTransitionSet) {
3639 mAm.mWindowManager.prepareAppTransition(TRANSIT_NONE,
3640 false /* alwaysKeepCurrent */);
3641 }
3642 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
3643
3644 // If there was a transition set already we don't want to interfere with it as we
3645 // might be starting it too early.
3646 if (!wasTransitionSet) {
3647 mAm.mWindowManager.executeAppTransition();
3648 }
3649 }
3650 if (callback != null) {
3651 callback.run();
3652 }
3653 }
3654
3655 @Override
3656 public void notifyKeyguardTrustedChanged() {
3657 synchronized (mGlobalLock) {
Wale Ogunwaled0412b32018-05-08 09:25:50 -07003658 if (mKeyguardController.isKeyguardShowing(DEFAULT_DISPLAY)) {
Wale Ogunwale6767eae2018-05-03 15:52:51 -07003659 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
3660 }
3661 }
3662 }
3663
3664 /**
3665 * Called after virtual display Id is updated by
3666 * {@link com.android.server.vr.Vr2dDisplay} with a specific
3667 * {@param vrVr2dDisplayId}.
3668 */
3669 @Override
3670 public void setVr2dDisplayId(int vr2dDisplayId) {
3671 if (DEBUG_STACK) Slog.d(TAG, "setVr2dDisplayId called for: " + vr2dDisplayId);
3672 synchronized (mGlobalLock) {
3673 mAm.mVr2dDisplayId = vr2dDisplayId;
3674 }
3675 }
3676
3677 @Override
3678 public void setFocusedActivity(IBinder token) {
3679 synchronized (mGlobalLock) {
3680 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
3681 if (r == null) {
3682 throw new IllegalArgumentException(
3683 "setFocusedActivity: No activity record matching token=" + token);
3684 }
3685 if (mStackSupervisor.moveFocusableActivityStackToFrontLocked(
3686 r, "setFocusedActivity")) {
3687 mStackSupervisor.resumeFocusedStackTopActivityLocked();
3688 }
3689 }
3690 }
3691
3692 @Override
3693 public boolean hasRunningActivity(int uid, @Nullable String packageName) {
3694 if (packageName == null) return false;
3695
3696 synchronized (mGlobalLock) {
3697 for (int i = 0; i < mAm.mLruProcesses.size(); i++) {
3698 final ProcessRecord processRecord = mAm.mLruProcesses.get(i);
3699 if (processRecord.uid == uid) {
3700 for (int j = 0; j < processRecord.activities.size(); j++) {
3701 final ActivityRecord activityRecord = processRecord.activities.get(j);
3702 if (packageName.equals(activityRecord.packageName)) {
3703 return true;
3704 }
3705 }
3706 }
3707 }
3708 }
3709 return false;
3710 }
3711
3712 @Override
3713 public void registerScreenObserver(ScreenObserver observer) {
3714 mAm.mScreenObservers.add(observer);
3715 }
3716
3717 @Override
3718 public boolean isCallerRecents(int callingUid) {
Wale Ogunwale16e505a2018-05-07 15:00:49 -07003719 return getRecentTasks().isCallerRecents(callingUid);
Wale Ogunwale6767eae2018-05-03 15:52:51 -07003720 }
3721
3722 @Override
3723 public boolean isRecentsComponentHomeActivity(int userId) {
Wale Ogunwale16e505a2018-05-07 15:00:49 -07003724 return getRecentTasks().isRecentsComponentHomeActivity(userId);
Wale Ogunwale6767eae2018-05-03 15:52:51 -07003725 }
3726
3727 @Override
3728 public void cancelRecentsAnimation(boolean restoreHomeStackPosition) {
3729 ActivityTaskManagerService.this.cancelRecentsAnimation(restoreHomeStackPosition);
3730 }
3731
3732 @Override
3733 public void enforceCallerIsRecentsOrHasPermission(String permission, String func) {
3734 mAm.enforceCallerIsRecentsOrHasPermission(permission, func);
3735 }
Wale Ogunwaled0412b32018-05-08 09:25:50 -07003736
3737 @Override
3738 public void notifyActiveVoiceInteractionServiceChanged(ComponentName component) {
3739 synchronized (mGlobalLock) {
3740 mActiveVoiceInteractionServiceComponent = component;
3741 }
3742 }
Wale Ogunwale6767eae2018-05-03 15:52:51 -07003743 }
Wale Ogunwale65ebd952018-04-25 15:41:44 -07003744}