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 }