• 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.dialer.simulator.impl;
18 
19 import android.net.Uri;
20 import android.os.Bundle;
21 import android.support.annotation.NonNull;
22 import android.telecom.Connection;
23 import android.telecom.ConnectionRequest;
24 import android.telecom.ConnectionService;
25 import android.telecom.PhoneAccount;
26 import android.telecom.PhoneAccountHandle;
27 import android.telecom.TelecomManager;
28 import android.telephony.TelephonyManager;
29 import android.widget.Toast;
30 import com.android.dialer.common.Assert;
31 import com.android.dialer.common.LogUtil;
32 import com.android.dialer.common.concurrent.ThreadUtil;
33 import com.android.dialer.simulator.Simulator;
34 import com.android.dialer.simulator.SimulatorComponent;
35 import com.android.dialer.simulator.SimulatorConnectionsBank;
36 import java.util.ArrayList;
37 import java.util.List;
38 
39 /** Simple connection provider to create phone calls. This is useful for emulators. */
40 public class SimulatorConnectionService extends ConnectionService {
41   private static final List<Listener> listeners = new ArrayList<>();
42   private static SimulatorConnectionService instance;
43   private SimulatorConnectionsBank simulatorConnectionsBank;
44 
getInstance()45   public static SimulatorConnectionService getInstance() {
46     return instance;
47   }
48 
addListener(@onNull Listener listener)49   public static void addListener(@NonNull Listener listener) {
50     listeners.add(Assert.isNotNull(listener));
51   }
52 
removeListener(@onNull Listener listener)53   public static void removeListener(@NonNull Listener listener) {
54     listeners.remove(Assert.isNotNull(listener));
55   }
56 
57   @Override
onCreate()58   public void onCreate() {
59     super.onCreate();
60     instance = this;
61     simulatorConnectionsBank = SimulatorComponent.get(this).getSimulatorConnectionsBank();
62   }
63 
64   @Override
onDestroy()65   public void onDestroy() {
66     LogUtil.enterBlock("SimulatorConnectionService.onDestroy");
67     instance = null;
68     simulatorConnectionsBank = null;
69     super.onDestroy();
70   }
71 
72   @Override
onCreateOutgoingConnection( PhoneAccountHandle phoneAccount, ConnectionRequest request)73   public Connection onCreateOutgoingConnection(
74       PhoneAccountHandle phoneAccount, ConnectionRequest request) {
75     LogUtil.enterBlock("SimulatorConnectionService.onCreateOutgoingConnection");
76     if (!SimulatorComponent.get(this).getSimulator().isSimulatorMode()
77         && !SimulatorSimCallManager.isSimulatorConnectionRequest(request)) {
78       LogUtil.i(
79           "SimulatorConnectionService.onCreateOutgoingConnection",
80           "outgoing call not from simulator, unregistering");
81       Toast.makeText(this, "Unregistering simulator, making a real phone call", Toast.LENGTH_LONG)
82           .show();
83       SimulatorSimCallManager.unregister(this);
84       return null;
85     }
86     SimulatorConnection connection = new SimulatorConnection(this, request);
87     if (SimulatorSimCallManager.isSimulatorConnectionRequest(request)) {
88       simulatorConnectionsBank.add(connection);
89       connection.setAddress(
90           request.getAddress(),
91           request
92               .getExtras()
93               .getInt(Simulator.PRESENTATION_CHOICE, TelecomManager.PRESENTATION_ALLOWED));
94       connection.setDialing();
95       ThreadUtil.postOnUiThread(
96           () ->
97               SimulatorComponent.get(instance)
98                   .getSimulatorConnectionsBank()
99                   .updateConferenceableConnections());
100       for (Listener listener : listeners) {
101         listener.onNewOutgoingConnection(connection);
102       }
103     } else {
104       connection.setAddress(request.getAddress(), 1);
105       Bundle extras = connection.getExtras();
106       extras.putString("connection_tag", "SimulatorMode");
107       connection.putExtras(extras);
108       simulatorConnectionsBank.add(connection);
109       connection.addListener(new NonSimulatorConnectionListener());
110       connection.setDialing();
111       ThreadUtil.postOnUiThread(connection::setActive);
112     }
113     return connection;
114   }
115 
116   @Override
onCreateIncomingConnection( PhoneAccountHandle phoneAccount, ConnectionRequest request)117   public Connection onCreateIncomingConnection(
118       PhoneAccountHandle phoneAccount, ConnectionRequest request) {
119     LogUtil.enterBlock("SimulatorConnectionService.onCreateIncomingConnection");
120     if (!SimulatorSimCallManager.isSimulatorConnectionRequest(request)) {
121       LogUtil.i(
122           "SimulatorConnectionService.onCreateIncomingConnection",
123           "incoming call not from simulator, unregistering");
124       Toast.makeText(this, "Unregistering simulator, got a real incoming call", Toast.LENGTH_LONG)
125           .show();
126       SimulatorSimCallManager.unregister(this);
127       return null;
128     }
129     SimulatorConnection connection = new SimulatorConnection(this, request);
130     connection.setAddress(
131         getPhoneNumber(request),
132         request
133             .getExtras()
134             .getInt(Simulator.PRESENTATION_CHOICE, TelecomManager.PRESENTATION_ALLOWED));
135     connection.setRinging();
136     simulatorConnectionsBank.add(connection);
137     ThreadUtil.postOnUiThread(
138         () ->
139             SimulatorComponent.get(instance)
140                 .getSimulatorConnectionsBank()
141                 .updateConferenceableConnections());
142     for (Listener listener : listeners) {
143       listener.onNewIncomingConnection(connection);
144     }
145     return connection;
146   }
147 
148   @Override
onConference(Connection connection1, Connection connection2)149   public void onConference(Connection connection1, Connection connection2) {
150     LogUtil.i(
151         "SimulatorConnectionService.onConference",
152         "connection1: "
153             + SimulatorSimCallManager.getConnectionTag(connection1)
154             + ", connection2: "
155             + SimulatorSimCallManager.getConnectionTag(connection2));
156     for (Listener listener : listeners) {
157       listener.onConference((SimulatorConnection) connection1, (SimulatorConnection) connection2);
158     }
159   }
160 
161   /** Callback used to notify listeners when a new connection has been added. */
162   public interface Listener {
onNewOutgoingConnection(@onNull SimulatorConnection connection)163     void onNewOutgoingConnection(@NonNull SimulatorConnection connection);
164 
onNewIncomingConnection(@onNull SimulatorConnection connection)165     void onNewIncomingConnection(@NonNull SimulatorConnection connection);
166 
onConference( @onNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2)167     void onConference(
168         @NonNull SimulatorConnection connection1, @NonNull SimulatorConnection connection2);
169   }
170 
getPhoneNumber(ConnectionRequest request)171   private static Uri getPhoneNumber(ConnectionRequest request) {
172     String phoneNumber = request.getExtras().getString(TelephonyManager.EXTRA_INCOMING_NUMBER);
173     return Uri.fromParts(PhoneAccount.SCHEME_TEL, phoneNumber, null);
174   }
175 }
176