我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android教程之开机流程全面解析

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android教程之开机流程全面解析

本文详细讲述了Android的开机流程。分享给大家供大家参考,具体如下:

开机过程中无线模块的初始化过程;如果sim卡锁开启,或者pin被锁住的时候,会要求输入pin或者puk,但是这个解锁动作必须在系统初始化完成以后才能进行。(图形系统都还没有初始化怎么输入密码阿?)当系统初始化完成以后会调用 wm.systemReady()来通知大家。这时候该做什么就做什么。

开机过程中无线模块的初始化过程:

rild 调用参考实现 Reference-ril.c (hardware\ril\reference-ril) 中的函数:


const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);
static void *mainLoop(void *param)
ret = at_open(fd, onUnsolicited);
RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);

在 initializeCallback 函数中对猫进行了初始化。


static void initializeCallback(void *param)
{
ATResponse *p_response = NULL;
int err;
setRadioState (RADIO_STATE_OFF);
at_handshake();



at_send_command("ATE0Q0V1", NULL);

at_send_command("ATS0=0", NULL);

at_send_command("AT+CMEE=1", NULL);

err = at_send_command("AT+CREG=2", &p_response);

if (err < 0 || p_response->success == 0) {
at_send_command("AT+CREG=1", NULL);
}
at_response_free(p_response);

at_send_command("AT+CGREG=1", NULL);

at_send_command("AT+CCWA=1", NULL);

at_send_command("AT+CMOD=0", NULL);

at_send_command("AT+CMUT=0", NULL);

at_send_command("AT+CSSN=0,1", NULL);

at_send_command("AT+COLP=0", NULL);

at_send_command("AT+CSCS=\"HEX\"", NULL);

at_send_command("AT+CUSD=1", NULL);

at_send_command("AT+CGEREP=1,0", NULL);

at_send_command("AT+CMGF=0", NULL);
#ifdef USE_TI_COMMANDS
at_send_command("AT%CPI=3", NULL);

at_send_command("AT%CSTAT=1", NULL);
#endif 

if (isRadioOn() > 0) {
setRadioState (RADIO_STATE_SIM_NOT_READY);
}
}

默认状况下假设射频模块是好的,
通过 setRadioState (RADIO_STATE_SIM_NOT_READY) 来触发对无线模块的初始化。

通过 static void onRadioPowerOn() 对无线模块初始化。

首先通过 pollSIMState(NULL); 轮询 sim卡状态 。


static void pollSIMState (void *param)
{
ATResponse *p_response;
int ret;
if (sState != RADIO_STATE_SIM_NOT_READY) {
// no longer valid to poll
return;
}
switch(getSIMStatus()) {
case RIL_SIM_ABSENT:
case RIL_SIM_PIN:
case RIL_SIM_PUK:
case RIL_SIM_NETWORK_PERSONALIZATION:
default:
setRadioState(RADIO_STATE_SIM_LOCKED_OR_ABSENT);
return;
case RIL_SIM_NOT_READY:
RIL_requestTimedCallback (pollSIMState, NULL, &TIMEVAL_SIMPOLL);
return;
case RIL_SIM_READY:
setRadioState(RADIO_STATE_SIM_READY);
return;
}
}

读取sim卡状态的函数是:getSIMStatus()


err = at_send_command_singleline("AT+CPIN?", "+CPIN:", &p_response);

它向猫发送了at命令 AT+CPIN? 来查询无线模块的状态,如果无线模块还没有就绪,那么他隔1秒钟继续调用

sim卡状态轮询函数 pollSIMState,直到获得sim卡状态。

当sim卡状态为就绪,那么通过 setRadioState(RADIO_STATE_SIM_READY) 设置变量 sState 为:

RADIO_STATE_SIM_READY,这时候会调用函数 static void onSIMReady()来进一步初始化无线模块。

发送的at命令有:


at_send_command_singleline("AT+CSMS=1", "+CSMS:", NULL);
at_send_command("AT+CNMI=1,2,2,1,1", NULL);

如果sim卡锁开启,或者pin被锁住的时候,会要求输入pin或者puk,但是这个解锁动作必须在系统初始化完成以后才能进行。(图形系统都还没有初始化怎么输入密码阿?)当系统初始化完成以后会调用 wm.systemReady()来通知大家。这时候该做什么就做什么。

wm.systemReady()的调用会触发解锁界面。具体流程如下:

