TelephonyConnectionService.java revision 6a6e769af983b973a67cff3e8926597525835aa9
1/* 2 * Copyright (C) 2014 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 17package com.android.services.telephony; 18 19import android.net.Uri; 20import android.text.TextUtils; 21 22import com.android.internal.telephony.CallStateException; 23import com.android.internal.telephony.Phone; 24import com.android.services.telecomm.Connection; 25import com.android.services.telecomm.ConnectionRequest; 26import com.android.services.telecomm.ConnectionService; 27import com.android.services.telecomm.Response; 28import com.android.services.telecomm.Subscription; 29 30import com.google.android.collect.Sets; 31 32import java.util.Set; 33 34/** 35 * The parent class for telephony-based call services. Subclasses provide the specific phone (GSM, 36 * CDMA, etc...) to use. 37 */ 38public abstract class TelephonyConnectionService extends ConnectionService { 39 private static final Set<com.android.internal.telephony.Connection> sKnownConnections 40 = Sets.newHashSet(); 41 42 /** {@inheritDoc} */ 43 @Override 44 public void onFindSubscriptions( 45 Uri handle, 46 Response<Uri, Subscription> response) { 47 try { 48 responseResult(handle, response, canCall(handle) ? new Subscription() : null); 49 } catch (Exception e) { 50 responseError(handle, response, "onFindSubscriptions error: " + e.toString()); 51 } 52 } 53 54 /** 55 * Initiates the underlying Telephony call, then creates a {@link TelephonyConnection} 56 * by calling 57 * {@link #createTelephonyConnection(ConnectionRequest, 58 * com.android.internal.telephony.Connection)} 59 * at the appropriate time. Should be called by the subclass. 60 */ 61 protected void startCallWithPhone( 62 Phone phone, 63 ConnectionRequest request, 64 Response<ConnectionRequest, Connection> response) { 65 Log.d(this, "startCallWithPhone: %s.", request); 66 67 if (phone == null) { 68 responseError(request, response, "Phone is null"); 69 return; 70 } 71 72 if (request.getHandle() == null) { 73 responseError(request, response, "Handle is null"); 74 return; 75 } 76 77 String number = request.getHandle().getSchemeSpecificPart(); 78 if (TextUtils.isEmpty(number)) { 79 responseError(request, response, "Unable to parse number"); 80 return; 81 } 82 83 com.android.internal.telephony.Connection connection; 84 try { 85 connection = phone.dial(number); 86 } catch (CallStateException e) { 87 Log.e(this, e, "Call to Phone.dial failed with exception"); 88 responseError(request, response, e.getMessage()); 89 return; 90 } 91 92 if (connection == null) { 93 responseError(request, response, "Call to phone.dial failed"); 94 return; 95 } 96 97 try { 98 responseResult(request, response, createTelephonyConnection(request, connection)); 99 } catch (Exception e) { 100 Log.e(this, e, "Call to createConnection failed with exception"); 101 responseError(request, response, e.getMessage()); 102 } 103 } 104 105 protected <REQUEST, RESULT> void responseError( 106 REQUEST request, 107 Response<REQUEST, RESULT> response, 108 String reason) { 109 Log.d(this, "responseError %s: %s", request, reason); 110 response.onError(request, reason); 111 } 112 113 protected void responseResult( 114 Uri request, 115 Response<Uri, Subscription> response, 116 Subscription result) { 117 Log.d(this, "responseResult %s -> %s", request, result); 118 response.onResult(request, result); 119 } 120 121 protected void responseResult( 122 ConnectionRequest request, 123 Response<ConnectionRequest, Connection> response, 124 Connection result) { 125 Log.d(this, "responseResult %s -> %s", request, result); 126 response.onResult(request, result); 127 } 128 129 protected final TelephonyConnection createTelephonyConnection( 130 ConnectionRequest request, 131 final com.android.internal.telephony.Connection connection) { 132 final TelephonyConnection telephonyConnection = 133 onCreateTelephonyConnection(request, connection); 134 sKnownConnections.add(connection); 135 telephonyConnection.addConnectionListener(new Connection.ListenerBase() { 136 @Override 137 public void onDestroyed(Connection c) { 138 telephonyConnection.removeConnectionListener(this); 139 sKnownConnections.remove(connection); 140 } 141 }); 142 return telephonyConnection; 143 } 144 145 protected static boolean isConnectionKnown( 146 com.android.internal.telephony.Connection connection) { 147 return sKnownConnections.contains(connection); 148 } 149 150 /** 151 * Determine whether this {@link TelephonyConnectionService} can place a call 152 * to the supplied handle (phone number). 153 * 154 * @param handle The proposed handle. 155 * @return {@code true} if the handle can be called. 156 */ 157 protected abstract boolean canCall(Uri handle); 158 159 /** 160 * Create a Telephony-specific {@link Connection} object. 161 * 162 * @param request A request for creating a {@link Connection}. 163 * @param connection An underlying Telephony {@link com.android.internal.telephony.Connection} 164 * to use. 165 * @return A new {@link TelephonyConnection}. 166 */ 167 protected abstract TelephonyConnection onCreateTelephonyConnection( 168 ConnectionRequest request, 169 com.android.internal.telephony.Connection connection); 170} 171