当前位置: 移动技术网 > IT编程>移动开发>Android > Android开发之程序在系统中如何完成启动?

Android开发之程序在系统中如何完成启动?

2018年09月29日  | 移动技术网IT编程  | 我要评论

六个月宝宝不爱吃奶,木偶然,流行 歌曲

一段程序的调用都有它的程序入口,众所周知java程序的入口在main方法。作为android来说应用程序的启动是通过 activitythread 类 来执行的。中对于该类的介绍如下:

该类是管理应用程序进程中主线程的执行,调度和执行活动,广播以及活动管理者请求的其他操作。

当我打开app时,首先调用的是这个类中的main方法,也就是说这里控制着程序的启动。

activitythread#main

 public static void main(string[] args) {
  trace.tracebegin(trace.trace_tag_activity_manager, "activitythreadmain");
  samplingprofilerintegration.start();

  // closeguard defaults to true and can be quite spammy.  we
  // disable it here, but selectively enable it later (via
  // strictmode) on debug builds, but using dropbox, not logs.
  closeguard.setenabled(false);

  //初始化当前的可访问环境,主要是系统内部的可存储环境
  environment.initforcurrentuser();

  // set the reporter for event logging in libcore
  eventlogger.setreporter(new eventloggingreporter());

  // make sure trustedcertificatestore looks in the right place for ca certificates
  final file configdir = environment.getuserconfigdirectory(userhandle.myuserid());
  trustedcertificatestore.setdefaultuserdirectory(configdir);

  process.setargv0("
");

  //step 1:
  looper.preparemainlooper();

  //step 2:
  activitythread thread = new activitythread();
  thread.attach(false);

  //初始化一个线程安全的handler对象
  if (smainthreadhandler == null) {
smainthreadhandler = thread.gethandler();
  }

  if (false) {
looper.mylooper().setmessagelogging(new
  logprinter(log.debug, "activitythread"));
  }

  // end of event activitythreadmain.
  trace.traceend(trace.trace_tag_activity_manager);

  //执行消息队列,不断轮询消息。
  looper.loop();

  throw new runtimeexception("main thread loop unexpectedly exited");
 }

main方法中重要的操作:

step 1:
looper.preparemainlooper() :初始化当前的线程作为一个looper,并且标记为应用中的main looper。后面还跟着对应的loop(),在消息队列中轮询接收的消息。

step 2:
实例化当前activitythread对象,并且调用attach。继续分析该方法中的调用。

activitythread#attach

private void attach(boolean system) {
 scurrentactivitythread = this;
 msystemthread = system;
 if (!system) {
  viewrootimpl.addfirstdrawhandler(new runnable() {
@override
public void run() {
 ensurejitenabled();
}
  });
  android.ddm.ddmhandleappname.setappname("
",
userhandle.myuserid());
  runtimeinit.setapplicationobject(mappthread.asbinder());

  //step 1: 将activitymanagerservice 和 applicationthread 关联起来
  final iactivitymanager mgr = activitymanager.getservice();
  try {
mgr.attachapplication(mappthread);
  } catch (remoteexception ex) {
throw ex.rethrowfromsystemserver();
  }
  // watch for getting close to heap limit.
  binderinternal.addgcwatcher(new runnable() {
@override public void run() {
 if (!msomeactivitieschanged) {
  return;
 }
 runtime runtime = runtime.getruntime();
 long dalvikmax = runtime.maxmemory();
 long dalvikused = runtime.totalmemory() - runtime.freememory();
 if (dalvikused > ((3*dalvikmax)/4)) {
  if (debug_memory_trim) slog.d(tag, "dalvik max=" + (dalvikmax/1024)
 + " total=" + (runtime.totalmemory()/1024)
 + " used=" + (dalvikused/1024));
  msomeactivitieschanged = false;
  try {
mgr.releasesomeactivities(mappthread);
  } catch (remoteexception e) {
throw e.rethrowfromsystemserver();
  }
 }
}
  });
 } else {
  // don't set application object here -- if the system crashes,
  // we can't display an alert, we just want to die die die.
  android.ddm.ddmhandleappname.setappname("system_process",
 userhandle.myuserid());
  try {
minstrumentation = new instrumentation();
contextimpl context = contextimpl.createappcontext(
  this, getsystemcontext().mpackageinfo);
minitialapplication = context.mpackageinfo.makeapplication(true, null);
minitialapplication.oncreate();
  } catch (exception e) {
throw new runtimeexception(
  "unable to instantiate application():" + e.tostring(), e);
  }
 }

 // add dropbox logging to libcore
 dropbox.setreporter(new dropboxreporter());

 viewrootimpl.configchangedcallback configchangedcallback
= (configuration globalconfig) -> {
  synchronized (mresourcesmanager) {
// we need to apply this change to the resources immediately, because upon returning
// the view hierarchy will be informed about it.
if (mresourcesmanager.applyconfigurationtoresourceslocked(globalconfig,
  null /* compat */)) {
 updatelocalelistfromappcontext(minitialapplication.getapplicationcontext(),
mresourcesmanager.getconfiguration().getlocales());

 // this actually changed the resources! tell everyone about it.
 if (mpendingconfiguration == null
|| mpendingconfiguration.isotherseqnewer(globalconfig)) {
  mpendingconfiguration = globalconfig;
  sendmessage(h.configuration_changed, globalconfig);
 }
}
  }
 };
 // 添加配置信息接口回调
 viewrootimpl.addconfigcallback(configchangedcallback);
}

上面方法中传入的参数为false,所以执行的是if中的逻辑。这里面主要的操作就是通过activitymanager.getservice() 返回了activitymanagerservice对象,然后调用attachapplication方法将applicationthread 对象关联。下面我们继续进入attachapplication 方法来分析。

activitymanagerservice#attachapplication

@override
public final void attachapplication(iapplicationthread thread) {
 synchronized (this) {
  int callingpid = binder.getcallingpid();
  final long origid = binder.clearcallingidentity();
  attachapplicationlocked(thread, callingpid);
  binder.restorecallingidentity(origid);
 }
}

activitymanagerservice#attachapplicationlocked

private final boolean attachapplicationlocked(iapplicationthread thread,
  int pid) {

 // find the application record that is being attached...  either via
 // the pid if we are running in multiple processes, or just pull the
 // next app record if we are emulating process with anonymous threads.

 // step 1: 记录正在运行的进程的详细信息
 processrecord app;
 long starttime = systemclock.uptimemillis();
 if (pid != my_pid && pid >= 0) {
  synchronized (mpidsselflocked) {
app = mpidsselflocked.get(pid);
  }
 } else {
  app = null;
 }

 //未找到对应pid的进程信息时,杀死该进程或者退出该applicationthread
 if (app == null) {
  slog.w(tag, "no pending application record for pid " + pid
 + " (iapplicationthread " + thread + "); dropping process");
  eventlog.writeevent(eventlogtags.am_drop_process, pid);
  if (pid > 0 && pid != my_pid) {
killprocessquiet(pid);
//todo: killprocessgroup(app.info.uid, pid);
  } else {
try {
 thread.scheduleexit();
} catch (exception e) {
 // ignore exceptions.
}
  }
  return false;
 }

 // if this application record is still attached to a previous
 // process, clean it up now.
 if (app.thread != null) {
  handleappdiedlocked(app, true, true);
 }

 // tell the process all about itself.

 if (debug_all) slog.v(
tag, "binding process pid " + pid + " to record " + app);

 // 初始化 processrecord 类中基本信息,来保存当前的一些状态
 final string processname = app.processname;
 try {
  appdeathrecipient adr = new appdeathrecipient(
 app, pid, thread);
  thread.asbinder().linktodeath(adr, 0);
  app.deathrecipient = adr;
 } catch (remoteexception e) {
  app.resetpackagelist(mprocessstats);
  startprocesslocked(app, "link fail", processname);
  return false;
 }

 eventlog.writeevent(eventlogtags.am_proc_bound, app.userid, app.pid, app.processname);

 app.makeactive(thread, mprocessstats);
 app.curadj = app.setadj = app.verifiedadj = processlist.invalid_adj;
 app.curschedgroup = app.setschedgroup = processlist.sched_group_default;
 app.forcingtoimportant = null;
 updateprocessforegroundlocked(app, false, false);
 app.hasshownui = false;
 app.debugging = false;
 app.cached = false;
 app.killedbyam = false;
 app.killed = false;


 // we carefully use the same state that packagemanager uses for
 // filtering, since we use this flag to decide if we need to install
 // providers when user is unlocked later
 app.unlocked = storagemanager.isuserkeyunlocked(app.userid);

 mhandler.removemessages(proc_start_timeout_msg, app);

 boolean normalmode = mprocessesready || isallowedwhilebooting(app.info);
 list providers = normalmode ? generateapplicationproviderslocked(app) : null;

 if (providers != null && checkappinlaunchingproviderslocked(app)) {
  message msg = mhandler.obtainmessage(content_provider_publish_timeout_msg);
  msg.obj = app;
  mhandler.sendmessagedelayed(msg, content_provider_publish_timeout);
 }

 checktime(starttime, "attachapplicationlocked: before bindapplication");

 if (!normalmode) {
  slog.i(tag, "launching preboot mode app: " + app);
 }

 if (debug_all) slog.v(
  tag, "new app record " + app
  + " thread=" + thread.asbinder() + " pid=" + pid);
 try {
  int testmode = applicationthreadconstants.debug_off;
  if (mdebugapp != null && mdebugapp.equals(processname)) {
testmode = mwaitfordebugger
 ? applicationthreadconstants.debug_wait
 : applicationthreadconstants.debug_on;
app.debugging = true;
if (mdebugtransient) {
 mdebugapp = morigdebugapp;
 mwaitfordebugger = morigwaitfordebugger;
}
  }
  string profilefile = app.instr != null ? app.instr.mprofilefile : null;
  parcelfiledescriptor profilefd = null;
  int samplinginterval = 0;
  boolean profileautostop = false;
  boolean profilestreamingoutput = false;
  if (mprofileapp != null && mprofileapp.equals(processname)) {
mprofileproc = app;
profilefile = mprofilefile;
profilefd = mprofilefd;
samplinginterval = msamplinginterval;
profileautostop = mautostopprofiler;
profilestreamingoutput = mstreamingoutput;
  }
  boolean enabletrackallocation = false;
  if (mtrackallocationapp != null && mtrackallocationapp.equals(processname)) {
enabletrackallocation = true;
mtrackallocationapp = null;
  }

  // if the app is being launched for restore or full backup, set it up specially
  boolean isrestrictedbackupmode = false;
  if (mbackuptarget != null && mbackupappname.equals(processname)) {
isrestrictedbackupmode = mbackuptarget.appinfo.uid >= first_application_uid
  && ((mbackuptarget.backupmode == backuprecord.restore)
 || (mbackuptarget.backupmode == backuprecord.restore_full)
 || (mbackuptarget.backupmode == backuprecord.backup_full));
  }

  if (app.instr != null) {
notifypackageuse(app.instr.mclass.getpackagename(),
  packagemanager.notify_package_use_instrumentation);
  }
  if (debug_configuration) slog.v(tag_configuration, "binding proc "
 + processname + " with config " + getglobalconfiguration());
  applicationinfo appinfo = app.instr != null ? app.instr.mtargetinfo : app.info;
  app.compat = compatibilityinfoforpackagelocked(appinfo);
  if (profilefd != null) {
profilefd = profilefd.dup();
  }
  profilerinfo profilerinfo = profilefile == null ? null
 : new profilerinfo(profilefile, profilefd, samplinginterval, profileautostop,
  profilestreamingoutput);

  // we deprecated build.serial and it is not accessible to
  // apps that target the v2 security sandbox. since access to
  // the serial is now behind a permission we push down the value.
  string buildserial = build.unknown;
  if (appinfo.targetsandboxversion != 2) {
buildserial = ideviceidentifierspolicyservice.stub.asinterface(
  servicemanager.getservice(context.device_identifiers_service))
  .getserial();
  }

  // check if this is a secondary process that should be incorporated into some
  // currently active instrumentation.  (note we do this after all of the profiling
  // stuff above because profiling can currently happen only in the primary
  // instrumentation process.)
  if (mactiveinstrumentation.size() > 0 && app.instr == null) {
for (int i = mactiveinstrumentation.size() - 1; i >= 0 && app.instr == null; i--) {
 activeinstrumentation ainstr = mactiveinstrumentation.get(i);
 if (!ainstr.mfinished && ainstr.mtargetinfo.uid == app.uid) {
  if (ainstr.mtargetprocesses.length == 0) {
// this is the wildcard mode, where every process brought up for
// the target instrumentation should be included.
if (ainstr.mtargetinfo.packagename.equals(app.info.packagename)) {
 app.instr = ainstr;
 ainstr.mrunningprocesses.add(app);
}
  } else {
for (string proc : ainstr.mtargetprocesses) {
 if (proc.equals(app.processname)) {
  app.instr = ainstr;
  ainstr.mrunningprocesses.add(app);
  break;
 }
}
  }
 }
}
  }

  checktime(starttime, "attachapplicationlocked: immediately before bindapplication");
  mstacksupervisor.mactivitymetricslogger.notifybindapplication(app);
  if (app.instr != null) {
thread.bindapplication(processname, appinfo, providers,
  app.instr.mclass,
  profilerinfo, app.instr.marguments,
  app.instr.mwatcher,
  app.instr.muiautomationconnection, testmode,
  mbindertransactiontrackingenabled, enabletrackallocation,
  isrestrictedbackupmode || !normalmode, app.persistent,
  new configuration(getglobalconfiguration()), app.compat,
  getcommonserviceslocked(app.isolated),
  mcoresettingsobserver.getcoresettingslocked(),
  buildserial);
  } else {
thread.bindapplication(processname, appinfo, providers, null, profilerinfo,
  null, null, null, testmode,
  mbindertransactiontrackingenabled, enabletrackallocation,
  isrestrictedbackupmode || !normalmode, app.persistent,
  new configuration(getglobalconfiguration()), app.compat,
  getcommonserviceslocked(app.isolated),
  mcoresettingsobserver.getcoresettingslocked(),
  buildserial);
  }

  checktime(starttime, "attachapplicationlocked: immediately after bindapplication");
  updatelruprocesslocked(app, false, null);
  checktime(starttime, "attachapplicationlocked: after updatelruprocesslocked");
  app.lastrequestedgc = app.lastlowmemory = systemclock.uptimemillis();
 } catch (exception e) {
  // todo: yikes!  what should we do?  for now we will try to
  // start another process, but that could easily get us in
  // an infinite loop of restarting processes...
  slog.wtf(tag, "exception thrown during bind of " + app, e);

  app.resetpackagelist(mprocessstats);
  app.unlinkdeathrecipient();
  startprocesslocked(app, "bind fail", processname);
  return false;
 }

 // remove this record from the list of starting applications.
 mpersistentstartingprocesses.remove(app);
 if (debug_processes && mprocessesonhold.contains(app)) slog.v(tag_processes,
"attach application locked removing on hold: " + app);
 mprocessesonhold.remove(app);

 boolean badapp = false;
 boolean didsomething = false;

 // see if the top visible activity is waiting to run in this process...
 // step2 : 顶部可见的活动等待启动
 if (normalmode) {
  try {
if (mstacksupervisor.attachapplicationlocked(app)) {
 didsomething = true;
}
  } catch (exception e) {
slog.wtf(tag, "exception thrown launching activities in " + app, e);
badapp = true;
  }
 }

 // find any services that should be running in this process...
 if (!badapp) {
  try {
didsomething |= mservices.attachapplicationlocked(app, processname);
checktime(starttime, "attachapplicationlocked: after mservices.attachapplicationlocked");
  } catch (exception e) {
slog.wtf(tag, "exception thrown starting services in " + app, e);
badapp = true;
  }
 }

 // check if a next-broadcast receiver is in this process...
 if (!badapp && ispendingbroadcastprocesslocked(pid)) {
  try {
didsomething |= sendpendingbroadcastslocked(app);
checktime(starttime, "attachapplicationlocked: after sendpendingbroadcastslocked");
  } catch (exception e) {
// if the app died trying to launch the receiver we declare it 'bad'
slog.wtf(tag, "exception thrown dispatching broadcasts in " + app, e);
badapp = true;
  }
 }

 // check whether the next backup agent is in this process...
 if (!badapp && mbackuptarget != null && mbackuptarget.app == app) {
  if (debug_backup) slog.v(tag_backup,
 "new app is backup target, launching agent for " + app);
  notifypackageuse(mbackuptarget.appinfo.packagename,
 packagemanager.notify_package_use_backup);
  try {
thread.schedulecreatebackupagent(mbackuptarget.appinfo,
  compatibilityinfoforpackagelocked(mbackuptarget.appinfo),
  mbackuptarget.backupmode);
  } catch (exception e) {
slog.wtf(tag, "exception thrown creating backup agent in " + app, e);
badapp = true;
  }
 }

 if (badapp) {
  app.kill("error during init", true);
  handleappdiedlocked(app, false, true);
  return false;
 }

 if (!didsomething) {
  updateoomadjlocked();
  checktime(starttime, "attachapplicationlocked: after updateoomadjlocked");
 }

 return true;
}

上面的方法中,首先使用了processrecord记录了进程中的一些信息,让后将processrecord 与 activitystacksupervisor 关联起来,通过activitystacksupervisor可以运行所有的活动栈。

activitystacksupervisor#attachapplicationlocked

boolean attachapplicationlocked(processrecord app) throws remoteexception {
 final string processname = app.processname;
 boolean didsomething = false;
 for (int displayndx = mactivitydisplays.size() - 1; displayndx >= 0; --displayndx) {
  arraylist stacks = mactivitydisplays.valueat(displayndx).mstacks;
  for (int stackndx = stacks.size() - 1; stackndx >= 0; --stackndx) {
final activitystack stack = stacks.get(stackndx);
if (!isfocusedstack(stack)) {
 continue;
}
//step 1:检查当前活动是否应该被显示
activityrecord hr = stack.toprunningactivitylocked();
if (hr != null) {
 if (hr.app == null && app.uid == hr.info.applicationinfo.uid
&& processname.equals(hr.processname)) {
  try {
//step 2:
if (realstartactivitylocked(hr, app, true, true)) {
 didsomething = true;
}
  } catch (remoteexception e) {
slog.w(tag, "exception in new application when starting activity "
+ hr.intent.getcomponent().flattentoshortstring(), e);
throw e;
  }
 }
}
  }
 }
 if (!didsomething) {
  ensureactivitiesvisiblelocked(null, 0, !preserve_windows);
 }
 return didsomething;
}

遍历活动栈后,首先执行方法toprunningactivitylocked,然后找出当前线程匹配的活动执行realstartactivitylocked方法。

final boolean realstartactivitylocked(activityrecord r, processrecord app,
  boolean andresume, boolean checkconfig) throws remoteexception {

 if (!allpausedactivitiescomplete()) {
  // while there are activities pausing we skipping starting any new activities until
  // pauses are complete. note: that we also do this for activities that are starting in
  // the paused state because they will first be resumed then paused on the client side.
  if (debug_switch || debug_pause || debug_states) slog.v(tag_pause,
 "realstartactivitylocked: skipping start of r=" + r
 + " some activities pausing...");
  return false;
 }

 r.startfreezingscreenlocked(app, 0);
 if (r.getstack().checkkeyguardvisibility(r, true /* shouldbevisible */, true /* istop */)) {
  // we only set the visibility to true if the activity is allowed to be visible based on
  // keyguard state. this avoids setting this into motion in window manager that is later
  // cancelled due to later calls to ensure visible activities that set visibility back to
  // false.
  r.setvisibility(true);
 }

 // schedule launch ticks to collect information about slow apps.
 r.startlaunchtickinglocked();

 // have the window manager re-evaluate the orientation of the screen based on the new
 // activity order.  note that as a result of this, it can call back into the activity
 // manager with a new orientation.  we don't care about that, because the activity is not
 // currently running so we are just restarting it anyway.
 if (checkconfig) {
  final int displayid = r.getdisplayid();
  final configuration config = mwindowmanager.updateorientationfromapptokens(
 getdisplayoverrideconfiguration(displayid),
 r.mayfreezescreenlocked(app) ? r.apptoken : null, displayid);
  // deferring resume here because we're going to launch new activity shortly.
  // we don't want to perform a redundant launch of the same record while ensuring
  // configurations and trying to resume top activity of focused stack.
  mservice.updatedisplayoverrideconfigurationlocked(config, r, true /* deferresume */,
 displayid);
 }

 if (mkeyguardcontroller.iskeyguardlocked()) {
  r.notifyunknownvisibilitylaunched();
 }
 final int applicationinfouid =
(r.info.applicationinfo != null) ? r.info.applicationinfo.uid : -1;
 if ((r.userid != app.userid) || (r.appinfo.uid != applicationinfouid)) {
  slog.wtf(tag,
 "user id for activity changing for " + r
+ " appinfo.uid=" + r.appinfo.uid
+ " info.ai.uid=" + applicationinfouid
+ " old=" + r.app + " new=" + app);
 }

 r.app = app;
 app.waitingtokill = null;
 r.launchcount++;
 r.lastlaunchtime = systemclock.uptimemillis();

 if (debug_all) slog.v(tag, "launching: " + r);

 int idx = app.activities.indexof(r);
 if (idx < 0) {
  app.activities.add(r);
 }
 mservice.updatelruprocesslocked(app, true, null);
 mservice.updateoomadjlocked();

 final taskrecord task = r.gettask();
 if (task.mlocktaskauth == lock_task_auth_launchable ||
task.mlocktaskauth == lock_task_auth_launchable_priv) {
  setlocktaskmodelocked(task, lock_task_mode_locked, "mlocktaskauth==launchable", false);
 }

 final activitystack stack = task.getstack();
 try {
  if (app.thread == null) {
throw new remoteexception();
  }
  list results = null;
  list newintents = null;
  if (andresume) {
// we don't need to deliver new intents and/or set results if activity is going
// to pause immediately after launch.
results = r.results;
newintents = r.newintents;
  }
  if (debug_switch) slog.v(tag_switch,
 "launching: " + r + " icicle=" + r.icicle + " with results=" + results
 + " newintents=" + newintents + " andresume=" + andresume);
  eventlog.writeevent(eventlogtags.am_restart_activity, r.userid,
 system.identityhashcode(r), task.taskid, r.shortcomponentname);
  if (r.ishomeactivity()) {
// home process is the root process of the task.
mservice.mhomeprocess = task.mactivities.get(0).app;
  }
  mservice.notifypackageuse(r.intent.getcomponent().getpackagename(),
 packagemanager.notify_package_use_activity);
  r.sleeping = false;
  r.forcenewconfig = false;
  mservice.showunsupportedzoomdialogifneededlocked(r);
  mservice.showaskcompatmodedialoglocked(r);
  r.compat = mservice.compatibilityinfoforpackagelocked(r.info.applicationinfo);
  profilerinfo profilerinfo = null;
  if (mservice.mprofileapp != null && mservice.mprofileapp.equals(app.processname)) {
if (mservice.mprofileproc == null || mservice.mprofileproc == app) {
 mservice.mprofileproc = app;
 final string profilefile = mservice.mprofilefile;
 if (profilefile != null) {
  parcelfiledescriptor profilefd = mservice.mprofilefd;
  if (profilefd != null) {
try {
 profilefd = profilefd.dup();
} catch (ioexception e) {
 if (profilefd != null) {
  try {
profilefd.close();
  } catch (ioexception o) {
  }
  profilefd = null;
 }
}
  }

  profilerinfo = new profilerinfo(profilefile, profilefd,
 mservice.msamplinginterval, mservice.mautostopprofiler,
 mservice.mstreamingoutput);
 }
}
  }

  app.hasshownui = true;
  app.pendinguiclean = true;
  app.forceprocessstateupto(mservice.mtopprocessstate);
  // because we could be starting an activity in the system process this may not go across
  // a binder interface which would create a new configuration. consequently we have to
  // always create a new configuration here.

  final mergedconfiguration mergedconfiguration = new mergedconfiguration(
 mservice.getglobalconfiguration(), r.getmergedoverrideconfiguration());
  r.setlastreportedconfiguration(mergedconfiguration);

  app.thread.schedulelaunchactivity(new intent(r.intent), r.apptoken,
 system.identityhashcode(r), r.info,
 // todo: have this take the merged configuration instead of separate global and
 // override configs.
 mergedconfiguration.getglobalconfiguration(),
 mergedconfiguration.getoverrideconfiguration(), r.compat,
 r.launchedfrompackage, task.voiceinteractor, app.repprocstate, r.icicle,
 r.persistentstate, results, newintents, !andresume,
 mservice.isnexttransitionforward(), profilerinfo);

  if ((app.info.privateflags&applicationinfo.private_flag_cant_save_state) != 0) {
// this may be a heavy-weight process!  note that the package
// manager will ensure that only activity can run in the main
// process of the .apk, which is the only thing that will be
// considered heavy-weight.
if (app.processname.equals(app.info.packagename)) {
 if (mservice.mheavyweightprocess != null
&& mservice.mheavyweightprocess != app) {
  slog.w(tag, "starting new heavy weight process " + app
 + " when already running "
 + mservice.mheavyweightprocess);
 }
 mservice.mheavyweightprocess = app;
 message msg = mservice.mhandler.obtainmessage(
activitymanagerservice.post_heavy_notification_msg);
 msg.obj = r;
 mservice.mhandler.sendmessage(msg);
}
  }

 } catch (remoteexception e) {
  if (r.launchfailed) {
// this is the second time we failed -- finish activity
// and give up.
slog.e(tag, "second failure launching "
+ r.intent.getcomponent().flattentoshortstring()
+ ", giving up", e);
mservice.appdiedlocked(app);
stack.requestfinishactivitylocked(r.apptoken, activity.result_canceled, null,
  "2nd-crash", false);
return false;
  }

  // this is the first time we failed -- restart process and
  // retry.
  r.launchfailed = true;
  app.activities.remove(r);
  throw e;
 }

 r.launchfailed = false;
 if (stack.updatelrulistlocked(r)) {
  slog.w(tag, "activity " + r + " being launched, but already in lru list");
 }

 if (andresume) {
  // as part of the process of launching, activitythread also performs
  // a resume.
  stack.minimalresumeactivitylocked(r);
 } else {
  // this activity is not starting in the resumed state... which should look like we asked
  // it to pause+stop (but remain visible), and it has done so and reported back the
  // current icicle and other state.
  if (debug_states) slog.v(tag_states,
 "moving to paused: " + r + " (starting in paused state)");
  r.state = paused;
 }

 // launch the new version setup screen if needed.  we do this -after-
 // launching the initial activity (that is, home), so that it can have
 // a chance to initialize itself while in the background, making the
 // switch back to it faster and look better.
 if (isfocusedstack(stack)) {
  mservice.startsetupactivitylocked();
 }

 // update any services we are bound to that might care about whether
 // their client may have activities.
 if (r.app != null) {
  mservice.mservices.updateserviceconnectionactivitieslocked(r.app);
 }

 return true;
}

通过这个方法中完成了一些启动activity的准备工作,然后调用schedulelaunchactivity方法,从上面我们可以知道这里调用的是applicationthread中的方法:

activitythread.applicationthread#schedulelaunchactivity

@override
public final void schedulelaunchactivity(intent intent, ibinder token, int ident,
  activityinfo info, configuration curconfig, configuration overrideconfig,
  compatibilityinfo compatinfo, string referrer, ivoiceinteractor voiceinteractor,
  int procstate, bundle state, persistablebundle persistentstate,
  list pendingresults, list pendingnewintents,
  boolean notresumed, boolean isforward, profilerinfo profilerinfo) {

 updateprocessstate(procstate, false);

 activityclientrecord r = new activityclientrecord();

 r.token = token;
 r.ident = ident;
 r.intent = intent;
 r.referrer = referrer;
 r.voiceinteractor = voiceinteractor;
 r.activityinfo = info;
 r.compatinfo = compatinfo;
 r.state = state;
 r.persistentstate = persistentstate;

 r.pendingresults = pendingresults;
 r.pendingintents = pendingnewintents;

 r.startsnotresumed = notresumed;
 r.isforward = isforward;

 r.profilerinfo = profilerinfo;

 r.overrideconfig = overrideconfig;
 updatependingconfiguration(curconfig);

 sendmessage(h.launch_activity, r);
}

在这里我们可以看到调用的是handler的消息通信机制,当activity状态改变时,都会有对应的一个消息发送出去。而且我们还看到applicationthread类中包含了许多不同的schedulexxx 类的方法,这些方法代表了不同启动状态,每个状态的改变都通过它来发送给handler进行处理。

public void handlemessage(message msg) {
 if (debug_messages) slog.v(tag, ">>> handling: " + codetostring(msg.what));
 switch (msg.what) {
  case launch_activity: {
trace.tracebegin(trace.trace_tag_activity_manager, "activitystart");
final activityclientrecord r = (activityclientrecord) msg.obj;

r.packageinfo = getpackageinfonocheck(
  r.activityinfo.applicationinfo, r.compatinfo);
handlelaunchactivity(r, null, "launch_activity");
trace.traceend(trace.trace_tag_activity_manager);
  } break;
  case relaunch_activity: {
trace.tracebegin(trace.trace_tag_activity_manager, "activityrestart");
activityclientrecord r = (activityclientrecord)msg.obj;
handlerelaunchactivity(r);
trace.traceend(trace.trace_tag_activity_manager);
  } break;
  case pause_activity: {
trace.tracebegin(trace.trace_tag_activity_manager, "activitypause");
someargs args = (someargs) msg.obj;
handlepauseactivity((ibinder) args.arg1, false,
  (args.argi1 & user_leaving) != 0, args.argi2,
  (args.argi1 & dont_report) != 0, args.argi3);
maybesnapshot();
trace.traceend(trace.trace_tag_activity_manager);
  } break;
  case pause_activity_finishing: {
trace.tracebegin(trace.trace_tag_activity_manager, "activitypause");
someargs args = (someargs) msg.obj;
handlepauseactivity((ibinder) args.arg1, true, (args.argi1 & user_leaving) != 0,
  args.argi2, (args.argi1 & dont_report) != 0, args.argi3);
trace.traceend(trace.trace_tag_activity_manager);
  } break;

  ....

由此我们可以得出一个结论,application运行过程中,对于activity的操作状态转变,都是通过handler消息机制来完成的。而这个消息队列就是在activitythread中main方法里面轮询的。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网