因为有: WindowManagerService wm = null;
所以 wm.systemReady()
调用的是 WindowManagerService 中的函数:


public void systemReady() {
mPolicy.systemReady();
}

WindowManagerService 中有:
代码如下:final WindowManagerPolicy mPolicy = PolicyManager.makeNewWindowManager();
PolicyManager.makeNewWindowManager 调用的是文件 PolicyManager.java 中的函数:


public static WindowManagerPolicy makeNewWindowManager() {
return sPolicy.makeNewWindowManager();
}

sPolicy.makeNewWindowManager 调用的是文件 Policy.java 中的函数:


public PhoneWindowManager makeNewWindowManager() {
return new PhoneWindowManager();
}

因为 PhoneWindowManager 继承自 WindowManagerPolicy
所以 mPolicy.systemReady() 最终调用的是文件 PhoneWindowManager.java 中的函数:


public void systemReady()
mKeyguardMediator.onSystemReady();
doKeyguard();
showLocked();
Message msg = mHandler.obtainMessage(SHOW);
mHandler.sendMessage(msg);

发送 SHOW 的消息。

文件 KeyguardViewMediator.java 中的消息处理函数:

public void handleMessage(Message msg) 对 SHOW 消息进行了处理。
如果 msg.what 等于 SHOW 那么执行:


handleShow();
private void handleShow()
...
mCallback.onKeyguardShow();
mKeyguardViewManager.show();
mShowing = true;

mKeyguardViewManager.show() 调用的是文件 KeyguardViewManager.java 中的函数:


public synchronized void show()
...
mKeyguardView = mKeyguardViewProperties.createKeyguardView(mContext, mUpdateMonitor, this);
...

mKeyguardViewProperties.createKeyguardView 调用的是文件 LockPatternKeyguardViewProperties.java中的函数:


public KeyguardViewBase createKeyguardView(Context context,
KeyguardUpdateMonitor updateMonitor,
KeyguardWindowController controller) {
return new LockPatternKeyguardView(context, updateMonitor,
mLockPatternUtils, controller);
}

new LockPatternKeyguardView 调用了类 LockPatternKeyguardView 的构造函数:


public LockPatternKeyguardView(
Context context,
KeyguardUpdateMonitor updateMonitor,
LockPatternUtils lockPatternUtils,
KeyguardWindowController controller)
...
mLockScreen = createLockScreen();
addView(mLockScreen);
final UnlockMode unlockMode = getUnlockMode();
mUnlockScreen = createUnlockScreenFor(unlockMode);
mUnlockScreenMode = unlockMode;
addView(mUnlockScreen);
updateScreen(mMode);

执行上面的程序然后弹出解锁界面,getUnlockMode 获得锁类型,通常有三种:


enum UnlockMode {
Pattern, //图案锁
SimPin, //输入pin或者puk
Account //账号锁
}

通过上面的过程我们可以知道,在系统初始化阶段启动rild的时候,rild与猫进行了通信,并对猫进行初始化。保存了网络的一系列状态。

待机状态下,飞行模式切换流程分析:

飞行模式切换比较复杂,它状态改变时涉及到极大模块状态切换:

GSM模块,蓝牙模块,wifi模块。

飞行模式的enabler层会发送广播消息:ACTION_AIRPLANE_MODE_CHANGED


private void setAirplaneModeOn(boolean enabling) {
mCheckBoxPref.setEnabled(false);
mCheckBoxPref.setSummary(enabling ? R.string.airplane_mode_turning_on
: R.string.airplane_mode_turning_off);
// Change the system setting
Settings.System.putInt(mContext.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
enabling ? 1 : 0);
// Post the intent
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", enabling);
mContext.sendBroadcast(intent);
}

因为GSM ,蓝牙,wifi模块分别注册了对 ACTION_AIRPLANE_MODE_CHANGED 消息的监测,所以收到该消息后,模块会进行切换。

BluetoothDeviceService.java

开启蓝牙:enable(false);
关闭蓝牙:disable(false);
PhoneApp.java (packages\apps\phone\class="lazy" data-src\com\android\phone)
设置GSM模块状态 phone.setRadioPower(enabled);
WifiService.java
设置 wifi 状态 setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());

GSM模块切换过程分析:

phone.setRadioPower(enabled)调用的是:

文件 GSMPhone.java 中的的函数:


public void setRadioPower(boolean power)
mSST.setRadioPower(power);

