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
16/**
17 * @file: Call management
18 */
19import CallDataManager from './CallDataManager';
20import CallUtils from '../common/utils/CallUtils';
21import Utils from '../common/utils/utils';
22import CallServiceProxy from './CallServiceProxy';
23import LogUtils from '../common/utils/LogUtils'
24import call from '@ohos.telephony.call';
25import CallStateConst from '../common/constant/CallStateConst';
26import DefaultCallData from '../common/struct/TypeUtils';
27import CallListStruct from '../common/struct/CallListStruct';
28import VibrationAndProximityUtils from '../common/utils/VibrationAndProximityUtils';
29
30const TAG = 'CallManager';
31const TIMING = 1000;
32
33/**
34 * class CallManager
35 */
36export default class CallManager {
37  private callData: DefaultCallData = new DefaultCallData();
38  private callList: Array<CallListStruct> = [];
39  private timer = null;
40  public callTimeList = [];
41  private ctx = [];
42  private sendNotificationHandle: Function;
43  private mCallDataManager: CallDataManager;
44  private mCallServiceProxy: CallServiceProxy;
45  private mUtils: Utils;
46  private diffSeconds
47  private mTimeMeter;
48  private isServiceConnected: boolean = false;
49
50  public static getInstance(): CallManager {
51    if (globalThis.callManager == null) {
52      globalThis.callManager = new CallManager();
53    }
54    return globalThis.callManager;
55  }
56
57  private constructor() {
58    this.mCallServiceProxy = CallServiceProxy.getInstance();
59    this.mUtils = Utils.getInstance();
60    this.timer = null;
61    this.mCallDataManager = CallDataManager.getInstance();
62  }
63
64  init(ctx) {
65    this.callData = ctx.callData;
66    this.ctx = ctx;
67    this.callTimeList = ctx.callTimeList;
68    this.mCallDataManager?.init(ctx.callData, ctx.callList, ctx.callTimeList);
69    this.openTimer();
70    this.sendNotificationHandle = (arg) => arg;
71    this.initCallData();
72  }
73
74  /**
75   * init CallData
76   */
77  private initCallData() {
78    if (globalThis.abilityWant && globalThis.abilityWant.parameters && ('callState' in globalThis.abilityWant.parameters)) {
79      if (!this.isServiceConnected) {
80        globalThis.calluiAbilityContext?.terminateSelf().then((data) => {
81          LogUtils.i(TAG, 'calluiAbility terminateSelf because service disconnected');
82        });
83        return;
84      }
85      let callData = this.getCallDataFromWant(globalThis.abilityWant.parameters);
86      this.update(callData);
87      LogUtils.i(TAG, 'initCallData featureAbility.getWant :')
88    } else {
89      this.mCallServiceProxy.publish({
90        key: 'getInitCallData',
91        params: []
92      });
93    }
94  }
95
96  setServiceConnected(isServiceConnected: boolean): void {
97      this.isServiceConnected = isServiceConnected;
98  }
99
100  /**
101   * get callData from want parameters
102   */
103  private getCallDataFromWant(parameters) {
104    return Object.assign({}, {
105      accountId: parameters.accountId,
106      accountNumber: parameters.accountNumber,
107      callId: parameters.callId,
108      callState: parameters.callState,
109      callType: parameters.callType,
110      conferenceState: parameters.conferenceState,
111      isEcc: parameters.isEcc,
112      startTime: parameters.startTime,
113      videoState: parameters.videoState});
114  }
115
116  /**
117   * update callData callBack
118   *
119   * @param { Object } callData -Object
120   */
121  async update(callData) {
122    LogUtils.i(TAG, 'update calldata:')
123    if (this.callData != undefined && this.callData.callId === callData.callId) {
124      const { callState } = this.callData;
125      if (callState === 6 && this.callList.length === 1) {
126        globalThis.calluiAbilityContext?.terminateSelf().then((data) => {
127          LogUtils.i(TAG, 'calluiAbility terminateSelf because service disconnected');
128        });
129        // remove Proximity Listener
130        VibrationAndProximityUtils.wakeupScreen();
131        VibrationAndProximityUtils.stopVibration();
132        return;
133      }
134    }
135    this.callData = callData;
136    this.mCallDataManager.update(callData);
137    call.formatPhoneNumber(callData.accountNumber, (err, data) => {
138      if (err) {
139        LogUtils.i(TAG, 'updata calldata formatPhoneNumber err:' + JSON.stringify(err));
140      } else if (data === undefined) {
141        AppStorage.SetOrCreate('AccountNumber', callData.accountNumber);
142      } else {
143        LogUtils.i(TAG, 'updata calldata formatPhoneNumber success:' + JSON.stringify(data));
144        AppStorage.SetOrCreate('AccountNumber', data);
145      }
146    });
147    CallUtils.isEmergencyPhoneNumber(callData.accountNumber);
148    LogUtils.i(TAG, 'update :');
149  }
150
151  /**
152   * update call time list
153   */
154  updateCallTimeList() {
155    if (!this.mCallDataManager.hasActiveCall()) {
156      LogUtils.i(TAG, 'no active calls to update');
157      return;
158    }
159
160    this.callTimeList = AppStorage.Get('CallTimeList');
161    this.callTimeList.forEach((item, i) => {
162      if (this.mCallDataManager.isActiveCall(item.callId)) {
163        item.endTimestamp = new Date().valueOf();
164        const diffSeconds = item.endTimestamp - item.startTimestamp;
165        this.diffSeconds = diffSeconds
166        item.callTime = this.mUtils.formatTime(diffSeconds);
167        this.callTimeList.splice(i, 1, {
168          ...item,
169        });
170        AppStorage.SetOrCreate('CallTimeList', this.callTimeList);
171      }
172    });
173    this.mTimeMeter = setTimeout(() => {
174      this.updateCallTimeList();
175    }, 1000 - this.diffSeconds % 1000);
176
177  }
178
179  /**
180   * open timer
181   *
182   * @param { Function } callBack - add updateCallTimeList callBack
183   */
184  openTimer() {
185    this.timer = setInterval(() => {
186      this.updateCallTimeList();
187      if (this.callData.callState === CallStateConst.CALL_STATUS_ACTIVE && this.callList.length === 1) {
188        clearInterval(this.timer);
189      }
190    }, TIMING);
191  }
192
193  /**
194   * clear timer
195   */
196  clearTimer() {
197    clearInterval(this.timer);
198  }
199}
200