技术标签: 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);
最后以一个序列图总结下:
第二部分:按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学习了,有时候学习方法真的很重要……
文章浏览阅读471次。replicationset控制器:1、确保pod副本的数量2、支持自定扩容和收缩3、不能支持服务的滚动部署deployment的很好的解决的replicationset 不能灰度发布的问题,支持了滚动部署了解三种部署红绿部署:创建所有服务新的版本后,将流量更换到新的版本上,再将所有旧版本干掉滚动部署:一部分一部分服务的升级,每升级一个服务,将在该旧服务的流量打到新的版本上,并干掉这部分旧服务(逐步替换)灰度部署(金丝雀):一部分一部分服务的升级,每升级一个服务,将在该旧服务的部_deployment 和deployment controller
文章浏览阅读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统计图像高频
文章浏览阅读346次。开发平台* 芯灵思SinlinxA33开发板淘宝店铺: https://sinlinx.taobao.com/嵌入式linux 开发板交流 641395230在嵌入式设备的管理与交互中,基于Web方式的应用成为目前的主流,这种程序结构也就是大家非常熟悉的B/S结构,即在 嵌入式..._cgi path_info boa
文章浏览阅读6.9k次,点赞2次,收藏19次。 AudioES8374驱动模块调试 目录 Audio ES8374. 2 一、Audio ES8374文件建立与编译... 2 二、Audio ES8374原理图... 3 三、Audio ES8374相关配置... 3 四、Audio ES8374 I2C读写... 4..._es8374 调试
文章浏览阅读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编译工具是什么
文章浏览阅读1.8k次。毕业论文插图格式、分辨率选择及高质量Word转PDF方法_什么格式的图像在word转pdf的时候损失小
文章浏览阅读229次。演示如何自定义 Button_xaml语言 botton
文章浏览阅读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
文章浏览阅读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
文章浏览阅读10w+次,点赞170次,收藏698次。利用matlab构建自己的colormap这个博客是自己的第一篇博客,瞎写实验中。。。因为平时绘制多条曲线,多种颜色的散点图以及二维色彩图时,经常受colormap折磨,嫌弃matlab自带的太丑,自己想要的效果没有。所以这篇文章主要从RGB格式和HSV格式两种颜色模式去衡量构造颜色条。1.颜色模式首先说一下RBG格式,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及..._matlab colormap
文章浏览阅读1.7k次。大数据目前比较火爆的任务调度平台DolphinScheduler,一篇详细讲解DolphinScheduler的文档。DolphinScheduler 2.0.5详解涵盖DolphinScheduler介绍、系统架构,dolphinScheduler集群部署和DolphinScheduler的功能应用及DolphinScheduler问题解决方案等。_apache-dolphinscheduler-2.0.5-
文章浏览阅读376次。@2019-04-17【小记】 百度云平台建立MQTT服务器时需要设置权限组,否则连接失败转载于:https://www.cnblogs.com/skullboyer/p/10722169.html_stm32 wifi mqtt 百度云