android流程分析,android - home键及launcher起动流程分析-程序员宅基地

技术标签: android流程分析  

android - home键及launcher启动流程分析

android - home键及launcher启动流程分析

launcher,也就是android的桌面应用程序,开机启动的第一个应用程序及按home键进入的都是这个程序。

如果需要修改启动流程或者制作一个新的launcher,都有必要了解一下这个流程。

第一部分:系统默认Home应用程序(launcher)启动流程

1、frameworks/base/services/java/com/android/server/SystemServer.java

一直以来大家都记得"hello world"程序就是写一个main函数,那么我们这里也从main函数开始:

public static void main(String[] args)

这里分为两个过程:

SystemServer.init1

启动几个重要navtive service,比如 SurfaceFlinger、SensorService

SystemServer.init2

启动java service,比如 ContentService、PowerManagerService、MountService、WindowManagerService 等等

2、frameworks/base/services/java/com/android/server/am/ActivityManagerServcie.java

启动 ActivityManagerService跳到如下:

Slog.i(TAG, "Activity Manager");

context = ActivityManagerService.main(factoryTest);

public static final Context main(int factoryTest) {

AThread thr = new AThread();

thr.start();

synchronized (thr) {

while (thr.mService == null) {

try {

thr.wait();

} catch (InterruptedException e) {

}

}

}

ActivityManagerService m = thr.mService;

mSelf = m;

ActivityThread at = ActivityThread.systemMain();

mSystemThread = at;

Context context = at.getSystemContext();

context.setTheme(android.R.style.Theme_Holo);

m.mContext = context;

m.mFactoryTest = factoryTest;

m.mMainStack = new ActivityStack(m, context, true);

m.mBatteryStatsService.publish(context);

m.mUsageStatsService.publish(context);

synchronized (thr) {

thr.mReady = true;

thr.notifyAll();

}

m.startRunning(null, null, null, null);

return context;

}

这个函数首先通过AThread线程对象来内部创建了一个ActivityManagerService实例,然后将这个实例保存其成员变量

mService中,接着又把这个ActivityManagerService实例保存在ActivityManagerService类的静态成员变量mSelf中,

最后初始化其它成员变量,就结束了。

AThread 线程启动代码如下:

AThread thr = new AThread();

thr.start();

static class AThread extends Thread {

ActivityManagerService mService;

boolean mReady = false;

public AThread() {

super("ActivityManager");

}

public void run() {

Looper.prepare();

android.os.Process.setThreadPriority(

android.os.Process.THREAD_PRIORITY_FOREGROUND);

android.os.Process.setCanSelfBackground(false);

ActivityManagerService m = new ActivityManagerService();

synchronized (this) {

mService = m;

notifyAll();

}

synchronized (this) {

while (!mReady) {

try {

wait();

} catch (InterruptedException e) {

}

}

}

...

}

3、ActivityManagerService.systemReady

ServerThread.run函数在将系统中的一系列服务都初始化完毕之后才调用

SystemService.java:

// We now tell the activity manager it is okay to run third party

// code. It will call back into us once it has gotten to the state

// where third party code can really run (but before it has actually

// started launching the initial applications), for us to complete our

// initialization.

ActivityManagerService.self().systemReady(new Runnable() {

public void run() {

Slog.i(TAG, "Making services ready");

核心代码如下:

public final class ActivityManagerService extends ActivityManagerNative

implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {

......

public void systemReady(final Runnable goingCallback) {

......

synchronized (this) {

......

mMainStack.resumeTopActivityLocked(null);

}

}

......

}

4、ActivityStack.resumeTopActivityLocked

final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {

// Find the first activity that is not finishing.

ActivityRecord next = topRunningActivityLocked(null);

// Remember how we'll process this pause/resume situation, and ensure

// that the state is reset however we wind up proceeding.

final boolean userLeaving = mUserLeaving;

mUserLeaving = false;

if (next == null) {

// There are no more activities! Let's just start up the

// Launcher...

if (mMainStack) {

ActivityOptions.abort(options);

return mService.startHomeActivityLocked(mCurrentUser);

}

}

...

}

这里调用函数topRunningActivityLocked返回的是当前系统Activity堆栈最顶端的Activity,由于此时还没有

Activity被启动过,因此,返回值为null,即next变量的值为null,于是就调用mService.startHomeActivityLocked函数

5、startHomeActivityLocked

boolean startHomeActivityLocked(int userId) {

...

Intent intent = new Intent(

mTopAction,

mTopData != null ? Uri.parse(mTopData) : null);

intent.setComponent(mTopComponent);

if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) {

intent.addCategory(Intent.CATEGORY_HOME);

}

ActivityInfo aInfo =

resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);

if (aInfo != null) {

intent.setComponent(new ComponentName(

aInfo.applicationInfo.packageName, aInfo.name));

// Don't do this if the home app is currently being

// instrumented.

aInfo = new ActivityInfo(aInfo);

aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);

ProcessRecord app = getProcessRecordLocked(aInfo.processName,

aInfo.applicationInfo.uid);

if (app == null || app.instrumentationClass == null) {

intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);

mMainStack.startActivityLocked(null, intent, null, aInfo,

null, null, 0, 0, 0, 0, null, false, null);

}

}

return true;

}

