省流:
client 封装真实intent到 PendingIntent ->
真正执行时 PendingIntent.send -> PendingIntentRecord.send & sendInner
-> ATMS.startActivityInPackage/startActivitiesInPackage/sendActivityResult/broadcastIntentInPackage/startServiceInPackage
即 xxxInPackage
1. 概念
PendingIntent:Intent的封装。
把这个封装好的intent交给别的程序,
别的程序根据这个intent延后处理intent中所描述的事情。
2. 三个方法:
getActivity(Context context, int requestCode, Intent intent, int flags, Bundle options)
getBroadcast(Context context, int requestCode, Intent intent, int flags)
getService(Context context, int requestCode, Intent intent, int flags)
3. PendingIntentRecord 向AMS 发起启动请求
最后通过 PendingIntentRecord 向AMS 发起启动请求, 调用AMS的对应方法 xxxInPackage(如startActivityInPackage)
源码:
frameworks/base/services/core/java/com/android/server/am/PendingIntentRecord.java
public int sendInner(int code, Intent intent, String resolvedType, IBinder allowlistToken,
IIntentReceiver finishedReceiver, String requiredPermission, IBinder resultTo,
String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle options) {
switch (key.type) {
case ActivityManager.INTENT_SENDER_ACTIVITY:
...
if (key.allIntents != null && key.allIntents.length > 1) {
res = controller.mAtmInternal.startActivitiesInPackage(
...
} else {
res = controller.mAtmInternal.startActivityInPackage(uid, callingPid,
...
case ActivityManager.INTENT_SENDER_BROADCAST:
int sent = controller.mAmInternal.broadcastIntentInPackage(key.packageName,
...
case ActivityManager.INTENT_SENDER_SERVICE:
case ActivityManager.INTENT_SENDER_FOREGROUND_SERVICE:
controller.mAmInternal.startServiceInPackage(uid, finalIntent, resolvedType,
其中: controller 是 PendingIntentController 对象,它的构造函数里,会去获取倒 ATMS 的本地代理对象, 即 ActivityTaskManagerInternal 对象
PendingIntentController(Looper looper, UserController userController,
ActivityManagerConstants constants) {
mH = new Handler(looper);
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
mUserController = userController;
mConstants = constants;
}
ActivityTaskManagerInternal 为 ATMS 的本地接口(system_server进程内部使用)
/**
* Activity Task manager local system service interface.
* @hide Only for use within system server
*/
public abstract class ActivityTaskManagerInternal { ...}
ActivityTaskManagerService 内部类 LocalService 实现了 ActivityTaskManagerInternal的接口,
并把LocalService 的对象添加到 LocalServices。
public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
public ActivityTaskManagerService(Context context) {
...
mInternal = new LocalService();
...
public ActivityTaskManagerInternal getAtmInternal() {
return mInternal;
}
private void start() {
LocalServices.addService(ActivityTaskManagerInternal.class, mInternal);
}
final class LocalService extends ActivityTaskManagerInternal {
@Override
public int startActivityInPackage(int uid, int realCallingPid, int realCallingUid..) {
return getActivityStartController().startActivityInPackage(...)
}
@Override
public int startActivityAsUser(IApplicationThread caller....) {
return ActivityTaskManagerService.this.startActivityAsUser(
}
因此, system_server 其它地方则可以通过 LocalServices.getService(ActivityTaskManagerInternal.class)
去获取到 ActivityTaskManagerInternal 的对象,
进而访问到 ATMS 或者直接处理。
4.参考:
PendingIntent源码分析: https://blog.csdn.net/konan1027/article/details/46914715
PendingIntentRecord 源码:
https://cs.android.com/android/platform/superproject/+/master:frameworks/base/services/core/java/com/android/server/am/PendingIntentRecord.java?hl=zh-cn
Android中pendingIntent的深入理解:https://blog.csdn.net/yuzhiboyi/article/details/8484771
Intent和PendingIntent的区别
a. Intent是立即使用的,而PendingIntent可以等到事件发生后触发,PendingIntent可以cancel
b. Intent在程序结束后即终止,而PendingIntent在程序结束后依然有效
c. PendingIntent自带Context,而Intent需要在某个Context内运行
d. Intent在原task中运行,PendingIntent在新的task中运行
5. 一个PendingIntent 执行的调用栈:
Client 调用AMS.sendIntentSender -> PendingIntentRecord.sendInner -> ActivityTaskManagerService.startActivityInPackage
->ActivityStartController.startActivityInPackage
-> ActivityStarter.execute/executeRequest
则会执行 start u
07-06 18:49:42.134 E 1876 5896 at com.android.server.wm.ActivityStarter.executeRequest(ActivityStarter.java:1197)
07-06 18:49:42.134 E 1876 5896 at com.android.server.wm.ActivityStarter.execute(ActivityStarter.java:1026)
07-06 18:49:42.134 E 1876 5896 at com.android.server.wm.ActivityStartController.startActivityInPackage(ActivityStartController.java:425)
07-06 18:49:42.134 E 1876 5896 at com.android.server.wm.ActivityTaskManagerService$LocalService.startActivityInPackage(ActivityTaskManagerService.java:6926)
07-06 18:49:42.134 E 1876 5896 at com.android.server.am.PendingIntentRecord.sendInner(PendingIntentRecord.java:586)
07-06 18:49:42.134 E 1876 5896 at com.android.server.am.ActivityManagerService.sendIntentSender(ActivityManagerService.java:6579)
07-06 18:49:42.134 E 1876 5896 at com.android.server.am.ActivityManagerService.sendIntentSender(ActivityManagerService.java:6568)
07-06 18:49:42.134 E 1876 5896 at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:4856)
07-06 18:49:42.134 E 1876 5896 at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:3135)
07-06 18:49:42.134 E 1876 5896 at android.os.Binder.execTransactInternal(Binder.java:1316)
07-06 18:49:42.134 E 1876 5896 at android.os.Binder.execTransact(Binder.java:1280)
6. 获取PendingIntent 对象 源码
以获取Activity 的PI 对象为例,
可见有两个方法,分别为 getActivity 和 getActivityAsUser, 前者是公开,后者是hide的。
后者可以传入 当前 user。
前者默认的user 是通过传入的 context 去获取的。
@SuppressWarnings("AndroidFrameworkPendingIntentMutability")
public static PendingIntent getActivity(Context context, int requestCode,
@NonNull Intent intent, @Flags int flags, @Nullable Bundle options) {
// Some tests only mock Context.getUserId(), so fallback to the id Context.getUser() is null
final UserHandle user = context.getUser();
return getActivityAsUser(context, requestCode, intent, flags, options,
user != null ? user : UserHandle.of(context.getUserId()));
}
/**
* @hide
* Note that UserHandle.CURRENT will be interpreted at the time the
* activity is started, not when the pending intent is created.
*/
@UnsupportedAppUsage
public static PendingIntent getActivityAsUser(Context context, int requestCode,
@NonNull Intent intent, int flags, Bundle options, UserHandle user) {
String packageName = context.getPackageName();
String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver());
checkFlags(flags, packageName);
try {
intent.migrateExtraStreamToClipData(context);
intent.prepareToLeaveProcess(context);
IIntentSender target =
ActivityManager.getService().getIntentSenderWithFeature(
INTENT_SENDER_ACTIVITY, packageName,
context.getAttributionTag(), null, null, requestCode, new Intent[] { intent },
resolvedType != null ? new String[] { resolvedType } : null,
flags, options, user.getIdentifier());
return target != null ? new PendingIntent(target) : null;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
--- End ---