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 android.app.ActivityManager.START_SUCCESS;
     20 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
     21 
     22 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
     23 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
     24 import static com.android.server.am.ActivityManagerService.ALLOW_FULL_ONLY;
     25 
     26 import android.app.IApplicationThread;
     27 import android.content.ComponentName;
     28 import android.content.ContentResolver;
     29 import android.content.Intent;
     30 import android.content.pm.ActivityInfo;
     31 import android.content.pm.ApplicationInfo;
     32 import android.content.pm.PackageManager;
     33 import android.content.pm.ResolveInfo;
     34 import android.os.Binder;
     35 import android.os.FactoryTest;
     36 import android.os.Handler;
     37 import android.os.IBinder;
     38 import android.os.Looper;
     39 import android.os.Message;
     40 import android.os.UserHandle;
     41 import android.provider.Settings;
     42 import android.util.Slog;
     43 import android.view.RemoteAnimationAdapter;
     44 
     45 import com.android.internal.annotations.VisibleForTesting;
     46 import com.android.server.am.ActivityStackSupervisor.PendingActivityLaunch;
     47 import com.android.server.am.ActivityStarter.DefaultFactory;
     48 import com.android.server.am.ActivityStarter.Factory;
     49 
     50 import java.io.PrintWriter;
     51 import java.util.ArrayList;
     52 import java.util.List;
     53 
     54 /**
     55  * Controller for delegating activity launches.
     56  *
     57  * This class' main objective is to take external activity start requests and prepare them into
     58  * a series of discrete activity launches that can be handled by an {@link ActivityStarter}. It is
     59  * also responsible for handling logic that happens around an activity launch, but doesn't
     60  * necessarily influence the activity start. Examples include power hint management, processing
     61  * through the pending activity list, and recording home activity launches.
     62  */
     63 public class ActivityStartController {
     64     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStartController" : TAG_AM;
     65 
     66     private static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 1;
     67 
     68     private final ActivityManagerService mService;
     69     private final ActivityStackSupervisor mSupervisor;
     70 
     71     /** Last home activity record we attempted to start. */
     72     private ActivityRecord mLastHomeActivityStartRecord;
     73 
     74     /** Temporary array to capture start activity results */
     75     private ActivityRecord[] tmpOutRecord = new ActivityRecord[1];
     76 
     77     /**The result of the last home activity we attempted to start. */
     78     private int mLastHomeActivityStartResult;
     79 
     80     /** A list of activities that are waiting to launch. */
     81     private final ArrayList<ActivityStackSupervisor.PendingActivityLaunch>
     82             mPendingActivityLaunches = new ArrayList<>();
     83 
     84     private final Factory mFactory;
     85 
     86     private final Handler mHandler;
     87 
     88     private final PendingRemoteAnimationRegistry mPendingRemoteAnimationRegistry;
     89 
     90     private final class StartHandler extends Handler {
     91         public StartHandler(Looper looper) {
     92             super(looper, null, true);
     93         }
     94 
     95         @Override
     96         public void handleMessage(Message msg) {
     97             switch(msg.what) {
     98                 case DO_PENDING_ACTIVITY_LAUNCHES_MSG:
     99                     synchronized (mService) {
    100                         doPendingActivityLaunches(true);
    101                     }
    102                     break;
    103             }
    104         }
    105     }
    106 
    107     /**
    108      * TODO(b/64750076): Capture information necessary for dump and
    109      * {@link #postStartActivityProcessingForLastStarter} rather than keeping the entire object
    110      * around
    111      */
    112     private ActivityStarter mLastStarter;
    113 
    114     ActivityStartController(ActivityManagerService service) {
    115         this(service, service.mStackSupervisor,
    116                 new DefaultFactory(service, service.mStackSupervisor,
    117                     new ActivityStartInterceptor(service, service.mStackSupervisor)));
    118     }
    119 
    120     @VisibleForTesting
    121     ActivityStartController(ActivityManagerService service, ActivityStackSupervisor supervisor,
    122             Factory factory) {
    123         mService = service;
    124         mSupervisor = supervisor;
    125         mHandler = new StartHandler(mService.mHandlerThread.getLooper());
    126         mFactory = factory;
    127         mFactory.setController(this);
    128         mPendingRemoteAnimationRegistry = new PendingRemoteAnimationRegistry(service,
    129                 service.mHandler);
    130     }
    131 
    132     /**
    133      * @return A starter to configure and execute starting an activity. It is valid until after
    134      *         {@link ActivityStarter#execute} is invoked. At that point, the starter should be
    135      *         considered invalid and no longer modified or used.
    136      */
    137     ActivityStarter obtainStarter(Intent intent, String reason) {
    138         return mFactory.obtain().setIntent(intent).setReason(reason);
    139     }
    140 
    141     void onExecutionComplete(ActivityStarter starter) {
    142         if (mLastStarter == null) {
    143             mLastStarter = mFactory.obtain();
    144         }
    145 
    146         mLastStarter.set(starter);
    147         mFactory.recycle(starter);
    148     }
    149 
    150     /**
    151      * TODO(b/64750076): usage of this doesn't seem right. We're making decisions based off the
    152      * last starter for an arbitrary task record. Re-evaluate whether we can remove.
    153      */
    154     void postStartActivityProcessingForLastStarter(ActivityRecord r, int result,
    155             ActivityStack targetStack) {
    156         if (mLastStarter == null) {
    157             return;
    158         }
    159 
    160         mLastStarter.postStartActivityProcessing(r, result, targetStack);
    161     }
    162 
    163     void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
    164         mSupervisor.moveHomeStackTaskToTop(reason);
    165 
    166         mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
    167                 .setOutActivity(tmpOutRecord)
    168                 .setCallingUid(0)
    169                 .setActivityInfo(aInfo)
    170                 .execute();
    171         mLastHomeActivityStartRecord = tmpOutRecord[0];
    172         if (mSupervisor.inResumeTopActivity) {
    173             // If we are in resume section already, home activity will be initialized, but not
    174             // resumed (to avoid recursive resume) and will stay that way until something pokes it
    175             // again. We need to schedule another resume.
    176             mSupervisor.scheduleResumeTopActivities();
    177         }
    178     }
    179 
    180     /**
    181      * Starts the "new version setup screen" if appropriate.
    182      */
    183     void startSetupActivity() {
    184         // Only do this once per boot.
    185         if (mService.getCheckedForSetup()) {
    186             return;
    187         }
    188 
    189         // We will show this screen if the current one is a different
    190         // version than the last one shown, and we are not running in
    191         // low-level factory test mode.
    192         final ContentResolver resolver = mService.mContext.getContentResolver();
    193         if (mService.mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL &&
    194                 Settings.Global.getInt(resolver,
    195                         Settings.Global.DEVICE_PROVISIONED, 0) != 0) {
    196             mService.setCheckedForSetup(true);
    197 
    198             // See if we should be showing the platform update setup UI.
    199             final Intent intent = new Intent(Intent.ACTION_UPGRADE_SETUP);
    200             final List<ResolveInfo> ris =
    201                     mService.mContext.getPackageManager().queryIntentActivities(intent,
    202                             PackageManager.MATCH_SYSTEM_ONLY | PackageManager.GET_META_DATA
    203                                     | ActivityManagerService.STOCK_PM_FLAGS);
    204             if (!ris.isEmpty()) {
    205                 final ResolveInfo ri = ris.get(0);
    206                 String vers = ri.activityInfo.metaData != null
    207                         ? ri.activityInfo.metaData.getString(Intent.METADATA_SETUP_VERSION)
    208                         : null;
    209                 if (vers == null && ri.activityInfo.applicationInfo.metaData != null) {
    210                     vers = ri.activityInfo.applicationInfo.metaData.getString(
    211                             Intent.METADATA_SETUP_VERSION);
    212                 }
    213                 String lastVers = Settings.Secure.getString(
    214                         resolver, Settings.Secure.LAST_SETUP_SHOWN);
    215                 if (vers != null && !vers.equals(lastVers)) {
    216                     intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
    217                     intent.setComponent(new ComponentName(
    218                             ri.activityInfo.packageName, ri.activityInfo.name));
    219                     obtainStarter(intent, "startSetupActivity")
    220                             .setCallingUid(0)
    221                             .setActivityInfo(ri.activityInfo)
    222                             .execute();
    223                 }
    224             }
    225         }
    226     }
    227 
    228     /**
    229      * If {@code validateIncomingUser} is true, check {@code targetUserId} against the real calling
    230      * user ID inferred from {@code realCallingUid}, then return the resolved user-id, taking into
    231      * account "current user", etc.
    232      *
    233      * If {@code validateIncomingUser} is false, it skips the above check, but instead
    234      * ensures {@code targetUserId} is a real user ID and not a special user ID such as
    235      * {@link android.os.UserHandle#USER_ALL}, etc.
    236      */
    237     int checkTargetUser(int targetUserId, boolean validateIncomingUser,
    238             int realCallingPid, int realCallingUid, String reason) {
    239         if (validateIncomingUser) {
    240             return mService.mUserController.handleIncomingUser(realCallingPid, realCallingUid,
    241                     targetUserId, false, ALLOW_FULL_ONLY, reason, null);
    242         } else {
    243             mService.mUserController.ensureNotSpecialUser(targetUserId);
    244             return targetUserId;
    245         }
    246     }
    247 
    248     final int startActivityInPackage(int uid, int realCallingPid, int realCallingUid,
    249             String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
    250             String resultWho, int requestCode, int startFlags, SafeActivityOptions options,
    251             int userId, TaskRecord inTask, String reason, boolean validateIncomingUser) {
    252 
    253         userId = checkTargetUser(userId, validateIncomingUser, realCallingPid, realCallingUid,
    254                 reason);
    255 
    256         // TODO: Switch to user app stacks here.
    257         return obtainStarter(intent, reason)
    258                 .setCallingUid(uid)
    259                 .setRealCallingPid(realCallingPid)
    260                 .setRealCallingUid(realCallingUid)
    261                 .setCallingPackage(callingPackage)
    262                 .setResolvedType(resolvedType)
    263                 .setResultTo(resultTo)
    264                 .setResultWho(resultWho)
    265                 .setRequestCode(requestCode)
    266                 .setStartFlags(startFlags)
    267                 .setActivityOptions(options)
    268                 .setMayWait(userId)
    269                 .setInTask(inTask)
    270                 .execute();
    271     }
    272 
    273     /**
    274      * Start intents as a package.
    275      *
    276      * @param uid Make a call as if this UID did.
    277      * @param callingPackage Make a call as if this package did.
    278      * @param intents Intents to start.
    279      * @param userId Start the intents on this user.
    280      * @param validateIncomingUser Set true to skip checking {@code userId} with the calling UID.
    281      */
    282     final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
    283             String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
    284             boolean validateIncomingUser) {
    285 
    286         final String reason = "startActivityInPackage";
    287 
    288         userId = checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(),
    289                 Binder.getCallingUid(), reason);
    290 
    291         // TODO: Switch to user app stacks here.
    292         return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options,
    293                 userId, reason);
    294     }
    295 
    296     int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
    297             Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options,
    298             int userId, String reason) {
    299         if (intents == null) {
    300             throw new NullPointerException("intents is null");
    301         }
    302         if (resolvedTypes == null) {
    303             throw new NullPointerException("resolvedTypes is null");
    304         }
    305         if (intents.length != resolvedTypes.length) {
    306             throw new IllegalArgumentException("intents are length different than resolvedTypes");
    307         }
    308 
    309         final int realCallingPid = Binder.getCallingPid();
    310         final int realCallingUid = Binder.getCallingUid();
    311 
    312         int callingPid;
    313         if (callingUid >= 0) {
    314             callingPid = -1;
    315         } else if (caller == null) {
    316             callingPid = realCallingPid;
    317             callingUid = realCallingUid;
    318         } else {
    319             callingPid = callingUid = -1;
    320         }
    321         final long origId = Binder.clearCallingIdentity();
    322         try {
    323             synchronized (mService) {
    324                 ActivityRecord[] outActivity = new ActivityRecord[1];
    325                 for (int i=0; i < intents.length; i++) {
    326                     Intent intent = intents[i];
    327                     if (intent == null) {
    328                         continue;
    329                     }
    330 
    331                     // Refuse possible leaked file descriptors
    332                     if (intent != null && intent.hasFileDescriptors()) {
    333                         throw new IllegalArgumentException("File descriptors passed in Intent");
    334                     }
    335 
    336                     boolean componentSpecified = intent.getComponent() != null;
    337 
    338                     // Don't modify the client's object!
    339                     intent = new Intent(intent);
    340 
    341                     // Collect information about the target of the Intent.
    342                     ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
    343                             null, userId, ActivityStarter.computeResolveFilterUid(
    344                                     callingUid, realCallingUid, UserHandle.USER_NULL));
    345                     // TODO: New, check if this is correct
    346                     aInfo = mService.getActivityInfoForUser(aInfo, userId);
    347 
    348                     if (aInfo != null &&
    349                             (aInfo.applicationInfo.privateFlags
    350                                     & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)  != 0) {
    351                         throw new IllegalArgumentException(
    352                                 "FLAG_CANT_SAVE_STATE not supported here");
    353                     }
    354 
    355                     final boolean top = i == intents.length - 1;
    356                     final SafeActivityOptions checkedOptions = top
    357                             ? options
    358                             : null;
    359                     final int res = obtainStarter(intent, reason)
    360                             .setCaller(caller)
    361                             .setResolvedType(resolvedTypes[i])
    362                             .setActivityInfo(aInfo)
    363                             .setResultTo(resultTo)
    364                             .setRequestCode(-1)
    365                             .setCallingPid(callingPid)
    366                             .setCallingUid(callingUid)
    367                             .setCallingPackage(callingPackage)
    368                             .setRealCallingPid(realCallingPid)
    369                             .setRealCallingUid(realCallingUid)
    370                             .setActivityOptions(checkedOptions)
    371                             .setComponentSpecified(componentSpecified)
    372                             .setOutActivity(outActivity)
    373 
    374                             // Top activity decides on animation being run, so we allow only for the
    375                             // top one as otherwise an activity below might consume it.
    376                             .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/)
    377                             .execute();
    378 
    379                     if (res < 0) {
    380                         return res;
    381                     }
    382 
    383                     resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
    384                 }
    385             }
    386         } finally {
    387             Binder.restoreCallingIdentity(origId);
    388         }
    389 
    390         return START_SUCCESS;
    391     }
    392 
    393     void schedulePendingActivityLaunches(long delayMs) {
    394         mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
    395         Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
    396         mHandler.sendMessageDelayed(msg, delayMs);
    397     }
    398 
    399     void doPendingActivityLaunches(boolean doResume) {
    400         while (!mPendingActivityLaunches.isEmpty()) {
    401             final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
    402             final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
    403             final ActivityStarter starter = obtainStarter(null /* intent */,
    404                     "pendingActivityLaunch");
    405             try {
    406                 starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags,
    407                         resume, null, null, null /* outRecords */);
    408             } catch (Exception e) {
    409                 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
    410                 pal.sendErrorResult(e.getMessage());
    411             }
    412         }
    413     }
    414 
    415     void addPendingActivityLaunch(PendingActivityLaunch launch) {
    416         mPendingActivityLaunches.add(launch);
    417     }
    418 
    419     boolean clearPendingActivityLaunches(String packageName) {
    420         final int pendingLaunches = mPendingActivityLaunches.size();
    421 
    422         for (int palNdx = pendingLaunches - 1; palNdx >= 0; --palNdx) {
    423             final PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
    424             final ActivityRecord r = pal.r;
    425             if (r != null && r.packageName.equals(packageName)) {
    426                 mPendingActivityLaunches.remove(palNdx);
    427             }
    428         }
    429         return mPendingActivityLaunches.size() < pendingLaunches;
    430     }
    431 
    432     void registerRemoteAnimationForNextActivityStart(String packageName,
    433             RemoteAnimationAdapter adapter) {
    434         mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter);
    435     }
    436 
    437     PendingRemoteAnimationRegistry getPendingRemoteAnimationRegistry() {
    438         return mPendingRemoteAnimationRegistry;
    439     }
    440 
    441     void dump(PrintWriter pw, String prefix, String dumpPackage) {
    442         pw.print(prefix);
    443         pw.print("mLastHomeActivityStartResult=");
    444         pw.println(mLastHomeActivityStartResult);
    445 
    446         if (mLastHomeActivityStartRecord != null) {
    447             pw.print(prefix);
    448             pw.println("mLastHomeActivityStartRecord:");
    449             mLastHomeActivityStartRecord.dump(pw, prefix + "  ");
    450         }
    451 
    452         final boolean dumpPackagePresent = dumpPackage != null;
    453 
    454         if (mLastStarter != null) {
    455             final boolean dump = !dumpPackagePresent
    456                     || mLastStarter.relatedToPackage(dumpPackage)
    457                     || (mLastHomeActivityStartRecord != null
    458                             && dumpPackage.equals(mLastHomeActivityStartRecord.packageName));
    459 
    460             if (dump) {
    461                 pw.print(prefix);
    462                 mLastStarter.dump(pw, prefix + "  ");
    463 
    464                 if (dumpPackagePresent) {
    465                     return;
    466                 }
    467             }
    468         }
    469 
    470         if (dumpPackagePresent) {
    471             pw.print(prefix);
    472             pw.println("(nothing)");
    473         }
    474     }
    475 }
    476