一、
在Android系统中,打开飞行模式会将Radio关闭
ps:什么是 Radio?Radio 是无线通信模块的驱动程序,负责网络通信。
二、
但是在一些特殊情况下,Android系统会在飞行模式下将Radio给打开:
1.用户主动操作:
● 当用户手动关闭飞行模式时,系统会重新请求 Modem 上线以便恢复网络连接,包括但不限于移动数据、电话和短信功能
2.系统内部需求:
● 在飞行模式开启状态下,如果有应用程序或系统服务尝试访问网络功能,例如 GPS 定位可能需要辅助数据网络以更快定位,这时系统可能会暂时解除飞行模式以激活 Modem,待获取必要的数据后再重新启用飞行模式
3.特殊功能触发:
● 某些特定条件下,如紧急呼叫功能(如在美国,即使在飞行模式下仍可以拨打 911 等紧急电话),
此时系统会临时请求 Modem 上线以建立紧急呼叫连接
4.系统更新或配置变更:
● 当系统进行软件更新或配置调整时,有可能需要短暂地启用 Modem 以检查更新或同步配置信息
5.自动化规则或情景模式:
● 设备设置了自动化规则(如 Do Not Disturb 模式结束时)或情景模式转换时,如果这些规则或模式设定要求网络连接恢复,那么在飞行模式下也可能触发 Modem online 请求
请注意,具体何时会将radio打开, 取决于操作系统版本、设备制造商定制以及用户设置等多种因素。在飞行模式下,默认情况下所有无线连接都会被禁用,但出于上述或其他特殊情况,系统或应用可能会临时打破这种禁用状态
三、
这是一份log,记录了Android设备打开飞行模式时Radio被打开的情况
// isAirplaneModeOn()=true,证明飞行模式还是打开状态的
04-09 08:55:57.335 D/BluetoothManagerService( 1899): Airplane Mode change - current state: OFF, isAirplaneModeOn()=true
04-09 08:55:57.335 D/BluetoothManagerService( 1899): Airplane ON: sendDisableMsg
// 在飞行模式的情况下,无线电开关被打开了
04-09 08:55:57.997 D/SST ( 2916): [0] setRadioPower power true forEmergencyCall false forceApply false reason 0
04-09 08:55:58.006 D/RILJ ( 2916): [0239]> RADIO_POWER on = true forEmergencyCall= false preferredForEmergencyCall=false [PHONE0]
04-09 08:55:58.008 D/SST ( 2916): [1] setRadioPower power true forEmergencyCall false forceApply false reason 0
04-09 08:55:58.013 D/RILJ ( 2916): [0240]> RADIO_POWER on = true forEmergencyCall= false preferredForEmergencyCall=false [PHONE1]
// 异常的地方: radioState 变成 1 了
04-09 08:55:58.812 D/SST ( 2916): [0] pollState: modemTriggered=true, radioState=1
从这些 log 中已经可以看出, AP 侧确实发起了 online 的请求,但是很奇怪的一点在于,模块此时
还是处于飞行模式的,为何无线电开关会被打开和下发 online 请求呢?继续跟踪 log
04-09 08:55:57.964 I/PhoneGlobals( 2916): Turning radio on – airplane
04-09 08:55:57.998 D/SST ( 2916): [0] setPowerStateToDesired:mDeviceShuttingDown=false, mDesiredPowerState=true, getRadioState=0, mRadioDisabledByCarrier=false, IMS reg state=false, pending radio off=false
04-09 08:55:58.322 D/GsmCdmaPhone( 2916): handleRadioPowerStateChange, state= 1
04-09 08:55:58.326 I/telephony-utils( 2737): QtiPrimaryImeiHandler : handleRadioPowerStateChanged, state[0]=1
04-09 08:55:58.326 D/QtiUiccSwitcher( 2737): handleRadioPowerStateChanged, state[0]=1
04-09 08:55:58.247 D/RILJ ( 2916): [UNSL]< UNSOL_RESPONSE_RADIO_STATE_CHANGED radioStateChanged: 1 [PHONE1]
04-09 08:55:58.324 D/SST ( 2916): [0] setPowerStateToDesired: mDeviceShuttingDown=false, mDesiredPowerState=true, getRadioState=1, mRadioDisabledByCarrier=false, IMS reg state=false, pending radio off=false
04-09 08:55:58.371 D/CiWlanNotificationReceiver( 2916): ACTION_RADIO_POWER_STATE_CHANGED
04-09 08:55:59.022 D/EmergencyNumberTracker( 2916): ACTION_NETWORK_COUNTRY_CHANGED: PhoneId: 0 CountryIso: cn
四、
从log里面看出了蹊跷,下一步就可以根据关键字在源代码中进行搜索,定位到具体的执行代码,然后分析里面的逻辑
QSSI.13/packages/services/Telephony/src/com/android/phone/PhoneGlobals.java
/**
* Receiver for misc intent broadcasts the Phone app cares about.
*/
private class PhoneAppBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
boolean airplaneMode = intent.getBooleanExtra("state", false);
handleAirplaneModeChange(airplaneMode);
-----------------------------------------------
-----------------------------------------------
-----------------------------------------------
}
五、
最后采用这个方案临时关闭Radio
diff --git a/QSSI.13/packages/services/Telephony/src/com/android/phone/PhoneGlobals.java b/QSSI.13/packages/services/Telephony/src/com/android/phone/PhoneGlobals.java
index ca4a3aa..bbdbb2e 100644
--- a/QSSI.13/packages/services/Telephony/src/com/android/phone/PhoneGlobals.java
+++ b/QSSI.13/packages/services/Telephony/src/com/android/phone/PhoneGlobals.java
@@ -804,7 +804,8 @@ public class PhoneGlobals extends ContextWrapper {
maybeTurnCellOff(isAirplaneNewlyOn);
break;
case PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG:
- maybeTurnCellOn(isAirplaneNewlyOn);
+ //maybeTurnCellOn(isAirplaneNewlyOn);
+ maybeTurnCellOff(isAirplaneNewlyOn);
break;
}
for (Phone phone : PhoneFactory.getPhones()) {
@@ -835,6 +836,7 @@ public class PhoneGlobals extends ContextWrapper {
}
private void setRadioPowerOn() {
Log.i(LOG_TAG, "Turning radio on - airplane");
Settings.Global.putInt(
getContentResolver(), Settings.Global.CELL_ON, PhoneConstants.CELL_ON_FLAG);
@@ -880,6 +882,7 @@ public class PhoneGlobals extends ContextWrapper {
String action = intent.getAction();
if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
boolean airplaneMode = intent.getBooleanExtra("state", false);
handleAirplaneModeChange(airplaneMode);
} else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
// re-register as it may be a new IccCard