1/** 2 * Copyright (c) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import BaseModel from "./BaseModel"; 17import common from "../data/commonData"; 18import HiLog from "../utils/HiLog"; 19import MmsPreferences from "../utils/MmsPreferences"; 20import telephonySMS from "@ohos.telephony.sms"; 21import telephonySim from "@ohos.telephony.sim"; 22import observer from '@ohos.telephony.observer'; 23import CommonEvent from '@ohos.commonEventManager'; 24import emitter from '@ohos.events.emitter' 25import radio from '@ohos.telephony.radio'; 26 27const TAG = "CardModel"; 28 29class CardModel extends BaseModel { 30 public SIM_STATE_CHANGE_EVENT: emitter.InnerEvent = { 31 eventId: common.int.EVENT_SIM_STATE_CHANGE, 32 priority: emitter.EventPriority.HIGH 33 } 34 public SLOTID_CHANGE_EVENT: emitter.InnerEvent = { 35 eventId: common.int.EVENT_SLOTID_CHANGE, 36 priority: emitter.EventPriority.HIGH 37 } 38 private mSimStateArray: Array<telephonySim.SimState> = [telephonySim.SimState.SIM_STATE_UNKNOWN, 39 telephonySim.SimState.SIM_STATE_UNKNOWN]; 40 private spn: string = ''; 41 private spnEventSubscriber: any; 42 private haveMultiSimCardReady: boolean = false; 43 private haveSimCardReady: boolean = false; 44 45 public init(): void { 46 try { 47 HiLog.i(TAG, "init start."); 48 this.setMaxSimCountToMap(); 49 this.getSimState(); 50 this.addSimStateChangeListener(); 51 this.subscribeSpnObserver(); 52 } catch (error) { 53 HiLog.e(TAG, "init error: " + JSON.stringify(error)); 54 } 55 } 56 57 public deInit(): void { 58 try { 59 HiLog.i(TAG, "deInit start."); 60 this.mSimStateArray = [telephonySim.SimState.SIM_STATE_UNKNOWN, telephonySim.SimState.SIM_STATE_UNKNOWN]; 61 this.removeSimStateChangeListener(); 62 this.unsubscribeSpnObserver(); 63 } catch (error) { 64 HiLog.e(TAG, "deInit error: " + JSON.stringify(error)); 65 } 66 } 67 68 public isSimReady(slotId: number): boolean { 69 return this.mSimStateArray[slotId] == telephonySim.SimState.SIM_STATE_READY 70 || this.mSimStateArray[slotId] == telephonySim.SimState.SIM_STATE_LOADED; 71 } 72 73 private setMaxSimCountToMap(): void { 74 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_MAX_SIM_COUNT, telephonySim.getMaxSimCount()); 75 } 76 77 private getSimState(): void { 78 for (let i = 0; i < telephonySim.getMaxSimCount(); i++) { 79 telephonySim.getSimState(i, (err, value) => { 80 if (err) { 81 HiLog.e(TAG, "getSimState, slotId: " + i + ", error: " + JSON.stringify(err)); 82 } else { 83 this.notifySimStateChange(i, value); 84 } 85 }); 86 } 87 } 88 89 private removeSimStateChangeListener(): void { 90 observer.off('simStateChange'); 91 } 92 93 private addSimStateChangeListener(): void { 94 for (let i = 0; i < telephonySim.getMaxSimCount(); i++) { 95 observer.on('simStateChange', { 96 slotId: i 97 }, value => { 98 let simState = value?.state; 99 HiLog.i(TAG, "simStateChange slotId: " + i + ", simState: " + simState); 100 this.notifySimStateChange(i, simState); 101 }); 102 } 103 } 104 105 private notifySimStateChange(slotId: number, simState): void { 106 let changed: boolean = (simState != this.mSimStateArray[slotId]); 107 if (!changed) { 108 return; 109 } 110 this.mSimStateArray[slotId] = simState; 111 if (this.isSimReady(slotId)) { 112 this.setSpnToMap(slotId); 113 this.setSimTelephoneNumberToMap(slotId); 114 this.setSmscNumberToPref(slotId); 115 } 116 this.setSimCardReadyFlagToMap(slotId, simState); 117 this.setDefaultSlotToMap(); 118 emitter.emit(this.SIM_STATE_CHANGE_EVENT, { 119 data: { 120 "simState": simState, 121 "slotId": slotId 122 } 123 }); 124 } 125 126 private setSimCardReadyFlagToMap(slotId: number, simState): void { 127 this.haveSimCardReady = this.isSimReady(common.int.SIM_ONE) || this.isSimReady(common.int.SIM_TWO); 128 this.haveMultiSimCardReady = this.isSimReady(common.int.SIM_ONE) && this.isSimReady(common.int.SIM_TWO); 129 HiLog.i(TAG, "updateSimCardReadyFlag slotId: " + slotId + ", simState: " + simState + ", haveSimCardReady: " 130 + this.haveSimCardReady + ", haveMultiSimCardReady: " + this.haveMultiSimCardReady); 131 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_HAVE_MULTI_SIM_CARD_READY, 132 this.haveMultiSimCardReady); 133 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_HAVE_SIM_CARD_READY, this.haveSimCardReady); 134 } 135 136 private setDefaultSlotToMap() { 137 if (this.haveSimCardReady) { 138 if (!this.haveMultiSimCardReady) { 139 if (this.isSimReady(common.int.SIM_ONE)) { 140 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_DEFAULT_SLOT, common.int.SIM_ONE); 141 } else { 142 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_DEFAULT_SLOT, common.int.SIM_TWO); 143 } 144 } else { 145 telephonySim.getDefaultVoiceSlotId((error, slotId: number) => { 146 if (error) { 147 HiLog.e(TAG, "getDefaultVoiceSlotId error, slotId: " + slotId + ", error: " + JSON.stringify(error)); 148 } else { 149 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_DEFAULT_SLOT, slotId); 150 } 151 }); 152 } 153 } 154 } 155 156 private setSpnToMap(slotId: number): void { 157 // get spn from sim card 158 telephonySim.getSimSpn(slotId, (error, data) => { 159 if (error || !data) { 160 HiLog.w(TAG, "getSpnFromSim fail, slotId: " + slotId + ", data: " + data + ", error: " 161 + JSON.stringify(error)); 162 } else { 163 this.notifySetSimSpnToMap(slotId, data); 164 return; 165 } 166 }); 167 // get spn from network 168 radio.getOperatorName(slotId, (error, data) => { 169 if (error || !data) { 170 HiLog.w(TAG, "getSpnFromSim fail, slotId: " + slotId + ", data: " + data + ", error: " 171 + JSON.stringify(error)); 172 } else { 173 this.notifySetSimSpnToMap(slotId, data); 174 return; 175 } 176 }); 177 // get plmn to replace spn 178 telephonySim.getSimOperatorNumeric(slotId, (error, data) => { 179 if (error || !data) { 180 HiLog.w(TAG, "getSimOperatorNumeric fail, slotId: " + slotId + ", data: " + data + ", error: " 181 + JSON.stringify(error)); 182 } else { 183 if (common.int.SIM_ONE === slotId) { 184 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_SIM_0_SPN, this.spn); 185 } else { 186 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_SIM_1_SPN, this.spn); 187 } 188 return; 189 } 190 }); 191 } 192 193 private notifySetSimSpnToMap(slotId: number, spn: string): void { 194 HiLog.d(TAG, "notifyUpdateSimSpn slotId: " + slotId + ", spn: " + spn); 195 this.spn = spn; 196 if (common.SPN_CHINA.MOBILE == spn) { 197 this.spn = globalThis.mmsContext.resourceManager.getStringSync($r('app.string.china_mobile').id); 198 } else if (common.SPN_CHINA.TELECOM == spn) { 199 this.spn = globalThis.mmsContext.resourceManager.getStringSync($r('app.string.china_telecom').id); 200 } else if (common.SPN_CHINA.UNICOM == spn) { 201 this.spn = globalThis.mmsContext.resourceManager.getStringSync($r('app.string.china_unicom').id); 202 } 203 if (common.int.SIM_ONE === slotId) { 204 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_SIM_0_SPN, this.spn); 205 } else { 206 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_SIM_1_SPN, this.spn); 207 } 208 } 209 210 private setSimTelephoneNumberToMap(slotId: number): void { 211 telephonySim.getSimTelephoneNumber(slotId, (error, value) => { 212 if (error) { 213 HiLog.e(TAG, "get slotId: " + slotId + " telephone number error: " + JSON.stringify(error)); 214 } else { 215 if (common.int.SIM_ONE === slotId) { 216 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_SIM_0_NUMBER, value); 217 } else { 218 MmsPreferences.getInstance().setValueToMap(common.string.KEY_OF_SIM_1_NUMBER, value); 219 } 220 } 221 }); 222 } 223 224 private unsubscribeSpnObserver() { 225 if (this.spnEventSubscriber) { 226 CommonEvent.unsubscribe(this.spnEventSubscriber); 227 } 228 } 229 230 private subscribeSpnObserver() { 231 let subscribeInfo = { 232 events: ['usual.event.SPN_INFO_CHANGED'] 233 }; 234 CommonEvent.createSubscriber(subscribeInfo, (err, data) => { 235 if (err) { 236 HiLog.e(TAG, "subscribeSpnObserver error: " + JSON.stringify(err)) 237 return 238 } 239 this.spnEventSubscriber = data; 240 CommonEvent.subscribe(data, (err, data) => { 241 if (data && data.parameters) { 242 let spn = data.parameters.CUR_SPN ? data.parameters.CUR_SPN : data.parameters.CUR_PLMN; 243 if (spn) { 244 HiLog.i(TAG, "SPN_INFO_CHANGED notify slotId: " + data.parameters.CUR_SLOT_ID + ", spn: " + spn); 245 this.notifySetSimSpnToMap(data.parameters.CUR_SLOT_ID, spn); 246 } 247 } 248 }) 249 }); 250 } 251 252 private setSmscNumberToPref(slotId: number): void { 253 telephonySMS.getSmscAddr(slotId).then((simPhoneNumber) => { 254 if (slotId == common.int.SIM_ONE) { 255 MmsPreferences.getInstance().setValueForSwitch(common.string.KEY_OF_NEW_SIM_0_SMSC, simPhoneNumber); 256 } else if (slotId == common.int.SIM_TWO) { 257 MmsPreferences.getInstance().setValueForSwitch(common.string.KEY_OF_NEW_SIM_1_SMSC, simPhoneNumber); 258 } 259 }).catch((error) => { 260 HiLog.e(TAG, "setSmscNumberToPref error: " + JSON.stringify(error.message)); 261 }); 262 } 263} 264 265// Singleton 266export default new CardModel();