Home | History | Annotate | Download | only in am
      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 
     17 package com.android.server.am;
     18 
     19 import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS_OR_RECENT_TASKS;
     20 import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
     21 
     22 import android.app.ActivityManager;
     23 import android.app.ActivityOptions;
     24 import android.app.IAppTask;
     25 import android.app.IApplicationThread;
     26 import android.content.Intent;
     27 import android.os.Binder;
     28 import android.os.Bundle;
     29 import android.os.IBinder;
     30 import 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  */
     37 class 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