安卓高手之路之 应用篇
安卓高手之路之 应用篇 - 修补C++ - ITeye技术网站
1. 安装应用流程:
PackageManagerService的installPackage 调用 InstallArgs的copyAPK完成了安装。如果在SD卡中,那么调用SdInstallArgs的copyApk完成安装。
2. 应用启动流程:
首先,直接从ActivityManagerService入手,首先调用startActivity这个函数:
public final int startActivity(IApplicationThread caller,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded, boolean debug,
String profileFile, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
return mMainStack.startActivityMayWait(caller, -1, intent, resolvedType,
grantedUriPermissions, grantedMode, resultTo, resultWho,
requestCode, onlyIfNeeded, debug, profileFile, profileFd, autoStopProfiler,
null, null);
}下面看AcitivityStack,
final int startActivityMayWait(IApplicationThread caller, int callingUid,
Intent intent, String resolvedType, Uri[] grantedUriPermissions,
int grantedMode, IBinder resultTo,
String resultWho, int requestCode, boolean onlyIfNeeded,
boolean debug, String profileFile, ParcelFileDescriptor profileFd,
boolean autoStopProfiler, WaitResult outResult, Configuration config) {
这个函数比较长,下面只看关键部位:
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, debug,
profileFile, profileFd, autoStopProfiler);这个调到了PackageManager里面的resolveActivity方法里面。这里既暂时不说了。后面再讨论。
往下继续看:
看到一个重量级app的含义,经分析,这样的app会在状态栏,发送一个如下的图标:
所以那段代码直接忽略。往下看,看到如下一句话:
int res = startActivityLocked(caller, intent, resolvedType,
grantedUriPermissions, grantedMode, aInfo,
resultTo, resultWho, requestCode, callingPid, callingUid,
onlyIfNeeded, componentSpecified, null);
这个方法比较长,要有耐性:
ProcessRecord callerApp = null;
if (caller != null) {
callerApp = mService.getRecordForAppLocked(caller);
if (callerApp != null) {
callingPid = callerApp.pid;
callingUid = callerApp.info.uid;
} else {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
err = START_PERMISSION_DENIED;
}
}
这段话找出调用者的ProcessRecordActivityRecord sourceRecord = null;
ActivityRecord resultRecord = null;
if (resultTo != null) {
int index = indexOfTokenLocked(resultTo);
if (DEBUG_RESULTS) Slog.v(
TAG, "Will send result to " + resultTo + " (index " + index + ")");
if (index >= 0) {
sourceRecord = mHistory.get(index);
if (requestCode >= 0 && !sourceRecord.finishing) {
resultRecord = sourceRecord;
}
}
}这段话,找出一个resultRecord。
然后是这句话
final int perm = mService.checkComponentPermission(aInfo.permission, callingPid,
callingUid, aInfo.applicationInfo.uid, aInfo.exported); 这个是权限检测,后面再说。下面这句话
if (mMainStack) {
if (mService.mController != null) {
boolean abort = false;
try {
// The Intent we give to the watcher has the extra data
// stripped off, since it can contain private information.
Intent watchIntent = intent.cloneFilter();
abort = !mService.mController.activityStarting(watchIntent,
aInfo.applicationInfo.packageName);
} catch (RemoteException e) {
mService.mController = null;
}
if (abort) {
if (resultRecord != null) {
sendActivityResultLocked(-1,
resultRecord, resultWho, requestCode,
Activity.RESULT_CANCELED, null);
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
mDismissKeyguardOnNextActivity = false;
return START_SUCCESS;
}
}
}有时候可以设置一个Controller到AcitivytManagerservice中。具体AM.java文件中有引用。例如,从命令行启动Acitivity。
ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid,
intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified);
if (outActivity != null) {
outActivity[0] = r;
}if (mMainStack) {
if (mResumedActivity == null
|| mResumedActivity.info.applicationInfo.uid != callingUid) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
PendingActivityLaunch pal = new PendingActivityLaunch();
pal.r = r;
pal.sourceRecord = sourceRecord;
pal.grantedUriPermissions = grantedUriPermissions;
pal.grantedMode = grantedMode;
pal.onlyIfNeeded = onlyIfNeeded;
mService.mPendingActivityLaunches.add(pal);
mDismissKeyguardOnNextActivity = false;
return START_SWITCHES_CANCELED;
}
}
if (mService.mDidAppSwitch) {
// This is the second allowed switch since we stopped switches,
// so now just generally allow switches. Use case: user presses
// home (switches disabled, switch to home, mDidAppSwitch now true);
// user taps a home icon (coming from home so allowed, we hit here
// and now allow anyone to switch again).
mService.mAppSwitchesAllowedTime = 0;
} else {
mService.mDidAppSwitch = true;
}
mService.doPendingActivityLaunchesLocked(false);
}关键是红色标注的那一句话。
final int N = mPendingActivityLaunches.size();
if (N <= 0) {
return;
}
for (int i=0; i<N; i++) {
PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
mMainStack.startActivityUncheckedLocked(pal.r, pal.sourceRecord,
pal.grantedUriPermissions, pal.grantedMode, pal.onlyIfNeeded,
doResume && i == (N-1));
}
mPendingActivityLaunches.clear();
把3PendingLaunch的进行启动。
最终进入:
err = startActivityUncheckedLocked(r, sourceRecord,
grantedUriPermissions, grantedMode, onlyIfNeeded, true);
if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
// Someone asked to have the keyguard dismissed on the next
// activity start, but we are not actually doing an activity
// switch... just dismiss the keyguard now, because we
// probably want to see whatever is behind it.
mDismissKeyguardOnNextActivity = false;
mService.mWindowManager.dismissKeyguard();
}
return err;err = startActivityUncheckedLocked(r, sourceRecord,
grantedUriPermissions, grantedMode, onlyIfNeeded, true);
if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
// Someone asked to have the keyguard dismissed on the next
// activity start, but we are not actually doing an activity
// switch... just dismiss the keyguard now, because we
// probably want to see whatever is behind it.
mDismissKeyguardOnNextActivity = false;
mService.mWindowManager.dismissKeyguard();
}
return err;
startActivityUncheckedLocked 这个方法也是很长。
其中FLAG_ACTIVITY_PREVIOUS_IS_TOP 说的是current不是top,之前的是top。也就是说,r不算是top。
ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
!= 0 ? r : null;
if (sourceRecord == null) {
// This activity is not being started from another... in this
// case we -always- start a new task.
if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
+ intent);
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}
不是从Acitivity启动的话,就要加一个newTask标志。这也可以说是同一个task的一个条件吧。
if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
// The original activity who is starting us is running as a single
// instance... this new activity it is starting must go on its
// own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;这个说的是如果sourceActivity是一个singleton,那么也启动一个newtask。
else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
// The activity being started is a single instance... it always
// gets launched into its own task.
launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
}或者说,自己是一个singletatask或者singleinstance。那么也是newtask。
LAUNCH_SINGLE_INSTANCE 一定是.LAUNCH_SINGLE_TASK,.LAUNCH_SINGLE_TASK 不一定是
LAUNCH_SINGLE_INSTANCE
既然是singletask,那么无法退出结果给 resultTo:
if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
// For whatever reason this activity is being launched into a new
// task... yet the caller has requested a result back. Well, that
// is pretty messed up, so instead immediately send back a cancel
// and let the new task continue launched as normal without a
// dependency on its originator.
Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
sendActivityResultLocked(-1,
r.resultTo, r.resultWho, r.requestCode,
Activity.RESULT_CANCELED, null);
r.resultTo = null;
}下面判断很有意思,如果是一个newTask
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE)找到top的task
ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(intent, r.info)
: findActivityLocked(intent, r.info);如果是LAUNCH_SINGLE_INSTANCE,那么就全找。否则,过滤掉LAUNCH_SINGLE_INSTANCE的activity。并且,找到一个task与此相同的。也就是说是new——task,并且不是singleton,这种情况下,找所有task的顶层activity。看是否满足条件。
ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
if (curTop != null && curTop.task != taskTop.task) {
r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
boolean callerAtFront = sourceRecord == null
|| curTop.task == sourceRecord.task;
if (callerAtFront) {
// We really do want to push this one into the
// user‘s face, right now.
moveHomeToFrontFromLaunchLocked(launchFlags);
moveTaskToFrontLocked(taskTop.task, r);
}
}新任务与当前的topTask不同的时候,先把home加到前面,然后把当前的加到前面。考虑的时候,排除notTop。
if (onlyIfNeeded) {
// We don‘t need to start a new activity, and
// the client said not to do anything if that
// is the case, so this is it! And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
resumeTopActivityLocked(null);
}
return START_RETURN_INTENT_TO_CALLER;
}不需要启动activity。只是resumetop。
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
&& taskTop.realActivity.equals(r.realActivity)) {
logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
if (taskTop.frontOfTask) {
taskTop.task.setIntent(r.intent, r.info);
}
taskTop.deliverNewIntentLocked(callingUid, r.intent);
}调用onNewInent。如果已经在top,那么就不再启动新的activity。
if (!addingToTask && reuseTask == null) {
// We didn‘t do anything... but it was needed (a.k.a., client
// don‘t use that intent!) And for paranoia, make
// sure we have correctly resumed the top activity.
if (doResume) {
resumeTopActivityLocked(null);
}
return START_TASK_TO_FRONT;
}不添加新的task,也不用旧的task,就什么都不干。
以上全是处理的newtask,singletask,singleinstance的东西。
if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
// For paranoia, make sure we have correctly
// resumed the top activity.
if (doResume) {
resumeTopActivityLocked(null);
}
if (onlyIfNeeded) {
// We don‘t need to start a new activity, and
// the client said not to do anything if that
// is the case, so this is it!
return START_RETURN_INTENT_TO_CALLER;
}
top.deliverNewIntentLocked(callingUid, r.intent);
return START_DELIVERED_TO_TOP;
如果是singletop,singletask,并且有一个在top,就直接onNewIntent。
最终进入ActivityStack的
startActivityLocked
最终进入:
private final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition) {
放入activity堆栈后,调用resumeTopActivityLocked
final boolean resumeTopActivityLocked(ActivityRecord prev)然后调用
startSpecificActivityLocked(next, true, true);
这个就是如下代码
private final void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity‘s application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid);
if (r.launchTime == 0) {
r.launchTime = SystemClock.uptimeMillis();
if (mInitialStartTime == 0) {
mInitialStartTime = r.launchTime;
}
} else if (mInitialStartTime == 0) {
mInitialStartTime = SystemClock.uptimeMillis();
}
if (app != null && app.thread != null) {
try {
app.addPackage(r.info.packageName);
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}// If a dead object exception was thrown -- fall through to
// restart the application.
}mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false);
}要么调用 realStartActivityLocked(r, app, andResume, checkConfig);
要么调用 startProcessLocked
realStartActivityLocked 调用 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration),
r.compat, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
而 startProcessLocked调用
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
下面是一些dbug开关。
if ("1".equals(SystemProperties.get("debug.checkjni"))) {
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
if ("1".equals(SystemProperties.get("debug.jni.logging"))) {
debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;
}
if ("1".equals(SystemProperties.get("debug.assert"))) {
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
调用如下来启动进程:
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags,
app.info.targetSdkVersion, null);然后掉到ActivityThread的:
private void attach(boolean system) 方法中
对于非系统进程就这几句话:
ViewRootImpl.addFirstDrawHandler(new Runnable() {
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}调用到
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}最终回调到ActivityThread的
private void handleBindApplication(AppBindData data)
等待调试的地方在这个地方:
if (data.debugMode != IApplicationThread.DEBUG_OFF) {
// XXX should have option to change the port.
Debug.changeDebugPort(8100);
if (data.debugMode == IApplicationThread.DEBUG_WAIT) {
Slog.w(TAG, "Application " + data.info.getPackageName()
+ " is waiting for the debugger on port 8100...");IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.showWaitingForDebugger(mAppThread, true);
} catch (RemoteException ex) {
}Debug.waitForDebugger();
try {
mgr.showWaitingForDebugger(mAppThread, false);
} catch (RemoteException ex) {
}} else {
Slog.w(TAG, "Application " + data.info.getPackageName()
+ " can be debugged on port 8100...");
}
}初始化context
ContextImpl appContext = new ContextImpl();
appContext.init(data.info, null, this);
InstrumentationInfo ii = null;获得apk的信息。
ApplicationInfo instrApp = new ApplicationInfo();
instrApp.packageName = ii.packageName;
instrApp.sourceDir = ii.sourceDir;
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true);
ContextImpl instrContext = new ContextImpl();
instrContext.init(pi, null, this);初始化instrContext
如果没有instrument则
mInstrumentation = new Instrumentation();
// If the app is being launched for full backup or restore, bring it up in
// a restricted environment with the base application class.
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;// don‘t bring up providers in restricted mode; they may depend on the
// app‘s custom Application class
if (!data.restrictedBackupMode){
List<ProviderInfo> providers = data.providers;
if (providers != null) {
installContentProviders(app, providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}创造一个应用,并且调用app的 onCreate方法。
下面进入app的onCreate方法
然后
// See if the top visible activity is waiting to run in this process...
ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
if (hr != null && normalMode) {
if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
badApp = true;
}
} else {
mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
}
}找到toplevel Activity进行启动。这个toplevelActivity就是刚才要启动的activity。这样activity就与新创建的进程进行了关联。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。