• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.server.telecom.testapps;
18 
19 import static android.app.UiModeManager.DEFAULT_PRIORITY;
20 
21 import android.app.Activity;
22 import android.app.NotificationChannel;
23 import android.app.NotificationManager;
24 import android.app.UiModeManager;
25 import android.app.role.RoleManager;
26 import android.content.Intent;
27 import android.media.AudioAttributes;
28 import android.media.RingtoneManager;
29 import android.net.Uri;
30 import android.os.Bundle;
31 import android.telecom.ConnectionRequest;
32 import android.telecom.PhoneAccountHandle;
33 import android.telecom.TelecomManager;
34 import android.telecom.VideoProfile;
35 import android.util.Log;
36 import android.view.View;
37 import android.view.WindowManager;
38 import android.widget.Button;
39 import android.widget.CheckBox;
40 import android.widget.EditText;
41 import android.widget.ListView;
42 import android.widget.RadioButton;
43 import android.widget.TextView;
44 import android.widget.Toast;
45 
46 import java.util.Objects;
47 
48 /**
49  * Provides a sample third-party calling app UX which implements the self managed connection service
50  * APIs.
51  */
52 public class SelfManagedCallingActivity extends Activity {
53     private static final String TAG = "SelfMgCallActivity";
54     private static final int REQUEST_ID = 1;
55     private SelfManagedCallList mCallList = SelfManagedCallList.getInstance();
56     private CheckBox mCheckIfPermittedBeforeCalling;
57     private Button mPlaceOutgoingCallButton;
58     private Button mPlaceSelfManagedOutgoingCallButton;
59     private Button mPlaceSelfManagedIncomingCallButton;
60     private Button mPlaceIncomingCallButton;
61     private Button mHandoverFrom;
62     private Button mRequestCallScreeningRole;
63     private Button mEnableCarMode;
64     private Button mDisableCarMode;
65     private RadioButton mUseAcct1Button;
66     private RadioButton mUseAcct2Button;
67     private RadioButton mUseAcct3Button;
68     private CheckBox mHoldableCheckbox;
69     private CheckBox mVideoCallCheckbox;
70     private EditText mNumber;
71     private ListView mListView;
72     private TextView mHasFocus;
73 
74     private SelfManagedCallListAdapter mListAdapter;
75 
76     private SelfManagedCallList.Listener mCallListListener = new SelfManagedCallList.Listener() {
77         @Override
78         public void onCreateIncomingConnectionFailed(ConnectionRequest request) {
79             Log.i(TAG, "onCreateIncomingConnectionFailed " + request);
80             Toast.makeText(SelfManagedCallingActivity.this,
81                     R.string.incomingCallNotPermittedCS , Toast.LENGTH_SHORT).show();
82         };
83 
84         @Override
85         public void onCreateOutgoingConnectionFailed(ConnectionRequest request) {
86             Log.i(TAG, "onCreateOutgoingConnectionFailed " + request);
87             Toast.makeText(SelfManagedCallingActivity.this,
88                     R.string.outgoingCallNotPermittedCS , Toast.LENGTH_SHORT).show();
89         };
90 
91         @Override
92         public void onConnectionListChanged() {
93             Log.i(TAG, "onConnectionListChanged");
94             mListAdapter.updateConnections();
95         };
96 
97         @Override
98         public void onConnectionServiceFocusLost() {
99             mHasFocus.setText("\uD83D\uDC4E No Focus \uD83D\uDC4E");
100         };
101 
102         @Override
103         public void onConnectionServiceFocusGained() {
104             mHasFocus.setText("\uD83D\uDC4D Has Focus \uD83D\uDC4D");
105         };
106     };
107 
108     @Override
onCreate(Bundle savedInstanceState)109     public void onCreate(Bundle savedInstanceState) {
110         super.onCreate(savedInstanceState);
111         int flags =
112                 WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
113                         | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
114                         | WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES;
115 
116         getWindow().addFlags(flags);
117         configureNotificationChannel();
118         setContentView(R.layout.self_managed_sample_main);
119         mCheckIfPermittedBeforeCalling = (CheckBox) findViewById(
120                 R.id.checkIfPermittedBeforeCalling);
121         mPlaceOutgoingCallButton = (Button) findViewById(R.id.placeOutgoingCallButton);
122         mPlaceOutgoingCallButton.setOnClickListener(new View.OnClickListener() {
123             @Override
124             public void onClick(View v) {
125                 placeOutgoingCall();
126             }
127         });
128         mPlaceSelfManagedOutgoingCallButton = (Button) findViewById(
129                 R.id.placeSelfManagedOutgoingCallButton);
130         mPlaceSelfManagedOutgoingCallButton.setOnClickListener(new View.OnClickListener() {
131             @Override
132             public void onClick(View v) {
133                 placeSelfManagedOutgoingCall();
134             }
135         });
136         mPlaceSelfManagedIncomingCallButton = (Button) findViewById(
137                 R.id.placeSelfManagedIncomingCallButton);
138         mPlaceSelfManagedIncomingCallButton.setOnClickListener(new View.OnClickListener() {
139             @Override
140             public void onClick(View v) { placeSelfManagedIncomingCall(); }
141         });
142         mPlaceIncomingCallButton = (Button) findViewById(R.id.placeIncomingCallButton);
143         mPlaceIncomingCallButton.setOnClickListener(new View.OnClickListener() {
144             @Override
145             public void onClick(View v) {
146                 placeIncomingCall();
147             }
148         });
149         mHandoverFrom = (Button) findViewById(R.id.handoverFrom);
150         mHandoverFrom.setOnClickListener((v -> {
151             initiateHandover();
152         }));
153         mRequestCallScreeningRole = (Button) findViewById(R.id.requestCallScreeningRole);
154         mRequestCallScreeningRole.setOnClickListener((v -> {
155             requestCallScreeningRole();
156         }));
157         mEnableCarMode = (Button) findViewById(R.id.enableCarMode);
158         mEnableCarMode.setOnClickListener((v -> {
159             enableCarMode();
160         }));
161         mDisableCarMode = (Button) findViewById(R.id.disableCarMode);
162         mDisableCarMode.setOnClickListener((v -> {
163             disableCarMode();
164         }));
165         mUseAcct1Button = findViewById(R.id.useAcct1Button);
166         mUseAcct2Button = findViewById(R.id.useAcct2Button);
167         mUseAcct3Button = findViewById(R.id.useAcct3Button);
168         mHasFocus = findViewById(R.id.hasFocus);
169         mVideoCallCheckbox = findViewById(R.id.videoCall);
170         mHoldableCheckbox = findViewById(R.id.holdable);
171         mNumber = (EditText) findViewById(R.id.phoneNumber);
172         mListView = (ListView) findViewById(R.id.callList);
173         mCallList.setListener(mCallListListener);
174         mCallList.registerPhoneAccounts(this);
175         mListAdapter = new SelfManagedCallListAdapter(getLayoutInflater(),
176                 mCallList.getConnections());
177         mListView.setAdapter(mListAdapter);
178         Log.i(TAG, "onCreate - mCallList id " + Objects.hashCode(mCallList));
179     }
180 
getSelectedPhoneAccountHandle()181     private PhoneAccountHandle getSelectedPhoneAccountHandle() {
182         if (mUseAcct1Button.isChecked()) {
183             return mCallList.getPhoneAccountHandle(SelfManagedCallList.SELF_MANAGED_ACCOUNT_1);
184         } else if (mUseAcct2Button.isChecked()) {
185             return mCallList.getPhoneAccountHandle(SelfManagedCallList.SELF_MANAGED_ACCOUNT_2);
186         } else if (mUseAcct3Button.isChecked()) {
187             return mCallList.getPhoneAccountHandle(SelfManagedCallList.SELF_MANAGED_ACCOUNT_3);
188         }
189         return null;
190     }
191 
placeOutgoingCall()192     private void placeOutgoingCall() {
193         TelecomManager tm = TelecomManager.from(this);
194         PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();
195 
196         if (mCheckIfPermittedBeforeCalling.isChecked()) {
197             if (!tm.isOutgoingCallPermitted(phoneAccountHandle)) {
198                 Toast.makeText(this, R.string.outgoingCallNotPermitted , Toast.LENGTH_SHORT).show();
199                 return;
200             }
201         }
202 
203         Bundle extras = new Bundle();
204         extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
205                 getSelectedPhoneAccountHandle());
206         if (mVideoCallCheckbox.isChecked()) {
207             extras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
208                     VideoProfile.STATE_BIDIRECTIONAL);
209         }
210         Bundle clientExtras = new Bundle();
211         clientExtras.putBoolean(SelfManagedConnectionService.EXTRA_HOLDABLE,
212                 mHoldableCheckbox.isChecked());
213         extras.putBundle(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, clientExtras);
214         tm.placeCall(Uri.parse(mNumber.getText().toString()), extras);
215     }
216 
placeSelfManagedOutgoingCall()217     private void placeSelfManagedOutgoingCall() {
218         TelecomManager tm = TelecomManager.from(this);
219         PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();
220 
221         if (mCheckIfPermittedBeforeCalling.isChecked()) {
222             Toast.makeText(this, R.string.outgoingCallNotPermitted, Toast.LENGTH_SHORT).show();
223             return;
224         }
225 
226         Bundle extras = new Bundle();
227         extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
228         if (mVideoCallCheckbox.isChecked()) {
229             extras.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
230                     VideoProfile.STATE_BIDIRECTIONAL);
231         }
232         tm.placeCall(Uri.parse(mNumber.getText().toString()), extras);
233     }
234 
initiateHandover()235     private void initiateHandover() {
236         TelecomManager tm = TelecomManager.from(this);
237         PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();
238         Uri address = Uri.parse(mNumber.getText().toString());
239         tm.acceptHandover(address, VideoProfile.STATE_BIDIRECTIONAL, phoneAccountHandle);
240     }
241 
placeIncomingCall()242     private void placeIncomingCall() {
243         TelecomManager tm = TelecomManager.from(this);
244         PhoneAccountHandle phoneAccountHandle = getSelectedPhoneAccountHandle();
245 
246         if (mCheckIfPermittedBeforeCalling.isChecked()) {
247             if (!tm.isIncomingCallPermitted(phoneAccountHandle)) {
248                 Toast.makeText(this, R.string.incomingCallNotPermitted , Toast.LENGTH_SHORT).show();
249                 return;
250             }
251         }
252 
253         Bundle extras = new Bundle();
254         extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
255                 Uri.parse(mNumber.getText().toString()));
256         extras.putBoolean(SelfManagedConnectionService.EXTRA_HOLDABLE,
257                 mHoldableCheckbox.isChecked());
258         if (mVideoCallCheckbox.isChecked()) {
259             extras.putInt(TelecomManager.EXTRA_INCOMING_VIDEO_STATE,
260                     VideoProfile.STATE_BIDIRECTIONAL);
261         }
262         tm.addNewIncomingCall(getSelectedPhoneAccountHandle(), extras);
263     }
264 
placeSelfManagedIncomingCall()265     private void placeSelfManagedIncomingCall() {
266         TelecomManager tm = TelecomManager.from(this);
267         PhoneAccountHandle phoneAccountHandle = mCallList.getPhoneAccountHandle(
268                 SelfManagedCallList.SELF_MANAGED_ACCOUNT_1A);
269 
270         if (mCheckIfPermittedBeforeCalling.isChecked()) {
271             if (!tm.isIncomingCallPermitted(phoneAccountHandle)) {
272                 Toast.makeText(this, R.string.incomingCallNotPermitted , Toast.LENGTH_SHORT).show();
273                 return;
274             }
275         }
276 
277         Bundle extras = new Bundle();
278         extras.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS,
279                 Uri.parse(mNumber.getText().toString()));
280         tm.addNewIncomingCall(phoneAccountHandle, extras);
281     }
282 
enableCarMode()283     private void enableCarMode() {
284         UiModeManager uiModeManager = getSystemService(UiModeManager.class);
285         uiModeManager.enableCarMode(0);
286         Toast.makeText(this, "Enabling car mode with priority " + DEFAULT_PRIORITY,
287                 Toast.LENGTH_LONG).show();
288     }
289 
disableCarMode()290     private void disableCarMode() {
291         UiModeManager uiModeManager = getSystemService(UiModeManager.class);
292         uiModeManager.disableCarMode(0);
293         Toast.makeText(this, "Disabling car mode", Toast.LENGTH_LONG).show();
294     }
295 
configureNotificationChannel()296     private void configureNotificationChannel() {
297         NotificationChannel channel = new NotificationChannel(
298                 SelfManagedConnection.INCOMING_CALL_CHANNEL_ID, "Incoming Calls",
299                 NotificationManager.IMPORTANCE_MAX);
300         channel.setShowBadge(false);
301         Uri ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
302         channel.setSound(ringtoneUri, new AudioAttributes.Builder()
303                 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
304                 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
305                 .build());
306         channel.enableLights(true);
307 
308         NotificationManager mgr = getSystemService(NotificationManager.class);
309         mgr.createNotificationChannel(channel);
310     }
311 
312     @Override
onActivityResult(int requestCode, int resultCode, Intent data)313     public void onActivityResult(int requestCode, int resultCode, Intent data) {
314         if (requestCode == REQUEST_ID) {
315             if (resultCode == android.app.Activity.RESULT_OK) {
316                 Toast.makeText(this, "Call screening role granted.", Toast.LENGTH_SHORT).show();
317             } else {
318                 Toast.makeText(this, "Call screening role NOT granted.", Toast.LENGTH_SHORT).show();
319             }
320         }
321     }
322 
requestCallScreeningRole()323     private void requestCallScreeningRole() {
324         RoleManager roleManager = (RoleManager) getSystemService(ROLE_SERVICE);
325         Intent intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
326         startActivityForResult(intent, REQUEST_ID);
327     }
328 }