函数首先创建一个CATEGORY_HOME类型的Intent,然后通过Intent.resolveActivityInfo函数向PackageManagerService

查询Category类型为HOME的Activity,即 packages/apps/Launcher2/AndroidManifest.xml文件中所示:

这里就是将拼装好的 home intent 发送出去即可

android:name="com.android.launcher2.Launcher"

android:launchMode="singleTask"

android:clearTaskOnLaunch="true"

android:stateNotNeeded="true"

android:theme="@style/Theme"

android:screenOrientation="nosensor"

android:windowSoftInputMode="stateUnspecified|adjustPan">

6、ResolverActivity.java

frameworks\base\core\java\com\android\internal\app\ResolverActivity.java

/**

* This activity is displayed when the system attempts to start an Intent for

* which there is more than one matching activity, allowing the user to decide

* which to go to. It is not normally used directly by application developers.

*/

public class ResolverActivity extends AlertActivity implements AdapterView.OnItemClickListener {

这是应用程序就是查找匹配的intent-filter应用程序,多于一个时则列表提示用户选择,默认或者只有一个则直接进入。

mCurrentResolveList = mPm.queryIntentActivities(

mIntent, PackageManager.MATCH_DEFAULT_ONLY);

最后以一个序列图总结下:

134739233.jpg

第二部分:按home键启动Home应用

既然是按键,这里就简要说明一下按键事件处理流程:

1、InputManager负责读取事件并把事件送到frameworks的java层

2、WindowManagerService里会有一个InputMonitor类来监听事件变化并做相应的分发处理。

3、在WindowManagerService会有一个WindowManagerPolicy来做消息拦截处理。

4、WindowManagerService会把消息发给最上面运行的窗口接收

5、这里最上面窗口就是 PhoneWindowManager

/**

* WindowManagerPolicy implementation for the Android phone UI. This

* introduces a new method suffix, Lp, for an internal lock of the

* PhoneWindowManager. This is used to protect some internal state, and

* can be acquired with either thw Lw and Li lock held, so has the restrictions

* of both of those when held.

*/

public class PhoneWindowManager implements WindowManagerPolicy

PhoneWindowManager 实现 Android UI

interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags)

这个方法就是预先处理按键消息的,即由系统处理,一般 HOME、MUTE、POWER等都是由系统先处理

/** {@inheritDoc} */

@Override

public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {

...

// First we always handle the home key here, so applications

// can never break it, although if keyguard is on, we do let

// it handle it, because that gives us the correct 5 second

// timeout.

if (keyCode == KeyEvent.KEYCODE_HOME) {

...

//单击home处理

launchHomeFromHotKey();

}

...

}

