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