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