1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.car.cluster; 17 18 import android.content.Context; 19 import android.telephony.TelephonyManager; 20 import android.text.TextUtils; 21 import android.text.format.DateUtils; 22 23 import androidx.lifecycle.LiveData; 24 import androidx.lifecycle.MediatorLiveData; 25 26 import com.android.car.telephony.common.TelecomUtils.PhoneNumberInfo; 27 28 /** 29 * Emits the description for the body in {@link PhoneFragmentViewModel}. 30 * 31 * This description may be the current duration of the call, call state, call type, 32 * or a combination of them. 33 * 34 * Possible strings: 35 * "Ringing" 36 * "1:05" 37 * "Mobile · Dialing" 38 * "Mobile · 1:05" 39 */ 40 public class SelfRefreshDescriptionLiveData extends MediatorLiveData<String> { 41 private final LiveData<Long> mConnectTimeLiveData; 42 private final LiveData<PhoneNumberInfo> mNumberLiveData; 43 private final LiveData<Integer> mStateLiveData; 44 private final Context mContext; 45 46 /** 47 * @param stateLiveData LiveData holding the {@link TelephonyManager} call state 48 * @param numberLiveData LiveData holding the call number 49 * @param connectTimeLiveData LiveData holding the starting timestamp of the call 50 */ SelfRefreshDescriptionLiveData(Context context, LiveData<Integer> stateLiveData, LiveData<PhoneNumberInfo> numberLiveData, LiveData<Long> connectTimeLiveData)51 public SelfRefreshDescriptionLiveData(Context context, 52 LiveData<Integer> stateLiveData, 53 LiveData<PhoneNumberInfo> numberLiveData, 54 LiveData<Long> connectTimeLiveData) { 55 mContext = context; 56 mNumberLiveData = numberLiveData; 57 mStateLiveData = stateLiveData; 58 mConnectTimeLiveData = connectTimeLiveData; 59 60 HeartBeatLiveData heartBeatLiveData = new HeartBeatLiveData(DateUtils.SECOND_IN_MILLIS); 61 62 addSource(stateLiveData, (trigger) -> updateDescription()); 63 addSource(heartBeatLiveData, (trigger) -> updateDescription()); 64 addSource(mNumberLiveData, (trigger) -> updateDescription()); 65 addSource(mConnectTimeLiveData, (trigger) -> updateDescription()); 66 } 67 updateDescription()68 private void updateDescription() { 69 PhoneNumberInfo number = mNumberLiveData.getValue(); 70 Integer callState = mStateLiveData.getValue(); 71 Long connectTime = mConnectTimeLiveData.getValue(); 72 if (callState != null) { 73 String newDescription = getCallInfoText(mContext, callState, number, 74 connectTime != null ? connectTime : 0); 75 76 String oldDescription = getValue(); 77 if (!newDescription.equals(oldDescription)) { 78 setValue(newDescription); 79 } 80 } else { 81 setValue(""); 82 } 83 } 84 85 /** 86 * @return A formatted string that has information about the phone call 87 * Possible strings: 88 * "Mobile · Dialing" 89 * "Mobile · 1:05" 90 */ getCallInfoText(Context context, Integer callState, PhoneNumberInfo number, Long connectTime)91 private String getCallInfoText(Context context, Integer callState, PhoneNumberInfo number, 92 Long connectTime) { 93 String label = number != null ? number.getTypeLabel() : null; 94 String text = ""; 95 if (callState == TelephonyManager.CALL_STATE_OFFHOOK) { 96 long duration = connectTime > 0 ? System.currentTimeMillis() 97 - connectTime : 0; 98 String durationString = DateUtils.formatElapsedTime(duration / 1000); 99 if (!TextUtils.isEmpty(durationString) && !TextUtils.isEmpty(label)) { 100 text = context.getString(R.string.phone_label_with_info, label, 101 durationString); 102 } else if (!TextUtils.isEmpty(durationString)) { 103 text = durationString; 104 } else if (!TextUtils.isEmpty(label)) { 105 text = label; 106 } 107 } else { 108 String state = callStateToUiString(context, callState); 109 if (!TextUtils.isEmpty(label)) { 110 text = context.getString(R.string.phone_label_with_info, label, state); 111 } else { 112 text = state; 113 } 114 } 115 116 return text; 117 } 118 119 /** 120 * @return A string representation of the call state that can be presented to a user. 121 */ callStateToUiString(Context context, int state)122 private String callStateToUiString(Context context, int state) { 123 switch (state) { 124 case TelephonyManager.CALL_STATE_IDLE: 125 return context.getString(R.string.call_state_call_ended); 126 case TelephonyManager.CALL_STATE_RINGING: 127 return context.getString(R.string.call_state_call_ringing); 128 case TelephonyManager.CALL_STATE_OFFHOOK: 129 return context.getString(R.string.call_state_call_active); 130 default: 131 return ""; 132 } 133 } 134 } 135