• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
StartHandler(Looper looper)91         public StartHandler(Looper looper) {
92             super(looper, null, true);
93         }
94 
95         @Override
handleMessage(Message msg)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 
ActivityStartController(ActivityManagerService service)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
ActivityStartController(ActivityManagerService service, ActivityStackSupervisor supervisor, Factory factory)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      */
obtainStarter(Intent intent, String reason)137     ActivityStarter obtainStarter(Intent intent, String reason) {
138         return mFactory.obtain().setIntent(intent).setReason(reason);
139     }
140 
onExecutionComplete(ActivityStarter starter)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      */
postStartActivityProcessingForLastStarter(ActivityRecord r, int result, ActivityStack targetStack)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 
startHomeActivity(Intent intent, ActivityInfo aInfo, String reason)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      */
startSetupActivity()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      */
checkTargetUser(int targetUserId, boolean validateIncomingUser, int realCallingPid, int realCallingUid, String reason)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 
startActivityInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, SafeActivityOptions options, int userId, TaskRecord inTask, String reason, boolean validateIncomingUser)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      */
startActivitiesInPackage(int uid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser)282     final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
283             String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId,
284             boolean validateIncomingUser) {
285         return startActivitiesInPackage(uid, 0, UserHandle.USER_NULL,
286              callingPackage, intents, resolvedTypes, resultTo, options, userId,
287              validateIncomingUser);
288     }
289 
startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, boolean validateIncomingUser)290     final int startActivitiesInPackage(int uid, int realCallingPid, int realCallingUid,
291             String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo,
292             SafeActivityOptions options, int userId, boolean validateIncomingUser) {
293         final String reason = "startActivityInPackage";
294 
295         userId = checkTargetUser(userId, validateIncomingUser, Binder.getCallingPid(),
296                 Binder.getCallingUid(), reason);
297 
298         // TODO: Switch to user app stacks here.
299         return startActivities(null, uid, realCallingPid, realCallingUid, callingPackage, intents,
300                 resolvedTypes, resultTo, options, userId, reason);
301     }
302 
startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid, int incomingRealCallingUid, String callingPackage, Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId, String reason)303     int startActivities(IApplicationThread caller, int callingUid, int incomingRealCallingPid,
304             int incomingRealCallingUid, String callingPackage, Intent[] intents, String[] resolvedTypes,
305             IBinder resultTo, SafeActivityOptions options, int userId, String reason) {
306         if (intents == null) {
307             throw new NullPointerException("intents is null");
308         }
309         if (resolvedTypes == null) {
310             throw new NullPointerException("resolvedTypes is null");
311         }
312         if (intents.length != resolvedTypes.length) {
313             throw new IllegalArgumentException("intents are length different than resolvedTypes");
314         }
315 
316         final int realCallingPid = incomingRealCallingPid != 0
317                                    ? incomingRealCallingPid
318                                    : Binder.getCallingPid();
319         final int realCallingUid = incomingRealCallingUid != UserHandle.USER_NULL
320                                    ? incomingRealCallingUid
321                                    : Binder.getCallingUid();
322         int callingPid;
323         if (callingUid >= 0) {
324             callingPid = -1;
325         } else if (caller == null) {
326             callingPid = realCallingPid;
327             callingUid = realCallingUid;
328         } else {
329             callingPid = callingUid = -1;
330         }
331         boolean forceNewTask = false;
332         final int filterCallingUid = ActivityStarter.computeResolveFilterUid(
333                 callingUid, realCallingUid, UserHandle.USER_NULL);
334         final long origId = Binder.clearCallingIdentity();
335         try {
336             synchronized (mService) {
337                 ActivityRecord[] outActivity = new ActivityRecord[1];
338                 for (int i=0; i < intents.length; i++) {
339                     Intent intent = intents[i];
340                     if (intent == null) {
341                         continue;
342                     }
343 
344                     // Refuse possible leaked file descriptors
345                     if (intent != null && intent.hasFileDescriptors()) {
346                         throw new IllegalArgumentException("File descriptors passed in Intent");
347                     }
348 
349                     boolean componentSpecified = intent.getComponent() != null;
350 
351                     // Don't modify the client's object!
352                     intent = new Intent(intent);
353                     if (forceNewTask) {
354                         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
355                     }
356 
357                     // Collect information about the target of the Intent.
358                     ActivityInfo aInfo = mSupervisor.resolveActivity(intent, resolvedTypes[i], 0,
359                             null, userId, filterCallingUid);
360                     // TODO: New, check if this is correct
361                     aInfo = mService.getActivityInfoForUser(aInfo, userId);
362 
363                     if (aInfo != null &&
364                             (aInfo.applicationInfo.privateFlags
365                                     & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)  != 0) {
366                         throw new IllegalArgumentException(
367                                 "FLAG_CANT_SAVE_STATE not supported here");
368                     }
369 
370                     final boolean top = i == intents.length - 1;
371                     final SafeActivityOptions checkedOptions = top
372                             ? options
373                             : null;
374                     final int res = obtainStarter(intent, reason)
375                             .setCaller(caller)
376                             .setResolvedType(resolvedTypes[i])
377                             .setActivityInfo(aInfo)
378                             .setResultTo(resultTo)
379                             .setRequestCode(-1)
380                             .setCallingPid(callingPid)
381                             .setCallingUid(callingUid)
382                             .setCallingPackage(callingPackage)
383                             .setRealCallingPid(realCallingPid)
384                             .setRealCallingUid(realCallingUid)
385                             .setActivityOptions(checkedOptions)
386                             .setComponentSpecified(componentSpecified)
387                             .setOutActivity(outActivity)
388 
389                             // Top activity decides on animation being run, so we allow only for the
390                             // top one as otherwise an activity below might consume it.
391                             .setAllowPendingRemoteAnimationRegistryLookup(top /* allowLookup*/)
392                             .execute();
393 
394                     if (res < 0) {
395                         return res;
396                     }
397 
398                     final ActivityRecord started = outActivity[0];
399                     if (started != null && started.getUid() == filterCallingUid) {
400                         // Only the started activity which has the same uid as the source caller can
401                         // be the caller of next activity.
402                         resultTo = started.appToken;
403                         forceNewTask = false;
404                     } else {
405                         // Different apps not adjacent to the caller are forced to be new task.
406                         resultTo = null;
407                         forceNewTask = true;
408                     }
409                 }
410             }
411         } finally {
412             Binder.restoreCallingIdentity(origId);
413         }
414 
415         return START_SUCCESS;
416     }
417 
schedulePendingActivityLaunches(long delayMs)418     void schedulePendingActivityLaunches(long delayMs) {
419         mHandler.removeMessages(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
420         Message msg = mHandler.obtainMessage(DO_PENDING_ACTIVITY_LAUNCHES_MSG);
421         mHandler.sendMessageDelayed(msg, delayMs);
422     }
423 
doPendingActivityLaunches(boolean doResume)424     void doPendingActivityLaunches(boolean doResume) {
425         while (!mPendingActivityLaunches.isEmpty()) {
426             final PendingActivityLaunch pal = mPendingActivityLaunches.remove(0);
427             final boolean resume = doResume && mPendingActivityLaunches.isEmpty();
428             final ActivityStarter starter = obtainStarter(null /* intent */,
429                     "pendingActivityLaunch");
430             try {
431                 starter.startResolvedActivity(pal.r, pal.sourceRecord, null, null, pal.startFlags,
432                         resume, null, null, null /* outRecords */);
433             } catch (Exception e) {
434                 Slog.e(TAG, "Exception during pending activity launch pal=" + pal, e);
435                 pal.sendErrorResult(e.getMessage());
436             }
437         }
438     }
439 
addPendingActivityLaunch(PendingActivityLaunch launch)440     void addPendingActivityLaunch(PendingActivityLaunch launch) {
441         mPendingActivityLaunches.add(launch);
442     }
443 
clearPendingActivityLaunches(String packageName)444     boolean clearPendingActivityLaunches(String packageName) {
445         final int pendingLaunches = mPendingActivityLaunches.size();
446 
447         for (int palNdx = pendingLaunches - 1; palNdx >= 0; --palNdx) {
448             final PendingActivityLaunch pal = mPendingActivityLaunches.get(palNdx);
449             final ActivityRecord r = pal.r;
450             if (r != null && r.packageName.equals(packageName)) {
451                 mPendingActivityLaunches.remove(palNdx);
452             }
453         }
454         return mPendingActivityLaunches.size() < pendingLaunches;
455     }
456 
registerRemoteAnimationForNextActivityStart(String packageName, RemoteAnimationAdapter adapter)457     void registerRemoteAnimationForNextActivityStart(String packageName,
458             RemoteAnimationAdapter adapter) {
459         mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter);
460     }
461 
getPendingRemoteAnimationRegistry()462     PendingRemoteAnimationRegistry getPendingRemoteAnimationRegistry() {
463         return mPendingRemoteAnimationRegistry;
464     }
465 
dump(PrintWriter pw, String prefix, String dumpPackage)466     void dump(PrintWriter pw, String prefix, String dumpPackage) {
467         pw.print(prefix);
468         pw.print("mLastHomeActivityStartResult=");
469         pw.println(mLastHomeActivityStartResult);
470 
471         if (mLastHomeActivityStartRecord != null) {
472             pw.print(prefix);
473             pw.println("mLastHomeActivityStartRecord:");
474             mLastHomeActivityStartRecord.dump(pw, prefix + "  ");
475         }
476 
477         final boolean dumpPackagePresent = dumpPackage != null;
478 
479         if (mLastStarter != null) {
480             final boolean dump = !dumpPackagePresent
481                     || mLastStarter.relatedToPackage(dumpPackage)
482                     || (mLastHomeActivityStartRecord != null
483                             && dumpPackage.equals(mLastHomeActivityStartRecord.packageName));
484 
485             if (dump) {
486                 pw.print(prefix);
487                 mLastStarter.dump(pw, prefix + "  ");
488 
489                 if (dumpPackagePresent) {
490                     return;
491                 }
492             }
493         }
494 
495         if (dumpPackagePresent) {
496             pw.print(prefix);
497             pw.println("(nothing)");
498         }
499     }
500 }
501