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