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
17package com.android.server.telecom.testapps;
18
19import android.app.Activity;
20import android.bluetooth.BluetoothDevice;
21import android.content.Intent;
22import android.os.Bundle;
23import android.telecom.Call;
24import android.telecom.CallAudioState;
25import android.telecom.PhoneAccount;
26import android.telecom.PhoneAccountHandle;
27import android.telecom.TelecomManager;
28import android.telecom.VideoProfile;
29import android.util.Log;
30import android.view.View;
31import android.view.View.OnClickListener;
32import android.view.ViewGroup;
33import android.widget.ArrayAdapter;
34import android.widget.ListView;
35import android.widget.Spinner;
36import android.widget.TextView;
37import android.widget.Toast;
38
39import java.util.Collection;
40import java.util.List;
41import java.util.Optional;
42
43public 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