1 /* 2 * Copyright (C) 2015 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.server.telecom.testapps; 18 19 import android.app.Activity; 20 import android.bluetooth.BluetoothDevice; 21 import android.content.Intent; 22 import android.os.Bundle; 23 import android.telecom.Call; 24 import android.telecom.CallAudioState; 25 import android.telecom.PhoneAccount; 26 import android.telecom.PhoneAccountHandle; 27 import android.telecom.TelecomManager; 28 import android.telecom.VideoProfile; 29 import android.util.Log; 30 import android.view.View; 31 import android.view.View.OnClickListener; 32 import android.view.ViewGroup; 33 import android.widget.ArrayAdapter; 34 import android.widget.ListView; 35 import android.widget.Spinner; 36 import android.widget.TextView; 37 import android.widget.Toast; 38 39 import java.util.Collection; 40 import java.util.List; 41 import java.util.Optional; 42 43 public class TestInCallUI extends Activity { 44 private class BluetoothDeviceAdapter extends ArrayAdapter<BluetoothDevice> { 45 public BluetoothDeviceAdapter() { 46 super(TestInCallUI.this, android.R.layout.simple_spinner_item); 47 setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 48 } 49 50 @Override 51 public View getView(int position, View convertView, ViewGroup parent) { 52 BluetoothDevice info = getItem(position); 53 TextView result = new TextView(TestInCallUI.this); 54 result.setText(info.getName()); 55 return result; 56 } 57 58 public void update(Collection<BluetoothDevice> devices) { 59 clear(); 60 addAll(devices); 61 } 62 } 63 64 public static TestInCallUI sInstance; 65 private ListView mListView; 66 private TestCallList mCallList; 67 private Spinner mBtDeviceList; 68 private BluetoothDeviceAdapter mBluetoothDeviceAdapter; 69 private TextView mCurrentRouteDisplay; 70 71 /** ${inheritDoc} */ 72 @Override 73 protected void onCreate(Bundle savedInstanceState) { 74 super.onCreate(savedInstanceState); 75 sInstance = this; 76 77 setContentView(R.layout.incall_screen); 78 79 mListView = (ListView) findViewById(R.id.callListView); 80 mListView.setAdapter(new CallListAdapter(this)); 81 mListView.setVisibility(View.VISIBLE); 82 83 mCallList = TestCallList.getInstance(); 84 mCallList.addListener(new TestCallList.Listener() { 85 @Override 86 public void onCallRemoved(Call call) { 87 if (mCallList.size() == 0) { 88 Log.i(TestInCallUI.class.getSimpleName(), "Ending the incall UI"); 89 finish(); 90 } 91 } 92 93 @Override 94 public void onRttStarted(Call call) { 95 Toast.makeText(TestInCallUI.this, "RTT now enabled", Toast.LENGTH_SHORT).show(); 96 } 97 98 @Override 99 public void onRttStopped(Call call) { 100 Toast.makeText(TestInCallUI.this, "RTT now disabled", Toast.LENGTH_SHORT).show(); 101 } 102 103 @Override 104 public void onRttInitiationFailed(Call call, int reason) { 105 Toast.makeText(TestInCallUI.this, String.format("RTT failed to init: %d", reason), 106 Toast.LENGTH_SHORT).show(); 107 } 108 109 @Override 110 public void onRttRequest(Call call, int id) { 111 Toast.makeText(TestInCallUI.this, String.format("RTT request: %d", id), 112 Toast.LENGTH_SHORT).show(); 113 } 114 }); 115 116 View endCallButton = findViewById(R.id.end_call_button); 117 View holdButton = findViewById(R.id.hold_button); 118 View muteButton = findViewById(R.id.mute_button); 119 View rttIfaceButton = findViewById(R.id.rtt_iface_button); 120 View answerButton = findViewById(R.id.answer_button); 121 View startRttButton = findViewById(R.id.start_rtt_button); 122 View acceptRttButton = findViewById(R.id.accept_rtt_button); 123 View handoverButton = findViewById(R.id.request_handover_button); 124 View setBtDeviceButton = findViewById(R.id.set_bt_device_button); 125 View earpieceButton = findViewById(R.id.earpiece_button); 126 View speakerButton = findViewById(R.id.speaker_button); 127 mBtDeviceList = findViewById(R.id.available_bt_devices); 128 mBluetoothDeviceAdapter = new BluetoothDeviceAdapter(); 129 mBtDeviceList.setAdapter(mBluetoothDeviceAdapter); 130 mCurrentRouteDisplay = findViewById(R.id.current_audio_route); 131 132 endCallButton.setOnClickListener(new OnClickListener() { 133 @Override 134 public void onClick(View view) { 135 Call call = mCallList.getCall(0); 136 if (call != null) { 137 call.disconnect(); 138 } 139 } 140 }); 141 holdButton.setOnClickListener(new OnClickListener() { 142 @Override 143 public void onClick(View view) { 144 Call call = mCallList.getCall(0); 145 if (call != null) { 146 if (call.getState() == Call.STATE_HOLDING) { 147 call.unhold(); 148 } else { 149 call.hold(); 150 } 151 } 152 } 153 }); 154 muteButton.setOnClickListener(new OnClickListener() { 155 @Override 156 public void onClick(View view) { 157 Call call = mCallList.getCall(0); 158 if (call != null) { 159 160 } 161 } 162 }); 163 164 rttIfaceButton.setOnClickListener((view) -> { 165 Call call = mCallList.getCall(0); 166 if (call.isRttActive()) { 167 Intent intent = new Intent(Intent.ACTION_MAIN); 168 intent.setClass(this, TestRttActivity.class); 169 startActivity(intent); 170 } 171 }); 172 173 answerButton.setOnClickListener(view -> { 174 Call call = mCallList.getCall(0); 175 if (call.getState() == Call.STATE_RINGING) { 176 call.answer(VideoProfile.STATE_AUDIO_ONLY); 177 } 178 }); 179 180 startRttButton.setOnClickListener(view -> { 181 Call call = mCallList.getCall(0); 182 if (!call.isRttActive()) { 183 call.sendRttRequest(); 184 } 185 }); 186 187 earpieceButton.setOnClickListener(view -> { 188 TestInCallServiceImpl.sInstance.setAudioRoute(CallAudioState.ROUTE_WIRED_OR_EARPIECE); 189 }); 190 191 speakerButton.setOnClickListener(view -> { 192 TestInCallServiceImpl.sInstance.setAudioRoute(CallAudioState.ROUTE_SPEAKER); 193 }); 194 195 setBtDeviceButton.setOnClickListener(view -> { 196 if (mBtDeviceList.getSelectedItem() != null 197 && TestInCallServiceImpl.sInstance != null) { 198 TestInCallServiceImpl.sInstance.requestBluetoothAudio( 199 (BluetoothDevice) mBtDeviceList.getSelectedItem()); 200 } 201 }); 202 203 acceptRttButton.setOnClickListener(view -> { 204 Call call = mCallList.getCall(0); 205 if (!call.isRttActive()) { 206 call.respondToRttRequest(mCallList.getLastRttRequestId(), true); 207 } 208 }); 209 210 handoverButton.setOnClickListener((v) -> { 211 Call call = mCallList.getCall(0); 212 Bundle extras = new Bundle(); 213 extras.putParcelable(Call.EXTRA_HANDOVER_PHONE_ACCOUNT_HANDLE, 214 getHandoverToPhoneAccountHandle()); 215 extras.putInt(Call.EXTRA_HANDOVER_VIDEO_STATE, VideoProfile.STATE_BIDIRECTIONAL); 216 call.sendCallEvent(Call.EVENT_REQUEST_HANDOVER, extras); 217 }); 218 } 219 220 public void updateCallAudioState(CallAudioState cas) { 221 mBluetoothDeviceAdapter.update(cas.getSupportedBluetoothDevices()); 222 String routeText; 223 switch (cas.getRoute()) { 224 case CallAudioState.ROUTE_EARPIECE: 225 routeText = "Earpiece"; 226 break; 227 case CallAudioState.ROUTE_SPEAKER: 228 routeText = "Speaker"; 229 break; 230 case CallAudioState.ROUTE_WIRED_HEADSET: 231 routeText = "Wired"; 232 break; 233 case CallAudioState.ROUTE_BLUETOOTH: 234 BluetoothDevice activeDevice = cas.getActiveBluetoothDevice(); 235 routeText = activeDevice == null ? "null bt" : activeDevice.getName(); 236 break; 237 default: 238 routeText = "unknown: " + cas.getRoute(); 239 } 240 mCurrentRouteDisplay.setText(routeText); 241 } 242 243 /** ${inheritDoc} */ 244 @Override 245 protected void onDestroy() { 246 sInstance = null; 247 super.onDestroy(); 248 } 249 250 @Override 251 protected void onPause() { 252 super.onPause(); 253 } 254 255 @Override 256 protected void onStart() { 257 super.onStart(); 258 } 259 260 @Override 261 protected void onResume() { 262 super.onResume(); 263 } 264 265 private PhoneAccountHandle getHandoverToPhoneAccountHandle() { 266 TelecomManager tm = TelecomManager.from(this); 267 268 List<PhoneAccountHandle> handles = tm.getAllPhoneAccountHandles(); 269 Optional<PhoneAccountHandle> found = handles.stream().filter(h -> { 270 PhoneAccount account = tm.getPhoneAccount(h); 271 Bundle extras = account.getExtras(); 272 return extras != null && extras.getBoolean(PhoneAccount.EXTRA_SUPPORTS_HANDOVER_TO); 273 }).findFirst(); 274 PhoneAccountHandle foundHandle = found.orElse(null); 275 Log.i(TestInCallUI.class.getSimpleName(), "getHandoverToPhoneAccountHandle() = " + 276 foundHandle); 277 return foundHandle; 278 } 279 } 280