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