安卓开机主卡选择流程(展讯4.4)
2019-11-05 本文已影响0人
DD_Dog
安卓4.4原生并不支持双卡,展讯4.4添加了双卡功能。
下面整理一下应用层的开机双卡选择流程:
Telephony开始
packages/services/Telephony/src/com/sprd/phone/BootCompletedReceiver.java
接收modem广播,判断是否是双卡
<receiver android:name="com.sprd.phone.BootCompletedReceiver" >
<intent-filter>
<action android:name="com.android.modemassert.MODEM_STAT_CHANGE" />
</intent-filter>
</receiver>
if (!TelephonyManager.isMultiSim()) { //isMultiSim()也是自定义的方法,结尾处有详述
// SPRD: modify for bug369560
if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
//SIM卡状态
String state = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
//phoneId,0或1
int phoneId = intent.getIntExtra(IccCardConstants.INTENT_KEY_PHONE_ID, 0);
if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(state) ||
IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state) ||
IccCardConstants.INTENT_VALUE_ICC_READY.equals(state)) {
mSimStateChangedFlag |= (1 << phoneId);
Message simMsg = new Message();
simMsg.what = EVENT_SIM_STATE_CHANGED;
simMsg.arg1 = mSimStateChangedFlag;
mHandler.sendMessage(simMsg);
}
}
return;
}
由mHandler处理
private static final String SHOW_SELECT_PRIMARY_CARD_DIALOG = "android.intent.action.SHOW_SELECT_PRIMARY_CARD_DIALOG";
Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int phoneCount = TelephonyManager.getPhoneCount();
switch(msg.what){
case EVENT_SELECTCARD:
boolean isSimPresent = false;
for(int i =0;i<phoneCount;i++){
if(PhoneFactory.getSimState(i) != State.ABSENT){
isSimPresent = true;
break;
}
}
if (isSimPresent) {
System.putInt(mContext.getContentResolver(),
System.Standby_Select_Card_Show, 1);
Intent it = new Intent(mContext, StandbyDialogActivity.class);
//提示SIM卡准备好
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(it);
}
break;
case EVENT_CHARCHANGED:
//提醒主卡改变
if (isAllSimChecked() && !mHasPromptCardChanged){
if (checkCard(mContext)) {
mHasPromptCardChanged = true;
Intent it = new Intent(mContext, PromptCardChanged.class);
it.putExtra(PromptCardChanged.SIM_CHANGE_STATUS, sim_change_status);
it.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(it);
}
}
break;
case EVENT_SIM_STATE_CHANGED: //SIM卡状态改变
boolean isSimsChanged = false;
for (int i = 0; i < mPhoneNumber; i++) {
String lastIccId = preferences.getString(SIM_ICC_ID + i, null);
String newIccId = getIccId(i);
if (newIccId == null || !newIccId.equals(lastIccId)) {
isSimsChanged = true; //其实也是判断iccid
}
}
if (isSimsChanged) {
mRadioTaskManager.savePreferredNetworkType(TelephonyManager.NT_UNKNOWN);
//这里开始双卡选择
setMultiModeSlotAccordingToPolicy();
} else {
int primaryCard = TelephonyManager.from(mContext).getPrimaryCard();
if (!SimManager.isValidPhoneId(primaryCard)) {
setMultiModeSlotAccordingToPolicy(); //SIM卡状态没变化 ,但是主卡验证失败也会重新选择
} else {
mRadioTaskManager.setDefaultDataPhoneIdNeedUpdate(false);
mRadioTaskManager.manualSetPrimaryCard(primaryCard);
}
}
}
private void setMultiModeSlotAccordingToPolicy() {
Settings.Secure.putInt( mContext.getContentResolver(),Settings.Secure.SERVICE_PRIMARY_CARD, -1);
SimManager simManager = SimManager.get(mContext);
if(simManager == null){
Log.d(TAG,"simManager = "+null);
return;
}
final Sim[] sims = simManager.getSims();
if (mPolicy.isPrimaryCardNeedManualSet() && sims.length > 1) {
prepareForMultiModeSlotChooseDialog(); //如果有两个卡进行双卡选择
} else {
mRadioTaskManager.autoSetPrimaryCardAccordingToPolicy();
String operatorName = SystemProperties.get("ro.operator", "");
if ("reliance".equals(operatorName)) {//这应该是一种特定运营商,不太清楚
prepareForMultiModeSlotChooseDialog();
}
}
}
//发送广播进行主卡选择,由Settings里面接收
private void prepareForMultiModeSlotChooseDialog() {
Intent intent = new Intent(SHOW_SELECT_PRIMARY_CARD_DIALOG);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendBroadcast(intent);
}
Settings
src/com/android/settings/sim/SimSelectNotification.java
<receiver android:name=".sim.SimSelectNotification">
<intent-filter>
<action android:name="android.intent.action.SIM_STATE_CHANGED"></action>
<action android:name="android.intent.action.SHOW_SELECT_PRIMARY_CARD_DIALOG"></action>
</intent-filter>
</receiver>
public void onReceive(Context context, Intent intent) {
/* SPRD: [Bug512963] Add for selecting primary card after boot with SIM card changed. @{ */
if (PRIMARY_CARD_SELECTION_DIALOG.equals(intent.getAction())) {
Log.d(TAG, "receive broadcast : SHOW_SELECT_PRIMARY_CARD_DIALOG");
//其实是打开SimDialogActivity
Intent targetIntent = new Intent(context, SimDialogActivity.class);
targetIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
targetIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
//弹出双卡选择,设置参数
targetIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.PRIMARY_PICK);
targetIntent.putExtra(SimDialogActivity.PRIMARYCARD_PICK_CANCELABLE, true);
context.startActivity(targetIntent);
}
/* @} */
}
src/com/android/settings/sim/SimDialogActivity.java
//在onCreate和onNewIntent方法中调用processIntent();
processIntent();
private void processIntent() {
final Bundle extras = getIntent().getExtras();
if (extras == null) {
Log.e(TAG, "invalid extras null");
finish();
return;
}
final int dialogType = extras.getInt(DIALOG_TYPE_KEY, INVALID_PICK);
mIsPrimaryCardCancelable = extras.getBoolean(PRIMARYCARD_PICK_CANCELABLE);
switch (dialogType) {
case DATA_PICK:
case CALLS_PICK:
case SMS_PICK:
case PRIMARY_PICK:
//创建Dialog并显示
mDialogType = dialogType;
mSimChooseDialog = createDialog(this, mDialogType);
mSimChooseDialog.show();
break;
case PREFERRED_PICK:
displayPreferredDialog(extras.getInt(PREFERRED_SIM));
break;
default:
throw new IllegalArgumentException("Invalid dialog type " + dialogType + " sent.");
}
}
再看一下createDialog方法,逻辑就很简单了:
public Dialog createDialog(final Context context, final int id) {
dismissSimChooseDialog();
final ArrayList<String> list = new ArrayList<String>();
final Sim[] subInfoList = mSimManager.getActiveSims();
final int selectableSubInfoLength = subInfoList == null ? 0 : subInfoList.length;
final StatusBarManager statusBarManager = (StatusBarManager) getSystemService(Context.STATUS_BAR_SERVICE);
final Sim[] subInfoListForCallAndSms = new Sim[selectableSubInfoLength + 1];
final DialogInterface.OnClickListener selectionListener =
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int value) {
// SPRD: modify by add radioButton on set defult sub id
setDefaltSubIdByDialogId(context, id, value, subInfoList);
}
};
Dialog.OnKeyListener keyListener = new Dialog.OnKeyListener() {
@Override
public boolean onKey(DialogInterface arg0, int keyCode,
KeyEvent event) {
/* SPRD: add option for selecting primary card @{ */
if (keyCode == KeyEvent.KEYCODE_BACK
&& !mIsPrimaryCardCancelable) {
finish();
return true;
} else if (keyCode == KeyEvent.KEYCODE_BACK
&& mIsPrimaryCardCancelable) {
return true;
} else {
return false;
}
/* @} */
}
};
if (id == CALLS_PICK || id == SMS_PICK) {
list.add(getResources().getString(R.string.sim_calls_ask_first_prefs_title));
for (int i = 1; i < subInfoListForCallAndSms.length; i++) {
subInfoListForCallAndSms[i] = subInfoList[i-1];
}
}
for (int i = 0; i < selectableSubInfoLength; ++i) {
final Sim sir = subInfoList[i];
CharSequence displayName = sir.getName();
if (displayName == null) {
displayName = "";
}
list.add(displayName.toString());
}
String[] arr = list.toArray(new String[0]);
AlertDialog.Builder builder = new AlertDialog.Builder(context,
AlertDialog.THEME_HOLO_LIGHT);
ListAdapter adapter = new SelectAccountListAdapter(
(id == CALLS_PICK || id == SMS_PICK)? subInfoListForCallAndSms: subInfoList,
builder.getContext(),
R.layout.select_account_list_item,
arr, id);
switch (id) {
case DATA_PICK:
builder.setTitle(R.string.select_sim_for_data);
break;
case CALLS_PICK:
builder.setTitle(R.string.select_sim_for_calls);
break;
case SMS_PICK:
builder.setTitle(R.string.sim_card_select_title);
break;
/* SPRD: add option of selecting primary card @{ */
case PRIMARY_PICK:
/* SPRD: add for bug 543820 @{ */
View titleView = LayoutInflater.from(this).inflate(
R.layout.select_primary_card_title, null);
TextView textview = (TextView) titleView
.findViewById(R.id.multi_mode_slot_introduce);
if (TelephonyManager.isDeviceSupportLte()) {
textview.setText(getString(R.string.select_primary_slot_description_4g));
}
textview.setTextColor(Color.BLACK);
builder.setCustomTitle(titleView);
/* @} */
break;
/* @} */
default:
throw new IllegalArgumentException("Invalid dialog type "
+ id + " in SIM dialog.");
}
Dialog dialog = builder.setAdapter(adapter, selectionListener).create();
dialog.setOnKeyListener(keyListener);
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialogInterface) {
finish();
}
});
/* SPRD: add option of selecting primary card @{ */
if (mIsPrimaryCardCancelable) {
dialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
statusBarManager.disable(StatusBarManager.DISABLE_NONE);
}
});
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
dialog.setCanceledOnTouchOutside(false);
statusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
}
/* @} */
return dialog;
}
TelephonyManager.isMultiSim()
frameworks/base/telephony/java/android/telephony/TelephonyManager.java
/** SPRD: check if is multiple sim */
public static boolean isMultiSim() {
return SprdPhoneSupport.isMultiSim(); //调用了SprdSupport.java的方法
}
frameworks/base/telephony/java/android/telephony/SprdPhoneSupport.java
//其实是判断的SIM卡插入的个数
public static boolean isMultiSim() {
return getPhoneCount() > 1;
}
public static final int DEFAULT_PHONE_COUNT = 1;
//获取SIM卡个数
public static int getPhoneCount() {
return SystemProperties.getInt("persist.msms.phone_count", DEFAULT_PHONE_COUNT);
}
所以最终修改的是persist.msms.phone_count
的属性值,那么它是在哪里被修改的?看下面
frameworks/base/telephony/java/android/telephony/TelephonyManager.java
//检查系统属性
public static void checkSystemProperties(Context context){
if(isSystemPropertiesInvalid(context,PROP_PHONE_COUNT)){
//设置persist.msms.phone_count属性,属性值通过getSystemString获取
SystemProperties.set(PROP_PHONE_COUNT, getSystemString(context, PROP_PHONE_COUNT));
}
...
}
//判断属性的合法性
private static boolean isSystemPropertiesInvalid(Context context, String string) {
Log.d(TAG, "isSystemPropertiesInvalid: string=" + string
+ ", getSystemString=" + getSystemString(context, string)
+ ", getSystemProperties=" + SystemProperties.get(string, ""));
//属性不为空,且系统属性值与prop文件内的属性值不相等。
//因为默认persist.msms.phone_count=2,如果只插一张卡(getSytemString为1)就需要修改了
return (!TextUtils.isEmpty(getSystemString(context, string)) && (!getSystemString(context,
string).equals(SystemProperties.get(string, ""))));
}
//获取系统属性值
private static String getSystemString(Context context, String string){
return Settings.System.getString(context.getContentResolver(), string);
}