下面就是处理home键的功能

/**

* A home key -> launch home action was detected. Take the appropriate action

* given the situation with the keyguard.

*/

void launchHomeFromHotKey() {

if (mKeyguardMediator != null && mKeyguardMediator.isShowingAndNotHidden()) {

// don't launch home if keyguard showing

} else if (!mHideLockScreen && mKeyguardMediator.isInputRestricted()) {

// when in keyguard restricted mode, must first verify unlock

// before launching home

mKeyguardMediator.verifyUnlock(new OnKeyguardExitResult() {

public void onKeyguardExitResult(boolean success) {

if (success) {

try {

ActivityManagerNative.getDefault().stopAppSwitches();

} catch (RemoteException e) {

}

sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);

startDockOrHome();

}

}

});

} else {

// no keyguard stuff to worry about, just launch home!

try {

ActivityManagerNative.getDefault().stopAppSwitches();

} catch (RemoteException e) {

}

sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);

startDockOrHome();

}

}

发送home intent出去:

void startDockOrHome() {

// We don't have dock home anymore. Home is home. If you lived here, you'd be home by now.

mContext.startActivityAsUser(mHomeIntent, UserHandle.CURRENT);

}

其中 mHomeIntent 是由init()函数初始化完成的

mHomeIntent = new Intent(Intent.ACTION_MAIN, null);

mHomeIntent.addCategory(Intent.CATEGORY_HOME);

mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK

| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

最后也是由 ResolverActivity 继续处理,上面已经讲过了,这里就略写了。

1楼supersugar3126昨天 16:57学习了,有时候学习方法真的很重要……

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_35853499/article/details/117550201

智能推荐

k8s(2)控制器deployment介绍_deployment 和deployment controller-程序员宅基地

文章浏览阅读471次。replicationset控制器:1、确保pod副本的数量2、支持自定扩容和收缩3、不能支持服务的滚动部署deployment的很好的解决的replicationset 不能灰度发布的问题,支持了滚动部署了解三种部署红绿部署:创建所有服务新的版本后,将流量更换到新的版本上,再将所有旧版本干掉滚动部署:一部分一部分服务的升级,每升级一个服务,将在该旧服务的流量打到新的版本上,并干掉这部分旧服务(逐步替换)灰度部署(金丝雀):一部分一部分服务的升级,每升级一个服务,将在该旧服务的部_deployment 和deployment controller

opencv 利用傅里叶变换获取低频和高频部分图像-07_opencv统计图像高频-程序员宅基地

文章浏览阅读6.4k次,点赞9次,收藏58次。1. 效果2. 代码# -*- coding: utf-8 -*-import cv2import cv2 as cvimport numpy as npfrom matplotlib import pyplot as pltdef filter_high_f(fshift, radius_ratio): """ 过滤掉除了中心区域外的高频信息 """ # 1, 生成圆形过滤器, 圆内值1, 其他部分为0的过滤器, 过滤 template _opencv统计图像高频

芯灵思Sinlinx A33开发板boa与CGI移植-程序员宅基地

文章浏览阅读346次。开发平台* 芯灵思SinlinxA33开发板淘宝店铺: https://sinlinx.taobao.com/嵌入式linux 开发板交流 641395230在嵌入式设备的管理与交互中,基于Web方式的应用成为目前的主流,这种程序结构也就是大家非常熟悉的B/S结构,即在 嵌入式..._cgi path_info boa

AudioES8374音频驱动调试_es8374 调试-程序员宅基地

文章浏览阅读6.9k次,点赞2次,收藏19次。 AudioES8374驱动模块调试 目录 Audio ES8374. 2 一、Audio ES8374文件建立与编译... 2 二、Audio ES8374原理图... 3 三、Audio ES8374相关配置... 3 四、Audio ES8374 I2C读写... 4..._es8374 调试

