一,應用程序創建
- 從AndroidManagerService開始,ActivityManagerService.StartProcessLocked
源碼位置:http://androidxref.com/4.4.4_r1/xref/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr){
··· ···
try {
int uid = app.uid;
int[] gids = null;
int mountExternal = Zygote.MOUNT_EXTERNAL_NONE;
if (!app.isolated) {
int[] permGids = null;
try {
final PackageManager pm = mContext.getPackageManager();
permGids = pm.getPackageGids(app.info.packageName);
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, null);
··· ···
}
首先獲取要創建的應用程序的進程uid和用戶組gid,然后通過Process類靜態成員函數start來創建應用程序進程。
- Process類,
Process.start
Process.startViaZygote
Process.zygote
源碼位置:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/os/Process.java
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
private static ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String[] extraArgs)
throws ZygoteStartFailedEx {
synchronized(Process.class) {
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-init, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-init");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
argsForZygote.add("--enable-jni-logging");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
argsForZygote.add("--enable-safemode");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
argsForZygote.add("--enable-debugger");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
argsForZygote.add("--enable-checkjni");
}
if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
argsForZygote.add("--enable-assert");
}
if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER) {
argsForZygote.add("--mount-external-multiuser");
} else if (mountExternal == Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL) {
argsForZygote.add("--mount-external-multiuser-all");
}
argsForZygote.add("--target-sdk-version=" + targetSdkVersion);
//TODO optionally enable debuger
//argsForZygote.add("--enable-debugger");
// --setgroups is a comma-separated list
if (gids != null && gids.length > 0) {
StringBuilder sb = new StringBuilder();
sb.append("--setgroups=");
int sz = gids.length;
for (int i = 0; i < sz; i++) {
if (i != 0) {
sb.append(',');
}
sb.append(gids[i]);
}
argsForZygote.add(sb.toString());
}
if (niceName != null) {
argsForZygote.add("--nice-name=" + niceName);
}
if (seInfo != null) {
argsForZygote.add("--seinfo=" + seInfo);
}
argsForZygote.add(processClass);
if (extraArgs != null) {
for (String arg : extraArgs) {
argsForZygote.add(arg);
}
}
return zygoteSendArgsAndGetResult(argsForZygote);
}
}
在《Android系統源代碼情景分析》一書中用的是2.3的代碼,里面的start函數包含supportsProcess來判斷系統是否支持Binder進程通信機制,而在本文中使用的是4.4的代碼,其中start函數已經刪除了該部分,start函數直接調用startViaZygote函數,實際的start已經沒有任何用處,至今保留是為了代碼兼容。
startViaZygote
首先將傳入的參數添加到字符串列表argsForZygote
中,然后調用zygoteSendArgsAndGetResult
函數來請求Zygote進程創建一個新的應用程序進程。
private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)
throws ZygoteStartFailedEx {
openZygoteSocketIfNeeded();
try {
/**
* See com.android.internal.os.ZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
sZygoteWriter.write(Integer.toString(args.size()));
sZygoteWriter.newLine();
int sz = args.size();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
if (arg.indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx(
"embedded newlines not allowed");
}
sZygoteWriter.write(arg);
sZygoteWriter.newLine();
}
sZygoteWriter.flush();
// Should there be a timeout on this?
ProcessStartResult result = new ProcessStartResult();
result.pid = sZygoteInputStream.readInt();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
result.usingWrapper = sZygoteInputStream.readBoolean();
return result;
} catch (IOException ex) {
try {
if (sZygoteSocket != null) {
sZygoteSocket.close();
}
} catch (IOException ex2) {
// we're going to fail anyway
Log.e(LOG_TAG,"I/O exception on routine close", ex2);
}
sZygoteSocket = null;
throw new ZygoteStartFailedEx(ex);
}
}
首先通過openZygoteSocketIfNeeded()
來創建一個LocalSocket對象,用來和Zygote進程通信,然后將傳入的參數寫道LocalSocket這個對象中,Zygote進程收到參數后就會創建新的應用進程,然后將Pid返回到result,然后這個pid就被返回到AMS(AndroidManagerService)中。
LocalSocket對象的創建過程如下:
private static void openZygoteSocketIfNeeded()
throws ZygoteStartFailedEx {
int retryCount;
if (sPreviousZygoteOpenFailed) {
/*
* If we've failed before, expect that we'll fail again and
* don't pause for retries.
*/
retryCount = 0;
} else {
retryCount = 10;
}
/*
* See bug #811181: Sometimes runtime can make it up before zygote.
* Really, we'd like to do something better to avoid this condition,
* but for now just wait a bit...
*/
for (int retry = 0; (sZygoteSocket == null) && (retry < (retryCount + 1)); retry++ ) {
if (retry > 0) {
try {
Log.i("Zygote", "Zygote not up yet, sleeping...");
Thread.sleep(ZYGOTE_RETRY_MILLIS);
} catch (InterruptedException ex) {
// should never happen
}
}
try {
sZygoteSocket = new LocalSocket();
sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, LocalSocketAddress.Namespace.RESERVED));
sZygoteInputStream = new DataInputStream(sZygoteSocket.getInputStream());
sZygoteWriter = new BufferedWriter(new OutputStreamWriter(sZygoteSocket.getOutputStream()), 256);
Log.i("Zygote", "Process: zygote socket opened");
sPreviousZygoteOpenFailed = false;
break;
} catch (IOException ex) {
if (sZygoteSocket != null) {
try {
sZygoteSocket.close();
} catch (IOException ex2) {
Log.e(LOG_TAG,"I/O exception on close after exception", ex2);
}
}
sZygoteSocket = null;
}
}
if (sZygoteSocket == null) {
sPreviousZygoteOpenFailed = true;
throw new ZygoteStartFailedEx("connect failed");
}
}
sZygoteSocket
是Process類中的一個靜態成員變量,首先new一個LocalSocket
對象,保存在sZygoteSocket
中,然后將之與ZYGOTE_SOCKET
建立連接,ZYGOTE_SOCKET(Zygote進程運行后會創建一個名為zygote
的Socket,這個Socket與設備文件/dev/socket/zygote
綁定在一起,這個Socket的地址就是ZYGOTE_SOCKET
),連接過程就是sZygoteSocket在/dev/socket/
文件夾下找到zygote文件,然后與之綁定的過程。
然后通過數據流的寫入和輸出完成了與Zygote進程的通信。
然后再來看下Zygote端:
上面說到,Zygote進程啟動后會創建一個名為zygote
的Socket,等待AMS與之通信,過程如下:
源碼位置:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
在2.3的代碼中名為runSelectLoopMode
,在4.4的代碼中名字改為了runSelectLoop
,
private static void runSelectLoop() throws MethodAndArgsCaller {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
FileDescriptor[] fdArray = new FileDescriptor[4];
fds.add(sServerSocket.getFileDescriptor());
peers.add(null);
int loopCount = GC_LOOP_COUNT;
while (true) {
int index;
/*
* Call gc() before we block in select().
* It's work that has to be done anyway, and it's better
* to avoid making every child do it. It will also
* madvise() any free memory as a side-effect.
*
* Don't call it every time, because walking the entire
* heap is a lot of overhead to free a few hundred bytes.
*/
if (loopCount <= 0) {
gc();
loopCount = GC_LOOP_COUNT;
} else {
loopCount--;
}
try {
fdArray = fds.toArray(fdArray);
index = selectReadable(fdArray);
} catch (IOException ex) {
throw new RuntimeException("Error in select()", ex);
}
if (index < 0) {
throw new RuntimeException("Error in select()");
} else if (index == 0) {
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
boolean done;
done = peers.get(index).runOnce();
if (done) {
peers.remove(index);
fds.remove(index);
}
}
}
}
從Socket中讀取參數傳遞到fds
,然后解析index,當index>0時,通過runOnce
函數來處理Socket請求。
然后來看runOnce
的實現,
源碼位置:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
Log.w(TAG, "IOException on command socket " + ex.getMessage());
closeSocket();
return true;
}
if (args == null) {
// EOF reached.
closeSocket();
return true;
}
/** the stderr of the most recent request, if avail */
PrintStream newStderr = null;
if (descriptors != null && descriptors.length >= 3) {
newStderr = new PrintStream(
new FileOutputStream(descriptors[2]));
}
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
try {
parsedArgs = new Arguments(args);
applyUidSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyRlimitSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyCapabilitiesSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyInvokeWithSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyseInfoSecurityPolicy(parsedArgs, peer, peerSecurityContext);
applyDebuggerSystemProperty(parsedArgs);
applyInvokeWithSystemProperty(parsedArgs);
int[][] rlimits = null;
if (parsedArgs.rlimits != null) {
rlimits = parsedArgs.rlimits.toArray(intArray2d);
}
if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
FileDescriptor[] pipeFds = Libcore.os.pipe();
childPipeFd = pipeFds[1];
serverPipeFd = pipeFds[0];
ZygoteInit.setCloseOnExec(serverPipeFd, true);
}
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName);
} catch (IOException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (ErrnoException ex) {
logAndPrintError(newStderr, "Exception creating pipe", ex);
} catch (IllegalArgumentException ex) {
logAndPrintError(newStderr, "Invalid zygote arguments", ex);
} catch (ZygoteSecurityException ex) {
logAndPrintError(newStderr,
"Zygote security policy prevents request: ", ex);
}
try {
if (pid == 0) {
// in child
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);
// should never get here, the child is expected to either
// throw ZygoteInit.MethodAndArgsCaller or exec().
return true;
} else {
// in parent...pid of < 0 means failure
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
首先通過readArgumentList()
函數來讀取傳入的所要創建的進程的參數,將之放到Arguments
類型的參數parsedArgs
中,然后將parseArgs
參數傳入到forkAndSpecialize
函數,通過forkAndSpecialize函數fork一個子進程,然后檢測pid是否為0來判斷當前進程是否是子進程,是的話就執行handleChildProc
函數來處理子進程,否則就進入下一段代碼執行handleParentProc
處理父進程(記錄子進程pid已經應用描述等信息)。
下面來看處理子進程的流程:
源碼位置同上也是在ZygoteConnection.java中
private void handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
throws ZygoteInit.MethodAndArgsCaller {
closeSocket();
ZygoteInit.closeServerSocket();
if (descriptors != null) {
try {
ZygoteInit.reopenStdio(descriptors[0],
descriptors[1], descriptors[2]);
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
newStderr = System.err;
} catch (IOException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}
if (parsedArgs.niceName != null) {
Process.setArgV0(parsedArgs.niceName);
}
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs);
}
} else {
String className;
try {
className = parsedArgs.remainingArgs[0];
} catch (ArrayIndexOutOfBoundsException ex) {
logAndPrintError(newStderr,
"Missing required class name argument", null);
return;
}
String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];
System.arraycopy(parsedArgs.remainingArgs, 1,
mainArgs, 0, mainArgs.length);
if (parsedArgs.invokeWith != null) {
WrapperInit.execStandalone(parsedArgs.invokeWith,
parsedArgs.classpath, className, mainArgs);
} else {
ClassLoader cloader;
if (parsedArgs.classpath != null) {
cloader = new PathClassLoader(parsedArgs.classpath,
ClassLoader.getSystemClassLoader());
} else {
cloader = ClassLoader.getSystemClassLoader();
}
try {
ZygoteInit.invokeStaticMain(cloader, className, mainArgs);
} catch (RuntimeException ex) {
logAndPrintError(newStderr, "Error starting.", ex);
}
}
}
}
首先是讀取描述信息等,這里的nicename不太明白是什么意思,暫時理解為應用信息的一個參數吧,重點是這一段代碼:
if (parsedArgs.runtimeInit) {
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
pipeFd, parsedArgs.remainingArgs);
} else {
RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs);
}
runtimeInit
這個參數之前在添加參數的時候是加過的,所以這里一定是true,invokeWith 參數是沒有添加的,所以執行的是RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs);
也就是運行時初始化。
接著往下看運行時初始化的過程:
public static final void zygoteInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");
redirectLogStreams();
commonInit();
nativeZygoteInit();
applicationInit(targetSdkVersion, argv);
}
zygoteInit
是RuntimeInit
類的一個靜態成員函數,通過commonInit
設置新應用的時區和鍵盤布局等通用信息,通過nativeZygoteInit()
在新的應用程序中創建一個Binder線程池,最后通過applicationInit
進入application初始化過程,下面分開來看創建進程池和application初始化過程。
二,線程池創建
上面說到通過nativeZygoteInit()
在新的進程中創建Binder線程池,在2.3的代碼中這個函數也叫做zygoteInitNative,我們還是繼續使用4.4的代碼來看,從名字可見這是一個jni函數,實現函數名為com_android_internal_os_RuntimeInit_nativeZygoteInit
private static final native void nativeZygoteInit();
源碼位置:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
gCurRuntime->onZygoteInit();
}
gCurRuntime
是一個全局變量,他是在AndroidRuntime
類的構造函數中初始化的,Zygote進程啟動時會創建一個AppRuntime類,由于AppRuntime類繼承了AndroidRuntime類,所以會導致AndroidRuntime類的構造函數被調用,調用過程中gCurRuntime變量會被初始化,指向的就是正在創建的AppRuntime對象。又因為每創建一個應用進程都會fork一個Zygote進程的地址空間,因此每一個應用進程中都存在一個gCurRuntime全局變量。所以這里調用的是AppRuntime的成員函數onZygoteInit()。
源碼地址:http://androidxref.com/4.4.4_r1/xref/frameworks/base/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
// Re-enable tracing now that we're no longer in Zygote.
atrace_set_tracing_enabled(true);
sp<ProcessState> proc = ProcessState::self();
ALOGV("App process: starting thread pool.\n");
proc->startThreadPool();
}
調用當前應用進程中的ProcessState對象的成員函數startThreadPool來啟動一個Binder線程池;
ProcessState.startThreadPool();
源碼位置:http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/binder/ProcessState.cpp
void ProcessState::startThreadPool()
{
AutoMutex _l(mLock);
if (!mThreadPoolStarted) {
mThreadPoolStarted = true;
spawnPooledThread(true);
}
}
Android系統中每個支持Binder進程間通信的進程都有唯一一個
ProcessState
對象,當這個對象的成員函數startThreadPool
第一次被調用時就會啟動Binder進程池,并且將mThreadPoolStarted
的值設為true,避免之后重復啟動。
這里可以看到先將mThreadStarted參數設置為true,避免之后重復啟動線程池,然后調用spawnPooledThread
函數。
void ProcessState::spawnPooledThread(bool isMain)
{
if (mThreadPoolStarted) {
String8 name = makeBinderThreadName();
ALOGV("Spawning new pooled thread, name=%s\n", name.string());
sp<Thread> t = new PoolThread(isMain);
t->run(name.string());
}
}
上一段代碼可見這里的isMain
參數為true
,表示:線程t是進程主動創建來加如到它的Binder線程池的,以區別于Binder驅動程序請求進程創建新的線程來加入到它的Binder線程池的情況。
new一個PoolThread
對象,然后調用它的成員函數run
,并將線程名傳入作為參數。
PoolThread
類繼承了線程類Thread
,并且重寫了它的線程入口成員函數threadLoop,改寫后如下:
class PoolThread : public Thread
{
public:
PoolThread(bool isMain)
: mIsMain(isMain)
{
}
protected:
virtual bool threadLoop()
{
IPCThreadState::self()->joinThreadPool(mIsMain);
return false;
}
const bool mIsMain;
};
調用了IPCThreadState
對象的成員函數joinThreadPool
將當前線程注冊到Binder驅動程序中去成為一個Binder線程,以便Binder驅動程序可以分發進程間通信請求給它處理,joinThreadPool
的代碼如下:
源碼路徑:http://androidxref.com/4.4.4_r1/xref/frameworks/native/libs/binder/IPCThreadState.cpp
void IPCThreadState::joinThreadPool(bool isMain)
{
LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
// This thread may have been spawned by a thread that was in the background
// scheduling group, so first we will make sure it is in the foreground
// one to avoid performing an initial transaction in the background.
set_sched_policy(mMyThreadId, SP_FOREGROUND);
status_t result;
do {
processPendingDerefs();
// now get the next command to be processed, waiting if necessary
result = getAndExecuteCommand();
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
ALOGE("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
mProcess->mDriverFD, result);
abort();
}
// Let this thread exit the thread pool if it is no longer
// needed and it is not the main process thread.
if(result == TIMED_OUT && !isMain) {
break;
}
} while (result != -ECONNREFUSED && result != -EBADF);
LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%p\n",
(void*)pthread_self(), getpid(), (void*)result);
mOut.writeInt32(BC_EXIT_LOOPER);
talkWithDriver(false);
}
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
這里的isMain
值為true,所以將BC_ENTER_LOOPER
命令寫入到IPCThreadState
類內部的命令協議緩沖區mOut
中,最后通過talkWithDriver
將命令發送給Binder驅動程序,完成注冊。
第一部分中說到Zygote收到AMS傳來的參數和命令之后會執行兩個動作,一個是通過nativeZygoteInit()來啟動線程池,另一個就是接下來要說的通過applicationInit完成application初始化的過程。
三,Application初始化
applicationInit
代碼如下:
源碼路徑:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java#applicationInit
private static void applicationInit(int targetSdkVersion, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
// If the application calls System.exit(), terminate the process
// immediately without running any shutdown hooks. It is not possible to
// shutdown an Android application gracefully. Among other things, the
// Android runtime shutdown hooks close the Binder driver, which can cause
// leftover running threads to crash before the process actually exits.
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
final Arguments args;
try {
args = new Arguments(argv);
} catch (IllegalArgumentException ex) {
Slog.e(TAG, ex.getMessage());
// let the process exit
return;
}
// Remaining arguments are passed to the start class's static main
invokeStaticMain(args.startClass, args.startArgs);
}
重點是最后一行,獲取傳入參數后調用invokeStaticMain函數:
private static void invokeStaticMain(String className, String[] argv)
throws ZygoteInit.MethodAndArgsCaller {
Class<?> cl;
try {
cl = Class.forName(className);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
/*
* This throw gets caught in ZygoteInit.main(), which responds
* by invoking the exception's run() method. This arrangement
* clears up all the stack frames that were required in setting
* up the process.
*/
throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}
通過第一部分AMS指定參數可知,這里傳入的className的值為android.app.ActivityThread
,其中這行代碼cl = Class.forName(className);
使用裝載當前類的類裝載器來裝載android.app.ActivityThread
類,在2.3版本的代碼中此處為cl = loader.loadClass(className)
二者的區別在于后者只是將信息裝載給jvm,需要手動制定裝載器的實例。
然后獲取android.app.ActivityThread
的main
函數保存到Method對象m中,最后將這個method封裝到一個MethodAndArgsCaller
對象中,并將這個MethodAndArgsCaller
對象作為一個異常拋給當前應用進程處理,
public static void main(String argv[]) {
try {
··· ···
}catch (MethodAndArgsCaller caller) {
caller.run();
}
當前進程收到異常后直接運行MethodAndArgsCaller
對象的run()方法。
MethodAndArgsCaller.run():
源碼路徑:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static class MethodAndArgsCaller extends Exception
implements Runnable {
/** method to call */
private final Method mMethod;
/** argument array */
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
因為這個mMethod對象是封裝的android.app.ActivityThread
的main
方法,所以這里要做的就是main方法的調用。
兜兜轉轉一大圈回來之后還是調用
android.app.ActivityThread
的main
方法,那么為什么沒有在第一步中直接調用main方法呢?因為新應用程序的一開始需要初始化運行時庫以及創建Binder線程池,為了利用java的異常處理機制清理掉前面的調用堆棧,所以要間接的調用main方法。
然后來看main方法的具體實現:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
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());
Security.addProvider(new AndroidKeyStoreProvider());
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
通過prepareMainLooper()
函數創建一個消息循環,然后new一個ActivityThread:thread
,并調用自身的attach()
方法,通過getHandler()
獲取thread
的Handle對象,然后再調用loop()函數使thread回到前面的消息循環中,讓ActivityThread類一直處于等待消息的工作狀態。
消息循環很容易理解,那么attach()
類做了什么呢?
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#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("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
} 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);
Application app = Instrumentation.newApplication(Application.class, context);
mAllApplications.add(app);
mInitialApplication = app;
app.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
// add dropbox logging to libcore
DropBox.setReporter(new DropBoxReporter());
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
@Override
public void onConfigurationChanged(Configuration newConfig) {
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(newConfig, null)) {
// This actually changed the resources! Tell
// everyone about it.
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(newConfig)) {
mPendingConfiguration = newConfig;
sendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
}
}
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(int level) {
}
});
}
從上一步代碼可見傳入參數是false
,那么將執行第一個if判斷里的內容,直接看核心代碼:
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
首先實例化一個IActivityManager
對象,然后調用它的attachApplication
方法,來看下這個方法具體實現:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/services/java/com/android/server/am/ActivityManagerService.java
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
主要是調用了attachApplicationLocked
函數:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
....
try {
...
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
//...
} catch (Exception e) {
return false;
}
....
其中調用的thread.bindApplication()
實現如下:
源碼路徑:http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java
public final void bindApplication(String processName,
ApplicationInfo appInfo, List<ProviderInfo> providers,
ComponentName instrumentationName, String profileFile,
ParcelFileDescriptor profileFd, boolean autoStopProfiler,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {
if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfileFile = profileFile;
data.initProfileFd = profileFd;
data.initAutoStopProfiler = false;
sendMessage(H.BIND_APPLICATION, data);
}
先把參數初始化,然后sendMessage到Handler中處理,
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}
在handler處理中調用了handleBindApplication
函數:
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
mConfiguration = new Configuration(data.config);
mCompatConfiguration = new Configuration(data.config);
mProfiler = new Profiler();
mProfiler.profileFile = data.initProfileFile;
mProfiler.profileFd = data.initProfileFd;
mProfiler.autoStopProfiler = data.initAutoStopProfiler;
// send up app name; do this *before* waiting for debugger
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
if (data.persistent) {
// Persistent processes on low-memory devices do not get to
// use hardware accelerated drawing, since this can add too much
// overhead to the process.
if (!ActivityManager.isHighEndGfx()) {
HardwareRenderer.disable(false);
}
}
if (mProfiler.profileFd != null) {
mProfiler.startProfiling();
}
// If the app is Honeycomb MR1 or earlier, switch its AsyncTask
// implementation to use the pool executor. Normally, we use the
// serialized executor as the default. This has to happen in the
// main thread so the main looper is set right.
if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
/*
* Before spawning a new process, reset the time zone to be the system time zone.
* This needs to be done because the system time zone could have changed after the
* the spawning of this process. Without doing this this process would have the incorrect
* system time zone.
*/
TimeZone.setDefault(null);
/*
* Initialize the default locale in this process for the reasons we set the time zone.
*/
Locale.setDefault(data.config.locale);
/*
* Update the system configuration since its preloaded and might not
* reflect configuration changes. The configuration object passed
* in AppBindData can be safely assumed to be up to date
*/
mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;
applyCompatConfiguration(mCurDefaultDisplayDpi);
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
/**
* Switch this process to density compatibility mode if needed.
*/
if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
== 0) {
mDensityCompatMode = true;
Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
}
updateDefaultDensity();
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if (!Process.isIsolated()) {
final File cacheDir = appContext.getCacheDir();
if (cacheDir != null) {
// Provide a usable directory for temporary files
System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
setupGraphicsSupport(data.info, cacheDir);
} else {
Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory");
}
}
/**
* For system applications on userdebug/eng builds, log stack
* traces of disk and network access to dropbox for analysis.
*/
if ((data.appInfo.flags &
(ApplicationInfo.FLAG_SYSTEM |
ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {
StrictMode.conditionallyEnableDebugLogging();
}
/**
* For apps targetting SDK Honeycomb or later, we don't allow
* network usage on the main event loop / UI thread.
*
* Note to those grepping: this is what ultimately throws
* NetworkOnMainThreadException ...
*/
if (data.appInfo.targetSdkVersion > 9) {
StrictMode.enableDeathOnNetwork();
}
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...");
}
}
// Enable OpenGL tracing if required
if (data.enableOpenGlTrace) {
GLUtils.setTracingLevel(1);
}
// Allow application-generated systrace messages if we're debuggable.
boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(appTracingAllowed);
/**
* Initialize the default http proxy in this process for the reasons we set the time zone.
*/
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
// In pre-boot mode (doing initial launch to collect password), not
// all system is up. This includes the connectivity service, so don't
// crash if we can't get it.
IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
ProxyProperties proxyProperties = service.getProxy();
Proxy.setHttpProxySystemProperty(proxyProperties);
} catch (RemoteException e) {}
}
if (data.instrumentationName != null) {
InstrumentationInfo ii = null;
try {
ii = appContext.getPackageManager().
getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
}
if (ii == null) {
throw new RuntimeException(
"Unable to find instrumentation info for: "
+ data.instrumentationName);
}
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationAppLibraryDir = ii.nativeLibraryDir;
mInstrumentationAppPackage = ii.packageName;
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedAppLibraryDir = data.info.getLibDir();
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 = ContextImpl.createAppContext(this, pi);
try {
java.lang.ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
mInstrumentation.init(this, instrContext, appContext,
new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,
data.instrumentationUiAutomationConnection);
if (mProfiler.profileFile != null && !ii.handleProfiling
&& mProfiler.profileFd == null) {
mProfiler.handlingProfiling = true;
File file = new File(mProfiler.profileFile);
file.getParentFile().mkdirs();
Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
}
} else {
mInstrumentation = new Instrumentation();
}
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
}
// Allow disk access during application and provider setup. This could
// block processing ordered broadcasts, but later processing would
// probably end up doing the same disk access.
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
try {
// 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);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
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);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
}
代碼很長,核心部分如下:
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
····
Application app;
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
try {
app = data.info.makeApplication(data.restrictedBackupMode, null);
····
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
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);
}
}
····
}
通過makeApplication函數創建一個Application:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/LoadedApk.java
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(
cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
if (!mActivityThread.mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to instantiate application " + appClass
+ ": " + e.toString(), e);
}
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
if (instrumentation != null) {
try {
instrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!instrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
}
return app;
}
獲取android.app.Application
的完整類名,獲取類加載器對象以及上下文,最后調用Instrumentation類的newApplication對象:
http://androidxref.com/4.4.4_r1/xref/frameworks/base/core/java/android/app/Instrumentation.java
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException, IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
}
這里通過反射的方式,創建了 Application 類的實例,并且綁定了 Application 的上下文,注意一下:在handleBindApplication
中調用makeApplication時候傳入的最后一個參數是null
,所以這里的 instrumentation 對象為空,并不會去執行makeApplication中的最后一個if判斷中的callApplicationOnCreate(),所以makeApplication
中直接返回了新建的這個app變量也就是Application類到handBindApplication
中然后執行mInstrumentation.callApplicationOnCreate(app);
這行代碼,直接調用Application
類的OnCreat()
方法,而這個方法就是我們寫代碼的時候主函數中重寫的Application
的OnCreat()
方法.
然后接下來就是執行我們寫的應用內部的代碼了。
至此我們的應用終于正常啟動起來!!!!!!!!!!
4,附錄:Application類的源碼:
上源碼
package android.app;
import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentCallbacks;
import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;
import android.view.autofill.AutofillManager;
import java.util.ArrayList;
/**
* Base class for maintaining global application state. You can provide your own
* implementation by creating a subclass and specifying the fully-qualified name
* of this subclass as the <code>"android:name"</code> attribute in your
* AndroidManifest.xml's <code><application></code> tag. The Application
* class, or your subclass of the Application class, is instantiated before any
* other class when the process for your application/package is created.
*
* <p class="note"><strong>Note: </strong>There is normally no need to subclass
* Application. In most situations, static singletons can provide the same
* functionality in a more modular way. If your singleton needs a global
* context (for example to register broadcast receivers), include
* {@link android.content.Context#getApplicationContext() Context.getApplicationContext()}
* as a {@link android.content.Context} argument when invoking your singleton's
* <code>getInstance()</code> method.
* </p>
*/
public class Application extends ContextWrapper implements ComponentCallbacks2 {
private static final String TAG = "Application";
@UnsupportedAppUsage
private ArrayList<ComponentCallbacks> mComponentCallbacks =
new ArrayList<ComponentCallbacks>();
@UnsupportedAppUsage
private ArrayList<ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
new ArrayList<ActivityLifecycleCallbacks>();
@UnsupportedAppUsage
private ArrayList<OnProvideAssistDataListener> mAssistCallbacks = null;
/** @hide */
@UnsupportedAppUsage
public LoadedApk mLoadedApk;
public interface ActivityLifecycleCallbacks {
/**
* Called as the first step of the Activity being created. This is always called before
* {@link Activity#onCreate}.
*/
default void onActivityPreCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
}
/**
* Called when the Activity calls {@link Activity#onCreate super.onCreate()}.
*/
void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState);
/**
* Called as the last step of the Activity being created. This is always called after
* {@link Activity#onCreate}.
*/
default void onActivityPostCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
}
/**
* Called as the first step of the Activity being started. This is always called before
* {@link Activity#onStart}.
*/
default void onActivityPreStarted(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onStart super.onStart()}.
*/
void onActivityStarted(@NonNull Activity activity);
/**
* Called as the last step of the Activity being started. This is always called after
* {@link Activity#onStart}.
*/
default void onActivityPostStarted(@NonNull Activity activity) {
}
/**
* Called as the first step of the Activity being resumed. This is always called before
* {@link Activity#onResume}.
*/
default void onActivityPreResumed(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onResume super.onResume()}.
*/
void onActivityResumed(@NonNull Activity activity);
/**
* Called as the last step of the Activity being resumed. This is always called after
* {@link Activity#onResume} and {@link Activity#onPostResume}.
*/
default void onActivityPostResumed(@NonNull Activity activity) {
}
/**
* Called as the first step of the Activity being paused. This is always called before
* {@link Activity#onPause}.
*/
default void onActivityPrePaused(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onPause super.onPause()}.
*/
void onActivityPaused(@NonNull Activity activity);
/**
* Called as the last step of the Activity being paused. This is always called after
* {@link Activity#onPause}.
*/
default void onActivityPostPaused(@NonNull Activity activity) {
}
/**
* Called as the first step of the Activity being stopped. This is always called before
* {@link Activity#onStop}.
*/
default void onActivityPreStopped(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onStop super.onStop()}.
*/
void onActivityStopped(@NonNull Activity activity);
/**
* Called as the last step of the Activity being stopped. This is always called after
* {@link Activity#onStop}.
*/
default void onActivityPostStopped(@NonNull Activity activity) {
}
/**
* Called as the first step of the Activity saving its instance state. This is always
* called before {@link Activity#onSaveInstanceState}.
*/
default void onActivityPreSaveInstanceState(@NonNull Activity activity,
@NonNull Bundle outState) {
}
/**
* Called when the Activity calls
* {@link Activity#onSaveInstanceState super.onSaveInstanceState()}.
*/
void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState);
/**
* Called as the last step of the Activity saving its instance state. This is always
* called after{@link Activity#onSaveInstanceState}.
*/
default void onActivityPostSaveInstanceState(@NonNull Activity activity,
@NonNull Bundle outState) {
}
/**
* Called as the first step of the Activity being destroyed. This is always called before
* {@link Activity#onDestroy}.
*/
default void onActivityPreDestroyed(@NonNull Activity activity) {
}
/**
* Called when the Activity calls {@link Activity#onDestroy super.onDestroy()}.
*/
void onActivityDestroyed(@NonNull Activity activity);
/**
* Called as the last step of the Activity being destroyed. This is always called after
* {@link Activity#onDestroy}.
*/
default void onActivityPostDestroyed(@NonNull Activity activity) {
}
}
/**
* Callback interface for use with {@link Application#registerOnProvideAssistDataListener}
* and {@link Application#unregisterOnProvideAssistDataListener}.
*/
public interface OnProvideAssistDataListener {
/**
* This is called when the user is requesting an assist, to build a full
* {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
* application. You can override this method to place into the bundle anything
* you would like to appear in the {@link Intent#EXTRA_ASSIST_CONTEXT} part
* of the assist Intent.
*/
public void onProvideAssistData(Activity activity, Bundle data);
}
public Application() {
super(null);
}
/**
* Called when the application is starting, before any activity, service,
* or receiver objects (excluding content providers) have been created.
*
* <p>Implementations should be as quick as possible (for example using
* lazy initialization of state) since the time spent in this function
* directly impacts the performance of starting the first activity,
* service, or receiver in a process.</p>
*
* <p>If you override this method, be sure to call {@code super.onCreate()}.</p>
*
* <p class="note">Be aware that direct boot may also affect callback order on
* Android {@link android.os.Build.VERSION_CODES#N} and later devices.
* Until the user unlocks the device, only direct boot aware components are
* allowed to run. You should consider that all direct boot unaware
* components, including such {@link android.content.ContentProvider}, are
* disabled until user unlock happens, especially when component callback
* order matters.</p>
*/
@CallSuper
public void onCreate() {
}
/**
* This method is for use in emulated process environments. It will
* never be called on a production Android device, where processes are
* removed by simply killing them; no user code (including this callback)
* is executed when doing so.
*/
@CallSuper
public void onTerminate() {
}
@CallSuper
public void onConfigurationChanged(@NonNull Configuration newConfig) {
Object[] callbacks = collectComponentCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ComponentCallbacks)callbacks[i]).onConfigurationChanged(newConfig);
}
}
}
@CallSuper
public void onLowMemory() {
Object[] callbacks = collectComponentCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ComponentCallbacks)callbacks[i]).onLowMemory();
}
}
}
@CallSuper
public void onTrimMemory(int level) {
Object[] callbacks = collectComponentCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
Object c = callbacks[i];
if (c instanceof ComponentCallbacks2) {
((ComponentCallbacks2)c).onTrimMemory(level);
}
}
}
}
public void registerComponentCallbacks(ComponentCallbacks callback) {
synchronized (mComponentCallbacks) {
mComponentCallbacks.add(callback);
}
}
public void unregisterComponentCallbacks(ComponentCallbacks callback) {
synchronized (mComponentCallbacks) {
mComponentCallbacks.remove(callback);
}
}
public void registerActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
synchronized (mActivityLifecycleCallbacks) {
mActivityLifecycleCallbacks.add(callback);
}
}
public void unregisterActivityLifecycleCallbacks(ActivityLifecycleCallbacks callback) {
synchronized (mActivityLifecycleCallbacks) {
mActivityLifecycleCallbacks.remove(callback);
}
}
public void registerOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
synchronized (this) {
if (mAssistCallbacks == null) {
mAssistCallbacks = new ArrayList<OnProvideAssistDataListener>();
}
mAssistCallbacks.add(callback);
}
}
public void unregisterOnProvideAssistDataListener(OnProvideAssistDataListener callback) {
synchronized (this) {
if (mAssistCallbacks != null) {
mAssistCallbacks.remove(callback);
}
}
}
/**
* Returns the name of the current process. A package's default process name
* is the same as its package name. Non-default processes will look like
* "$PACKAGE_NAME:$NAME", where $NAME corresponds to an android:process
* attribute within AndroidManifest.xml.
*/
public static String getProcessName() {
return ActivityThread.currentProcessName();
}
// ------------------ Internal API ------------------
/**
* @hide
*/
@UnsupportedAppUsage
/* package */ final void attach(Context context) {
attachBaseContext(context);
mLoadedApk = ContextImpl.getImpl(context).mPackageInfo;
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPreCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreCreated(activity,
savedInstanceState);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ActivityLifecycleCallbacks)callbacks[i]).onActivityCreated(activity,
savedInstanceState);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPostCreated(@NonNull Activity activity,
@Nullable Bundle savedInstanceState) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostCreated(activity,
savedInstanceState);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPreStarted(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStarted(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityStarted(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ActivityLifecycleCallbacks)callbacks[i]).onActivityStarted(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPostStarted(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostStarted(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPreResumed(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreResumed(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityResumed(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ActivityLifecycleCallbacks)callbacks[i]).onActivityResumed(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPostResumed(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostResumed(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPrePaused(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPrePaused(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPaused(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ActivityLifecycleCallbacks)callbacks[i]).onActivityPaused(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPostPaused(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostPaused(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPreStopped(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreStopped(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityStopped(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ActivityLifecycleCallbacks)callbacks[i]).onActivityStopped(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPostStopped(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostStopped(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPreSaveInstanceState(@NonNull Activity activity,
@NonNull Bundle outState) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreSaveInstanceState(
activity, outState);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivitySaveInstanceState(@NonNull Activity activity,
@NonNull Bundle outState) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ActivityLifecycleCallbacks)callbacks[i]).onActivitySaveInstanceState(activity,
outState);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPostSaveInstanceState(@NonNull Activity activity,
@NonNull Bundle outState) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostSaveInstanceState(
activity, outState);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPreDestroyed(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPreDestroyed(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityDestroyed(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((ActivityLifecycleCallbacks)callbacks[i]).onActivityDestroyed(activity);
}
}
}
@UnsupportedAppUsage
/* package */ void dispatchActivityPostDestroyed(@NonNull Activity activity) {
Object[] callbacks = collectActivityLifecycleCallbacks();
if (callbacks != null) {
for (int i = 0; i < callbacks.length; i++) {
((ActivityLifecycleCallbacks) callbacks[i]).onActivityPostDestroyed(activity);
}
}
}
private Object[] collectComponentCallbacks() {
Object[] callbacks = null;
synchronized (mComponentCallbacks) {
if (mComponentCallbacks.size() > 0) {
callbacks = mComponentCallbacks.toArray();
}
}
return callbacks;
}
@UnsupportedAppUsage
private Object[] collectActivityLifecycleCallbacks() {
Object[] callbacks = null;
synchronized (mActivityLifecycleCallbacks) {
if (mActivityLifecycleCallbacks.size() > 0) {
callbacks = mActivityLifecycleCallbacks.toArray();
}
}
return callbacks;
}
/* package */ void dispatchOnProvideAssistData(Activity activity, Bundle data) {
Object[] callbacks;
synchronized (this) {
if (mAssistCallbacks == null) {
return;
}
callbacks = mAssistCallbacks.toArray();
}
if (callbacks != null) {
for (int i=0; i<callbacks.length; i++) {
((OnProvideAssistDataListener)callbacks[i]).onProvideAssistData(activity, data);
}
}
}
/** @hide */
@Override
public AutofillManager.AutofillClient getAutofillClient() {
final AutofillManager.AutofillClient client = super.getAutofillClient();
if (client != null) {
return client;
}
if (android.view.autofill.Helper.sVerbose) {
Log.v(TAG, "getAutofillClient(): null on super, trying to find activity thread");
}
// Okay, ppl use the application context when they should not. This breaks
// autofill among other things. We pick the focused activity since autofill
// interacts only with the currently focused activity and we need the fill
// client only if a call comes from the focused activity. Sigh...
final ActivityThread activityThread = ActivityThread.currentActivityThread();
if (activityThread == null) {
return null;
}
final int activityCount = activityThread.mActivities.size();
for (int i = 0; i < activityCount; i++) {
final ActivityThread.ActivityClientRecord record =
activityThread.mActivities.valueAt(i);
if (record == null) {
continue;
}
final Activity activity = record.activity;
if (activity == null) {
continue;
}
if (activity.getWindow().getDecorView().hasFocus()) {
if (android.view.autofill.Helper.sVerbose) {
Log.v(TAG, "getAutofillClient(): found activity for " + this + ": " + activity);
}
return activity;
}
}
if (android.view.autofill.Helper.sVerbose) {
Log.v(TAG, "getAutofillClient(): none of the " + activityCount + " activities on "
+ this + " have focus");
}
return null;
}
}
Tips:
程序啟動時,系統會自動創建 Application 對象,然后運行 onCreate() 方法,其中 android.app.Application.onCreate() 方法體為空,可以在 onCreate() 中做一些初始化工作。Application 不能自己創建,就如同不能自己創建 Activity 一樣,如果我們通過 new 創建一個 Application,會得到一個普通的類的實例,如果需要應用 Application 的地方用的是我們 new 出來的實例,則會出現空指針異常。綜上所述,使用 Application 一定要使用程序自己創建的 Application,在 onCreate() 中將對象賦值給一個變量(mMyApplication = this),后面開發中使用這個變量即可。
在 Android 應用中,Application 的生命周期是和整個應用一致的,只要應用沒有被系統回收,這個 Application 對象就會一直存在。但是這個 Application 對象并不是始終在內存中的,它有可能會由于系統內存不足而被回收。但系統在你重新打開這個應用時并不是重新啟動這個 Application 對象,它會創建一個新的 Application 對象并且啟動上次用戶離開時的 Activity,造成這個 app 從來沒有被 kill 掉的假象。這樣,之前在 Application 中緩存的數據都會重新初始化。不僅 Application 對象是這樣,其它的單例或者公有靜態類也有可能會由于系統內存而被殺掉。
參考:
Android系統原代碼情景分析(第三版)第五章8.2節:啟動Binder線程池
Android系統原代碼情景分析(第三版)第12章:安卓應用程序進程的啟動過程
Android Application 啟動流程源碼分析
Android:全面解析 熟悉而陌生 的Application類使用