

极力推荐Android 开发大总结文章:欢迎收藏
Android 开发技术文章大总结

本篇文章主要详情 Android 9.0 Crash 机制部分知识点,通过阅读本篇文章,您将收获以下内容:
一、Crash 概述
二、Crash解决流程
三、handleApplicationCrash解决分析
四、handleApplicationCrashInner 解决分析
五、APP Error info分析
六、makeAppCrashingLocked解决分析
七、startAppProblemLocked解决分析
八、stopFreezingAllLocked解决分析

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java/frameworks/base/core/java/android/app/ActivityManagerNative.java (含内部类AMP)/frameworks/base/core/java/android/app/ApplicationErrorReport.java/frameworks/base/services/core/java/com/android/server/ - am/ActivityManagerService.java - am/ProcessRecord.java - am/ActivityRecord.java - am/ActivityStackSupervisor.java - am/ActivityStack.java - am/ActivityRecord.java - am/BroadcastQueue.java - wm/WindowManagerService.java/libcore/libart/src/main/java/java/lang/Thread.javaApp Crash (全称Application Crash), 对于Crash可分为Native Crash和 Framework Crash(包含app crash在内),对于Crash相信很多app开发者都会遇到,那么上层什么时候会出现Crash呢,系统又是如何解决Crash的呢。例如,在app大家经常使用try...catch语句,那么假如没有有效catch exception,就是导致应用Crash,发生没有catch exception,系统便会来进行捕获,并进入Crash流程。假如你是从事Android系统开发或者者架构相关工作,或者者遇到需要解系统性的疑难杂症,那么很有必要理解系统Crash解决流程,知其然还需知其所以然;假如你仅仅是App初级开发,可能本文并非很适合阅读,整个系统流程错综复杂。
在Android系统启动系列文章,已讲述过上层应用都是由Zygote fork孵化而来,分为system_server系统进程和各种应用进程,在这些进程创立之初会设置未捕获异常的解决器,当系统抛出未捕获的异常时,最终都交给异常解决器。
system_server进程:system_server启动过程中由RuntimeInit.java的commonInit方法设置UncaughtHandler,用于解决未捕获异常;RuntimeInit.java的commonInit方法设置UncaughtHandler。crash流程的方法调用关系如下:
AMP.handleApplicationCrash AMS.handleApplicationCrash AMS.findAppProcess AMS.handleApplicationCrashInner AMS.addErrorToDropBox AMS.crashApplication AMS.makeAppCrashingLocked AMS.startAppProblemLocked ProcessRecord.stopFreezingAllLocked ActivityRecord.stopFreezingScreenLocked WMS.stopFreezingScreenLocked WMS.stopFreezingDisplayLocked AMS.handleAppCrashLocked mUiHandler.sendMessage(SHOW_ERROR_MSG)Process.killProcess(Process.myPid());System.exit(10);RuntimeInit.java类的 main方法会调用commonInit()方法。
public static final void main(String[] argv) { enableDdms(); if (argv.length == 2 && argv[1].equals("application")) { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application"); redirectLogStreams(); } else { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting tool"); } // AP Crash 解决流程初始化 commonInit(); // Native Crash 解决流程初始化 nativeFinishInit(); if (DEBUG) Slog.d(TAG, "Leaving RuntimeInit!"); }那么接下来以commonInit()方法为起点来开展说明。
RuntimeInit.java
protected static final void commonInit() { /* * set handlers; these apply to all threads in the VM. Apps can replace * the default handler, but not the pre handler. */ LoggingHandler loggingHandler = new LoggingHandler(); // app不能 替换 setUncaughtExceptionPreHandler Thread.setUncaughtExceptionPreHandler(loggingHandler); // 将异常解决器handler对象赋给Thread成员变量, Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler)); ... ... }接下来我们看看LoggingHandler的实现。LoggingHandler实现 Thread.UncaughtExceptionHandler 方法。
private static class LoggingHandler implements Thread.UncaughtExceptionHandler { public volatile boolean mTriggered = false; @Override public void uncaughtException(Thread t, Throwable e) { mTriggered = true; //保证crash解决过程不会重入 if (mCrashing) return; //mApplicationObject等于null,肯定不是普通的app进程. //但是除了system进程, 也有可能是shell进程, //即通过app_process + 命令参数 的方式创立的进程. if (mApplicationObject == null && (Process.SYSTEM_UID == Process.myUid())) { //系统 进程Crash打印的Log 信息 /** 发生 系统Crash 时候可以搜索 关键字 FATAL EXCEPTION IN SYSTEM PROCESS **/ Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e); } else { /** 发生 APP Crash 时候可以搜索 关键字 FATAL EXCEPTION **/ StringBuilder message = new StringBuilder(); message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n"); final String processName = ActivityThread.currentProcessName(); if (processName != null) { message.append("Process: ").append(processName).append(", "); } message.append("PID: ").append(Process.myPid()); Clog_e(TAG, message.toString(), e); } } }开头 FATAL EXCEPTION IN SYSTEM PROCESS [线程名],接着输出Crash时的调用栈信息;
开头 FATAL EXCEPTION: [线程名],紧接着 Process: [进程名], PID: [进程id];最后输出发生Crash时的调用栈信息。
看到这里,你就会发现要从log中搜索Crash信息,只要要搜索关键词 FATAL EXCEPTION,就可查看出是那种异常;假如需要进一步挑选只搜索系统crash信息,则可以搜索的关键词可以有多样,比方 FATAL EXCEPTION IN SYSTEM PROCESS。
当输出完Crash信息到logcat里面,这只是Crash流程的刚开始阶段,接下来弹出Crash对话框,ActivityManagerNative.getDefault()返回的是ActivityManagerProxy(简称AMP),AMP经过binder调用最终交给ActivityManagerService(简称AMS)中相应的方法去解决,而后调用的是AMS.handleApplicationCrash()。
分析完LoggingHandler后,我们继续看setDefaultUncaughtExceptionHandler(),它只是将异常解决器handler对象赋给Thread成员变量,即Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler(loggingHandler));。接下来看看KillApplicationHandler对象实例化过程。
RuntimeInit.java
KillApplicationHandler 实现 Thread.UncaughtExceptionHandler方法,主要解决因为未捕获的异常Crash导致APP 崩溃,运行在Main Thread的Framework 代码会捕获这些异常。
KillApplicationHandler 方法需要传递一个LoggingHandler的参数,
既 LoggingHandler loggingHandler = new LoggingHandler();,LoggingHandler在上文已经分析过,接下来我们看看KillApplicationHandler方法.
KillApplicationHandler方法如下:
private static class KillApplicationHandler implements Thread.UncaughtExceptionHandler { private final LoggingHandler mLoggingHandler; public KillApplicationHandler(LoggingHandler loggingHandler) { // 构造方法,初始化 loggingHandler this.mLoggingHandler = Objects.requireNonNull(loggingHandler); } @Override public void uncaughtException(Thread t, Throwable e) { try { ensureLogging(t, e); // 保证crash解决过程不会重入 if (mCrashing) return; mCrashing = true; ... ... //启动crash对话框,等待解决完成 【见小节2.1和3】 ActivityManager.getService().handleApplicationCrash( mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e)); } catch (Throwable t2) { ... ... } finally { //确保当前进程彻底杀掉【见小节11】 Process.killProcess(Process.myPid()); System.exit(10); } } ... ...}接下来我们看看启动Crash弹窗的解决。new ApplicationErrorReport.ParcelableCrashInfo(e)方法。
ApplicationErrorReport 主要用来形容 APP Error信息。
APP ERROR 信息分类如下:
// 主要解决 APP Error 信息public class ApplicationErrorReport implements Parcelable { ... ... public static class ParcelableCrashInfo extends CrashInfo implements Parcelable { //创立 CrashInfo 实例,初始化异常信息 public ParcelableCrashInfo(Throwable tr) { super(tr); } ... ... public static final Parcelable.Creator<ParcelableCrashInfo> CREATOR = new Parcelable.Creator<ParcelableCrashInfo>() { @Override public ParcelableCrashInfo createFromParcel(Parcel in) { return new ParcelableCrashInfo(in); } @Override public ParcelableCrashInfo[] newArray(int size) { return new ParcelableCrashInfo[size]; } }; } ... ...}ParcelableCrashInfo 继承 CrashInfo,接下来我们看看 CrashInfo的实现。
**CrashInfo ** 主要是将Crash信息文件名,类名,方法名,对应行号以及异常信息都封装到CrashInfo对象。
// 形容 Crash 信息 public static class CrashInfo { ... ... public CrashInfo() { } //CrashInfo 初始化实例 public CrashInfo(Throwable tr) { StringWriter sw = new StringWriter(); PrintWriter pw = new FastPrintWriter(sw, false, 256); //输出栈trace tr.printStackTrace(pw); pw.flush(); stackTrace = sanitizeString(sw.toString()); exceptionMessage = tr.getMessage(); // 显示异常的根本起因 Throwable rootTr = tr; while (tr.getCause() != null) { tr = tr.getCause(); if (tr.getStackTrace() != null && tr.getStackTrace().length > 0) { rootTr = tr; } String msg = tr.getMessage(); if (msg != null && msg.length() > 0) { exceptionMessage = msg; } } // Crash 异常类名称 exceptionClassName = rootTr.getClass().getName(); if (rootTr.getStackTrace().length > 0) { StackTraceElement trace = rootTr.getStackTrace()[0]; // 获取 trace 文件名、类名、方法名、Crash 行号 throwFileName = trace.getFileName(); throwClassName = trace.getClassName(); throwMethodName = trace.getMethodName(); throwLineNumber = trace.getLineNumber(); } else { throwFileName = "unknown"; ... ... } exceptionMessage = sanitizeString(exceptionMessage); }handleApplicationCrash 会通过 JNI接口调用AMS中的方法。
//发送 Crash 弹窗handler,直到Dialog dismiss ActivityManager.getService().handleApplicationCrash( mApplicationObject, new ApplicationErrorReport.ParcelableCrashInfo(e));ActivityManagerService.javahandleApplicationCrash 通过JNI 回调用 AMS中的handleApplicationCrash方法,进而调用AMS 中的内部方法handleApplicationCrashInner。
handleApplicationCrash
IBinder对象为空Null时,则进程名为system_server;IBinder对象不为空,且ProcessRecord为空时,则进程名为unknown;IBinder对象不为空,且ProcessRecord不为空时,则进程名为ProcessRecord对象中相应进程名。 // 当app Crash 时候,会调用此方法。 //调用结束后 ,app 进程就会推出 public void handleApplicationCrash(IBinder app, ApplicationErrorReport.ParcelableCrashInfo crashInfo) { // findAppProcess 详见 3.1 分析 ProcessRecord r = findAppProcess(app, "Crash"); // system_server 进程 为Null final String processName = app == null ? "system_server" : (r == null ? "unknown" : r.processName); //handleApplicationCrashInner 详见 4 分析 handleApplicationCrashInner("crash", r, processName, crashInfo); }handleApplicationCrashInner主要是调用 AppErrors类中的crashApplication 方法解决。
void handleApplicationCrashInner(String eventType, ProcessRecord r, String processName, ApplicationErrorReport.CrashInfo crashInfo) { ... ... //调用APP Error 类方法中的 crashApplication mAppErrors.crashApplication(r, crashInfo); }ActivityManagerService.javafindAppProcess主要是通过for循环遍历查找出IBinder对应的Process.
private ProcessRecord findAppProcess(IBinder app, String reason) { ... ... synchronized (this) { final int NP = mProcessNames.getMap().size(); for (int ip=0; ip<NP; ip++) { SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip); final int NA = apps.size(); for (int ia=0; ia<NA; ia++) { ProcessRecord p = apps.valueAt(ia); //当找到目标进程则返回 if (p.thread != null && p.thread.asBinder() == app) { return p; } } } //假如代码执行到这里,表明无法找到应用所在的进程 return null; } }其中 mProcessNames = new ProcessMap<ProcessRecord>();对于代码mProcessNames.getMap()返回的是mMap,而mMap= new ArrayMap<String, SparseArray<ProcessRecord>>();
知识延伸:SparseArray和ArrayMap是Android专门针对内存优化而设计的取代Java API中的HashMap的数据结构。
对于key是int类型则使用SparseArray,可避免自动装箱过程;
对于key为其余类型则使用ArrayMap。HashMap的查找和插入时间复杂度为O(1)的代价是牺牲大量的内存来实现的,而SparseArray和ArrayMap性能略逊于HashMap,但更节省内存。
再回到mMap,这是以进程name为key,再以(uid为key,以ProcessRecord为Value的)结构体作为value。下面看看其get()和put()方法
public E get(String name, int uid) { SparseArray<E> uids = mMap.get(name); if (uids == null) return null; return uids.get(uid); } public E put(String name, int uid, E value) { SparseArray<E> uids = mMap.get(name); if (uids == null) { uids = new SparseArray<E>(2); mMap.put(name, uids); } uids.put(uid, value); return value; } findAppProcess()根据app(IBinder类型)来查询相应的目标对象ProcessRecord。
有了进程记录对象ProcessRecord和进程名processName,则进入执行Crash解决方法 AppErrors.java,继续往下看。
ActivityManagerService.java
void handleApplicationCrashInner(String eventType, ProcessRecord r, String processName, ApplicationErrorReport.CrashInfo crashInfo) { ... ... //将错误信息追加到DropBox addErrorToDropBox(eventType, r, processName, null, null, null, null, null, crashInfo); //【见小节5】 mAppErrors.crashApplication(r, crashInfo); }其中addErrorToDropBox是将Crash的信息输出到目录/data/system/dropbox。例如system_server的dropbox文件名为system_server_crash@xxx.txt (xxx代表的是时间戳)
AppErrors.java
AppErrors 主要是 控制APP Crash的场景条件。
void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { ... ... try { // 调用内部 crashApplicationInner方法 crashApplicationInner(r, crashInfo, callingPid, callingUid); } finally { Binder.restoreCallingIdentity(origId); } }crashApplicationInner内部方法
void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, int callingPid, int callingUid) { ... ... AppErrorResult result = new AppErrorResult(); TaskRecord task; synchronized (mService) { // 假如是通过IActivityController 实例导致的Crash ,则不显示弹窗 // 详见5.1 if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace, timeMillis, callingPid, callingUid)) { return; } ... ... AppErrorDialog.Data data = new AppErrorDialog.Data(); data.result = result; data.proc = r; // 无法势必的进程 也不显示Crash 弹窗【见小节6】 if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { return; } final Message msg = Message.obtain(); msg.what = ActivityManagerService.SHOW_ERROR_UI_MSG; task = data.task; msg.obj = data; //发送消息SHOW_ERROR_MSG,弹出提醒crash的对话框,等待客户选择【见小节10】 mService.mUiHandler.sendMessage(msg); } //进入阻塞等待,直到客户选择crash对话框"退出"或者者"退出并报告" int res = result.get(); Intent appErrorIntent = null; MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); if (res == AppErrorDialog.TIMEOUT || res == AppErrorDialog.CANCEL) { res = AppErrorDialog.FORCE_QUIT; } ... ...}handleAppCrashInActivityController,通过IActivityController 实例导致的Crash ,则不显示弹窗.AppError.java
private boolean handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, String stackTrace, long timeMillis, int callingPid, int callingUid) { ... ... // 当存在ActivityController的情况,比方monkey try { String name = r != null ? r.processName : null; int pid = r != null ? r.pid : callingPid; int uid = r != null ? r.info.uid : callingUid; //调用monkey的 appCrashed if (!mService.mController.appCrashed(name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) && "Native crash".equals(crashInfo.exceptionClassName)) { Slog.w(TAG, "Skip killing native crashed app " + name + "(" + pid + ") during testing"); } else { Slog.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); if (r != null) { //调用`makeAppCrashingLocked`,继续解决crash流程 // 详见 小结 6 if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) { r.kill("crash", true); } } else { // Huh. Process.killProcess(pid); ActivityManagerService.killProcessGroup(uid, pid); } } return true; } } catch (RemoteException e) { mService.mController = null; Watchdog.getInstance().setActivityController(null); } return false; }该方法主要做的两件事:
makeAppCrashingLocked,继续解决Crash流程;SHOW_ERROR_MSG,弹出提醒Crash的对话框,等待客户选择;makeAppCrashingLocked实现。AppError.java
private boolean makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { app.crashing = true; //封装crash信息到crashingReport对象 app.crashingReport = generateProcessError(app, ActivityManager.ProcessErrorStateInfo.CRASHED, null, shortMsg, longMsg, stackTrace); //【见小节7】 startAppProblemLocked(app); //中止屏幕冻结【见小节8】 app.stopFreezingAllLocked(); //【见小节9】 return handleAppCrashLocked(app, "force-crash" /*reason*/, shortMsg, longMsg, stackTrace, data); }AppError.javastartAppProblemLocked 该方法主要功能:
crash应用的error receiver;App的广播接收; void startAppProblemLocked(ProcessRecord app) { // 假如不是当前user正在运行 app,这置为空 app.errorReportReceiver = null; for (int userId : mService.mUserController.getCurrentProfileIds()) { if (app.userId == userId) { //获取当前客户下的crash应用的error receiver【见小节7.1】 app.errorReportReceiver = ApplicationErrorReport.getErrorReportReceiver( mContext, app.info.packageName, app.info.flags); } } //忽略当前app的广播接收【见小节7.2】 mService.skipCurrentReceiverLocked(app); }ApplicationErrorReport.java
获取当前客户下的Crash应用的error receiver
public static ComponentName getErrorReportReceiver(Context context, String packageName, int appFlags) { //检查Settings中的"send_action_app_error"能否使能错误报告的功能 int enabled = Settings.Global.getInt(context.getContentResolver(), Settings.Global.SEND_ACTION_APP_ERROR, 0); if (enabled == 0) { //1.当未使能时,则直接返回 return null; } PackageManager pm = context.getPackageManager(); // look for receiver in the installer package String candidate = null; ComponentName result = null; try { //获取该crash应用的安装器的包名 candidate = pm.getInstallerPackageName(packageName); } catch (IllegalArgumentException e) { // the package could already removed } if (candidate != null) { result = getErrorReportReceiver(pm, packageName, candidate); if (result != null) { //2.当找到该crash应用的安装器,则返回; return result; } } //该系统属性名为"ro.error.receiver.system.apps" if ((appFlags&ApplicationInfo.FLAG_SYSTEM) != 0) { candidate = SystemProperties.get(SYSTEM_APPS_ERROR_RECEIVER_PROPERTY); // 通过上下文对象传参,调用类内部方法 result = getErrorReportReceiver(pm, packageName, candidate); if (result != null) { //3.当crash应用是系统应用时,且系统属性指定error receiver时,则返回; return result; } } //该默认属性名为"ro.error.receiver.default" candidate = SystemProperties.get(DEFAULT_ERROR_RECEIVER_PROPERTY); //4.当默认属性值指定error receiver时,则返回; return getErrorReportReceiver(pm, packageName, candidate); }getErrorReportReceiver:这是同名不同输入参数的另一个方法:
static ComponentName getErrorReportReceiver(PackageManager pm, String errorPackage, String receiverPackage) { if (receiverPackage == null || receiverPackage.length() == 0) { return null; } //当安装应用程序的安装器Crash,则直接返回 if (receiverPackage.equals(errorPackage)) { return null; } //ACTION_APP_ERROR值为"android.intent.action.APP_ERROR" Intent intent = new Intent(Intent.ACTION_APP_ERROR); intent.setPackage(receiverPackage); ResolveInfo info = pm.resolveActivity(intent, 0); if (info == null || info.activityInfo == null) { return null; } //创立包名为receiverPackage的组件 return new ComponentName(receiverPackage, info.activityInfo.name); }ActivityManagerService.java
忽略当前app的广播接收
void skipCurrentReceiverLocked(ProcessRecord app) { for (BroadcastQueue queue : mBroadcastQueues) { // 会调用BroadcastQueue 中的方法【见小节7.2.1】 queue.skipCurrentReceiverLocked(app); } }BroadcastQueue.java skipCurrentReceiverLocked忽略当前app的广播接收.
public void skipCurrentReceiverLocked(ProcessRecord app) { BroadcastRecord r = null; //查看app进程中的广播 if (mOrderedBroadcasts.size() > 0) { BroadcastRecord br = mOrderedBroadcasts.get(0); // 判断能否一致 if (br.curApp == app) { r = br; } } ... ... if (r != null) { // 见7.2.2 skipReceiverLocked(r); } }BroadcastQueue.java
private void skipReceiverLocked(BroadcastRecord r) { logBroadcastReceiverDiscardLocked(r); //结束app进程的广播结束 finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); //执行广播调度 scheduleBroadcastsLocked(); }AppError.java中的 makeAppCrashingLocked方法(第6步),会调用stopFreezingAllLocked 方法
ProcessRecord.java
public void stopFreezingAllLocked() { int i = activities.size(); while (i > 0) { i--; // 中止进程里所有的`Activity`. 详见8.1 activities.get(i).stopFreezingScreenLocked(true); } }其中activities类型为ArrayList<ActivityRecord>,中止进程里所有的Activity.
ActivityRecord.java,stopFreezingScreenLocked中止进程里所有的Activity.
public void stopFreezingScreenLocked(boolean force) { if (force || frozenBeforeDestroy) { frozenBeforeDestroy = false; // mWindowContainerController 见【8.1.1】 mWindowContainerController.stopFreezingScreen(force); } }stopFreezingScreen.java
public void stopFreezingScreen(boolean force) { synchronized(mWindowMap) { if (mContainer == null) { return; } if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Clear freezing of " + mToken + ": hidden=" + mContainer.isHidden() + " freezing=" + mContainer.isFreezingScreen()); mContainer.stopFreezingScreen(true, force); } }WindowManagerService.java
@Override public void stopFreezingScreen() { ... ... synchronized(mWindowMap) { if (mClientFreezingScreen) { mClientFreezingScreen = false; mLastFinishedFreezeSource = "client"; final long origId = Binder.clearCallingIdentity(); try { // 详见 8.1.1.2 stopFreezingDisplayLocked(); } finally { Binder.restoreCallingIdentity(origId); } } } }WindowManagerService.java
该方法主要功能:
解决屏幕旋转相关逻辑;
移除冻屏的超时消息;
屏幕旋转动画的相关操作;
使能输入事件分发功能;display冻结时,执行gc操作;
升级当前的屏幕方向;
向mH发送configuraion改变的消息
rivate void stopFreezingDisplayLocked() { if (!mDisplayFrozen) { return; //显示没有冻结,则直接返回 } //往往跟屏幕旋转相关 ... mDisplayFrozen = false; //从上次冻屏到现在的总时长 mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime); //移除冻屏的超时消息 mH.removeMessages(H.APP_FREEZE_TIMEOUT); mH.removeMessages(H.CLIENT_FREEZE_TIMEOUT); boolean updateRotation = false; //获取默认的DisplayContent final DisplayContent displayContent = getDefaultDisplayContentLocked(); final int displayId = displayContent.getDisplayId(); ScreenRotationAnimation screenRotationAnimation = mAnimator.getScreenRotationAnimationLocked(displayId); //屏幕旋转动画的相关操作 if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null && screenRotationAnimation.hasScreenshot()) { DisplayInfo displayInfo = displayContent.getDisplayInfo(); boolean isDimming = displayContent.isDimming(); if (!mPolicy.validateRotationAnimationLw(mExitAnimId, mEnterAnimId, isDimming)) { mExitAnimId = mEnterAnimId = 0; } //加载动画最大时长为10s if (screenRotationAnimation.dismiss(mFxSession, MAX_ANIMATION_DURATION, getTransitionAnimationScaleLocked(), displayInfo.logicalWidth, displayInfo.logicalHeight, mExitAnimId, mEnterAnimId)) { scheduleAnimationLocked(); } else { screenRotationAnimation.kill(); mAnimator.setScreenRotationAnimationLocked(displayId, null); updateRotation = true; } } else { if (screenRotationAnimation != null) { screenRotationAnimation.kill(); mAnimator.setScreenRotationAnimationLocked(displayId, null); } updateRotation = true; } //经过层层调用到InputManagerService服务,IMS服务使能输入事件分发功能 mInputMonitor.thawInputDispatchingLw(); boolean configChanged; //当display被冻结时不再计算屏幕方向,以避免不连续的状态。 configChanged = updateOrientationFromAppTokensLocked(false); //display冻结时,执行gc操作 mH.removeMessages(H.FORCE_GC); mH.sendEmptyMessageDelayed(H.FORCE_GC, 2000); //mScreenFrozenLock的类型为PowerManager.WakeLock,即释放屏幕冻结的锁 mScreenFrozenLock.release(); if (updateRotation) { //升级当前的屏幕方向 configChanged |= updateRotationUncheckedLocked(false); } if (configChanged) { //向mH发送configuraion改变的消息 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); }}
长按识别二维码,领福利至此,本篇已结束,如有不对的地方,欢迎您的建议与指正。同时期待您的关注,感谢您的阅读,谢谢!

如有侵权,请联络小编,小编对此深感抱歉,届时小编会删除文章,立即中止侵权行为,请您多多包涵。