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