同 Activity 一样,Client App 在 Menifest 中注册的静态广播外部 AMS 是无法知晓的,经过前几章的分析,相信大家已经是老司机了,我们可以先尝试提出自己的观点。
从前面我们知道,VAService 的启动时机实在 BinderProvider.onCreate():
@Override
public boolean onCreate() {
.....................
VAppManagerService.get().scanApps();
.....................
return true;
}
看到 VAppManagerService.get().scanApps()————>PersistenceLayer.read()——————->PackagePersistenceLayer.readPersistenceData()——————>VAppManagerService.loadPackage()———->VAppManagerService.loadPackageInnerLocked()————–>BroadcastSystem.startUp();
// 静态 Receiver 的注册
public void startApp(VPackage p) {
PackageSetting setting = (PackageSetting) p.mExtras;
// 遍历 Client App 的 Receiver
for (VPackage.ActivityComponent receiver : p.receivers) {
ActivityInfo info = receiver.info;
// 得到对应 Client App 在 VAService 中的记录列表
List<BroadcastReceiver> receivers = mReceivers.get(p.packageName);
if (receivers == null) {
receivers = new ArrayList<>();
mReceivers.put(p.packageName, receivers);
}
// 注册显式意图
String componentAction = String.format("_VA_%s_%s", info.packageName, info.name);
IntentFilter componentFilter = new IntentFilter(componentAction);
BroadcastReceiver r = new StaticBroadcastReceiver(setting.appId, info, componentFilter);
mContext.registerReceiver(r, componentFilter, null, mScheduler);
// 推入记录
receivers.add(r);
// 遍历注册隐式意图
for (VPackage.ActivityIntentInfo ci : receiver.intents) {
IntentFilter cloneFilter = new IntentFilter(ci.filter);
SpecialComponentList.protectIntentFilter(cloneFilter);
r = new StaticBroadcastReceiver(setting.appId, info, cloneFilter);
mContext.registerReceiver(r, cloneFilter, null, mScheduler);
// 推入记录
receivers.add(r);
}
}
}
这里对每个 Client App 静态 Receiver 的信息使用统一的代理 StaticBroadcastReceiver 注册。
这样我们的代理 Receiver 注册完毕了。
下面当代理 Receiver 收到广播时:
@Override
public void onReceive(Context context, Intent intent) {
if (mApp.isBooting()) {
return;
}
if ((intent.getFlags() & FLAG_RECEIVER_REGISTERED_ONLY) != 0 || isInitialStickyBroadcast()) {
return;
}
String privilegePkg = intent.getStringExtra("_VA_|_privilege_pkg_");
if (privilegePkg != null && !info.packageName.equals(privilegePkg)) {
return;
}
PendingResult result = goAsync();
if (!mAMS.handleStaticBroadcast(appId, info, intent, new PendingResultData(result))) {
result.finish();
}
}
然后看到 handleStaticBroadcast
boolean handleStaticBroadcast(int appId, ActivityInfo info, Intent intent,
PendingResultData result) {
// 这里是取出真正的目标 Intent
Intent realIntent = intent.getParcelableExtra("_VA_|_intent_");
// 取出真正的目标 component
ComponentName component = intent.getParcelableExtra("_VA_|_component_");
// 用户 id
int userId = intent.getIntExtra("_VA_|_user_id_", VUserHandle.USER_NULL);
if (realIntent == null) {
return false;
}
if (userId < 0) {
VLog.w(TAG, "Sent a broadcast without userId " + realIntent);
return false;
}
int vuid = VUserHandle.getUid(userId, appId);
return handleUserBroadcast(vuid, info, component, realIntent, result);
}
注意这里取出了真正的 Intent,和 Activity 类似,但是和 Activity 处理不同的是现在的逻辑还在 VAService 中:
然后 handleUserBroadcast()———–>handleStaticBroadcastAsUser()————>performScheduleReceiver():
private void performScheduleReceiver(IVClient client, int vuid, ActivityInfo info, Intent intent,
PendingResultData result) {
ComponentName componentName = ComponentUtils.toComponentName(info);
BroadcastSystem.get().broadcastSent(vuid, info, result);
try {
// 远程调用 client app 的 scheduleReceiver
client.scheduleReceiver(info.processName, componentName, intent, result);
} catch (Throwable e) {
if (result != null) {
result.finish();
}
}
}
client.scheduleReceiver() 这时候远程调用了 Client App 的 scheduleReceiver。这样我们回到了 Client App 进程空间:
@Override
public void scheduleReceiver(String processName, ComponentName component, Intent intent, PendingResultData resultData) {
ReceiverData receiverData = new ReceiverData();
receiverData.resultData = resultData;
receiverData.intent = intent;
receiverData.component = component;
receiverData.processName = processName;
sendMessage(RECEIVER, receiverData);
}
跟到消息队列中:
case RECEIVER: {
handleReceiver((ReceiverData) msg.obj);
}
private void handleReceiver(ReceiverData data) {
BroadcastReceiver.PendingResult result = data.resultData.build();
try {
// 依然是检测 Application 是否初始化,没有则初始化
if (!isBound()) {
bindApplication(data.component.getPackageName(), data.processName);
}
// 获取 Receiver 的 Context,这个context是一个ReceiverRestrictedContext实例,它有两个主要函数被禁掉:registerReceiver()和 bindService()。这两个函数在BroadcastReceiver.onReceive()不允许调用。每次Receiver处理一个广播,传递进来的context都是一个新的实例。
Context context = mInitialApplication.getBaseContext();
Context receiverContext = ContextImpl.getReceiverRestrictedContext.call(context);
String className = data.component.getClassName();
// 实例化目标 Receiver
BroadcastReceiver receiver = (BroadcastReceiver) context.getClassLoader().loadClass(className).newInstance();
mirror.android.content.BroadcastReceiver.setPendingResult.call(receiver, result);
data.intent.setExtrasClassLoader(context.getClassLoader());
// 手动调用 onCreate
receiver.onReceive(receiverContext, data.intent);
// 通知 Pending 结束
if (mirror.android.content.BroadcastReceiver.getPendingResult.call(receiver) != null) {
result.finish();
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(
"Unable to start receiver " + data.component
+ ": " + e.toString(), e);
}
// 这里需要远程通知 VAService 广播已送到
VActivityManager.get().broadcastFinish(data.resultData);
}
这里就是最关键的地方了,简单点概括就是 new 了真正的 Receiver 然后调用 onCreate 而已。Receiver 生命周期真的非常简单。
需要注意的是,broadCast 发送有个超时机制:
void broadcastFinish(PendingResultData res) {
synchronized (mBroadcastRecords) {
BroadcastRecord record = mBroadcastRecords.remove(res.mToken);
if (record == null) {
VLog.e(TAG, "Unable to find the BroadcastRecord by token: " + res.mToken);
}
}
mTimeoutHandler.removeMessages(0, res.mToken);
res.finish();
}
private final class TimeoutHandler extends Handler {
@Override
public void handleMessage(Message msg) {
IBinder token = (IBinder) msg.obj;
BroadcastRecord r = mBroadcastRecords.remove(token);
if (r != null) {
VLog.w(TAG, "Broadcast timeout, cancel to dispatch it.");
r.pendingResult.finish();
}
}
}
这里如果广播超时则会通知 PendingResult 结束,告诉发送方广播结束了。
其实上一部分已经讲了很多发送广播的处理了。
这里 Hook 了 broacastIntent 方法:
static class BroadcastIntent extends MethodProxy {
@Override
public String getMethodName() {
return "broadcastIntent";
}
@Override
public Object call(Object who, Method method, Object... args) throws Throwable {
Intent intent = (Intent) args[1];
String type = (String) args[2];
intent.setDataAndType(intent.getData(), type);
if (VirtualCore.get().getComponentDelegate() != null) {
VirtualCore.get().getComponentDelegate().onSendBroadcast(intent);
}
Intent newIntent = handleIntent(intent);
if (newIntent != null) {
args[1] = newIntent;
} else {
return 0;
}
if (args[7] instanceof String || args[7] instanceof String[]) {
// clear the permission
args[7] = null;
}
return method.invoke(who, args);
}
private Intent handleIntent(final Intent intent) {
final String action = intent.getAction();
if ("android.intent.action.CREATE_SHORTCUT".equals(action)
|| "com.android.launcher.action.INSTALL_SHORTCUT".equals(action)) {
return VASettings.ENABLE_INNER_SHORTCUT ? handleInstallShortcutIntent(intent) : null;
} else if ("com.android.launcher.action.UNINSTALL_SHORTCUT".equals(action)) {
handleUninstallShortcutIntent(intent);
} else {
return ComponentUtils.redirectBroadcastIntent(intent, VUserHandle.myUserId());
}
return intent;
}
private Intent handleInstallShortcutIntent(Intent intent) {
Intent shortcut = intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
if (shortcut != null) {
ComponentName component = shortcut.resolveActivity(VirtualCore.getPM());
if (component != null) {
String pkg = component.getPackageName();
Intent newShortcutIntent = new Intent();
newShortcutIntent.setClassName(getHostPkg(), Constants.SHORTCUT_PROXY_ACTIVITY_NAME);
newShortcutIntent.addCategory(Intent.CATEGORY_DEFAULT);
newShortcutIntent.putExtra("_VA_|_intent_", shortcut);
newShortcutIntent.putExtra("_VA_|_uri_", shortcut.toUri(0));
newShortcutIntent.putExtra("_VA_|_user_id_", VUserHandle.myUserId());
intent.removeExtra(Intent.EXTRA_SHORTCUT_INTENT);
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, newShortcutIntent);
Intent.ShortcutIconResource icon = intent.getParcelableExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
if (icon != null && !TextUtils.equals(icon.packageName, getHostPkg())) {
try {
Resources resources = VirtualCore.get().getResources(pkg);
int resId = resources.getIdentifier(icon.resourceName, "drawable", pkg);
if (resId > 0) {
//noinspection deprecation
Drawable iconDrawable = resources.getDrawable(resId);
Bitmap newIcon = BitmapUtils.drawableToBitmap(iconDrawable);
if (newIcon != null) {
intent.removeExtra(Intent.EXTRA_SHORTCUT_ICON_RESOURCE);
intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, newIcon);
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}
return intent;
}
public static Intent redirectBroadcastIntent(Intent intent, int userId) {
Intent newIntent = intent.cloneFilter();
newIntent.setComponent(null);
newIntent.setPackage(null);
ComponentName component = intent.getComponent();
String pkg = intent.getPackage();
if (component != null) {
newIntent.putExtra("_VA_|_user_id_", userId);
// 这里显式意图被重定位成 _VA_PKGNAME_CLASSNAME 的格式,与前面注册的时候对应
newIntent.setAction(String.format("_VA_%s_%s", component.getPackageName(), component.getClassName()));
newIntent.putExtra("_VA_|_component_", component);
newIntent.putExtra("_VA_|_intent_", new Intent(intent));
} else if (pkg != null) {
newIntent.putExtra("_VA_|_user_id_", userId);
newIntent.putExtra("_VA_|_creator_", pkg);
newIntent.putExtra("_VA_|_intent_", new Intent(intent));
String protectedAction = SpecialComponentList.protectAction(intent.getAction());
if (protectedAction != null) {
newIntent.setAction(protectedAction);
}
} else {
newIntent.putExtra("_VA_|_user_id_", userId);
newIntent.putExtra("_VA_|_intent_", new Intent(intent));
String protectedAction = SpecialComponentList.protectAction(intent.getAction());
if (protectedAction != null) {
newIntent.setAction(protectedAction);
}
}
return newIntent;
}
Ok, BroadcastReceiver 完毕,下一张分析最后一个组件 ContentProvider。
转载:https://blog.csdn.net/ganyao939543405/article/details/76229480