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 */
15import observer from '@ohos.telephony.observer';
16import telephonySim from '@ohos.telephony.sim';
17import { HiLog } from '../../../../../../common';
18
19export const simId_NONE: number = -1;
20
21export const simId_ONE: number = 0;
22
23export const simId_TWO: number = 1;
24
25const TAG = 'SimCardState';
26
27class SimCardState {
28  mListener: () => void;
29  mSimStateArray: Array<telephonySim.SimState> =
30    [telephonySim.SimState.SIM_STATE_UNKNOWN, telephonySim.SimState.SIM_STATE_UNKNOWN];
31  haveSimCard: boolean = false;
32  haveMultiSimCard: boolean = false;
33
34  /**
35   * isSimReady
36   *
37   * @param slotId the sim slot id number
38   * @return boolean the sim is ready or not
39   */
40  public isSimReady(slotId: number) {
41    return this.mSimStateArray[slotId] == telephonySim.SimState.SIM_STATE_READY || this.mSimStateArray[slotId]
42    == telephonySim.SimState.SIM_STATE_LOADED;
43  }
44
45  /*
46   * Initialization is required only when callback is required. Callback is required to ensure data accuracy and timeliness.
47   */
48  public init() {
49    try {
50      HiLog.i(TAG, 'SimCardState, init.')
51      this.addSimChangeListener();
52      this.getSimCardState();
53    } catch (error) {
54      HiLog.w(TAG, 'SimCardState, get sim state error.')
55    }
56  }
57
58  public removeSimChangeListener() {
59    HiLog.i(TAG, 'removeSimChangeListener ! ');
60    observer.off('simStateChange');
61  }
62
63  public setListener(listener: () => void) {
64    this.mListener = listener;
65  }
66
67  private addSimChangeListener() {
68    for (let i = 0; i < telephonySim.getMaxSimCount(); i++) {
69      observer.on('simStateChange', {
70        slotId: i
71      }, value => {
72        let simState = value?.state;
73        HiLog.i(TAG, `simStateChange for ${i}, SIM value: ` + simState);
74        this.parseSimCardStateForSlot(i, simState);
75      });
76    }
77  }
78
79  private getSimCardState() {
80    for (let i = 0; i < telephonySim.getMaxSimCount(); i++) {
81      telephonySim.getSimState(i, (err, value) => {
82        if (err) {
83          HiLog.e(TAG, `getSimCardState, ${i} error: ${JSON.stringify(err.message)}`);
84        } else {
85          this.parseSimCardStateForSlot(i, value)
86        }
87      });
88    }
89  }
90
91  private parseSimCardStateForSlot(slotId: number, value) {
92    let changed: boolean = (value != this.mSimStateArray[slotId]);
93    if (!changed) {
94      return;
95    }
96    this.mSimStateArray[slotId] = value;
97    this.haveSimCard = this.isSimReady(simId_ONE) || this.isSimReady(simId_TWO);
98    this.haveMultiSimCard = this.isSimReady(simId_ONE) && this.isSimReady(simId_TWO);
99    AppStorage.SetOrCreate<boolean>('haveMultiSimCard', this.haveMultiSimCard);
100    AppStorage.SetOrCreate<boolean>('haveSimCard', this.haveSimCard);
101    HiLog.i(TAG, `parseSimCardStateForSlot sim ${slotId}} state ${value}}, haveSimCard: ` + this.haveSimCard +
102    ', haveMultiSimCard: ' + this.haveMultiSimCard);
103    this.setDefaultSlot();
104    if (this.mListener) {
105      this.mListener();
106    }
107  }
108
109  private setDefaultSlot() {
110    if (this.haveSimCard) {
111      if (!this.haveMultiSimCard) {
112        if (this.isSimReady(simId_ONE)) {
113          AppStorage.SetOrCreate<number>('defaultSlot', simId_ONE);
114        } else {
115          AppStorage.SetOrCreate<number>('defaultSlot', simId_TWO);
116        }
117      } else {
118        telephonySim.getDefaultVoiceSlotId((err, slot: number) => {
119          if (err) {
120            HiLog.e(TAG, `getDefaultVoiceSlotId, ${slot} error: ${JSON.stringify(err)}`);
121          } else {
122            AppStorage.SetOrCreate<number>('defaultSlot', slot);
123          }
124        })
125      }
126    } else {
127      if (AppStorage.Has('defaultSlot')) {
128        AppStorage.Delete('defaultSlot')
129      }
130    }
131  }
132}
133
134export default new SimCardState();