学习Activity启动流程
来源:互联网 发布:淘宝上买的弹弓枪 编辑:程序博客网 时间:2024/05/21 11:19
1.startActivity(intent)
@Override
public void startActivity(Intent intent) {
this.startActivity(intent, null);
}
2.调用 startActivity(intent,null)
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
// Note we want to go through this call for compatibility with
// applications that may have overridden the method.
startActivityForResult(intent, -1);
}
}
3.调用 startActivityForResult
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
if (mParent == null) {
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
// activity hidden during this time, to avoid flickering.
// This can only be done when a result is requested because
// that guarantees we will get information back when the
// activity is finished, no matter what happens to it.
mStartedActivity = true;
}
cancelInputsAndStartExitTransition(options);
// TODO Consider clearing/flushing other event sources and events for child windows.
} else {
if (options != null) {
mParent.startActivityFromChild(this, intent, requestCode, options);
} else {
// Note we want to go through this method for compatibility with
// existing applications that may have overridden it.
mParent.startActivityFromChild(this, intent, requestCode);
}
}
}
4.mInstrumentation
private Instrumentation mInstrumentation;
5.找到execStartActivity方法
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
if (mActivityMonitors != null) {
synchronized (mSync) {
final int N = mActivityMonitors.size();
for (int i=0; i<N; i++) {
final ActivityMonitor am = mActivityMonitors.get(i);
if (am.match(who, null, intent)) {
am.mHits++;
if (am.isBlocking()) {
return requestCode >= 0 ? am.getResult() : null;
}
break;
}
}
}
}
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess(who);
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
6.ActivityManagerNative 这边有服务端的东西
ActivityManagerNative.getDefault()
查看startActivity 写入东西
class ActivityManagerProxy implements IActivityManager
{
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeString(callingPackage);
intent.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(resultTo);
data.writeString(resultWho);
data.writeInt(requestCode);
data.writeInt(startFlags);
if (profilerInfo != null) {
data.writeInt(1);
profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} else {
data.writeInt(0);
}
if (options != null) {
data.writeInt(1);
options.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
reply.readException();
int result = reply.readInt();
reply.recycle();
data.recycle();
return result;
}
查看 mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply,0); 根据标识查找
case START_ACTIVITY_TRANSACTION:
{
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
String callingPackage = data.readString();
Intent intent = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
IBinder resultTo = data.readStrongBinder();
String resultWho = data.readString();
int requestCode = data.readInt();
int startFlags = data.readInt();
ProfilerInfo profilerInfo = data.readInt() != 0
? ProfilerInfo.CREATOR.createFromParcel(data) : null;
Bundle options = data.readInt() != 0
? Bundle.CREATOR.createFromParcel(data) : null;
int result = startActivity(app, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
reply.writeNoException();
reply.writeInt(result);
return true;
}
点击查找 startActivity
public interface IActivityManager extends IInterface {
public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
String resolvedType, IBinder resultTo, String resultWho, int requestCode, int flags,
ProfilerInfo profilerInfo, Bundle options) throws RemoteException;
找到具体实现 在ActivityManagerService中
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, bOptions,
UserHandle.getCallingUserId());
}
查看startActivityAsUser
@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, null);
}
查看 mActivityStarter.startActivityMayWait
final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, IActivityManager.WaitResult outResult, Configuration config,
Bundle bOptions, boolean ignoreTargetSecurity, int userId,
IActivityContainer iContainer, TaskRecord inTask) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
mSupervisor.mActivityMetricsLogger.notifyActivityLaunching();
boolean componentSpecified = intent.getComponent() != null;
// Save a copy in case ephemeral needs it
final Intent ephemeralIntent = new Intent(intent);
// Don't modify the client's object!
intent = new Intent(intent);
ResolveInfo rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId);
if (rInfo == null) {
UserInfo userInfo = mSupervisor.getUserInfo(userId);
if (userInfo != null && userInfo.isManagedProfile()) {
// Special case for managed profiles, if attempting to launch non-cryto aware
// app in a locked managed profile from an unlocked parent allow it to resolve
// as user will be sent via confirm credentials to unlock the profile.
UserManager userManager = UserManager.get(mService.mContext);
boolean profileLockedAndParentUnlockingOrUnlocked = false;
long token = Binder.clearCallingIdentity();
try {
UserInfo parent = userManager.getProfileParent(userId);
profileLockedAndParentUnlockingOrUnlocked = (parent != null)
&& userManager.isUserUnlockingOrUnlocked(parent.id)
&& !userManager.isUserUnlockingOrUnlocked(userId);
} finally {
Binder.restoreCallingIdentity(token);
}
if (profileLockedAndParentUnlockingOrUnlocked) {
rInfo = mSupervisor.resolveIntent(intent, resolvedType, userId,
PackageManager.MATCH_DIRECT_BOOT_AWARE
| PackageManager.MATCH_DIRECT_BOOT_UNAWARE);
}
}
}
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
ActivityOptions options = ActivityOptions.fromBundle(bOptions);
ActivityStackSupervisor.ActivityContainer container =
(ActivityStackSupervisor.ActivityContainer)iContainer;
synchronized (mService) {
if (container != null && container.mParentActivity != null &&
container.mParentActivity.state != RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
final int realCallingPid = Binder.getCallingPid();
final int realCallingUid = Binder.getCallingUid();
int callingPid;
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = realCallingPid;
callingUid = realCallingUid;
} else {
callingPid = callingUid = -1;
}
final ActivityStack stack;
if (container == null || container.mStack.isOnHomeDisplay()) {
stack = mSupervisor.mFocusedStack;
} else {
stack = container.mStack;
}
stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Starting activity when config will change = " + stack.mConfigWillChange);
final long origId = Binder.clearCallingIdentity();
if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
& ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
// This may be a heavy-weight process! Check to see if we already
// have another, different heavy-weight process running.
if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
final ProcessRecord heavy = mService.mHeavyWeightProcess;
if (heavy != null && (heavy.info.uid != aInfo.applicationInfo.uid
|| !heavy.processName.equals(aInfo.processName))) {
int appCallingUid = callingUid;
if (caller != null) {
ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
appCallingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
ActivityOptions.abort(options);
return ActivityManager.START_PERMISSION_DENIED;
}
}
IIntentSender target = mService.getIntentSenderLocked(
ActivityManager.INTENT_SENDER_ACTIVITY, "android",
appCallingUid, userId, null, null, 0, new Intent[] { intent },
new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
| PendingIntent.FLAG_ONE_SHOT, null);
Intent newIntent = new Intent();
if (requestCode >= 0) {
// Caller is requesting a result.
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
new IntentSender(target));
if (heavy.activities.size() > 0) {
ActivityRecord hist = heavy.activities.get(0);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
hist.packageName);
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
hist.task.taskId);
}
newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
aInfo.packageName);
newIntent.setFlags(intent.getFlags());
newIntent.setClassName("android",
HeavyWeightSwitcherActivity.class.getName());
intent = newIntent;
resolvedType = null;
caller = null;
callingUid = Binder.getCallingUid();
callingPid = Binder.getCallingPid();
componentSpecified = true;
rInfo = mSupervisor.resolveIntent(intent, null /*resolvedType*/, userId);
aInfo = rInfo != null ? rInfo.activityInfo : null;
if (aInfo != null) {
aInfo = mService.getActivityInfoForUser(aInfo, userId);
}
}
}
}
final ActivityRecord[] outRecord = new ActivityRecord[1];
int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor,
resultTo, resultWho, requestCode, callingPid,
callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, outRecord, container,
inTask);
Binder.restoreCallingIdentity(origId);
if (stack.mConfigWillChange) {
// If the caller also wants to switch to a new configuration,
// do so now. This allows a clean switch, as we are waiting
// for the current activity to pause (so we will not destroy
// it), and have not yet started the next activity.
mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
"updateConfiguration()");
stack.mConfigWillChange = false;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Updating to new configuration after starting activity.");
mService.updateConfigurationLocked(config, null, false);
}
if (outResult != null) {
outResult.result = res;
if (res == ActivityManager.START_SUCCESS) {
mSupervisor.mWaitingActivityLaunched.add(outResult);
do {
try {
mService.wait();
} catch (InterruptedException e) {
}
} while (outResult.result != START_TASK_TO_FRONT
&& !outResult.timeout && outResult.who == null);
if (outResult.result == START_TASK_TO_FRONT) {
res = START_TASK_TO_FRONT;
}
}
if (res == START_TASK_TO_FRONT) {
ActivityRecord r = stack.topRunningActivityLocked();
if (r.nowVisible && r.state == RESUMED) {
outResult.timeout = false;
outResult.who = new ComponentName(r.info.packageName, r.info.name);
outResult.totalTime = 0;
outResult.thisTime = 0;
} else {
outResult.thisTime = SystemClock.uptimeMillis();
mSupervisor.mWaitingActivityVisible.add(outResult);
do {
try {
mService.wait();
} catch (InterruptedException e) {
}
} while (!outResult.timeout && outResult.who == null);
}
}
}
final ActivityRecord launchedActivity = mReusedActivity != null
? mReusedActivity : outRecord[0];
mSupervisor.mActivityMetricsLogger.notifyActivityLaunched(res, launchedActivity);
return res;
}
}
查看 resolveIntent
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId) {
return resolveIntent(intent, resolvedType, userId, 0);
}
ResolveInfo resolveIntent(Intent intent, String resolvedType, int userId, int flags) {
try {
return AppGlobals.getPackageManager().resolveIntent(intent, resolvedType,
PackageManager.MATCH_DEFAULT_ONLY | flags
| ActivityManagerService.STOCK_PM_FLAGS, userId);
} catch (RemoteException e) {
}
return null;
}
查看 AppGlobals 找到 getPackageManager()方法
public static IPackageManager getPackageManager() {
return ActivityThread.getPackageManager();
}
查看 ActivityThread 中的 getPackageManager()
public static IPackageManager getPackageManager() {
if (sPackageManager != null) {
//Slog.v("PackageManager", "returning cur default = " + sPackageManager);
return sPackageManager;
}
IBinder b = ServiceManager.getService("package");
//Slog.v("PackageManager", "default service binder = " + b);
sPackageManager = IPackageManager.Stub.asInterface(b);
//Slog.v("PackageManager", "default service = " + sPackageManager);
return sPackageManager;
}
查看sPackageManager 是什么
static volatile IPackageManager sPackageManager;
在PackageManagerService中查看resolveIntent
@Override
public ResolveInfo resolveIntent(Intent intent, String resolvedType,
int flags, int userId) {
try {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForResolve(flags, userId, intent);
enforceCrossUserPermission(Binder.getCallingUid(), userId,
false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
flags, userId);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
final ResolveInfo bestChoice =
chooseBestActivity(intent, resolvedType, flags, query, userId);
if (isEphemeralAllowed(intent, query, userId)) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveEphemeral");
final EphemeralResolveInfo ai =
getEphemeralResolveInfo(intent, resolvedType, userId);
if (ai != null) {
if (DEBUG_EPHEMERAL) {
Slog.v(TAG, "Returning an EphemeralResolveInfo");
}
bestChoice.ephemeralInstaller = mEphemeralInstallerInfo;
bestChoice.ephemeralResolveInfo = ai;
}
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
return bestChoice;
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
查看chooseBestActivity
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
int flags, List<ResolveInfo> query, int userId) {
if (query != null) {
final int N = query.size();
if (N == 1) {
return query.get(0);
} else if (N > 1) {
final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
// If there is more than one activity with the same priority,
// then let the user decide between them.
ResolveInfo r0 = query.get(0);
ResolveInfo r1 = query.get(1);
if (DEBUG_INTENT_MATCHING || debug) {
Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs "
+ r1.activityInfo.name + "=" + r1.priority);
}
// If the first activity has a higher priority, or a different
// default, then it is always desirable to pick it.
if (r0.priority != r1.priority
|| r0.preferredOrder != r1.preferredOrder
|| r0.isDefault != r1.isDefault) {
return query.get(0);
}
// If we have saved a preference for a preferred activity for
// this Intent, use that.
ResolveInfo ri = findPreferredActivity(intent, resolvedType,
flags, query, r0.priority, true, false, debug, userId);
if (ri != null) {
return ri;
}
ri = new ResolveInfo(mResolveInfo);
ri.activityInfo = new ActivityInfo(ri.activityInfo);
ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
// If all of the options come from the same package, show the application's
// label and icon instead of the generic resolver's.
// Some calls like Intent.resolveActivityInfo query the ResolveInfo from here
// and then throw away the ResolveInfo itself, meaning that the caller loses
// the resolvePackageName. Therefore the activityInfo.labelRes above provides
// a fallback for this case; we only set the target package's resources on
// the ResolveInfo, not the ActivityInfo.
final String intentPackage = intent.getPackage();
if (!TextUtils.isEmpty(intentPackage) && allHavePackage(query, intentPackage)) {
final ApplicationInfo appi = query.get(0).activityInfo.applicationInfo;
ri.resolvePackageName = intentPackage;
if (userNeedsBadging(userId)) {
ri.noResourceId = true;
} else {
ri.icon = appi.icon;
}
ri.iconResourceId = appi.icon;
ri.labelRes = appi.labelRes;
}
ri.activityInfo.applicationInfo = new ApplicationInfo(
ri.activityInfo.applicationInfo);
if (userId != 0) {
ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId,
UserHandle.getAppId(ri.activityInfo.applicationInfo.uid));
}
// Make sure that the resolver is displayable in car mode
if (ri.activityInfo.metaData == null) ri.activityInfo.metaData = new Bundle();
ri.activityInfo.metaData.putBoolean(Intent.METADATA_DOCK_HOME, true);
return ri;
}
}
return null;
}
查找findPreferredActivity
ResolveInfo findPreferredActivity(Intent intent, String resolvedType, int flags,
List<ResolveInfo> query, int priority, boolean always,
boolean removeMatches, boolean debug, int userId) {
if (!sUserManager.exists(userId)) return null;
flags = updateFlagsForResolve(flags, userId, intent);
// writer
synchronized (mPackages) {
if (intent.getSelector() != null) {
intent = intent.getSelector();
}
if (DEBUG_PREFERRED) intent.addFlags(Intent.FLAG_DEBUG_LOG_RESOLUTION);
// Try to find a matching persistent preferred activity.
ResolveInfo pri = findPersistentPreferredActivityLP(intent, resolvedType, flags, query,
debug, userId);
// If a persistent preferred activity matched, use it.
if (pri != null) {
return pri;
}
PreferredIntentResolver pir = mSettings.mPreferredActivities.get(userId);
// Get the list of preferred activities that handle the intent
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Looking for preferred activities...");
List<PreferredActivity> prefs = pir != null
? pir.queryIntent(intent, resolvedType,
(flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId)
: null;
if (prefs != null && prefs.size() > 0) {
boolean changed = false;
try {
// First figure out how good the original match set is.
// We will only allow preferred activities that came
// from the same match quality.
int match = 0;
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Figuring out best match...");
final int N = query.size();
for (int j=0; j<N; j++) {
final ResolveInfo ri = query.get(j);
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Match for " + ri.activityInfo
+ ": 0x" + Integer.toHexString(match));
if (ri.match > match) {
match = ri.match;
}
}
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Best match: 0x"
+ Integer.toHexString(match));
match &= IntentFilter.MATCH_CATEGORY_MASK;
final int M = prefs.size();
for (int i=0; i<M; i++) {
final PreferredActivity pa = prefs.get(i);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Checking PreferredActivity ds="
+ (pa.countDataSchemes() > 0 ? pa.getDataScheme(0) : "<none>")
+ "\n component=" + pa.mPref.mComponent);
pa.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
}
if (pa.mPref.mMatch != match) {
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping bad match "
+ Integer.toHexString(pa.mPref.mMatch));
continue;
}
// If it's not an "always" type preferred activity and that's what we're
// looking for, skip it.
if (always && !pa.mPref.mAlways) {
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Skipping mAlways=false entry");
continue;
}
final ActivityInfo ai = getActivityInfo(
pa.mPref.mComponent, flags | MATCH_DISABLED_COMPONENTS
| MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
userId);
if (DEBUG_PREFERRED || debug) {
Slog.v(TAG, "Found preferred activity:");
if (ai != null) {
ai.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), " ");
} else {
Slog.v(TAG, " null");
}
}
if (ai == null) {
// This previously registered preferred activity
// component is no longer known. Most likely an update
// to the app was installed and in the new version this
// component no longer exists. Clean it up by removing
// it from the preferred activities list, and skip it.
Slog.w(TAG, "Removing dangling preferred activity: "
+ pa.mPref.mComponent);
pir.removeFilter(pa);
changed = true;
continue;
}
for (int j=0; j<N; j++) {
final ResolveInfo ri = query.get(j);
if (!ri.activityInfo.applicationInfo.packageName
.equals(ai.applicationInfo.packageName)) {
continue;
}
if (!ri.activityInfo.name.equals(ai.name)) {
continue;
}
if (removeMatches) {
pir.removeFilter(pa);
changed = true;
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Removing match " + pa.mPref.mComponent);
}
break;
}
// Okay we found a previously set preferred or last chosen app.
// If the result set is different from when this
// was created, we need to clear it and re-ask the
// user their preference, if we're looking for an "always" type entry.
if (always && !pa.mPref.sameSet(query)) {
Slog.i(TAG, "Result set changed, dropping preferred activity for "
+ intent + " type " + resolvedType);
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Removing preferred activity since set changed "
+ pa.mPref.mComponent);
}
pir.removeFilter(pa);
// Re-add the filter as a "last chosen" entry (!always)
PreferredActivity lastChosen = new PreferredActivity(
pa, pa.mPref.mMatch, null, pa.mPref.mComponent, false);
pir.addFilter(lastChosen);
changed = true;
return null;
}
// Yay! Either the set matched or we're looking for the last chosen
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "Returning preferred activity: "
+ ri.activityInfo.packageName + "/" + ri.activityInfo.name);
return ri;
}
}
} finally {
if (changed) {
if (DEBUG_PREFERRED) {
Slog.v(TAG, "Preferred activity bookkeeping changed; writing restrictions");
}
scheduleWritePackageRestrictionsLocked(userId);
}
}
}
}
if (DEBUG_PREFERRED || debug) Slog.v(TAG, "No preferred activity to return");
return null;
}
总结:
IActivityManager具体实现 ActivityManagerService
ApplicationThread在ActivityThread中
ActivityStarter这个类收集所有的逻辑,以确定如何将意图和标志转换为一个活动和相关的任务和堆栈。
ActivityStackSupervisor activity任务栈管理
IPackageManager 的实现是PackageManagerService
阅读全文
0 0
- 学习Activity启动流程
- Activity的启动流程
- activity 启动流程分析
- Activity启动流程
- activity启动流程
- Activity的启动流程
- Activity的启动流程
- activity 启动流程分析
- Activity启动流程
- Activity 视图启动流程
- Activity的启动流程
- Activity启动流程
- activity的启动流程
- Activity启动流程
- Activity启动流程阅读
- Activity的启动流程
- Activity的启动流程
- Activity的启动流程
- html5/Css3 网页设计 带音乐与食品模块
- NB-IoT蜂窝窄带物联网概念
- ConfigurableWebApplicationContext wac的refresh方法
- StringBuffer类及相关内容
- 美图秀秀 v5.1.0.2 免费版
- 学习Activity启动流程
- 22:紧急措施
- NGUI字体或图片高亮(灰化)
- 【正一专栏】从中超走向世界领先的保利尼奥
- js基础-基本包装类型(Boolean、Number、String )★☆
- ARM说时序
- 如何判断StringBuffer中是否包含某一个子串
- zookeeper的伪集群的搭建
- 刚刚,吴恩达讲了干货满满的一节全新AI课,全程手写板书