本文以點選桌面快捷方式啟動app來看源碼
Launcher process -> Binder -> System process -> Binder -> Target process
LauncherActivity -> ActivityManagerProxy ->AMS -> ApplicationThreadProxy -> Instrumentation.newActivity
1、先看LaunchActivity源碼
public abstract class LauncherActivity extends ListActivity {
//如果通過component、schema啟動一個app,那麼這個mIntent中會有資料
Intent mIntent;
...
private class ActivityAdapter extends BaseAdapter implements Filterable {
...
public ActivityAdapter(IconResizer resizer) {
...
mActivitiesList = makeListItems();
}
public Intent intentForPosition(int position) {
if (mActivitiesList == null) {
return null;
}
//mIntent一個空的intent,貌似m
Intent intent = new Intent(mIntent);
ListItem item = mActivitiesList.get(position);
intent.setClassName(item.packageName, item.className);
if (item.extras != null) {
intent.putExtras(item.extras);
}
return intent;
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
//從adapter中取出點選item的資料封裝成intent
Intent intent = intentForPosition(position);
startActivity(intent);//這裡啟動activity
}
/**
* 傳回點選的item的app資訊
*/
protected Intent intentForPosition(int position) {
ActivityAdapter adapter = (ActivityAdapter) mAdapter;
return adapter.intentForPosition(position);
}
//擷取資料源,Launcher顯示的資料
public List<ListItem> makeListItems() {
//關于這個mIntent
List<ResolveInfo> list = onQueryPackageManager(mIntent);
onSortResultList(list);
ArrayList<ListItem> result = new ArrayList<ListItem>(list.size());
int listSize = list.size();
for (int i = 0; i < listSize; i++) {
ResolveInfo resolveInfo = list.get(i);
result.add(new ListItem(mPackageManager, resolveInfo, null));
}
return result;
}
}
關于LauncherActivity中mIntent的作用簡述:
調用鍊
PackageManager->ApplicationPackageManager->PackageManagerService
>> LauncherActivity.onQueryPackageManager(mIntent) -> PackageManager.queryIntentActivities(queryIntent, 0)
-> ApplicationPackageManager.queryIntentActivities(intent, flag)
-> ApplicationPackageManager.queryIntentActivitiesAsUser(intent, flag, userId)
-> PackageManagerService.queryIntentActivities(Intent intent, String resolvedType, int flags, int userId)
-> PackageManagerService.queryIntentActivitiesInternal(Intent intent, String resolvedType, int flags, int userId)
/**真正的調用在這裡
* 這裡根據intent中傳入資料在不同範圍比對查詢
* 比如有些通過schema、component啟動其他程序的app時,intent是有資料的
*/
public class PackageManagerService extends IPackageManager.Stub {
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent, String resolvedType, int flags, int userId) {
if (!sUserManager.exists(userId)) return Collections.emptyList();
flags = updateFlagsForResolve(flags, userId, intent);
enforceCrossUserPermission(Binder.getCallingUid(), userId, false /* requireFullPermission */, false /* checkShell */, "query intent activities");
ComponentName comp = intent.getComponent();
if (comp == null) {//intent傳入的component
if (intent.getSelector() != null) {
intent = intent.getSelector();
comp = intent.getComponent();
}
}
if (comp != null) {//根據intent傳入的component傳回需要查詢的資料
final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
final ActivityInfo ai = getActivityInfo(comp, flags, userId);
if (ai != null) {
final ResolveInfo ri = new ResolveInfo();
ri.activityInfo = ai;
list.add(ri);
}
return list;
}
//intent中沒有傳入component
synchronized (mPackages) {
/* intent未傳入packageName,需要在整個系統範圍内進行比對查詢
* intent有傳入packageName則在指定pkg下比對查詢
*/
...
}
...
}
}
參考資料