Handler
Handler是用来分发和处理消息的,通常我们创建Handler都是使用其无参数的构造方法
public Handler() {
this(null, false);
}
其内部调用的是2个参数的构造方法
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
//大概的意思就是创建Handler的匿名内部类,成员类,局部类的时候会给出下面log的提示
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
//获取当前线程的Looper对象,如果是在UI线程(四大组件)中创建Handler,那么这里拿到的就是主线程的Looper
mLooper = Looper.myLooper();
if (mLooper == null) {
//在子线程中创建Handler如果没有事先初始化Looper,是拿不到Looper的,因此会抛异常
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//记录Looper对象内的MessageQueue消息队列
mQueue = mLooper.mQueue;
//记录传递进来的callback接口,注意这里的Callback接口是定义在Handler类内部的.
mCallback = callback;
//记录是否是异步,默认构造方法传入的是false,表示同步处理消息
mAsynchronous = async;
}
//内部接口
public interface Callback {
public boolean handleMessage(Message msg);
}
分析上面的源码可以发现,在new Handler的时候,内部会得到一个Looper对象,以及该Looper的MessageQueue对象.
同时提到了 "Can't create handler inside thread that has not called Looper.prepare()");
这个异常,仅当Looper获取为空的时候抛出.
另外,参数async表示此创建的Handler是否用于处理异步消息,如果是则需要通过Message的方式来异步处理,而如果不是,那就通过postRunnable的方式来处理同步的消息.
Looper
上面创建handler的时候提到了Looper,那么现在我们来分析下Looper的源码
public final class Looper {
private static final String TAG = "Looper";
// 通过ThreadLocal绑定Looper对象到当前线程,默认情况下sThreadLocal.get()会返回null,除非你事先调用了prepare()方法.
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
// 主线程的Looper对象,在主线程中创建Handler,默认会初始化一个Looper与主线程绑定
private static Looper sMainLooper;
//消息队列,每个Looper对象内部都有一个消息队列
final MessageQueue mQueue;
//当前线程
final Thread mThread;
//log输出对象
private Printer mLogging;
/**
* 初始化Looper,给当前线程绑定一个Looper对象,该方法创建的Looper,默认是支持结束loop的
*/
public static void prepare() {
prepare(true);
}
/**
* 私有的初始化Looper对象方法
* 参数quitAllowed表示是否支持结束loop,通过调用quit()或者quitSafely()方法进行结束
*/
private static void prepare(boolean quitAllowed) {
//一个线程只能绑定一次Looper
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//创建一个Looper,并将Looper绑定到当前线程中
sThreadLocal.set(new Looper(quitAllowed));
}
/**
* 私有构造方法,因此创建Looper必须要通过prepare方法创建
*/
private Looper(boolean quitAllowed) {
//初始化该Looper的MessageQueue对象,Handler发送消息的时候会用到mQueue,它用于存储Handler发送的Message
mQueue = new MessageQueue(quitAllowed);
//获取当前线程,作为sThreadLocal的key,value就是该绑定的Looper对象
mThread = Thread.currentThread();
}
/**
*初始化主线程的Looper对象,由android系统调用,不需要我们自己调用
*/
public static void prepareMainLooper() {
//初始化Looper,主线程创建的Looper是不需要结束loop的,如果手动调用结束方法会抛出异常
prepare(false);
//主线程的Looper只能由android系统初始化,我们自己初始化会抛异常
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
//记录主线程的Looper
sMainLooper = myLooper();
}
}
/** 获取主线程的Looper
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
/**
* 返回与当前线程相关Looper对象,如果返回null,则说明当前线程没有关联Looper
*/
public static Looper myLooper() {
return sThreadLocal.get();
}
/**
* 返回当前线程绑定的Looper对象内的MessageQueue ,这个必须在Looper中运行的线程中调用,否则会报空指针异常
*/
public static MessageQueue myQueue() {
return myLooper().mQueue;
}
/**
* 轮询MessageQueue中的Message,如果是子线则需要手动调用loop方法轮询处理消息
*/
public static void loop() {
//1.获取当前线程绑定的looper对象
final Looper me = myLooper();
if (me == null) {
//在子线程中创建Handler,如果没有调用Looper.prepare(),那么myLooper()方法是获取不到Looper对象的.则会抛异常,
//而主线程由于系统已经调用了prepareMainLooper方法,因此没有这个问题
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//2.获取Looper的消息队列
final MessageQueue queue = me.mQueue;
// ...
for (;;) {
//3.这里是死循环,从MessageQueue中遍历所有的Message对象
Message msg = queue.next(); // might block (next方法是阻塞的方法)
//消息为null,结束loop
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
// ...
/* 4.获取Message所关联的target,这里的target其实就是Handler对象,后面会解释
调用关联的Handler对象的dispatchMessage方法,将消息传递给Handler去处理*/
msg.target.dispatchMessage(msg);
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// ...
// 释放消息,清空Message中保存的各种引用
msg.recycle();
}
}
/**
* 判断当前Looper内的线程是否就是当前线程
*/
public boolean isCurrentThread() {
return Thread.currentThread() == mThread;
}
/**
* 非安全的退出Looper,会导致loop方法终止,退出时并不保证消息队列中的所有message都已处理完毕
*/
public void quit() {
mQueue.quit(false);
}
/**
* 安全的结束Looper,loop方法仅当消息队列中的所有message都处理完毕后才终止,但是不包括延时处理的message
*/
public void quitSafely() {
mQueue.quit(true);
}
/**
* 获取与之Looper关联的线程对象
*/
public Thread getThread() {
return mThread;
}
...
通过分析Looper的源码,我们可以了解到Looper类是用来轮询当前线程相关联的Message对象的,每轮询一个message,就会通过该message持有的Handler的引用也就是target去处理消息,具体是通过dispatchMessage方法分发处理消息,稍后会讲到.
默认创建的线程是没有与任何Looper进行关联的,必须要先通过Looper的prepare()静态方法来创建并通过ThreadLocal进行关联绑定,接着轮询处理消息的时候必须要手动调用loop方法进行处理.
子线程创建Handler
下面是一个经典的子线程中创建Handelr,并通过Looper轮询和处理消息的例子:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
//初始化Looper
Looper.prepare();
//创建处理消息的Handler,最开始已经分析过子线程中创建Handler,必须要先有Looper
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
//开始轮询
Looper.loop();
}
}
在主线程中创建Handler的,系统已经帮我们完成了Looper.prepare();和 Looper.loop();的工作了,因此我们可以直接使用Handler.
疑问
分析Looper源码的时候有以下2个疑问待解决,定位到loop方法中的msg.target.dispatchMessage(msg);
1.target是何时与Message进行关联的呢?
2.dispatchMessage是如何处理轮询出来的消息(message对象)?
target的由来
target是Message对象的一个属性,要知道它是啥时候赋值的,那么我们可以先Message的创建说起,Message有多中方式创建,通过空参的构造方法创建,或者通过其多个静态的obtain方法创建.
空参的构造方法内一行代码也没有,看不到有啥有用的线索,obtain方法倒是有几个可以直接看出对target的赋值声明,例如:
...
public static Message obtain(Handler h) {
Message m = obtain();
m.target = h;
return m;
}
public static Message obtain(Handler h, Runnable callback) {
Message m = obtain();
m.target = h;
m.callback = callback;
return m;
}
...
但是这些静态方法并不是创建Message的唯一途径,因此都不能保证target就已经关联了Handler对象,那么我们只能从Handler的sendMessage方法入手了.
public final boolean sendMessage(Message msg) {
//继续往下调用sendMessageDelayed方法,该方法是一个延时发送消息的方法,这里传递0表示马上发送.
return sendMessageDelayed(msg, 0);
}
接着sendMessageDelayed方法
public final boolean sendMessageDelayed(Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
//继续往下调用sendMessageAtTime,功能是一样的,名字不同而已.
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
接着sendMessageAtTime方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
//判断此时的Looper的MessageQueue是否为null,是者打印警告log
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
//继续往下调用enqueueMessage
return enqueueMessage(queue, msg, uptimeMillis);
}
接着enqueueMessage方法
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
/*ok,终于找到看到真相了.this就是当前创建的Handler,也就是说我们通过Handler的sendMessage发送Message的时候,
该Message对象将该Handler保存到它的target变量中.*/
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
//这一步是将消息存放到消息队列中
return queue.enqueueMessage(msg, uptimeMillis);
}
Handler#dispatchMessage的处理
dispatchMessage是Handler的方法,就是用来分发处理消息的,直接看源码
/**
* 分发消息
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
//交由Message处理,通过Handler的post方法发送的消息Runnable会赋值给msg的callback属性
handleCallback(msg);
} else {
//交由handler的Callback处理
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
//如果Callback的handleMessage方法返回true,那么dispatchMessage方法将结束,意味着下面的Handler的handleMessage方法将不被回调.
return;
}
}
/*如果mCallback==null,或者Callback的handleMessage方法返回false的话,Handler的
handleMessage才可以接受到消息.通过Handler的无参构造方法创建Handler的话mCallback就是等于null的.
因此我们重写Handler的handleMessage方法就可以接收到我们发送的Message对象*/
handleMessage(msg);
}
}
//回调给我们处理自己的消息
public void handleMessage(Message msg) {
}
//直接处理Message内的Runnable中的run方法
private static void handleCallback(Message message) {
message.callback.run();
}
分析Handler的事件分发机制可知,当Handler收到消息开分发的时候优先会判断Message中是否有绑定Runnable对象,如果有的话,直接执行run方法的逻辑,否则继续判断Handler中是否有绑定Callback对象,如果有则执行Callback的handleMessage方法,并判断其返回值,如果返回true则分发结束,返回false,则会执行我们重写Handler的handleMessage方法.
总结
通过上面的Handler,Looper,Message的源码分析,大概的结论是:
1.Handler通过发送和处理Message
2. Looper通过轮询MessageQueue无限循环轮询Message,同时将Message回传给对应的Handler处理
3. 创建Handler必须要调用Looper.prepare()方法去初始化Looper,否则将报异常,主线程的Looper是由android系统去调用Looper.prepare()的;
4. Looper的loop()方法将是开启消息轮询的关键方法,非UI线程必须
扩展
Handler#post方法分析
post方法会将Runnable对象添加到message queue中,Runnable中的run方法最终是在什么线程中执行是要看创建该Handler所在的线程,如果是在主线程中创建的Handler,那么该run方法就会在主线程中执行,否则是在子线程中执行.
返回值表示该Runnable是否成功的添加到了消息队列中
public final boolean post(Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
getPostMessage做了什么操作呢?
很简单,就是创建一个Message,然后将Runnable对象赋值给它的callback 属性.
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
接着就和Handler#sendMessage方法一样了.将消息发送到Looper中的MessageQueue中.具体是通过上面提到的enqueueMessage方法.
主线程的Looper在哪里创建
Activity的启动一般会调用到ActivityThread,里面有main方法,是初始化activity必经阶段,主线程的Looper创建和调用轮询都是在ActivityThread的main方法中执行的
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>");
//1.创建主线程的Looper
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
//2.创建主线程的Handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
//3.开启轮询
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
主线程中的Looper.loop()一直无限循环为什么不会造成ANR?
分析Looper的loop源码的时候可以知道MessageQueue是通过next()方法去获取Message的,而next()方法又是一个阻塞的方法,所以主线程是阻塞的,因此CPU并不会消耗太多资源在主线程中,像我们平时自己new 的线程一样,如果run方法里面没有阻塞的语句,那么很快就得结束回收掉了.
既然主线程阻塞了,那么为什么还能调用各种生命周期呢?
调用生命周期是因为有Looper,有MessageQueue,还有沟通的桥梁Handler,通过IPC机制调用Handler发送各种消息,保存到MessageQueue中,然后在主线程中的Looper提取了消息,并在主线程中调用Handler的方法去处理消息.最终完成各种生命周期方法的调用.
下面贴出主线程的Handler的handleMessage方法的处理代码:
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case RELAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
handleRelaunchActivity(r);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
case PAUSE_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, false, msg.arg1 != 0, msg.arg2);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PAUSE_ACTIVITY_FINISHING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
handlePauseActivity((IBinder)msg.obj, true, msg.arg1 != 0, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_SHOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
handleStopActivity((IBinder)msg.obj, true, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_ACTIVITY_HIDE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStop");
handleStopActivity((IBinder)msg.obj, false, msg.arg2);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SHOW_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityShowWindow");
handleWindowVisibility((IBinder)msg.obj, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case HIDE_WINDOW:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityHideWindow");
handleWindowVisibility((IBinder)msg.obj, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RESUME_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
handleResumeActivity((IBinder)msg.obj, true,
msg.arg1 != 0, true);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SEND_RESULT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDeliverResult");
handleSendResult((ResultData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case DESTROY_ACTIVITY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityDestroy");
handleDestroyActivity((IBinder)msg.obj, msg.arg1 != 0,
msg.arg2, false);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
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;
case EXIT_APPLICATION:
if (mInitialApplication != null) {
mInitialApplication.onTerminate();
}
Looper.myLooper().quit();
break;
case NEW_INTENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityNewIntent");
handleNewIntent((NewIntentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case RECEIVER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastReceiveComp");
handleReceiver((ReceiverData)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceCreate");
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case BIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
handleBindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UNBIND_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceUnbind");
handleUnbindService((BindServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SERVICE_ARGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStart");
handleServiceArgs((ServiceArgsData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case STOP_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceStop");
handleStopService((IBinder)msg.obj);
maybeSnapshot();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case REQUEST_THUMBNAIL:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "requestThumbnail");
handleRequestThumbnail((IBinder)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "configChanged");
mCurDefaultDisplayDpi = ((Configuration)msg.obj).densityDpi;
handleConfigurationChanged((Configuration)msg.obj, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case CLEAN_UP_CONTEXT:
ContextCleanupInfo cci = (ContextCleanupInfo)msg.obj;
cci.context.performFinalCleanup(cci.who, cci.what);
break;
case GC_WHEN_IDLE:
scheduleGcIdler();
break;
case DUMP_SERVICE:
handleDumpService((DumpComponentInfo)msg.obj);
break;
case LOW_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "lowMemory");
handleLowMemory();
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ACTIVITY_CONFIGURATION_CHANGED:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityConfigChanged");
handleActivityConfigurationChanged((IBinder)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case PROFILER_CONTROL:
handleProfilerControl(msg.arg1 != 0, (ProfilerControlData)msg.obj, msg.arg2);
break;
case CREATE_BACKUP_AGENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupCreateAgent");
handleCreateBackupAgent((CreateBackupAgentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case DESTROY_BACKUP_AGENT:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backupDestroyAgent");
handleDestroyBackupAgent((CreateBackupAgentData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SUICIDE:
Process.killProcess(Process.myPid());
break;
case REMOVE_PROVIDER:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "providerRemove");
completeRemoveProvider((ProviderRefCount)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case ENABLE_JIT:
ensureJitEnabled();
break;
case DISPATCH_PACKAGE_BROADCAST:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "broadcastPackage");
handleDispatchPackageBroadcast(msg.arg1, (String[])msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SCHEDULE_CRASH:
throw new RemoteServiceException((String)msg.obj);
case DUMP_HEAP:
handleDumpHeap(msg.arg1 != 0, (DumpHeapData)msg.obj);
break;
case DUMP_ACTIVITY:
handleDumpActivity((DumpComponentInfo)msg.obj);
break;
case DUMP_PROVIDER:
handleDumpProvider((DumpComponentInfo)msg.obj);
break;
case SLEEPING:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "sleeping");
handleSleeping((IBinder)msg.obj, msg.arg1 != 0);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case SET_CORE_SETTINGS:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "setCoreSettings");
handleSetCoreSettings((Bundle) msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UPDATE_PACKAGE_COMPATIBILITY_INFO:
handleUpdatePackageCompatibilityInfo((UpdateCompatibilityData)msg.obj);
break;
case TRIM_MEMORY:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "trimMemory");
handleTrimMemory(msg.arg1);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
case UNSTABLE_PROVIDER_DIED:
handleUnstableProviderDied((IBinder)msg.obj, false);
break;
case REQUEST_ASSIST_CONTEXT_EXTRAS:
handleRequestAssistContextExtras((RequestAssistContextExtras)msg.obj);
break;
case TRANSLUCENT_CONVERSION_COMPLETE:
handleTranslucentConversionComplete((IBinder)msg.obj, msg.arg1 == 1);
break;
case INSTALL_PROVIDER:
handleInstallProvider((ProviderInfo) msg.obj);
break;
}
if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}