ActivityRecord:Activity 在 AMS中的存在形式
创建的位置:
executeRequest()
ActivityStarter.java services\core\java\com\android\server\wm
//这里是正式创建ActivityRecord了
final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, callingFeatureId, intent, resolvedType, aInfo,
mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
sourceRecord);
我们注意到这里有一个 intent,调用方就通过这个intent 来启动目标Activity。
在ActivityRecord 的构造方法中,就通过这个intent 来创建了内部成员 appToken。这个appToken 很关键!
final ActivityRecord.Token appToken;
appToken 是一个类型为Token 的 成员变量, Token 是ActivityRecord的静态内部类,和普通的内部类不一样,这个静态内部类产生的对象不会默认持有外部类对象的引用。作用就相当于一个外部类,放在内部可读性更高。
Token 实现了 IApplicationToken.Stub,可见它是一个Binder服务端。创建Activity时,
system_server进程 的 AMS服务通过调用scheduleLaunchActivity()将appToken传递到App进程。这样,客户端的就能持有ActivityRecord 的弱引用啦
这个类的组成也很简单,成员有三个
- 名字
- Token名字,和1几乎一样
- ActivityRecord的弱引用,通过私有方法 attach 设置,在ActivityRecord初始化的时候会调用这个方法将当前ActivityRecord 设置进appToken中
另外还有一个静态方法来获取这个ActivityRecord。
啥是弱引用?
在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。就是说如果这个对象是偶尔的使用,并且希望在使用时随时就能获取到,但又不想影响此对象的垃圾收集。
它的代理端是传给谁呢?什么时候传过去的呢?
在创建这个Activity的时候传过去的,传给ActivityThread,通过ClientTransaction 这种方式
final ActivityRecord.Token appToken;
static class Token extends IApplicationToken.Stub {
private WeakReference<ActivityRecord> weakActivity;
private final String name;
private final String tokenString;
Token(Intent intent) {
name = intent.getComponent().flattenToShortString();
tokenString = "Token{" + Integer.toHexString(System.identityHashCode(this)) + "}";
}
private void attach(ActivityRecord activity) {
if (weakActivity != null) {
throw new IllegalStateException("Already attached..." + this);
}
weakActivity = new WeakReference<>(activity);
}
private static @Nullable ActivityRecord tokenToActivityRecordLocked(Token token) {
if (token == null) {
return null;
}
ActivityRecord r = token.weakActivity.get();
if (r == null || r.getRootTask() == null) {
return null;
}
return r;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder(128);
sb.append("Token{");
sb.append(Integer.toHexString(System.identityHashCode(this)));
sb.append(' ');
if (weakActivity != null) {
sb.append(weakActivity.get());
}
sb.append('}');
return sb.toString();
}
@Override
public String getName() {
return name;
}
}
里面有一个成员变量
它在哪里创建?
继承自 WindowToken 类,WindowToken类就是 AMS 和 WMS 的通信类
WindowToken是窗口管理器中一组相关窗口的容器。 通常这是一个 AppWindowToken,它是用于显示窗口的 Activity 的句柄。 对于嵌套窗口,会为父窗口创建一个 WindowToken 来管理其子窗口。
ActivityThread 继承自 ClientTransactionHandler
ClientTransactionHandler 是一个虚类,主要是定义了一些方法让子类ActivityThread重写。
ActivityThread 有一个类型为 ApplicationThread 的内部成员 mAppThread,在构造函数调用之前就初始化好了。
final ApplicationThread mAppThread = new ApplicationThread();
直接看它的源码,可以看出它是一个Binder服务端,没有默认的无参构造方法,所以系统会默认给它送一个。既然作为Binder服务端,那么肯定有Binder客户端,它的客户端就是AMS,ApplicationThread 是APP 和 AMS 沟通的桥梁~
private class ApplicationThread extends IApplicationThread.Stub {
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
public final void scheduleReceiver(Intent intent, ActivityInfo info,
CompatibilityInfo compatInfo, int resultCode, String data, Bundle extras,
boolean sync, int sendingUser, int processState) {
updateProcessState(processState, false);
ReceiverData r = new ReceiverData(intent, resultCode, data, extras,
sync, false, mAppThread.asBinder(), sendingUser);
r.info = info;
r.compatInfo = compatInfo;
sendMessage(H.RECEIVER, r);
}
public final void scheduleCreateBackupAgent(ApplicationInfo app,
CompatibilityInfo compatInfo, int backupMode, int userId) {
CreateBackupAgentData d = new CreateBackupAgentData();
d.appInfo = app;
d.compatInfo = compatInfo;
d.backupMode = backupMode;
d.userId = userId;
sendMessage(H.CREATE_BACKUP_AGENT, d);
}
public final void scheduleDestroyBackupAgent(ApplicationInfo app,
CompatibilityInfo compatInfo, int userId) {
CreateBackupAgentData d = new CreateBackupAgentData();
d.appInfo = app;
d.compatInfo = compatInfo;
d.userId = userId;
sendMessage(H.DESTROY_BACKUP_AGENT, d);
}
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;
sendMessage(H.CREATE_SERVICE, s);
}
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState) {
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;
if (DEBUG_SERVICE)
Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
sendMessage(H.BIND_SERVICE, s);
}
public final void scheduleUnbindService(IBinder token, Intent intent) {
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
sendMessage(H.UNBIND_SERVICE, s);
}
public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {
List<ServiceStartArgs> list = args.getList();
for (int i = 0; i < list.size(); i++) {
ServiceStartArgs ssa = list.get(i);
ServiceArgsData s = new ServiceArgsData();
s.token = token;
s.taskRemoved = ssa.taskRemoved;
s.startId = ssa.startId;
s.flags = ssa.flags;
s.args = ssa.args;
sendMessage(H.SERVICE_ARGS, s);
}
}
public final void scheduleStopService(IBinder token) {
sendMessage(H.STOP_SERVICE, token);
}
@Override
public final void bindApplication(String processName, ApplicationInfo appInfo,
ProviderInfoList providerList, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
for (Object oname : services.keySet()) {
if (services.get(oname) == null) {
continue; // AM just passed in a null service.
}
String name = (String) oname;
// See b/79378449 about the following exemption.
switch (name) {
case "package":
case Context.WINDOW_SERVICE:
continue;
}
if (ServiceManager.getService(name) == null) {
Log.wtf(TAG, "Service " + name + " should be accessible by this app");
}
}
}
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providerList.getList();
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
data.autofillOptions = autofillOptions;
data.contentCaptureOptions = contentCaptureOptions;
data.disabledCompatChanges = disabledCompatChanges;
sendMessage(H.BIND_APPLICATION, data);
}
public final void runIsolatedEntryPoint(String entryPoint, String[] entryPointArgs) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = entryPoint;
args.arg2 = entryPointArgs;
sendMessage(H.RUN_ISOLATED_ENTRY_POINT, args);
}
public final void scheduleExit() {
sendMessage(H.EXIT_APPLICATION, null);
}
public final void scheduleSuicide() {
sendMessage(H.SUICIDE, null);
}
public void scheduleApplicationInfoChanged(ApplicationInfo ai) {
mH.removeMessages(H.APPLICATION_INFO_CHANGED, ai);
sendMessage(H.APPLICATION_INFO_CHANGED, ai);
}
public void updateTimeZone() {
TimeZone.setDefault(null);
}
public void clearDnsCache() {
// a non-standard API to get this to libcore
InetAddress.clearDnsCache();
// Allow libcore to perform the necessary actions as it sees fit upon a network
// configuration change.
NetworkEventDispatcher.getInstance().dispatchNetworkConfigurationChange();
}
public void updateHttpProxy() {
ActivityThread.updateHttpProxy(
getApplication() != null ? getApplication() : getSystemContext());
}
public void processInBackground() {
mH.removeMessages(H.GC_WHEN_IDLE);
mH.sendMessage(mH.obtainMessage(H.GC_WHEN_IDLE));
}
public void dumpService(ParcelFileDescriptor pfd, IBinder servicetoken, String[] args) {
DumpComponentInfo data = new DumpComponentInfo();
try {
data.fd = pfd.dup();
data.token = servicetoken;
data.args = args;
sendMessage(H.DUMP_SERVICE, data, 0, 0, true /*async*/);
} catch (IOException e) {
Slog.w(TAG, "dumpService failed", e);
} finally {
IoUtils.closeQuietly(pfd);
}
}
// This function exists to make sure all receiver dispatching is
// correctly ordered, since these are one-way calls and the binder driver
// applies transaction ordering per object for such calls.
public void scheduleRegisteredReceiver(IIntentReceiver receiver, Intent intent,
int resultCode, String dataStr, Bundle extras, boolean ordered,
boolean sticky, int sendingUser, int processState) throws RemoteException {
updateProcessState(processState, false);
receiver.performReceive(intent, resultCode, dataStr, extras, ordered,
sticky, sendingUser);
}
@Override
public void scheduleLowMemory() {
sendMessage(H.LOW_MEMORY, null);
}
@Override
public void profilerControl(boolean start, ProfilerInfo profilerInfo, int profileType) {
sendMessage(H.PROFILER_CONTROL, profilerInfo, start ? 1 : 0, profileType);
}
@Override
public void dumpHeap(boolean managed, boolean mallocInfo, boolean runGc, String path,
ParcelFileDescriptor fd, RemoteCallback finishCallback) {
DumpHeapData dhd = new DumpHeapData();
dhd.managed = managed;
dhd.mallocInfo = mallocInfo;
dhd.runGc = runGc;
dhd.path = path;
try {
// Since we're going to dump the heap asynchronously, dup the file descriptor before
// it's closed on returning from the IPC call.
dhd.fd = fd.dup();
} catch (IOException e) {
Slog.e(TAG, "Failed to duplicate heap dump file descriptor", e);
return;
} finally {
IoUtils.closeQuietly(fd);
}
dhd.finishCallback = finishCallback;
sendMessage(H.DUMP_HEAP, dhd, 0, 0, true /*async*/);
}
public void attachAgent(String agent) {
sendMessage(H.ATTACH_AGENT, agent);
}
public void attachStartupAgents(String dataDir) {
sendMessage(H.ATTACH_STARTUP_AGENTS, dataDir);
}
public void setSchedulingGroup(int group) {
// Note: do this immediately, since going into the foreground
// should happen regardless of what pending work we have to do
// and the activity manager will wait for us to report back that
// we are done before sending us to the background.
try {
Process.setProcessGroup(Process.myPid(), group);
} catch (Exception e) {
Slog.w(TAG, "Failed setting process group to " + group, e);
}
}
public void dispatchPackageBroadcast(int cmd, String[] packages) {
sendMessage(H.DISPATCH_PACKAGE_BROADCAST, packages, cmd);
}
public void scheduleCrash(String msg) {
sendMessage(H.SCHEDULE_CRASH, msg);
}
public void dumpActivity(ParcelFileDescriptor pfd, IBinder activitytoken,
String prefix, String[] args) {
DumpComponentInfo data = new DumpComponentInfo();
try {
data.fd = pfd.dup();
data.token = activitytoken;
data.prefix = prefix;
data.args = args;
sendMessage(H.DUMP_ACTIVITY, data, 0, 0, true /*async*/);
} catch (IOException e) {
Slog.w(TAG, "dumpActivity failed", e);
} finally {
IoUtils.closeQuietly(pfd);
}
}
public void dumpProvider(ParcelFileDescriptor pfd, IBinder providertoken,
String[] args) {
DumpComponentInfo data = new DumpComponentInfo();
try {
data.fd = pfd.dup();
data.token = providertoken;
data.args = args;
sendMessage(H.DUMP_PROVIDER, data, 0, 0, true /*async*/);
} catch (IOException e) {
Slog.w(TAG, "dumpProvider failed", e);
} finally {
IoUtils.closeQuietly(pfd);
}
}
@Override
public void dumpMemInfo(ParcelFileDescriptor pfd, Debug.MemoryInfo mem, boolean checkin,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
boolean dumpUnreachable, String[] args) {
FileOutputStream fout = new FileOutputStream(pfd.getFileDescriptor());
PrintWriter pw = new FastPrintWriter(fout);
try {
dumpMemInfo(pw, mem, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
} finally {
pw.flush();
IoUtils.closeQuietly(pfd);
}
}
private void dumpMemInfo(PrintWriter pw, Debug.MemoryInfo memInfo, boolean checkin,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly, boolean dumpUnreachable) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
Runtime runtime = Runtime.getRuntime();
runtime.gc(); // Do GC since countInstancesOfClass counts unreachable objects.
long dalvikMax = runtime.totalMemory() / 1024;
long dalvikFree = runtime.freeMemory() / 1024;
long dalvikAllocated = dalvikMax - dalvikFree;
Class[] classesToCount = new Class[] {
ContextImpl.class,
Activity.class,
WebView.class,
OpenSSLSocketImpl.class
};
long[] instanceCounts = VMDebug.countInstancesOfClasses(classesToCount, true);
long appContextInstanceCount = instanceCounts[0];
long activityInstanceCount = instanceCounts[1];
long webviewInstanceCount = instanceCounts[2];
long openSslSocketCount = instanceCounts[3];
long viewInstanceCount = ViewDebug.getViewInstanceCount();
long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
int globalAssetCount = AssetManager.getGlobalAssetCount();
int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
long parcelSize = Parcel.getGlobalAllocSize();
long parcelCount = Parcel.getGlobalAllocCount();
SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
dumpMemInfoTable(pw, memInfo, checkin, dumpFullInfo, dumpDalvik, dumpSummaryOnly,
Process.myPid(),
(mBoundApplication != null) ? mBoundApplication.processName : "unknown",
nativeMax, nativeAllocated, nativeFree,
dalvikMax, dalvikAllocated, dalvikFree);
if (checkin) {
// NOTE: if you change anything significant below, also consider changing
// ACTIVITY_THREAD_CHECKIN_VERSION.
// Object counts
pw.print(viewInstanceCount); pw.print(',');
pw.print(viewRootInstanceCount); pw.print(',');
pw.print(appContextInstanceCount); pw.print(',');
pw.print(activityInstanceCount); pw.print(',');
pw.print(globalAssetCount); pw.print(',');
pw.print(globalAssetManagerCount); pw.print(',');
pw.print(binderLocalObjectCount); pw.print(',');
pw.print(binderProxyObjectCount); pw.print(',');
pw.print(binderDeathObjectCount); pw.print(',');
pw.print(openSslSocketCount); pw.print(',');
// SQL
pw.print(stats.memoryUsed / 1024); pw.print(',');
pw.print(stats.memoryUsed / 1024); pw.print(',');
pw.print(stats.pageCacheOverflow / 1024); pw.print(',');
pw.print(stats.largestMemAlloc / 1024);
for (int i = 0; i < stats.dbStats.size(); i++) {
DbStats dbStats = stats.dbStats.get(i);
pw.print(','); pw.print(dbStats.dbName);
pw.print(','); pw.print(dbStats.pageSize);
pw.print(','); pw.print(dbStats.dbSize);
pw.print(','); pw.print(dbStats.lookaside);
pw.print(','); pw.print(dbStats.cache);
pw.print(','); pw.print(dbStats.cache);
}
pw.println();
return;
}
pw.println(" ");
pw.println(" Objects");
printRow(pw, TWO_COUNT_COLUMNS, "Views:", viewInstanceCount, "ViewRootImpl:",
viewRootInstanceCount);
printRow(pw, TWO_COUNT_COLUMNS, "AppContexts:", appContextInstanceCount,
"Activities:", activityInstanceCount);
printRow(pw, TWO_COUNT_COLUMNS, "Assets:", globalAssetCount,
"AssetManagers:", globalAssetManagerCount);
printRow(pw, TWO_COUNT_COLUMNS, "Local Binders:", binderLocalObjectCount,
"Proxy Binders:", binderProxyObjectCount);
printRow(pw, TWO_COUNT_COLUMNS, "Parcel memory:", parcelSize/1024,
"Parcel count:", parcelCount);
printRow(pw, TWO_COUNT_COLUMNS, "Death Recipients:", binderDeathObjectCount,
"OpenSSL Sockets:", openSslSocketCount);
printRow(pw, ONE_COUNT_COLUMN, "WebViews:", webviewInstanceCount);
// SQLite mem info
pw.println(" ");
pw.println(" SQL");
printRow(pw, ONE_COUNT_COLUMN, "MEMORY_USED:", stats.memoryUsed / 1024);
printRow(pw, TWO_COUNT_COLUMNS, "PAGECACHE_OVERFLOW:",
stats.pageCacheOverflow / 1024, "MALLOC_SIZE:", stats.largestMemAlloc / 1024);
pw.println(" ");
int N = stats.dbStats.size();
if (N > 0) {
pw.println(" DATABASES");
printRow(pw, DB_INFO_FORMAT, "pgsz", "dbsz", "Lookaside(b)", "cache",
"Dbname");
for (int i = 0; i < N; i++) {
DbStats dbStats = stats.dbStats.get(i);
printRow(pw, DB_INFO_FORMAT,
(dbStats.pageSize > 0) ? String.valueOf(dbStats.pageSize) : " ",
(dbStats.dbSize > 0) ? String.valueOf(dbStats.dbSize) : " ",
(dbStats.lookaside > 0) ? String.valueOf(dbStats.lookaside) : " ",
dbStats.cache, dbStats.dbName);
}
}
// Asset details.
String assetAlloc = AssetManager.getAssetAllocations();
if (assetAlloc != null) {
pw.println(" ");
pw.println(" Asset Allocations");
pw.print(assetAlloc);
}
// Unreachable native memory
if (dumpUnreachable) {
boolean showContents = ((mBoundApplication != null)
&& ((mBoundApplication.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0))
|| android.os.Build.IS_DEBUGGABLE;
pw.println(" ");
pw.println(" Unreachable memory");
pw.print(Debug.getUnreachableMemory(100, showContents));
}
}
@Override
public void dumpMemInfoProto(ParcelFileDescriptor pfd, Debug.MemoryInfo mem,
boolean dumpFullInfo, boolean dumpDalvik, boolean dumpSummaryOnly,
boolean dumpUnreachable, String[] args) {
ProtoOutputStream proto = new ProtoOutputStream(pfd.getFileDescriptor());
try {
dumpMemInfo(proto, mem, dumpFullInfo, dumpDalvik, dumpSummaryOnly, dumpUnreachable);
} finally {
proto.flush();
IoUtils.closeQuietly(pfd);
}
}
private void dumpMemInfo(ProtoOutputStream proto, Debug.MemoryInfo memInfo,
boolean dumpFullInfo, boolean dumpDalvik,
boolean dumpSummaryOnly, boolean dumpUnreachable) {
long nativeMax = Debug.getNativeHeapSize() / 1024;
long nativeAllocated = Debug.getNativeHeapAllocatedSize() / 1024;
long nativeFree = Debug.getNativeHeapFreeSize() / 1024;
Runtime runtime = Runtime.getRuntime();
runtime.gc(); // Do GC since countInstancesOfClass counts unreachable objects.
long dalvikMax = runtime.totalMemory() / 1024;
long dalvikFree = runtime.freeMemory() / 1024;
long dalvikAllocated = dalvikMax - dalvikFree;
Class[] classesToCount = new Class[] {
ContextImpl.class,
Activity.class,
WebView.class,
OpenSSLSocketImpl.class
};
long[] instanceCounts = VMDebug.countInstancesOfClasses(classesToCount, true);
long appContextInstanceCount = instanceCounts[0];
long activityInstanceCount = instanceCounts[1];
long webviewInstanceCount = instanceCounts[2];
long openSslSocketCount = instanceCounts[3];
long viewInstanceCount = ViewDebug.getViewInstanceCount();
long viewRootInstanceCount = ViewDebug.getViewRootImplCount();
int globalAssetCount = AssetManager.getGlobalAssetCount();
int globalAssetManagerCount = AssetManager.getGlobalAssetManagerCount();
int binderLocalObjectCount = Debug.getBinderLocalObjectCount();
int binderProxyObjectCount = Debug.getBinderProxyObjectCount();
int binderDeathObjectCount = Debug.getBinderDeathObjectCount();
long parcelSize = Parcel.getGlobalAllocSize();
long parcelCount = Parcel.getGlobalAllocCount();
SQLiteDebug.PagerStats stats = SQLiteDebug.getDatabaseInfo();
final long mToken = proto.start(MemInfoDumpProto.AppData.PROCESS_MEMORY);
proto.write(MemInfoDumpProto.ProcessMemory.PID, Process.myPid());
proto.write(MemInfoDumpProto.ProcessMemory.PROCESS_NAME,
(mBoundApplication != null) ? mBoundApplication.processName : "unknown");
dumpMemInfoTable(proto, memInfo, dumpDalvik, dumpSummaryOnly,
nativeMax, nativeAllocated, nativeFree,
dalvikMax, dalvikAllocated, dalvikFree);
proto.end(mToken);
final long oToken = proto.start(MemInfoDumpProto.AppData.OBJECTS);
proto.write(MemInfoDumpProto.AppData.ObjectStats.VIEW_INSTANCE_COUNT,
viewInstanceCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.VIEW_ROOT_INSTANCE_COUNT,
viewRootInstanceCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.APP_CONTEXT_INSTANCE_COUNT,
appContextInstanceCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.ACTIVITY_INSTANCE_COUNT,
activityInstanceCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.GLOBAL_ASSET_COUNT,
globalAssetCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.GLOBAL_ASSET_MANAGER_COUNT,
globalAssetManagerCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.LOCAL_BINDER_OBJECT_COUNT,
binderLocalObjectCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.PROXY_BINDER_OBJECT_COUNT,
binderProxyObjectCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.PARCEL_MEMORY_KB,
parcelSize / 1024);
proto.write(MemInfoDumpProto.AppData.ObjectStats.PARCEL_COUNT, parcelCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.BINDER_OBJECT_DEATH_COUNT,
binderDeathObjectCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.OPEN_SSL_SOCKET_COUNT,
openSslSocketCount);
proto.write(MemInfoDumpProto.AppData.ObjectStats.WEBVIEW_INSTANCE_COUNT,
webviewInstanceCount);
proto.end(oToken);
// SQLite mem info
final long sToken = proto.start(MemInfoDumpProto.AppData.SQL);
proto.write(MemInfoDumpProto.AppData.SqlStats.MEMORY_USED_KB,
stats.memoryUsed / 1024);
proto.write(MemInfoDumpProto.AppData.SqlStats.PAGECACHE_OVERFLOW_KB,
stats.pageCacheOverflow / 1024);
proto.write(MemInfoDumpProto.AppData.SqlStats.MALLOC_SIZE_KB,
stats.largestMemAlloc / 1024);
int n = stats.dbStats.size();
for (int i = 0; i < n; i++) {
DbStats dbStats = stats.dbStats.get(i);
final long dToken = proto.start(MemInfoDumpProto.AppData.SqlStats.DATABASES);
proto.write(MemInfoDumpProto.AppData.SqlStats.Database.NAME, dbStats.dbName);
proto.write(MemInfoDumpProto.AppData.SqlStats.Database.PAGE_SIZE, dbStats.pageSize);
proto.write(MemInfoDumpProto.AppData.SqlStats.Database.DB_SIZE, dbStats.dbSize);
proto.write(MemInfoDumpProto.AppData.SqlStats.Database.LOOKASIDE_B,
dbStats.lookaside);
proto.write(MemInfoDumpProto.AppData.SqlStats.Database.CACHE, dbStats.cache);
proto.end(dToken);
}
proto.end(sToken);
// Asset details.
String assetAlloc = AssetManager.getAssetAllocations();
if (assetAlloc != null) {
proto.write(MemInfoDumpProto.AppData.ASSET_ALLOCATIONS, assetAlloc);
}
// Unreachable native memory
if (dumpUnreachable) {
int flags = mBoundApplication == null ? 0 : mBoundApplication.appInfo.flags;
boolean showContents = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0
|| android.os.Build.IS_DEBUGGABLE;
proto.write(MemInfoDumpProto.AppData.UNREACHABLE_MEMORY,
Debug.getUnreachableMemory(100, showContents));
}
}
@Override
public void dumpGfxInfo(ParcelFileDescriptor pfd, String[] args) {
nDumpGraphicsInfo(pfd.getFileDescriptor());
WindowManagerGlobal.getInstance().dumpGfxInfo(pfd.getFileDescriptor(), args);
IoUtils.closeQuietly(pfd);
}
@Override
public void dumpCacheInfo(ParcelFileDescriptor pfd, String[] args) {
PropertyInvalidatedCache.dumpCacheInfo(pfd.getFileDescriptor(), args);
IoUtils.closeQuietly(pfd);
}
private File getDatabasesDir(Context context) {
// There's no simple way to get the databases/ path, so do it this way.
return context.getDatabasePath("a").getParentFile();
}
private void dumpDatabaseInfo(ParcelFileDescriptor pfd, String[] args, boolean isSystem) {
PrintWriter pw = new FastPrintWriter(
new FileOutputStream(pfd.getFileDescriptor()));
PrintWriterPrinter printer = new PrintWriterPrinter(pw);
SQLiteDebug.dump(printer, args, isSystem);
pw.flush();
}
@Override
public void dumpDbInfo(final ParcelFileDescriptor pfd, final String[] args) {
if (mSystemThread) {
// Ensure this invocation is asynchronous to prevent writer waiting if buffer cannot
// be consumed. But it must duplicate the file descriptor first, since caller might
// be closing it.
final ParcelFileDescriptor dup;
try {
dup = pfd.dup();
} catch (IOException e) {
Log.w(TAG, "Could not dup FD " + pfd.getFileDescriptor().getInt$());
return;
} finally {
IoUtils.closeQuietly(pfd);
}
AsyncTask.THREAD_POOL_EXECUTOR.execute(new Runnable() {
@Override
public void run() {
try {
dumpDatabaseInfo(dup, args, true);
} finally {
IoUtils.closeQuietly(dup);
}
}
});
} else {
dumpDatabaseInfo(pfd, args, false);
IoUtils.closeQuietly(pfd);
}
}
@Override
public void unstableProviderDied(IBinder provider) {
sendMessage(H.UNSTABLE_PROVIDER_DIED, provider);
}
@Override
public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
int requestType, int sessionId, int flags) {
RequestAssistContextExtras cmd = new RequestAssistContextExtras();
cmd.activityToken = activityToken;
cmd.requestToken = requestToken;
cmd.requestType = requestType;
cmd.sessionId = sessionId;
cmd.flags = flags;
sendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
}
public void setCoreSettings(Bundle coreSettings) {
sendMessage(H.SET_CORE_SETTINGS, coreSettings);
}
public void updatePackageCompatibilityInfo(String pkg, CompatibilityInfo info) {
UpdateCompatibilityData ucd = new UpdateCompatibilityData();
ucd.pkg = pkg;
ucd.info = info;
sendMessage(H.UPDATE_PACKAGE_COMPATIBILITY_INFO, ucd);
}
public void scheduleTrimMemory(int level) {
final Runnable r = PooledLambda.obtainRunnable(ActivityThread::handleTrimMemory,
ActivityThread.this, level).recycleOnUse();
// Schedule trimming memory after drawing the frame to minimize jank-risk.
Choreographer choreographer = Choreographer.getMainThreadInstance();
if (choreographer != null) {
choreographer.postCallback(Choreographer.CALLBACK_COMMIT, r, null);
} else {
mH.post(r);
}
}
public void scheduleTranslucentConversionComplete(IBinder token, boolean drawComplete) {
sendMessage(H.TRANSLUCENT_CONVERSION_COMPLETE, token, drawComplete ? 1 : 0);
}
public void scheduleOnNewActivityOptions(IBinder token, Bundle options) {
sendMessage(H.ON_NEW_ACTIVITY_OPTIONS,
new Pair<IBinder, ActivityOptions>(token, ActivityOptions.fromBundle(options)));
}
public void setProcessState(int state) {
updateProcessState(state, true);
}
/**
* Updates {@link #mNetworkBlockSeq}. This is used by ActivityManagerService to inform
* the main thread that it needs to wait for the network rules to get updated before
* launching an activity.
*/
@Override
public void setNetworkBlockSeq(long procStateSeq) {
synchronized (mNetworkPolicyLock) {
mNetworkBlockSeq = procStateSeq;
}
}
@Override
public void scheduleInstallProvider(ProviderInfo provider) {
sendMessage(H.INSTALL_PROVIDER, provider);
}
@Override
public final void updateTimePrefs(int timeFormatPreference) {
final Boolean timeFormatPreferenceBool;
// For convenience we are using the Intent extra values.
if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR) {
timeFormatPreferenceBool = Boolean.FALSE;
} else if (timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_24_HOUR) {
timeFormatPreferenceBool = Boolean.TRUE;
} else {
// timeFormatPreference == Intent.EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT
// (or unknown).
timeFormatPreferenceBool = null;
}
DateFormat.set24HourTimePref(timeFormatPreferenceBool);
}
@Override
public void scheduleEnterAnimationComplete(IBinder token) {
sendMessage(H.ENTER_ANIMATION_COMPLETE, token);
}
@Override
public void notifyCleartextNetwork(byte[] firstPacket) {
if (StrictMode.vmCleartextNetworkEnabled()) {
StrictMode.onCleartextNetworkDetected(firstPacket);
}
}
@Override
public void startBinderTracking() {
sendMessage(H.START_BINDER_TRACKING, null);
}
@Override
public void stopBinderTrackingAndDump(ParcelFileDescriptor pfd) {
try {
sendMessage(H.STOP_BINDER_TRACKING_AND_DUMP, pfd.dup());
} catch (IOException e) {
} finally {
IoUtils.closeQuietly(pfd);
}
}
@Override
public void scheduleLocalVoiceInteractionStarted(IBinder token,
IVoiceInteractor voiceInteractor) throws RemoteException {
SomeArgs args = SomeArgs.obtain();
args.arg1 = token;
args.arg2 = voiceInteractor;
sendMessage(H.LOCAL_VOICE_INTERACTION_STARTED, args);
}
@Override
public void handleTrustStorageUpdate() {
NetworkSecurityPolicy.getInstance().handleTrustStorageUpdate();
}
@Override
public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
ActivityThread.this.scheduleTransaction(transaction);
}
@Override
public void requestDirectActions(@NonNull IBinder activityToken,
@NonNull IVoiceInteractor interactor, @Nullable RemoteCallback cancellationCallback,
@NonNull RemoteCallback callback) {
final CancellationSignal cancellationSignal = new CancellationSignal();
if (cancellationCallback != null) {
final ICancellationSignal transport = createSafeCancellationTransport(
cancellationSignal);
final Bundle cancellationResult = new Bundle();
cancellationResult.putBinder(VoiceInteractor.KEY_CANCELLATION_SIGNAL,
transport.asBinder());
cancellationCallback.sendResult(cancellationResult);
}
mH.sendMessage(PooledLambda.obtainMessage(ActivityThread::handleRequestDirectActions,
ActivityThread.this, activityToken, interactor, cancellationSignal, callback));
}
@Override
public void performDirectAction(@NonNull IBinder activityToken, @NonNull String actionId,
@Nullable Bundle arguments, @Nullable RemoteCallback cancellationCallback,
@NonNull RemoteCallback resultCallback) {
final CancellationSignal cancellationSignal = new CancellationSignal();
if (cancellationCallback != null) {
final ICancellationSignal transport = createSafeCancellationTransport(
cancellationSignal);
final Bundle cancellationResult = new Bundle();
cancellationResult.putBinder(VoiceInteractor.KEY_CANCELLATION_SIGNAL,
transport.asBinder());
cancellationCallback.sendResult(cancellationResult);
}
mH.sendMessage(PooledLambda.obtainMessage(ActivityThread::handlePerformDirectAction,
ActivityThread.this, activityToken, actionId, arguments,
cancellationSignal, resultCallback));
}
}
继续看它是怎么绑定,怎么发送到AMS里面的。
调用main方法后,会new一个类型为ActivityThread的thread对象,然后调用ActivityThread的成员函数attach,最终会走到 AMS的attachApplication
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
mgr.attachApplication(mAppThread, startSeq);
} 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 {
ActivityTaskManager.getService().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();
mInstrumentation.basicInit(this);
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);
}
}
ViewRootImpl.ConfigChangedCallback configChangedCallback
= (Configuration globalConfig) -> {
synchronized (mResourcesManager) {
// TODO (b/135719017): Temporary log for debugging IME service.
if (Build.IS_DEBUGGABLE && mHasImeComponent) {
Log.d(TAG, "ViewRootImpl.ConfigChangedCallback for IME, "
+ "config=" + globalConfig);
}
// 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 */,
mInitialApplication.getResources().getDisplayAdjustments())) {
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);
}
在AMS中,拿到的是ApplicationThread 的客户端,最终会调用到这个binder对象的成员函数 bindApplication,把一些初始的参数传给它,比如Configuration 等,然后 Application 将这些参数保存进一个类型为 AppBindData的对象中,然后通过 外部类 ActivityThread 的 成员 mH ,一个Handler,通知ActivityThread 一个 BIND_APPLICATION 这样的消息。
处理逻辑是:
handleBindApplication,这里就不细讲了,大意是将参数保存下来,做一些初始化的操作。创建 Instrumentation,通过这个Instrumentation 创建一个Application 对象,然后调用它的onCreate()
WindowProcessController
// 在WMS端驱动进程状态的控制器。
ClientTransaction 机制