因为有 ServiceStateTracker mSST;

mSST.setRadioPower 调用的是文件 ServiceStateTracker.java 中的函数:


public void setRadioPower(boolean power)
mDesiredPowerState = power;
setPowerStateToDesired();
cm.setRadioPower(true, null);

或者


cm.setRadioPower(false, null);

因为有:


CommandsInterface cm;
public final class RIL extends BaseCommands implements CommandsInterface

所以 cm.setRadioPower 调用的是文件 RIL.java 中的函数:


public void setRadioPower(boolean on, Message result)
RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result);
rr.mp.writeInt(1);
...
send(rr)

通过 send 向 rild 发送 RIL_REQUEST_RADIO_POWER 请求来开启或者关闭GSM模块。

rild 数据接收流程:

收到 RIL_REQUEST_RADIO_POWER 执行:


requestRadioPower(data, datalen, t);

然后根据条件往无线模块发送模块开启和关闭请求

主要的at命令有:


err = at_send_command("AT+CFUN=0", &p_response);
err = at_send_command("AT+CFUN=1", &p_response);

蓝牙模块切换过程分析:


enable(false);

蓝牙开启调用文件 BluetoothDeviceService.java 中的函数:


public synchronized boolean enable(boolean saveSetting)
setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON);
mEnableThread = new EnableThread(saveSetting);
mEnableThread.start();
----
disable(false)

蓝牙关闭调用文件 中的函数:


public synchronized boolean disable(boolean saveSetting)
setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF);

wifi模块切换过程分析:

广播 wifi 状态改变的消息:WIFI_STATE_CHANGED_ACTION
代码如下:setWifiEnabledState(enable ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING, uid);
更新 wifi 状态:


private void updateWifiState()

如果需要使能开启 wifi 那么会发送:


sendEnableMessage(true, false, mLastEnableUid);
sendStartMessage(strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY);
mWifiHandler.sendEmptyMessage(MESSAGE_STOP_WIFI);

消息循环中处理命令消息:


public void handleMessage(Message msg)

如果使能wifi:setWifiEnabledBlocking(true, msg.arg1 == 1, msg.arg2);

开启wifi:


mWifiStateTracker.setScanOnlyMode(msg.arg1 != 0);
setWifiEnabledBlocking(false, msg.arg1 == 1, msg.arg2);

断开


mWifiStateTracker.disconnectAndStop();

开启过程步骤:

1> 装载 wifi 驱动: WifiNative.loadDriver()
2> 启动后退 daemo supplicant: WifiNative.startSupplicant()
关闭过程步骤:
1> 停止后退 daemo supplicant:WifiNative.stopSupplicant()
2> 卸载 wifi 驱动: WifiNative.unloadDriver()

如果 wifi 状态默认为开启那么 WifiService 服务的构造函数:


WifiService(Context context, WifiStateTracker tracker)
boolean wifiEnabled = getPersistedWifiEnabled();
setWifiEnabledBlocking(wifiEnabled, false, Process.myUid());

会开启wifi模块。

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android数据库操作技巧总结》、《Android编程之activity操作技巧总结》、《Android文件操作技巧汇总》、《Android编程开发之SD卡操作方法汇总》、《Android开发入门与进阶教程》、《Android资源操作技巧汇总》、《Android视图View技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。

您可能感兴趣的文章:Android APP启动方式、启动流程及启动优化分析分析Android中应用的启动流程从源码分析Android的Glide库的图片加载流程及特点Android系统关机的全流程解析Android Bluetooth蓝牙技术使用流程详解Android Mms之:短信发送流程(图文详解)Android Mms之:接收信息流程(图文详解)Android中打电话的数据流程分析Android 2.3 拨号上网流程从源码角度进行分析Android编程输入事件流程详解


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android教程之开机流程全面解析

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android教程之开机流程全面解析

