该文档来自根据源码的推论,并没有实际的Log佐证。
1 入口
用户可选择的界面最终会使用如下配置开关:
/packages/apps/Settings/src/com/android/settings/network/telephony/EnabledNetworkModePreferenceController.java
@Override
public boolean onPreferenceChange(Preference preference, Object object) {
final int newPreferredNetworkMode = Integer.parseInt((String) object);
final ListPreference listPreference = (ListPreference) preference;
if (mTelephonyManager.setPreferredNetworkTypeBitmask(
MobileNetworkUtils.getRafFromNetworkType(newPreferredNetworkMode))) {
mBuilder.setPreferenceValueAndSummary(newPreferredNetworkMode);
listPreference.setValue(Integer.toString(mBuilder.getSelectedEntryValue()));
listPreference.setSummary(mBuilder.getSummary());
return true;
}
return false;
}
2 Framework流程
/frameworks/base/telephony/java/android/telephony/TelephonyManager.java
/**
* Set the preferred network type bitmask but if {@link #setAllowedNetworkTypes} has been set,
* only the allowed network type will set to the modem.
*
* If this object has been created with {@link #createForSubscriptionId}, applies to the
* given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()}
*
*
Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the calling
* app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
* If {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported}
* ({@link TelephonyManager#CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK}) returns true, then
* setAllowedNetworkTypesBitmap is used on the radio interface. Otherwise,
* setPreferredNetworkTypesBitmap is used instead.
*
* @param networkTypeBitmask The bitmask of preferred network types.
* @return true on success; false on any failure.
* @hide
* @deprecated Use {@link #setAllowedNetworkTypesForReason} instead.
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
@SystemApi
public boolean setPreferredNetworkTypeBitmask(@NetworkTypeBitMask long networkTypeBitmask) {
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
return telephony.setAllowedNetworkTypesForReason(getSubId(),
TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, networkTypeBitmask);
}
} catch (RemoteException ex) {
Rlog.e(TAG, "setPreferredNetworkTypeBitmask RemoteException", ex);
}
return false;
}
/packages/services/Telephony/src/com/android/phone/PhoneInterfaceManager.java
/**
* Set the allowed network types of the device and
* provide the reason triggering the allowed network change.
*
* @param subId the id of the subscription.
* @param reason the reason the allowed network type change is taking place
* @param allowedNetworkTypes the allowed network types.
* @return true on success; false on any failure.
*/
@Override
public boolean setAllowedNetworkTypesForReason(int subId,
@TelephonyManager.AllowedNetworkTypesReason int reason,
@TelephonyManager.NetworkTypeBitMask long allowedNetworkTypes) {
TelephonyPermissions.enforceCallingOrSelfModifyPermissionOrCarrierPrivilege(
mApp, subId, "setAllowedNetworkTypesForReason");
if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
loge("setAllowedNetworkTypesForReason: Invalid allowed network type reason: " + reason);
return false;
}
if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
loge("setAllowedNetworkTypesForReason: Invalid subscriptionId:" + subId);
return false;
}
log("setAllowedNetworkTypesForReason: " + reason + " value: "
+ TelephonyManager.convertNetworkTypeBitmaskToString(allowedNetworkTypes));
if (allowedNetworkTypes == getPhoneFromSubId(subId).getAllowedNetworkTypes(reason)) {
log("setAllowedNetworkTypesForReason: " + reason + "does not change value");
return true;
}
final long identity = Binder.clearCallingIdentity();
try {
Boolean success = (Boolean) sendRequest(
CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON,
new Pair(reason, allowedNetworkTypes), subId);
if (DBG) log("setAllowedNetworkTypesForReason: " + (success ? "ok" : "fail"));
return success;
} finally {
Binder.restoreCallingIdentity(identity);
}
}
case CMD_SET_ALLOWED_NETWORK_TYPES_FOR_REASON:
request = (MainThreadRequest) msg.obj;
onCompleted = obtainMessage(EVENT_SET_ALLOWED_NETWORK_TYPES_FOR_REASON_DONE,
request);
Pair reasonWithNetworkTypes =
(Pair) request.argument;
getPhoneFromRequest(request).setAllowedNetworkTypes(
reasonWithNetworkTypes.first,
reasonWithNetworkTypes.second,
onCompleted);
break;
/frameworks/opt/telephony/src/java/com/android/internal/telephony/Phone.java
/**
* Requests to set the allowed network types for a specific reason
*
* @param reason reason to configure allowed network type
* @param networkTypes one of the network types
*/
public void setAllowedNetworkTypes(@TelephonyManager.AllowedNetworkTypesReason int reason,
@TelephonyManager.NetworkTypeBitMask long networkTypes, Message response) {
int subId = getSubId();
if (!TelephonyManager.isValidAllowedNetworkTypesReason(reason)) {
loge("setAllowedNetworkTypes: Invalid allowed network type reason: " + reason);
AsyncResult.forMessage(response, null,
new CommandException(CommandException.Error.INVALID_ARGUMENTS));
response.sendToTarget();
return;
}
if (!SubscriptionManager.isUsableSubscriptionId(subId)
|| !mIsAllowedNetworkTypesLoadedFromDb) {
loge("setAllowedNetworkTypes: no sim or network type is not loaded. SubscriptionId: "
+ subId + ", isNetworkTypeLoaded" + mIsAllowedNetworkTypesLoadedFromDb);
AsyncResult.forMessage(response, null,
new CommandException(CommandException.Error.MISSING_RESOURCE));
response.sendToTarget();
return;
}
String mapAsString = "";
synchronized (mAllowedNetworkTypesForReasons) {
mAllowedNetworkTypesForReasons.put(reason, networkTypes);
mapAsString = mAllowedNetworkTypesForReasons.keySet().stream()
.map(key -> convertAllowedNetworkTypeMapIndexToDbName(key) + "="
+ mAllowedNetworkTypesForReasons.get(key))
.collect(Collectors.joining(","));
}
SubscriptionManager.setSubscriptionProperty(subId,
SubscriptionManager.ALLOWED_NETWORK_TYPES,
mapAsString);
logd("setAllowedNetworkTypes: SubId" + subId + ",setAllowedNetworkTypes " + mapAsString);
updateAllowedNetworkTypes(response);
notifyAllowedNetworkTypesChanged(reason);
}
Phone.java的如下方法不仅会在配置的时候调用,在其他情况也会被调用:
protected void updateAllowedNetworkTypes(Message response) {
int modemRaf = getRadioAccessFamily();
if (modemRaf == RadioAccessFamily.RAF_UNKNOWN) {
Rlog.d(LOG_TAG, "setPreferredNetworkType: Abort, unknown RAF: "
+ modemRaf);
if (response != null) {
CommandException ex;
ex = new CommandException(CommandException.Error.GENERIC_FAILURE);
AsyncResult.forMessage(response, null, ex);
response.sendToTarget();
}
return;
}
int filteredRaf = (int) (modemRaf & getEffectiveAllowedNetworkTypes());
logd("setAllowedNetworkTypes: modemRafBitMask = " + modemRaf
+ " ,modemRaf = " + TelephonyManager.convertNetworkTypeBitmaskToString(modemRaf)
+ " ,filteredRafBitMask = " + filteredRaf
+ " ,filteredRaf = " + TelephonyManager.convertNetworkTypeBitmaskToString(
filteredRaf));
mCi.setAllowedNetworkTypesBitmap(filteredRaf, response);
mPreferredNetworkTypeRegistrants.notifyRegistrants();
}
最终会调用:
/frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
@Override
public void setAllowedNetworkTypesBitmap(
@TelephonyManager.NetworkTypeBitMask int networkTypeBitmask, Message result) {
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
if (mRadioVersion.less(RADIO_HAL_VERSION_1_6)) {
// For older HAL, redirects the call to setPreferredNetworkType.
setPreferredNetworkType(
RadioAccessFamily.getNetworkTypeFromRaf(networkTypeBitmask), result);
return;
}
android.hardware.radio.V1_6.IRadio radioProxy16 =
(android.hardware.radio.V1_6.IRadio) radioProxy;
RILRequest rr = obtainRequest(RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP, result,
mRILDefaultWorkSource);
if (RILJ_LOGD) {
riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
}
mAllowedNetworkTypesBitmask = networkTypeBitmask;
try {
radioProxy16.setAllowedNetworkTypesBitmap(rr.mSerial,
convertToHalRadioAccessFamily(mAllowedNetworkTypesBitmask));
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "setAllowedNetworkTypeBitmask", e);
}
}
}
3 RILD流程
3.1 源码
这里假设RILC最终会调用:
/device/google/cuttlefish/guest/hals/ril/reference-libril/ril_service.cpp
Return RadioImpl_1_6::setAllowedNetworkTypesBitmap(
uint32_t serial, hidl_bitfield networkTypeBitmap) {
#if VDBG
RLOGD("setAllowedNetworkTypesBitmap: serial %d", serial);
#endif
dispatchInts(serial, mSlotId, RIL_REQUEST_SET_ALLOWED_NETWORK_TYPES_BITMAP, 1, networkTypeBitmap);
return Void();
}
等Modem有返回时,使用如下方法返回给Framework:
/frameworks/opt/telephony/src/java/com/android/internal/telephony/RadioResponse.java
private void responseVoid_1_6(android.hardware.radio.V1_6.RadioResponseInfo responseInfo) {
RILRequest rr = mRil.processResponse_1_6(responseInfo);
if (rr != null) {
Object ret = null;
if (responseInfo.error == RadioError.NONE) {
sendMessageResponse(rr.mResult, ret);
}
mRil.processResponseDone_1_6(rr, responseInfo, ret);
}
}
@Override
public void setAllowedNetworkTypesBitmapResponse(
android.hardware.radio.V1_6.RadioResponseInfo info) {
responseVoid_1_6(info);
}
3.2 流程图
4 参考文档
Android源码
http://aospxref.com/android-12.0.0_r3/
http://aosp.opersys.com/xref/android-12.0.0_r2/
版权声明:本文为 无痕1024 原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.jianshu.com/p/a661982ecfee