blob: d032e1b6b48a9db9beeac9f021f41d4ffbfd7449 [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 = () -> {
Wale Ogunwalef276a6f2018-06-15 08:26:07 -07002810 synchronized (mGlobalLock) {
2811 // Only update the saved args from the args that are set
2812 r.pictureInPictureArgs.copyOnlySet(params);
2813 final float aspectRatio = r.pictureInPictureArgs.getAspectRatio();
2814 final List<RemoteAction> actions = r.pictureInPictureArgs.getActions();
2815 // Adjust the source bounds by the insets for the transition down
2816 final Rect sourceBounds = new Rect(
2817 r.pictureInPictureArgs.getSourceRectHint());
2818 mStackSupervisor.moveActivityToPinnedStackLocked(
2819 r, sourceBounds, aspectRatio, "enterPictureInPictureMode");
2820 final PinnedActivityStack stack = r.getStack();
2821 stack.setPictureInPictureAspectRatio(aspectRatio);
2822 stack.setPictureInPictureActions(actions);
2823 MetricsLoggerWrapper.logPictureInPictureEnter(mContext, r.appInfo.uid,
2824 r.shortComponentName, r.supportsEnterPipOnTaskSwitch);
2825 logPictureInPictureArgs(params);
2826 }
Wale Ogunwale04d9cb52018-04-30 13:55:07 -07002827 };
2828
2829 if (mAm.isKeyguardLocked()) {
2830 // If the keyguard is showing or occluded, then try and dismiss it before
2831 // entering picture-in-picture (this will prompt the user to authenticate if the
2832 // device is currently locked).
2833 dismissKeyguard(token, new KeyguardDismissCallback() {
2834 @Override
2835 public void onDismissSucceeded() throws RemoteException {
2836 mAm.mHandler.post(enterPipRunnable);
2837 }
2838 }, null /* message */);
2839 } else {
2840 // Enter picture in picture immediately otherwise
2841 enterPipRunnable.run();
2842 }
2843 return true;
2844 }
2845 } finally {
2846 Binder.restoreCallingIdentity(origId);
2847 }
2848 }
2849
2850 @Override
2851 public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) {
2852 final long origId = Binder.clearCallingIdentity();
2853 try {
2854 synchronized (mGlobalLock) {
2855 final ActivityRecord r = ensureValidPictureInPictureActivityParamsLocked(
2856 "setPictureInPictureParams", token, params);
2857
2858 // Only update the saved args from the args that are set
2859 r.pictureInPictureArgs.copyOnlySet(params);
2860 if (r.inPinnedWindowingMode()) {
2861 // If the activity is already in picture-in-picture, update the pinned stack now
2862 // if it is not already expanding to fullscreen. Otherwise, the arguments will
2863 // be used the next time the activity enters PiP
2864 final PinnedActivityStack stack = r.getStack();
2865 if (!stack.isAnimatingBoundsToFullscreen()) {
2866 stack.setPictureInPictureAspectRatio(
2867 r.pictureInPictureArgs.getAspectRatio());
2868 stack.setPictureInPictureActions(r.pictureInPictureArgs.getActions());
2869 }
2870 }
2871 logPictureInPictureArgs(params);
2872 }
2873 } finally {
2874 Binder.restoreCallingIdentity(origId);
2875 }
2876 }
2877
2878 @Override
2879 public int getMaxNumPictureInPictureActions(IBinder token) {
2880 // Currently, this is a static constant, but later, we may change this to be dependent on
2881 // the context of the activity
2882 return 3;
2883 }
2884
2885 private void logPictureInPictureArgs(PictureInPictureParams params) {
2886 if (params.hasSetActions()) {
2887 MetricsLogger.histogram(mContext, "tron_varz_picture_in_picture_actions_count",
2888 params.getActions().size());
2889 }
2890 if (params.hasSetAspectRatio()) {
2891 LogMaker lm = new LogMaker(MetricsEvent.ACTION_PICTURE_IN_PICTURE_ASPECT_RATIO_CHANGED);
2892 lm.addTaggedData(MetricsEvent.PICTURE_IN_PICTURE_ASPECT_RATIO, params.getAspectRatio());
2893 MetricsLogger.action(lm);
2894 }
2895 }
2896
2897 /**
2898 * Checks the state of the system and the activity associated with the given {@param token} to
2899 * verify that picture-in-picture is supported for that activity.
2900 *
2901 * @return the activity record for the given {@param token} if all the checks pass.
2902 */
2903 private ActivityRecord ensureValidPictureInPictureActivityParamsLocked(String caller,
2904 IBinder token, PictureInPictureParams params) {
2905 if (!mAm.mSupportsPictureInPicture) {
2906 throw new IllegalStateException(caller
2907 + ": Device doesn't support picture-in-picture mode.");
2908 }
2909
2910 final ActivityRecord r = ActivityRecord.forTokenLocked(token);
2911 if (r == null) {
2912 throw new IllegalStateException(caller
2913 + ": Can't find activity for token=" + token);
2914 }
2915
2916 if (!r.supportsPictureInPicture()) {
2917 throw new IllegalStateException(caller
2918 + ": Current activity does not support picture-in-picture.");
2919 }
2920
2921 if (params.hasSetAspectRatio()
2922 && !mAm.mWindowManager.isValidPictureInPictureAspectRatio(r.getStack().mDisplayId,
2923 params.getAspectRatio())) {
2924 final float minAspectRatio = mContext.getResources().getFloat(
2925 com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
2926 final float maxAspectRatio = mContext.getResources().getFloat(
2927 com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
2928 throw new IllegalArgumentException(String.format(caller
2929 + ": Aspect ratio is too extreme (must be between %f and %f).",
2930 minAspectRatio, maxAspectRatio));
2931 }
2932
2933 // Truncate the number of actions if necessary
2934 params.truncateActions(getMaxNumPictureInPictureActions(token));
2935
2936 return r;
2937 }
2938
2939 @Override
2940 public IBinder getUriPermissionOwnerForActivity(IBinder activityToken) {
2941 mAm.enforceNotIsolatedCaller("getUriPermissionOwnerForActivity");
2942 synchronized (mGlobalLock) {
2943 ActivityRecord r = ActivityRecord.isInStackLocked(activityToken);
2944 if (r == null) {
2945 throw new IllegalArgumentException("Activity does not exist; token="
2946 + activityToken);
2947 }
2948 return r.getUriPermissionsLocked().getExternalTokenLocked();
2949 }
2950 }
2951
2952 @Override
2953 public void resizeDockedStack(Rect dockedBounds, Rect tempDockedTaskBounds,
2954 Rect tempDockedTaskInsetBounds,
2955 Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds) {
2956 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizeDockedStack()");
2957 long ident = Binder.clearCallingIdentity();
2958 try {
2959 synchronized (mGlobalLock) {
2960 mStackSupervisor.resizeDockedStackLocked(dockedBounds, tempDockedTaskBounds,
2961 tempDockedTaskInsetBounds, tempOtherTaskBounds, tempOtherTaskInsetBounds,
2962 PRESERVE_WINDOWS);
2963 }
2964 } finally {
2965 Binder.restoreCallingIdentity(ident);
2966 }
2967 }
2968
2969 @Override
2970 public void setSplitScreenResizing(boolean resizing) {
2971 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "setSplitScreenResizing()");
2972 final long ident = Binder.clearCallingIdentity();
2973 try {
2974 synchronized (mGlobalLock) {
2975 mStackSupervisor.setSplitScreenResizing(resizing);
2976 }
2977 } finally {
2978 Binder.restoreCallingIdentity(ident);
2979 }
2980 }
2981
2982 @Override
2983 public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) {
2984 mAm.enforceSystemHasVrFeature();
2985
2986 final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class);
2987
2988 ActivityRecord r;
2989 synchronized (mGlobalLock) {
2990 r = ActivityRecord.isInStackLocked(token);
2991 }
2992
2993 if (r == null) {
2994 throw new IllegalArgumentException();
2995 }
2996
2997 int err;
2998 if ((err = vrService.hasVrPackage(packageName, r.userId)) !=
2999 VrManagerInternal.NO_ERROR) {
3000 return err;
3001 }
3002
3003 // Clear the binder calling uid since this path may call moveToTask().
3004 final long callingId = Binder.clearCallingIdentity();
3005 try {
3006 synchronized (mGlobalLock) {
3007 r.requestedVrComponent = (enabled) ? packageName : null;
3008
3009 // Update associated state if this activity is currently focused
3010 if (r == mStackSupervisor.getResumedActivityLocked()) {
3011 mAm.applyUpdateVrModeLocked(r);
3012 }
3013 return 0;
3014 }
3015 } finally {
3016 Binder.restoreCallingIdentity(callingId);
3017 }
3018 }
3019
3020 @Override
3021 public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) {
3022 Slog.i(TAG, "Activity tried to startLocalVoiceInteraction");
3023 synchronized (mGlobalLock) {
3024 ActivityRecord activity = mAm.getFocusedStack().getTopActivity();
3025 if (ActivityRecord.forTokenLocked(callingActivity) != activity) {
3026 throw new SecurityException("Only focused activity can call startVoiceInteraction");
3027 }
3028 if (mAm.mRunningVoice != null || activity.getTask().voiceSession != null
3029 || activity.voiceSession != null) {
3030 Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction");
3031 return;
3032 }
3033 if (activity.pendingVoiceInteractionStart) {
3034 Slog.w(TAG, "Pending start of voice interaction already.");
3035 return;
3036 }
3037 activity.pendingVoiceInteractionStart = true;
3038 }
3039 LocalServices.getService(VoiceInteractionManagerInternal.class)
3040 .startLocalVoiceInteraction(callingActivity, options);
3041 }
3042
3043 @Override
3044 public void stopLocalVoiceInteraction(IBinder callingActivity) {
3045 LocalServices.getService(VoiceInteractionManagerInternal.class)
3046 .stopLocalVoiceInteraction(callingActivity);
3047 }
3048
3049 @Override
3050 public boolean supportsLocalVoiceInteraction() {
3051 return LocalServices.getService(VoiceInteractionManagerInternal.class)
3052 .supportsLocalVoiceInteraction();
3053 }
3054
3055 /** Notifies all listeners when the pinned stack animation starts. */
3056 @Override
3057 public void notifyPinnedStackAnimationStarted() {
3058 mAm.mTaskChangeNotificationController.notifyPinnedStackAnimationStarted();
3059 }
3060
3061 /** Notifies all listeners when the pinned stack animation ends. */
3062 @Override
3063 public void notifyPinnedStackAnimationEnded() {
3064 mAm.mTaskChangeNotificationController.notifyPinnedStackAnimationEnded();
3065 }
3066
3067 @Override
3068 public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
3069 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizePinnedStack()");
3070 final long ident = Binder.clearCallingIdentity();
3071 try {
3072 synchronized (mGlobalLock) {
3073 mStackSupervisor.resizePinnedStackLocked(pinnedBounds, tempPinnedTaskBounds);
3074 }
3075 } finally {
3076 Binder.restoreCallingIdentity(ident);
3077 }
3078 }
3079
3080 @Override
3081 public boolean updateDisplayOverrideConfiguration(Configuration values, int displayId) {
3082 mAm.enforceCallingPermission(CHANGE_CONFIGURATION, "updateDisplayOverrideConfiguration()");
3083
3084 synchronized (mGlobalLock) {
3085 // Check if display is initialized in AM.
3086 if (!mStackSupervisor.isDisplayAdded(displayId)) {
3087 // Call might come when display is not yet added or has already been removed.
3088 if (DEBUG_CONFIGURATION) {
3089 Slog.w(TAG, "Trying to update display configuration for non-existing displayId="
3090 + displayId);
3091 }
3092 return false;
3093 }
3094
3095 if (values == null && mAm.mWindowManager != null) {
3096 // sentinel: fetch the current configuration from the window manager
3097 values = mAm.mWindowManager.computeNewConfiguration(displayId);
3098 }
3099
3100 if (mAm.mWindowManager != null) {
3101 // Update OOM levels based on display size.
3102 mAm.mProcessList.applyDisplaySize(mAm.mWindowManager);
3103 }
3104
3105 final long origId = Binder.clearCallingIdentity();
3106 try {
3107 if (values != null) {
3108 Settings.System.clearConfiguration(values);
3109 }
3110 mAm.updateDisplayOverrideConfigurationLocked(values, null /* starting */,
3111 false /* deferResume */, displayId, mTmpUpdateConfigurationResult);
3112 return mTmpUpdateConfigurationResult.changes != 0;
3113 } finally {
3114 Binder.restoreCallingIdentity(origId);
3115 }
3116 }
3117 }
3118
3119 @Override
3120 public boolean updateConfiguration(Configuration values) {
3121 mAm.enforceCallingPermission(CHANGE_CONFIGURATION, "updateConfiguration()");
3122
3123 synchronized (mGlobalLock) {
3124 if (values == null && mAm.mWindowManager != null) {
3125 // sentinel: fetch the current configuration from the window manager
3126 values = mAm.mWindowManager.computeNewConfiguration(DEFAULT_DISPLAY);
3127 }
3128
3129 if (mAm.mWindowManager != null) {
3130 // Update OOM levels based on display size.
3131 mAm.mProcessList.applyDisplaySize(mAm.mWindowManager);
3132 }
3133
3134 final long origId = Binder.clearCallingIdentity();
3135 try {
3136 if (values != null) {
3137 Settings.System.clearConfiguration(values);
3138 }
3139 mAm.updateConfigurationLocked(values, null, false, false /* persistent */,
3140 UserHandle.USER_NULL, false /* deferResume */,
3141 mTmpUpdateConfigurationResult);
3142 return mTmpUpdateConfigurationResult.changes != 0;
3143 } finally {
3144 Binder.restoreCallingIdentity(origId);
3145 }
3146 }
3147 }
3148
3149 @Override
3150 public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback,
3151 CharSequence message) {
3152 if (message != null) {
3153 mAm.enforceCallingPermission(
3154 Manifest.permission.SHOW_KEYGUARD_MESSAGE, "dismissKeyguard()");
3155 }
3156 final long callingId = Binder.clearCallingIdentity();
3157 try {
3158 synchronized (mGlobalLock) {
3159 mAm.mKeyguardController.dismissKeyguard(token, callback, message);
3160 }
3161 } finally {
3162 Binder.restoreCallingIdentity(callingId);
3163 }
3164 }
3165
3166 @Override
3167 public void cancelTaskWindowTransition(int taskId) {
3168 mAm.enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS,
3169 "cancelTaskWindowTransition()");
3170 final long ident = Binder.clearCallingIdentity();
3171 try {
3172 synchronized (mGlobalLock) {
3173 final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId,
3174 MATCH_TASK_IN_STACKS_ONLY);
3175 if (task == null) {
3176 Slog.w(TAG, "cancelTaskWindowTransition: taskId=" + taskId + " not found");
3177 return;
3178 }
3179 task.cancelWindowTransition();
3180 }
3181 } finally {
3182 Binder.restoreCallingIdentity(ident);
3183 }
3184 }
3185
3186 @Override
3187 public ActivityManager.TaskSnapshot getTaskSnapshot(int taskId, boolean reducedResolution) {
3188 mAm.enforceCallerIsRecentsOrHasPermission(READ_FRAME_BUFFER, "getTaskSnapshot()");
3189 final long ident = Binder.clearCallingIdentity();
3190 try {
3191 final TaskRecord task;
3192 synchronized (mGlobalLock) {
3193 task = mStackSupervisor.anyTaskForIdLocked(taskId,
3194 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
3195 if (task == null) {
3196 Slog.w(TAG, "getTaskSnapshot: taskId=" + taskId + " not found");
3197 return null;
3198 }
3199 }
3200 // Don't call this while holding the lock as this operation might hit the disk.
3201 return task.getSnapshot(reducedResolution);
3202 } finally {
3203 Binder.restoreCallingIdentity(ident);
3204 }
3205 }
3206
3207 @Override
3208 public void setDisablePreviewScreenshots(IBinder token, boolean disable) {
3209 synchronized (mGlobalLock) {
3210 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
3211 if (r == null) {
3212 Slog.w(TAG, "setDisablePreviewScreenshots: Unable to find activity for token="
3213 + token);
3214 return;
3215 }
3216 final long origId = Binder.clearCallingIdentity();
3217 try {
3218 r.setDisablePreviewScreenshots(disable);
3219 } finally {
3220 Binder.restoreCallingIdentity(origId);
3221 }
3222 }
3223 }
3224
3225 /** Return the user id of the last resumed activity. */
3226 @Override
3227 public @UserIdInt
3228 int getLastResumedActivityUserId() {
3229 mAm.enforceCallingPermission(
3230 Manifest.permission.INTERACT_ACROSS_USERS_FULL, "getLastResumedActivityUserId()");
3231 synchronized (mGlobalLock) {
3232 if (mAm.mLastResumedActivity == null) {
3233 return mAm.mUserController.getCurrentUserId();
3234 }
3235 return mAm.mLastResumedActivity.userId;
3236 }
3237 }
3238
3239 @Override
3240 public void updateLockTaskFeatures(int userId, int flags) {
3241 final int callingUid = Binder.getCallingUid();
3242 if (callingUid != 0 && callingUid != SYSTEM_UID) {
3243 mAm.enforceCallingPermission(android.Manifest.permission.UPDATE_LOCK_TASK_PACKAGES,
3244 "updateLockTaskFeatures()");
3245 }
3246 synchronized (mGlobalLock) {
3247 if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Allowing features " + userId + ":0x" +
3248 Integer.toHexString(flags));
3249 mAm.getLockTaskController().updateLockTaskFeatures(userId, flags);
3250 }
3251 }
3252
3253 @Override
3254 public void setShowWhenLocked(IBinder token, boolean showWhenLocked) {
3255 synchronized (mGlobalLock) {
3256 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
3257 if (r == null) {
3258 return;
3259 }
3260 final long origId = Binder.clearCallingIdentity();
3261 try {
3262 r.setShowWhenLocked(showWhenLocked);
3263 } finally {
3264 Binder.restoreCallingIdentity(origId);
3265 }
3266 }
3267 }
3268
3269 @Override
3270 public void setTurnScreenOn(IBinder token, boolean turnScreenOn) {
3271 synchronized (mGlobalLock) {
3272 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
3273 if (r == null) {
3274 return;
3275 }
3276 final long origId = Binder.clearCallingIdentity();
3277 try {
3278 r.setTurnScreenOn(turnScreenOn);
3279 } finally {
3280 Binder.restoreCallingIdentity(origId);
3281 }
3282 }
3283 }
3284
3285 @Override
3286 public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) {
3287 mAm.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
3288 "registerRemoteAnimations");
3289 definition.setCallingPid(Binder.getCallingPid());
3290 synchronized (mGlobalLock) {
3291 final ActivityRecord r = ActivityRecord.isInStackLocked(token);
3292 if (r == null) {
3293 return;
3294 }
3295 final long origId = Binder.clearCallingIdentity();
3296 try {
3297 r.registerRemoteAnimations(definition);
3298 } finally {
3299 Binder.restoreCallingIdentity(origId);
3300 }
3301 }
3302 }
3303
3304 @Override
3305 public void registerRemoteAnimationForNextActivityStart(String packageName,
3306 RemoteAnimationAdapter adapter) {
3307 mAm.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS,
3308 "registerRemoteAnimationForNextActivityStart");
3309 adapter.setCallingPid(Binder.getCallingPid());
3310 synchronized (mGlobalLock) {
3311 final long origId = Binder.clearCallingIdentity();
3312 try {
3313 mAm.getActivityStartController().registerRemoteAnimationForNextActivityStart(
3314 packageName, adapter);
3315 } finally {
3316 Binder.restoreCallingIdentity(origId);
3317 }
3318 }
3319 }
3320
3321 /** @see android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning */
3322 @Override
3323 public void alwaysShowUnsupportedCompileSdkWarning(ComponentName activity) {
3324 synchronized (mGlobalLock) {
3325 final long origId = Binder.clearCallingIdentity();
3326 try {
3327 mAm.mAppWarnings.alwaysShowUnsupportedCompileSdkWarning(activity);
3328 } finally {
3329 Binder.restoreCallingIdentity(origId);
3330 }
3331 }
3332 }
Wale Ogunwale65ebd952018-04-25 15:41:44 -07003333}