1/* 2 * Copyright (C) 2017 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 19import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS; 20import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS; 21 22import android.app.ActivityManager; 23import android.app.ActivityOptions; 24import android.app.IAppTask; 25import android.app.IApplicationThread; 26import android.content.Intent; 27import android.os.Binder; 28import android.os.Bundle; 29import android.os.IBinder; 30import android.os.UserHandle; 31 32/** 33 * An implementation of IAppTask, that allows an app to manage its own tasks via 34 * {@link android.app.ActivityManager.AppTask}. We keep track of the callingUid to ensure that 35 * only the process that calls getAppTasks() can call the AppTask methods. 36 */ 37class AppTaskImpl extends IAppTask.Stub { 38 private ActivityManagerService mService; 39 40 private int mTaskId; 41 private int mCallingUid; 42 43 public AppTaskImpl(ActivityManagerService service, int taskId, int callingUid) { 44 mService = service; 45 mTaskId = taskId; 46 mCallingUid = callingUid; 47 } 48 49 private void checkCaller() { 50 if (mCallingUid != Binder.getCallingUid()) { 51 throw new SecurityException("Caller " + mCallingUid 52 + " does not match caller of getAppTasks(): " + Binder.getCallingUid()); 53 } 54 } 55 56 @Override 57 public void finishAndRemoveTask() { 58 checkCaller(); 59 60 synchronized (mService) { 61 long origId = Binder.clearCallingIdentity(); 62 try { 63 // We remove the task from recents to preserve backwards 64 if (!mService.mStackSupervisor.removeTaskByIdLocked(mTaskId, false, 65 REMOVE_FROM_RECENTS, "finish-and-remove-task")) { 66 throw new IllegalArgumentException("Unable to find task ID " + mTaskId); 67 } 68 } finally { 69 Binder.restoreCallingIdentity(origId); 70 } 71 } 72 } 73 74 @Override 75 public ActivityManager.RecentTaskInfo getTaskInfo() { 76 checkCaller(); 77 78 synchronized (mService) { 79 long origId = Binder.clearCallingIdentity(); 80 try { 81 TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId, 82 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); 83 if (tr == null) { 84 throw new IllegalArgumentException("Unable to find task ID " + mTaskId); 85 } 86 return mService.getRecentTasks().createRecentTaskInfo(tr); 87 } finally { 88 Binder.restoreCallingIdentity(origId); 89 } 90 } 91 } 92 93 @Override 94 public void moveToFront() { 95 checkCaller(); 96 // Will bring task to front if it already has a root activity. 97 final int callingPid = Binder.getCallingPid(); 98 final int callingUid = Binder.getCallingUid(); 99 final long origId = Binder.clearCallingIdentity(); 100 try { 101 synchronized (mService) { 102 mService.mStackSupervisor.startActivityFromRecents(callingPid, callingUid, mTaskId, 103 null); 104 } 105 } finally { 106 Binder.restoreCallingIdentity(origId); 107 } 108 } 109 110 @Override 111 public int startActivity(IBinder whoThread, String callingPackage, 112 Intent intent, String resolvedType, Bundle bOptions) { 113 checkCaller(); 114 115 int callingUser = UserHandle.getCallingUserId(); 116 TaskRecord tr; 117 IApplicationThread appThread; 118 synchronized (mService) { 119 tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId, 120 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); 121 if (tr == null) { 122 throw new IllegalArgumentException("Unable to find task ID " + mTaskId); 123 } 124 appThread = IApplicationThread.Stub.asInterface(whoThread); 125 if (appThread == null) { 126 throw new IllegalArgumentException("Bad app thread " + appThread); 127 } 128 } 129 130 return mService.getActivityStartController().obtainStarter(intent, "AppTaskImpl") 131 .setCaller(appThread) 132 .setCallingPackage(callingPackage) 133 .setResolvedType(resolvedType) 134 .setActivityOptions(bOptions) 135 .setMayWait(callingUser) 136 .setInTask(tr) 137 .execute(); 138 } 139 140 @Override 141 public void setExcludeFromRecents(boolean exclude) { 142 checkCaller(); 143 144 synchronized (mService) { 145 long origId = Binder.clearCallingIdentity(); 146 try { 147 TaskRecord tr = mService.mStackSupervisor.anyTaskForIdLocked(mTaskId, 148 MATCH_TASK_IN_STACKS_OR_RECENT_TASKS); 149 if (tr == null) { 150 throw new IllegalArgumentException("Unable to find task ID " + mTaskId); 151 } 152 Intent intent = tr.getBaseIntent(); 153 if (exclude) { 154 intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 155 } else { 156 intent.setFlags(intent.getFlags() 157 & ~Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); 158 } 159 } finally { 160 Binder.restoreCallingIdentity(origId); 161 } 162 } 163 } 164} 165