本文详细讲述了Android的开机流程。分享给大家供大家参考,具体如下: 开机过程中无线模块的初始化过程;如果sim卡锁开启,或者pin被锁住的时候,会要求输入pin或者puk,但是这个解锁动作必须在系统初始化完成以后才能进行。(图形系统都
2022-06-06

Android View 测量流程(Measure)全面解析

前言 上一篇文章,笔者主要讲述了DecorView以及ViewRootImpl相关的作用,这里回顾一下上一章所说的内容:DecorView是视图的顶级View,我们添加的布局文件是它的一个子布局,而ViewRootImpl则负责渲染视图,它
2022-06-06

Android View 绘制流程(Draw)全面解析

前言 前几篇文章,笔者分别讲述了DecorView,measure,layout流程等,接下来将详细分析三大工作流程的最后一个流程——绘制流程。测量流程决定了View的大小,布局流程决定了View的位置,那么绘制流程将决定View的样子,一
2022-06-06

Android View 布局流程(Layout)全面解析

前言 上一篇文章,笔者详细讲述了View三大工作流程的第一个,Measure流程,如果对测量流程还不熟悉的读者可以参考一下上一篇文章。测量流程主要是对View树进行测量,获取每一个View的测量宽高,那么有了测量宽高,就是要进行布局流程了,
2022-06-06

Android系统关机的全流程解析

在PowerManager的API文档中,给出了一个关机/重启接口: public void reboot (String reason) 对于这个接口的描述很简单,就是几句话。 接口的作用就是重启设备,而且,就算重启成功了也没有返回值。
2022-06-06

android开发教程之子线程中更新界面

每个Handler对象与创建它的线程相关联,并且每个Handler对象只能与一个线程相关联。Handler一般有两种用途:1)执行计划任务,你可以再预定的实现执行某些任务,可以模拟定时器。2)线程间通信。在Android的应用启动时,会创建
2022-06-06

android基础教程之开机启动示例

Manifest.xml文件: 代码如下:
2022-06-06

21天学习android开发教程之XML解析与生成

本文使用SAX来解析XML,在Android里面可以使用SAX和DOM,DOM需要把整个XML文件读入内存再解析,比较消耗内存,而SAX基于事件驱动的处理方式,可以在各节点触发回调函数,不过SAX适合节点结构简单的XML文档,复杂的XML文
2022-06-06

android开发教程之开机启动服务service示例

个例子实现的功能是:1,安装程序后看的一个Activity程序界面,里面有个按钮,点击按钮就会启动一个Service服务,此时在设置程序管理里面会看的有个Activity和一个Service服务运行2,如果手机关机重启,会触发你的程序里面的
2022-06-06

Android开发教程之电源管理详解

本文实例讲述了Android电源管理。分享给大家供大家参考,具体如下: 一、 相关概念 1. 出于节电的需要,一般应用在用户一段时间无操作的情况下屏幕变暗,然后进入休眠状态 2. 用户只能在”设置->声音和显示”中设置所有应用默认的屏幕亮度
2022-06-06

从环境配置到项目部署:全面解析Golang开发流程

Golang开发步骤详解:从环境搭建到项目部署,需要具体代码示例在当前的软件开发领域,Golang已经成为了备受关注的一门编程语言。其简洁的语法、高效的性能以及强大的并发特性,使得Golang成为了很多开发者的首选之一。本文将从环境搭建开
从环境配置到项目部署:全面解析Golang开发流程
2024-01-23

Android系统的开机画面显示过程分析

函数fb_find_logo实现在文件kernel/goldfish/drivers/video/logo/logo.c文件中,如下所示:extern const struct linux_logo logo_linux_mono;  ex
2023-01-31

android教程之textview解析带图片的html示例

代码如下:public class MainActivity extends Activity { private Handler handler; private String html; private TextView tv; pr
2022-06-06

阿里云ECS端口打开工具全面解析和使用教程

阿里云ECS端口打开工具是一款可以帮助用户轻松管理阿里云ECS实例的端口的工具。这款工具可以帮助用户实现对ECS实例的端口进行快速的配置和管理,从而提高工作效率。本文将详细介绍这款工具的功能、使用方法和注意事项。正文:一、阿里云ECS端口打开工具的功能阿里云ECS端口打开工具是一款可以帮助用户实现对ECS实例的端
阿里云ECS端口打开工具全面解析和使用教程
2023-12-14

Java基础夯实之线程问题全面解析

操作系统支持多个应用程序并发执行,每个应用程序至少对应一个进程 。进程是资源分配的最小单位,而线程是CPU调度的最小单位。本文将带大家全面解析线程相关问题,感兴趣的可以了解一下
2022-11-13

android开发教程之自定义属性用法详解

最近项目中经常需要用到自定义控件,因此自定义属性也是经常要用到的,在此说明一下自定义属性的用法: 自定义属性都存在于/value/attr.xml文件中,以如下格式存在。 代码如下:
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录