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