1 /* 2 * Copyright (C) 2017 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 17 package com.android.incallui.call; 18 19 import android.content.ActivityNotFoundException; 20 import android.content.Intent; 21 import android.os.Looper; 22 import android.support.annotation.MainThread; 23 import android.support.annotation.VisibleForTesting; 24 import android.telecom.InCallService; 25 import com.android.dialer.common.LogUtil; 26 import java.util.List; 27 28 /** Wrapper around Telecom APIs. */ 29 public class TelecomAdapter implements InCallServiceListener { 30 31 private static final String ADD_CALL_MODE_KEY = "add_call_mode"; 32 33 private static TelecomAdapter sInstance; 34 private InCallService mInCallService; 35 36 private TelecomAdapter() {} 37 38 @MainThread 39 public static TelecomAdapter getInstance() { 40 if (!Looper.getMainLooper().isCurrentThread()) { 41 throw new IllegalStateException(); 42 } 43 if (sInstance == null) { 44 sInstance = new TelecomAdapter(); 45 } 46 return sInstance; 47 } 48 49 @VisibleForTesting(otherwise = VisibleForTesting.NONE) 50 public static void setInstanceForTesting(TelecomAdapter telecomAdapter) { 51 sInstance = telecomAdapter; 52 } 53 54 @Override 55 public void setInCallService(InCallService inCallService) { 56 mInCallService = inCallService; 57 } 58 59 @Override 60 public void clearInCallService() { 61 mInCallService = null; 62 } 63 64 private android.telecom.Call getTelecomCallById(String callId) { 65 DialerCall call = CallList.getInstance().getCallById(callId); 66 return call == null ? null : call.getTelecomCall(); 67 } 68 69 public void mute(boolean shouldMute) { 70 if (mInCallService != null) { 71 mInCallService.setMuted(shouldMute); 72 } else { 73 LogUtil.e("TelecomAdapter.mute", "mInCallService is null"); 74 } 75 } 76 77 public void setAudioRoute(int route) { 78 if (mInCallService != null) { 79 mInCallService.setAudioRoute(route); 80 } else { 81 LogUtil.e("TelecomAdapter.setAudioRoute", "mInCallService is null"); 82 } 83 } 84 85 public void merge(String callId) { 86 android.telecom.Call call = getTelecomCallById(callId); 87 if (call != null) { 88 List<android.telecom.Call> conferenceable = call.getConferenceableCalls(); 89 if (!conferenceable.isEmpty()) { 90 call.conference(conferenceable.get(0)); 91 // It's safe to clear restrict count for merge action. 92 DialerCall.clearRestrictedCount(); 93 } else { 94 if (call.getDetails().can(android.telecom.Call.Details.CAPABILITY_MERGE_CONFERENCE)) { 95 call.mergeConference(); 96 // It's safe to clear restrict count for merge action. 97 DialerCall.clearRestrictedCount(); 98 } 99 } 100 } else { 101 LogUtil.e("TelecomAdapter.merge", "call not in call list " + callId); 102 } 103 } 104 105 public void swap(String callId) { 106 android.telecom.Call call = getTelecomCallById(callId); 107 if (call != null) { 108 if (call.getDetails().can(android.telecom.Call.Details.CAPABILITY_SWAP_CONFERENCE)) { 109 call.swapConference(); 110 } 111 } else { 112 LogUtil.e("TelecomAdapter.swap", "call not in call list " + callId); 113 } 114 } 115 116 public void addCall() { 117 if (mInCallService != null) { 118 Intent intent = new Intent(Intent.ACTION_DIAL); 119 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 120 121 // when we request the dialer come up, we also want to inform 122 // it that we're going through the "add call" option from the 123 // InCallScreen / PhoneUtils. 124 intent.putExtra(ADD_CALL_MODE_KEY, true); 125 try { 126 LogUtil.d("TelecomAdapter.addCall", "Sending the add DialerCall intent"); 127 mInCallService.startActivity(intent); 128 } catch (ActivityNotFoundException e) { 129 // This is rather rare but possible. 130 // Note: this method is used even when the phone is encrypted. At that moment 131 // the system may not find any Activity which can accept this Intent. 132 LogUtil.e("TelecomAdapter.addCall", "Activity for adding calls isn't found.", e); 133 } 134 } 135 } 136 137 public void playDtmfTone(String callId, char digit) { 138 android.telecom.Call call = getTelecomCallById(callId); 139 if (call != null) { 140 call.playDtmfTone(digit); 141 } else { 142 LogUtil.e("TelecomAdapter.playDtmfTone", "call not in call list " + callId); 143 } 144 } 145 146 public void stopDtmfTone(String callId) { 147 android.telecom.Call call = getTelecomCallById(callId); 148 if (call != null) { 149 call.stopDtmfTone(); 150 } else { 151 LogUtil.e("TelecomAdapter.stopDtmfTone", "call not in call list " + callId); 152 } 153 } 154 155 public void postDialContinue(String callId, boolean proceed) { 156 android.telecom.Call call = getTelecomCallById(callId); 157 if (call != null) { 158 call.postDialContinue(proceed); 159 } else { 160 LogUtil.e("TelecomAdapter.postDialContinue", "call not in call list " + callId); 161 } 162 } 163 164 public boolean canAddCall() { 165 if (mInCallService != null) { 166 return mInCallService.canAddCall(); 167 } 168 return false; 169 } 170 } 171