利用Vitis开发基于ZCU106的神经网络加速器(二)——DPU编译及Demo_dpu kernel编译工具是什么-程序员宅基地

文章浏览阅读4.4k次,点赞2次,收藏26次。前言上一篇文章讲到了如何生成可供Vitis使用的XRT platform。这次我们使用生成的platform来开发一个完整的加速器Demo并在ZCU06上跑通。DPU概述DPU是Vitis AI中官方提供的FPGA神经网络加速器,其架构如下图:DP(Deep Learning Processor Unit)是专用于卷积神经网络的可配置计算引擎。 引擎中使用的并行度是设计参数和应用程序。 它包含一组高度优化的指令,并支持大多数卷积神经网络,例如VGG,ResNet,GoogleNet,YOLO,SS_dpu kernel编译工具是什么

毕业论文图片格式、分辨率选择及高质量Word转PDF方法_什么格式的图像在word转pdf的时候损失小-程序员宅基地

文章浏览阅读1.8k次。毕业论文插图格式、分辨率选择及高质量Word转PDF方法_什么格式的图像在word转pdf的时候损失小

随便推点

了解 Xamarin.Forms 创建移动应用程序的基础知识 4 - Button_xaml语言 botton-程序员宅基地

文章浏览阅读229次。演示如何自定义 Button_xaml语言 botton

stm32资料库 6_stm ibis-程序员宅基地

文章浏览阅读1.1k次。PC端软件 1.DfuSe DfuSe——USB设备固件升级 ST扩展:包含PC端演示程序、调试演示程序和所有协议层源程序 2009年7月 DfuSe DfuSe——USB设备固件升级 ST扩展 程序包DfuSe DfuSe——USB设备固件升级 ST扩展 英文文档2.Flash loader demonstrator STM32F101xx和STM32F103xx闪存加载演示程序:包含PC端演示程序、命令行演示程序和头文件源码 20_stm ibis

GeoServer速成:安装启动,发布地图,加载QGIS_qgis geoserver-程序员宅基地

文章浏览阅读1.6k次,点赞2次,收藏11次。本节主题:Geoserver下载配置启动,发布地图,发布服务用QGIS查看。预计时间15分钟。练习数据位置:https://download.csdn.net/download/sinat_41310868/19362372视频教程见:https://www.bilibili.com/video/BV1Sg41137EZ/如果CSDN图片不清楚,请移步知乎:https://zhuanlan.zhihu.com/p/377826133一、下载配置启动访问http://geoserver_qgis geoserver

利用matlab构建自己的colormap(色彩搭配)_matlab colormap-程序员宅基地

文章浏览阅读10w+次,点赞170次,收藏698次。利用matlab构建自己的colormap这个博客是自己的第一篇博客,瞎写实验中。。。因为平时绘制多条曲线,多种颜色的散点图以及二维色彩图时,经常受colormap折磨,嫌弃matlab自带的太丑,自己想要的效果没有。所以这篇文章主要从RGB格式和HSV格式两种颜色模式去衡量构造颜色条。1.颜色模式首先说一下RBG格式,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及..._matlab colormap

DolphinScheduler 2.0.5详解_apache-dolphinscheduler-2.0.5--程序员宅基地

文章浏览阅读1.7k次。大数据目前比较火爆的任务调度平台DolphinScheduler,一篇详细讲解DolphinScheduler的文档。DolphinScheduler 2.0.5详解涵盖DolphinScheduler介绍、系统架构,dolphinScheduler集群部署和DolphinScheduler的功能应用及DolphinScheduler问题解决方案等。_apache-dolphinscheduler-2.0.5-

学习STM32F769DK-OTA例程之百度云平台建立MQTT服务器-程序员宅基地

文章浏览阅读376次。@2019-04-17【小记】  百度云平台建立MQTT服务器时需要设置权限组,否则连接失败转载于:https://www.cnblogs.com/skullboyer/p/10722169.html_stm32 wifi mqtt 百度云

推荐文章

热门文章

相关标签