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.content.ComponentName;
20 import android.content.Context;
21 import android.net.Uri;
22 import android.os.Bundle;
23 import android.telecom.ConnectionRequest;
24 import android.telecom.Log;
25 import android.telecom.PhoneAccount;
26 import android.telecom.PhoneAccountHandle;
27 import android.telecom.TelecomManager;
28 import android.util.ArrayMap;
29 
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Optional;
34 
35 /**
36  * Manages the list of {@link SelfManagedConnection} active in the sample third-party calling app.
37  */
38 public class SelfManagedCallList {
39     public abstract static class Listener {
onCreateIncomingConnectionFailed(ConnectionRequest request)40         public void onCreateIncomingConnectionFailed(ConnectionRequest request) {};
onCreateOutgoingConnectionFailed(ConnectionRequest request)41         public void onCreateOutgoingConnectionFailed(ConnectionRequest request) {};
onConnectionListChanged()42         public void onConnectionListChanged() {};
onConnectionServiceFocusLost()43         public void onConnectionServiceFocusLost() {};
onConnectionServiceFocusGained()44         public void onConnectionServiceFocusGained() {};
45     }
46 
47     public static String SELF_MANAGED_ACCOUNT_1 = "1";
48     public static String SELF_MANAGED_ACCOUNT_2 = "2";
49     public static String SELF_MANAGED_ACCOUNT_1A = "1A";
50     public static String SELF_MANAGED_ACCOUNT_3 = "3";
51     public static String SELF_MANAGED_NAME_1 = "SuperCall";
52     public static String SELF_MANAGED_NAME_2 = "Mega Call";
53     public static String SELF_MANAGED_NAME_1A = "SM Call";
54     public static String SELF_MANAGED_NAME_3 = "Sep Process";
55     public static String CUSTOM_URI_SCHEME = "custom";
56 
57     private static SelfManagedCallList sInstance;
58     private static ComponentName COMPONENT_NAME = new ComponentName(
59             SelfManagedCallList.class.getPackage().getName(),
60             SelfManagedConnectionService.class.getName());
61     private static ComponentName OTHER_COMPONENT_NAME = new ComponentName(
62             SelfManagedCallList.class.getPackage().getName(),
63             OtherSelfManagedConnectionService.class.getName());
64     private static Uri SELF_MANAGED_ADDRESS_1 = Uri.fromParts(PhoneAccount.SCHEME_TEL, "555-1212",
65             "");
66     private static Uri SELF_MANAGED_ADDRESS_2 = Uri.fromParts(PhoneAccount.SCHEME_SIP,
67             "me@test.org", "");
68     private static Uri SELF_MANAGED_ADDRESS_3 = Uri.fromParts(PhoneAccount.SCHEME_SIP,
69             "hilda@test.org", "");
70     private static Map<String, PhoneAccountHandle> mPhoneAccounts = new ArrayMap();
71 
getInstance()72     public static SelfManagedCallList getInstance() {
73         if (sInstance == null) {
74             sInstance = new SelfManagedCallList();
75         }
76         return sInstance;
77     }
78 
79     private Listener mListener;
80 
81     private List<SelfManagedConnection> mConnections = new ArrayList<>();
82 
83     private SelfManagedConnection.Listener mConnectionListener =
84             new SelfManagedConnection.Listener() {
85                 @Override
86                 public void onConnectionStateChanged(SelfManagedConnection connection) {
87                     notifyCallModified();
88                 }
89 
90                 @Override
91                 public void onConnectionRemoved(SelfManagedConnection connection) {
92                     removeConnection(connection);
93                     notifyCallModified();
94                 }
95     };
96 
getConnectionListener()97     public SelfManagedConnection.Listener getConnectionListener() {
98         return mConnectionListener;
99     }
100 
101 
setListener(Listener listener)102     public void setListener(Listener listener) {
103         mListener = listener;
104     }
105 
registerPhoneAccounts(Context context)106     public void registerPhoneAccounts(Context context) {
107         registerPhoneAccount(context, SELF_MANAGED_ACCOUNT_1, SELF_MANAGED_ADDRESS_1,
108                 SELF_MANAGED_NAME_1, true /* areCallsLogged */);
109         registerPhoneAccount(context, SELF_MANAGED_ACCOUNT_2, SELF_MANAGED_ADDRESS_2,
110                 SELF_MANAGED_NAME_2, false /* areCallsLogged */);
111         registerPhoneAccount(context, SELF_MANAGED_ACCOUNT_1A, SELF_MANAGED_ADDRESS_1,
112                 SELF_MANAGED_NAME_1A, true /* areCallsLogged */);
113         registerPhoneAccount(context, SELF_MANAGED_ACCOUNT_1A, SELF_MANAGED_ADDRESS_1,
114                 SELF_MANAGED_NAME_1A, true /* areCallsLogged */);
115         registerPhoneAccount(context, OTHER_COMPONENT_NAME, SELF_MANAGED_ACCOUNT_3,
116                 SELF_MANAGED_ADDRESS_3, SELF_MANAGED_NAME_3, false /* areCallsLogged */);
117     }
118 
registerPhoneAccount(Context context, String id, Uri address, String name, boolean areCallsLogged)119     public void registerPhoneAccount(Context context, String id, Uri address, String name,
120             boolean areCallsLogged) {
121         registerPhoneAccount(context, COMPONENT_NAME, id, address, name, areCallsLogged);
122     }
123 
registerPhoneAccount(Context context, ComponentName componentName, String id, Uri address, String name, boolean areCallsLogged)124     public void registerPhoneAccount(Context context, ComponentName componentName, String id,
125             Uri address, String name, boolean areCallsLogged) {
126         TelecomManager telecomManager = context.getSystemService(TelecomManager.class);
127         PhoneAccountHandle handle = new PhoneAccountHandle(componentName, id);
128         mPhoneAccounts.put(id, handle);
129         Bundle extras = new Bundle();
130         extras.putBoolean(PhoneAccount.EXTRA_SUPPORTS_HANDOVER_TO, true);
131         if (areCallsLogged) {
132             extras.putBoolean(PhoneAccount.EXTRA_LOG_SELF_MANAGED_CALLS, true);
133         }
134         if (id.equals(SELF_MANAGED_ACCOUNT_1A)) {
135             extras.putBoolean(PhoneAccount.EXTRA_ADD_SELF_MANAGED_CALLS_TO_INCALLSERVICE, true);
136         }
137         PhoneAccount.Builder builder = PhoneAccount.builder(handle, name)
138                 .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
139                 .addSupportedUriScheme(PhoneAccount.SCHEME_SIP)
140                 .addSupportedUriScheme(CUSTOM_URI_SCHEME)
141                 .setAddress(address)
142                 .setCapabilities(PhoneAccount.CAPABILITY_SELF_MANAGED |
143                         PhoneAccount.CAPABILITY_VIDEO_CALLING |
144                         PhoneAccount.CAPABILITY_SUPPORTS_VIDEO_CALLING)
145                 .setExtras(extras)
146                 .setShortDescription(name);
147 
148         telecomManager.registerPhoneAccount(builder.build());
149     }
150 
getPhoneAccountHandle(String id)151     public PhoneAccountHandle getPhoneAccountHandle(String id) {
152         return mPhoneAccounts.get(id);
153     }
154 
notifyCreateIncomingConnectionFailed(ConnectionRequest request)155     public void notifyCreateIncomingConnectionFailed(ConnectionRequest request) {
156         if (mListener != null) {
157             mListener.onCreateIncomingConnectionFailed(request);
158         }
159     }
160 
notifyCreateOutgoingConnectionFailed(ConnectionRequest request)161     public void notifyCreateOutgoingConnectionFailed(ConnectionRequest request) {
162         if (mListener != null) {
163             mListener.onCreateOutgoingConnectionFailed(request);
164         }
165     }
166 
notifyConnectionServiceFocusGained()167     public void notifyConnectionServiceFocusGained() {
168         if (mListener != null) {
169             mListener.onConnectionServiceFocusGained();
170         }
171     }
172 
notifyConnectionServiceFocusLost()173     public void notifyConnectionServiceFocusLost() {
174         if (mListener != null) {
175             mListener.onConnectionServiceFocusLost();
176         }
177     }
178 
addConnection(SelfManagedConnection connection)179     public void addConnection(SelfManagedConnection connection) {
180         Log.i(this, "addConnection %s", connection);
181         mConnections.add(connection);
182         if (mListener != null) {
183             Log.i(this, "addConnection calling onConnectionListChanged %s", connection);
184             mListener.onConnectionListChanged();
185         }
186     }
187 
removeConnection(SelfManagedConnection connection)188     public void removeConnection(SelfManagedConnection connection) {
189         Log.i(this, "removeConnection %s", connection);
190         mConnections.remove(connection);
191         if (mListener != null) {
192             Log.i(this, "removeConnection calling onConnectionListChanged %s", connection);
193             mListener.onConnectionListChanged();
194         }
195     }
196 
getConnections()197     public List<SelfManagedConnection> getConnections() {
198         return mConnections;
199     }
200 
getConnectionById(int callId)201     public SelfManagedConnection getConnectionById(int callId) {
202         Optional<SelfManagedConnection> foundOptional = mConnections.stream()
203                 .filter((c) -> {return c.getCallId() == callId;})
204                 .findFirst();
205         return foundOptional.orElse(null);
206     }
207 
notifyCallModified()208     public void notifyCallModified() {
209         if (mListener != null) {
210             mListener.onConnectionListChanged();
211         }
212     }
213 }
214