InCallService.java revision 159f35c8e4a2d5902cbbeb8d3b9a80bddf247de3
1f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes/* 2f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Copyright (C) 2013 The Android Open Source Project 3f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 4f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * you may not use this file except in compliance with the License. 6f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * You may obtain a copy of the License at 7f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 8f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * 10f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Unless required by applicable law or agreed to in writing, software 11f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * See the License for the specific language governing permissions and 14f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * limitations under the License. 15f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes */ 16f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampepackage android.telecom; 18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 1907ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughesimport android.annotation.SdkConstant; 2076b6167407c2b6f5d40ad895b2793a6b037f54b2Elliott Hughesimport android.annotation.SystemApi; 21f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesimport android.app.Service; 22d49012909625c3bf87bf51138fe79315ce1b1bdcAndreas Gampeimport android.content.Intent; 23eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughesimport android.hardware.camera2.CameraManager; 2487583b3de6e811e141f8c97c1f796eb516e8a751Andreas Gampeimport android.net.Uri; 25e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Morelandimport android.os.Bundle; 26e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Morelandimport android.os.Handler; 27e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Morelandimport android.os.IBinder; 280795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartierimport android.os.Looper; 29bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughesimport android.os.Message; 30f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesimport android.view.Surface; 31f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 32f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesimport com.android.internal.os.SomeArgs; 331bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughesimport com.android.internal.telecom.IInCallAdapter; 34545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughesimport com.android.internal.telecom.IInCallService; 35f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 36f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughesimport java.lang.String; 3700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersimport java.util.Collections; 3853b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogersimport java.util.List; 39545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes 40f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes/** 41f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * This service is implemented by any app that wishes to provide the user-interface for managing 421bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes * phone calls. Telecom binds to this service while there exists a live (active or incoming) call, 438c2ff641294715864013737fdec57cdfd410270cMan Cao * and uses it to notify the in-call app of any live and recently disconnected calls. An app must 44f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * first be set as the default phone app (See {@link TelecomManager#getDefaultDialerPackage()}) 45f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * before the telecom service will bind to its {@code InCallService} implementation. 46f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * <p> 47f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * Below is an example manifest registration for an {@code InCallService}. The meta-data 482cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier * ({@link TelecomManager#METADATA_IN_CALL_SERVICE_UI}) indicates that this particular 49f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes * {@code InCallService} implementation intends to replace the built-in in-call UI. 50bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes * <pre> 5153b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers * {@code 52970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * <service android:name="your.package.YourInCallServiceImplementation" 53970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * android:permission="android.permission.BIND_INCALL_SERVICE"> 54970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * <meta-data android:name="android.telecom.IN_CALL_SERVICE_UI" android:value="true" /> 55970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * <intent-filter> 56ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz * <action android:name="android.telecom.InCallService"/> 57970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * </intent-filter> 5800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * </service> 59970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * } 60970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz * </pre> 6114e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch */ 6214e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birchpublic abstract class InCallService extends Service { 6314e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch 6414e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch /** 6514e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch * The {@link Intent} that must be declared as handled by the service. 6614e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch */ 6714e81447ebaa1d80aae0c53312d4ff238d3fd98aJohnnie Birch @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) 6846f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light public static final String SERVICE_INTERFACE = "android.telecom.InCallService"; 6946f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light 7046f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light private static final int MSG_SET_IN_CALL_ADAPTER = 1; 71970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz private static final int MSG_ADD_CALL = 2; 72970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz private static final int MSG_UPDATE_CALL = 3; 73970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz private static final int MSG_SET_POST_DIAL_WAIT = 4; 74ee1d79a603c77c0667b27c075a983579d5c51f7eSebastien Hertz private static final int MSG_ON_CALL_AUDIO_STATE_CHANGED = 5; 75970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz private static final int MSG_BRING_TO_FOREGROUND = 6; 76970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz private static final int MSG_ON_CAN_ADD_CALL_CHANGED = 7; 77970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz private static final int MSG_SILENCE_RINGER = 8; 7888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light private static final int MSG_ON_CONNECTION_EVENT = 9; 7988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light private static final int MSG_ON_RTT_UPGRADE_REQUEST = 10; 80970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz 81970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz /** Default Handler used to consolidate binder method calls onto a single thread. */ 82970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz private final Handler mHandler = new Handler(Looper.getMainLooper()) { 83970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz @Override 84970c10e175b903c13fa3aea0231ce87834c4ca65Sebastien Hertz public void handleMessage(Message msg) { 8515bf2d34efa2218e287b584fb3653d268b9edc8dIan Rogers if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) { 86bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes return; 8753b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers } 88bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 89bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes switch (msg.what) { 90bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes case MSG_SET_IN_CALL_ADAPTER: 91bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes String callingPackage = getApplicationContext().getOpPackageName(); 92bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage, 93bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes getApplicationContext().getApplicationInfo().targetSdkVersion); 94bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes mPhone.addListener(mPhoneListener); 95bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes onPhoneCreated(mPhone); 96bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes break; 97bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes case MSG_ADD_CALL: 98bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes mPhone.internalAddCall((ParcelableCall) msg.obj); 99bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes break; 100bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes case MSG_UPDATE_CALL: 101bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes mPhone.internalUpdateCall((ParcelableCall) msg.obj); 102bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes break; 103bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes case MSG_SET_POST_DIAL_WAIT: { 104bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes SomeArgs args = (SomeArgs) msg.obj; 105bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes try { 106bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes String callId = (String) args.arg1; 107bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes String remaining = (String) args.arg2; 10821f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes mPhone.internalSetPostDialWait(callId, remaining); 109bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes } finally { 110bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes args.recycle(); 111bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes } 112bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes break; 113bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes } 114bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes case MSG_ON_CALL_AUDIO_STATE_CHANGED: 115bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes mPhone.internalCallAudioStateChanged((CallAudioState) msg.obj); 116bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes break; 117bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes case MSG_BRING_TO_FOREGROUND: 118bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes mPhone.internalBringToForeground(msg.arg1 == 1); 119bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes break; 120ba0b9c55adce3f533845ab1b25c552589e5b4118Elliott Hughes case MSG_ON_CAN_ADD_CALL_CHANGED: 1212921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom mPhone.internalSetCanAddCall(msg.arg1 == 1); 1222921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom break; 1232921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom case MSG_SILENCE_RINGER: 1242921201dce37ba40c55b89c0deca3c34bf64168eBrian Carlstrom mPhone.internalSilenceRinger(); 125bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes break; 12621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes case MSG_ON_CONNECTION_EVENT: { 127d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers SomeArgs args = (SomeArgs) msg.obj; 128920af3e556c730a5fbdab90a6d0ec1a2dbe8940bJeff Hao try { 12921f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes String callId = (String) args.arg1; 13021f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes String event = (String) args.arg2; 13121f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes Bundle extras = (Bundle) args.arg3; 13221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes mPhone.internalOnConnectionEvent(callId, event, extras); 133f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } finally { 134f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes args.recycle(); 135f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 136bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes break; 13750b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers } 138bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes case MSG_ON_RTT_UPGRADE_REQUEST: { 13950b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers String callId = (String) msg.obj; 140bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes int requestId = msg.arg1; 141bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes mPhone.internalOnRttUpgradeRequest(callId, requestId); 14221f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes break; 143bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes } 144bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes default: 14521f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes break; 14621f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes } 14721f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes } 148bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes }; 14921f32d704a21bcd67d7b87b149b6314ff92946cbElliott Hughes 150bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes /** Manages the binder calls so that the implementor does not need to deal with it. */ 151bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes private final class InCallServiceBinder extends IInCallService.Stub { 152bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes @Override 1532cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier public void setInCallAdapter(IInCallAdapter inCallAdapter) { 154545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget(); 155545a064aca775ba801790fced3d713d8a87bfc61Elliott Hughes } 156bfe487be25652c5456236661b9d9c3579d2296c1Elliott Hughes 157f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes @Override 158f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes public void addCall(ParcelableCall call) { 15900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget(); 16053b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers } 161767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes 162f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes @Override 163f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes public void updateCall(ParcelableCall call) { 1641bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget(); 165767a147529da3ee8240f3ce4cd3af22ae454be64Elliott Hughes } 166f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 167f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes @Override 1681bac54ffa933fbe9b92b62437577f2f4583eff1aElliott Hughes public void setPostDial(String callId, String remaining) { 16947fce01c0f27dba716fa6b97242562fbc5c26eeaElliott Hughes // TODO: Unused 170f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 171f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 172f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes @Override 173f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes public void setPostDialWait(String callId, String remaining) { 1743b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin SomeArgs args = SomeArgs.obtain(); 1753b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin args.arg1 = callId; 176f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes args.arg2 = remaining; 177f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes mHandler.obtainMessage(MSG_SET_POST_DIAL_WAIT, args).sendToTarget(); 1783b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin } 179f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes 180f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes @Override 181f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes public void onCallAudioStateChanged(CallAudioState callAudioState) { 182f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes mHandler.obtainMessage(MSG_ON_CALL_AUDIO_STATE_CHANGED, callAudioState).sendToTarget(); 183f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes } 184eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes 185f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes @Override 186f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes public void bringToForeground(boolean showDialpad) { 187f6a1e1e44b94221c4e6b063b36921c712a33910bElliott Hughes mHandler.obtainMessage(MSG_BRING_TO_FOREGROUND, showDialpad ? 1 : 0, 0).sendToTarget(); 188 } 189 190 @Override 191 public void onCanAddCallChanged(boolean canAddCall) { 192 mHandler.obtainMessage(MSG_ON_CAN_ADD_CALL_CHANGED, canAddCall ? 1 : 0, 0) 193 .sendToTarget(); 194 } 195 196 @Override 197 public void silenceRinger() { 198 mHandler.obtainMessage(MSG_SILENCE_RINGER).sendToTarget(); 199 } 200 201 @Override 202 public void onConnectionEvent(String callId, String event, Bundle extras) { 203 SomeArgs args = SomeArgs.obtain(); 204 args.arg1 = callId; 205 args.arg2 = event; 206 args.arg3 = extras; 207 mHandler.obtainMessage(MSG_ON_CONNECTION_EVENT, args).sendToTarget(); 208 } 209 210 @Override 211 public void onRttUpgradeRequest(String callId, int id) { 212 mHandler.obtainMessage(MSG_ON_RTT_UPGRADE_REQUEST, id, 0, callId).sendToTarget(); 213 } 214 } 215 216 private Phone.Listener mPhoneListener = new Phone.Listener() { 217 /** ${inheritDoc} */ 218 @Override 219 public void onAudioStateChanged(Phone phone, AudioState audioState) { 220 InCallService.this.onAudioStateChanged(audioState); 221 } 222 223 public void onCallAudioStateChanged(Phone phone, CallAudioState callAudioState) { 224 InCallService.this.onCallAudioStateChanged(callAudioState); 225 }; 226 227 /** ${inheritDoc} */ 228 @Override 229 public void onBringToForeground(Phone phone, boolean showDialpad) { 230 InCallService.this.onBringToForeground(showDialpad); 231 } 232 233 /** ${inheritDoc} */ 234 @Override 235 public void onCallAdded(Phone phone, Call call) { 236 InCallService.this.onCallAdded(call); 237 } 238 239 /** ${inheritDoc} */ 240 @Override 241 public void onCallRemoved(Phone phone, Call call) { 242 InCallService.this.onCallRemoved(call); 243 } 244 245 /** ${inheritDoc} */ 246 @Override 247 public void onCanAddCallChanged(Phone phone, boolean canAddCall) { 248 InCallService.this.onCanAddCallChanged(canAddCall); 249 } 250 251 /** ${inheritDoc} */ 252 @Override 253 public void onSilenceRinger(Phone phone) { 254 InCallService.this.onSilenceRinger(); 255 } 256 257 }; 258 259 private Phone mPhone; 260 261 public InCallService() { 262 } 263 264 @Override 265 public IBinder onBind(Intent intent) { 266 return new InCallServiceBinder(); 267 } 268 269 @Override 270 public boolean onUnbind(Intent intent) { 271 if (mPhone != null) { 272 Phone oldPhone = mPhone; 273 mPhone = null; 274 275 oldPhone.destroy(); 276 // destroy sets all the calls to disconnected if any live ones still exist. Therefore, 277 // it is important to remove the Listener *after* the call to destroy so that 278 // InCallService.on* callbacks are appropriately called. 279 oldPhone.removeListener(mPhoneListener); 280 281 onPhoneDestroyed(oldPhone); 282 } 283 284 return false; 285 } 286 287 /** 288 * Obtain the {@code Phone} associated with this {@code InCallService}. 289 * 290 * @return The {@code Phone} object associated with this {@code InCallService}, or {@code null} 291 * if the {@code InCallService} is not in a state where it has an associated 292 * {@code Phone}. 293 * @hide 294 * @deprecated Use direct methods on InCallService instead of {@link Phone}. 295 */ 296 @SystemApi 297 @Deprecated 298 public Phone getPhone() { 299 return mPhone; 300 } 301 302 /** 303 * Obtains the current list of {@code Call}s to be displayed by this in-call service. 304 * 305 * @return A list of the relevant {@code Call}s. 306 */ 307 public final List<Call> getCalls() { 308 return mPhone == null ? Collections.<Call>emptyList() : mPhone.getCalls(); 309 } 310 311 /** 312 * Returns if the device can support additional calls. 313 * 314 * @return Whether the phone supports adding more calls. 315 */ 316 public final boolean canAddCall() { 317 return mPhone == null ? false : mPhone.canAddCall(); 318 } 319 320 /** 321 * Obtains the current phone call audio state. 322 * 323 * @return An object encapsulating the audio state. Returns null if the service is not 324 * fully initialized. 325 * @deprecated Use {@link #getCallAudioState()} instead. 326 * @hide 327 */ 328 @Deprecated 329 public final AudioState getAudioState() { 330 return mPhone == null ? null : mPhone.getAudioState(); 331 } 332 333 /** 334 * Obtains the current phone call audio state. 335 * 336 * @return An object encapsulating the audio state. Returns null if the service is not 337 * fully initialized. 338 */ 339 public final CallAudioState getCallAudioState() { 340 return mPhone == null ? null : mPhone.getCallAudioState(); 341 } 342 343 /** 344 * Sets the microphone mute state. When this request is honored, there will be change to 345 * the {@link #getCallAudioState()}. 346 * 347 * @param state {@code true} if the microphone should be muted; {@code false} otherwise. 348 */ 349 public final void setMuted(boolean state) { 350 if (mPhone != null) { 351 mPhone.setMuted(state); 352 } 353 } 354 355 /** 356 * Sets the audio route (speaker, bluetooth, etc...). When this request is honored, there will 357 * be change to the {@link #getCallAudioState()}. 358 * 359 * @param route The audio route to use. 360 */ 361 public final void setAudioRoute(int route) { 362 if (mPhone != null) { 363 mPhone.setAudioRoute(route); 364 } 365 } 366 367 /** 368 * Invoked when the {@code Phone} has been created. This is a signal to the in-call experience 369 * to start displaying in-call information to the user. Each instance of {@code InCallService} 370 * will have only one {@code Phone}, and this method will be called exactly once in the lifetime 371 * of the {@code InCallService}. 372 * 373 * @param phone The {@code Phone} object associated with this {@code InCallService}. 374 * @hide 375 * @deprecated Use direct methods on InCallService instead of {@link Phone}. 376 */ 377 @SystemApi 378 @Deprecated 379 public void onPhoneCreated(Phone phone) { 380 } 381 382 /** 383 * Invoked when a {@code Phone} has been destroyed. This is a signal to the in-call experience 384 * to stop displaying in-call information to the user. This method will be called exactly once 385 * in the lifetime of the {@code InCallService}, and it will always be called after a previous 386 * call to {@link #onPhoneCreated(Phone)}. 387 * 388 * @param phone The {@code Phone} object associated with this {@code InCallService}. 389 * @hide 390 * @deprecated Use direct methods on InCallService instead of {@link Phone}. 391 */ 392 @SystemApi 393 @Deprecated 394 public void onPhoneDestroyed(Phone phone) { 395 } 396 397 /** 398 * Called when the audio state changes. 399 * 400 * @param audioState The new {@link AudioState}. 401 * @deprecated Use {@link #onCallAudioStateChanged(CallAudioState) instead}. 402 * @hide 403 */ 404 @Deprecated 405 public void onAudioStateChanged(AudioState audioState) { 406 } 407 408 /** 409 * Called when the audio state changes. 410 * 411 * @param audioState The new {@link CallAudioState}. 412 */ 413 public void onCallAudioStateChanged(CallAudioState audioState) { 414 } 415 416 /** 417 * Called to bring the in-call screen to the foreground. The in-call experience should 418 * respond immediately by coming to the foreground to inform the user of the state of 419 * ongoing {@code Call}s. 420 * 421 * @param showDialpad If true, put up the dialpad when the screen is shown. 422 */ 423 public void onBringToForeground(boolean showDialpad) { 424 } 425 426 /** 427 * Called when a {@code Call} has been added to this in-call session. The in-call user 428 * experience should add necessary state listeners to the specified {@code Call} and 429 * immediately start to show the user information about the existence 430 * and nature of this {@code Call}. Subsequent invocations of {@link #getCalls()} will 431 * include this {@code Call}. 432 * 433 * @param call A newly added {@code Call}. 434 */ 435 public void onCallAdded(Call call) { 436 } 437 438 /** 439 * Called when a {@code Call} has been removed from this in-call session. The in-call user 440 * experience should remove any state listeners from the specified {@code Call} and 441 * immediately stop displaying any information about this {@code Call}. 442 * Subsequent invocations of {@link #getCalls()} will no longer include this {@code Call}. 443 * 444 * @param call A newly removed {@code Call}. 445 */ 446 public void onCallRemoved(Call call) { 447 } 448 449 /** 450 * Called when the ability to add more calls changes. If the phone cannot 451 * support more calls then {@code canAddCall} is set to {@code false}. If it can, then it 452 * is set to {@code true}. This can be used to control the visibility of UI to add more calls. 453 * 454 * @param canAddCall Indicates whether an additional call can be added. 455 */ 456 public void onCanAddCallChanged(boolean canAddCall) { 457 } 458 459 /** 460 * Called to silence the ringer if a ringing call exists. 461 */ 462 public void onSilenceRinger() { 463 } 464 465 /** 466 * Unused; to handle connection events issued by a {@link ConnectionService}, implement the 467 * {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)} callback. 468 * <p> 469 * See {@link Connection#sendConnectionEvent(String, Bundle)}. 470 * 471 * @param call The call the event is associated with. 472 * @param event The event. 473 * @param extras Any associated extras. 474 */ 475 public void onConnectionEvent(Call call, String event, Bundle extras) { 476 } 477 478 /** 479 * Used to issue commands to the {@link Connection.VideoProvider} associated with a 480 * {@link Call}. 481 */ 482 public static abstract class VideoCall { 483 484 /** @hide */ 485 public abstract void destroy(); 486 487 /** 488 * Registers a callback to receive commands and state changes for video calls. 489 * 490 * @param callback The video call callback. 491 */ 492 public abstract void registerCallback(VideoCall.Callback callback); 493 494 /** 495 * Registers a callback to receive commands and state changes for video calls. 496 * 497 * @param callback The video call callback. 498 * @param handler A handler which commands and status changes will be delivered to. 499 */ 500 public abstract void registerCallback(VideoCall.Callback callback, Handler handler); 501 502 /** 503 * Clears the video call callback set via {@link #registerCallback}. 504 * 505 * @param callback The video call callback to clear. 506 */ 507 public abstract void unregisterCallback(VideoCall.Callback callback); 508 509 /** 510 * Sets the camera to be used for the outgoing video. 511 * <p> 512 * Handled by {@link Connection.VideoProvider#onSetCamera(String)}. 513 * 514 * @param cameraId The id of the camera (use ids as reported by 515 * {@link CameraManager#getCameraIdList()}). 516 */ 517 public abstract void setCamera(String cameraId); 518 519 /** 520 * Sets the surface to be used for displaying a preview of what the user's camera is 521 * currently capturing. When video transmission is enabled, this is the video signal which 522 * is sent to the remote device. 523 * <p> 524 * Handled by {@link Connection.VideoProvider#onSetPreviewSurface(Surface)}. 525 * 526 * @param surface The {@link Surface}. 527 */ 528 public abstract void setPreviewSurface(Surface surface); 529 530 /** 531 * Sets the surface to be used for displaying the video received from the remote device. 532 * <p> 533 * Handled by {@link Connection.VideoProvider#onSetDisplaySurface(Surface)}. 534 * 535 * @param surface The {@link Surface}. 536 */ 537 public abstract void setDisplaySurface(Surface surface); 538 539 /** 540 * Sets the device orientation, in degrees. Assumes that a standard portrait orientation of 541 * the device is 0 degrees. 542 * <p> 543 * Handled by {@link Connection.VideoProvider#onSetDeviceOrientation(int)}. 544 * 545 * @param rotation The device orientation, in degrees. 546 */ 547 public abstract void setDeviceOrientation(int rotation); 548 549 /** 550 * Sets camera zoom ratio. 551 * <p> 552 * Handled by {@link Connection.VideoProvider#onSetZoom(float)}. 553 * 554 * @param value The camera zoom ratio. 555 */ 556 public abstract void setZoom(float value); 557 558 /** 559 * Issues a request to modify the properties of the current video session. 560 * <p> 561 * Example scenarios include: requesting an audio-only call to be upgraded to a 562 * bi-directional video call, turning on or off the user's camera, sending a pause signal 563 * when the {@link InCallService} is no longer the foreground application. 564 * <p> 565 * Handled by 566 * {@link Connection.VideoProvider#onSendSessionModifyRequest(VideoProfile, VideoProfile)}. 567 * 568 * @param requestProfile The requested call video properties. 569 */ 570 public abstract void sendSessionModifyRequest(VideoProfile requestProfile); 571 572 /** 573 * Provides a response to a request to change the current call video session 574 * properties. This should be called in response to a request the {@link InCallService} has 575 * received via {@link VideoCall.Callback#onSessionModifyRequestReceived}. 576 * <p> 577 * Handled by 578 * {@link Connection.VideoProvider#onSendSessionModifyResponse(VideoProfile)}. 579 * 580 * @param responseProfile The response call video properties. 581 */ 582 public abstract void sendSessionModifyResponse(VideoProfile responseProfile); 583 584 /** 585 * Issues a request to the {@link Connection.VideoProvider} to retrieve the capabilities 586 * of the current camera. The current camera is selected using 587 * {@link VideoCall#setCamera(String)}. 588 * <p> 589 * Camera capabilities are reported to the caller via 590 * {@link VideoCall.Callback#onCameraCapabilitiesChanged(VideoProfile.CameraCapabilities)}. 591 * <p> 592 * Handled by {@link Connection.VideoProvider#onRequestCameraCapabilities()}. 593 */ 594 public abstract void requestCameraCapabilities(); 595 596 /** 597 * Issues a request to the {@link Connection.VideoProvider} to retrieve the cumulative data 598 * usage for the video component of the current call (in bytes). Data usage is reported 599 * to the caller via {@link VideoCall.Callback#onCallDataUsageChanged}. 600 * <p> 601 * Handled by {@link Connection.VideoProvider#onRequestConnectionDataUsage()}. 602 */ 603 public abstract void requestCallDataUsage(); 604 605 /** 606 * Provides the {@link Connection.VideoProvider} with the {@link Uri} of an image to be 607 * displayed to the peer device when the video signal is paused. 608 * <p> 609 * Handled by {@link Connection.VideoProvider#onSetPauseImage(Uri)}. 610 * 611 * @param uri URI of image to display. 612 */ 613 public abstract void setPauseImage(Uri uri); 614 615 /** 616 * The {@link InCallService} extends this class to provide a means of receiving callbacks 617 * from the {@link Connection.VideoProvider}. 618 * <p> 619 * When the {@link InCallService} receives the 620 * {@link Call.Callback#onVideoCallChanged(Call, VideoCall)} callback, it should create an 621 * instance its {@link VideoCall.Callback} implementation and set it on the 622 * {@link VideoCall} using {@link VideoCall#registerCallback(Callback)}. 623 */ 624 public static abstract class Callback { 625 /** 626 * Called when the {@link Connection.VideoProvider} receives a session modification 627 * request from the peer device. 628 * <p> 629 * The {@link InCallService} may potentially prompt the user to confirm whether they 630 * wish to accept the request, or decide to automatically accept the request. In either 631 * case the {@link InCallService} should call 632 * {@link VideoCall#sendSessionModifyResponse(VideoProfile)} to indicate the video 633 * profile agreed upon. 634 * <p> 635 * Callback originates from 636 * {@link Connection.VideoProvider#receiveSessionModifyRequest(VideoProfile)}. 637 * 638 * @param videoProfile The requested video profile. 639 */ 640 public abstract void onSessionModifyRequestReceived(VideoProfile videoProfile); 641 642 /** 643 * Called when the {@link Connection.VideoProvider} receives a response to a session 644 * modification request previously sent to the peer device. 645 * <p> 646 * The new video state should not be considered active by the {@link InCallService} 647 * until the {@link Call} video state changes (the 648 * {@link Call.Callback#onDetailsChanged(Call, Call.Details)} callback is triggered 649 * when the video state changes). 650 * <p> 651 * Callback originates from 652 * {@link Connection.VideoProvider#receiveSessionModifyResponse(int, VideoProfile, 653 * VideoProfile)}. 654 * 655 * @param status Status of the session modify request. Valid values are 656 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_SUCCESS}, 657 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_FAIL}, 658 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_INVALID}, 659 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_TIMED_OUT}, 660 * {@link Connection.VideoProvider#SESSION_MODIFY_REQUEST_REJECTED_BY_REMOTE}. 661 * @param requestedProfile The original request which was sent to the peer device. 662 * @param responseProfile The actual profile changes made by the peer device. 663 */ 664 public abstract void onSessionModifyResponseReceived(int status, 665 VideoProfile requestedProfile, VideoProfile responseProfile); 666 667 /** 668 * Handles events related to the current video session which the {@link InCallService} 669 * may wish to handle. These are separate from requested changes to the session due to 670 * the underlying protocol or connection. 671 * <p> 672 * Callback originates from 673 * {@link Connection.VideoProvider#handleCallSessionEvent(int)}. 674 * 675 * @param event The event. Valid values are: 676 * {@link Connection.VideoProvider#SESSION_EVENT_RX_PAUSE}, 677 * {@link Connection.VideoProvider#SESSION_EVENT_RX_RESUME}, 678 * {@link Connection.VideoProvider#SESSION_EVENT_TX_START}, 679 * {@link Connection.VideoProvider#SESSION_EVENT_TX_STOP}, 680 * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_FAILURE}, 681 * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_READY}, 682 * {@link Connection.VideoProvider#SESSION_EVENT_CAMERA_PERMISSION_ERROR}. 683 */ 684 public abstract void onCallSessionEvent(int event); 685 686 /** 687 * Handles a change to the video dimensions from the peer device. This could happen if, 688 * for example, the peer changes orientation of their device, or switches cameras. 689 * <p> 690 * Callback originates from 691 * {@link Connection.VideoProvider#changePeerDimensions(int, int)}. 692 * 693 * @param width The updated peer video width. 694 * @param height The updated peer video height. 695 */ 696 public abstract void onPeerDimensionsChanged(int width, int height); 697 698 /** 699 * Handles a change to the video quality. 700 * <p> 701 * Callback originates from {@link Connection.VideoProvider#changeVideoQuality(int)}. 702 * 703 * @param videoQuality The updated peer video quality. Valid values: 704 * {@link VideoProfile#QUALITY_HIGH}, 705 * {@link VideoProfile#QUALITY_MEDIUM}, 706 * {@link VideoProfile#QUALITY_LOW}, 707 * {@link VideoProfile#QUALITY_DEFAULT}. 708 */ 709 public abstract void onVideoQualityChanged(int videoQuality); 710 711 /** 712 * Handles an update to the total data used for the current video session. 713 * <p> 714 * Used by the {@link Connection.VideoProvider} in response to 715 * {@link VideoCall#requestCallDataUsage()}. May also be called periodically by the 716 * {@link Connection.VideoProvider}. 717 * <p> 718 * Callback originates from {@link Connection.VideoProvider#setCallDataUsage(long)}. 719 * 720 * @param dataUsage The updated data usage (in bytes). 721 */ 722 public abstract void onCallDataUsageChanged(long dataUsage); 723 724 /** 725 * Handles a change in the capabilities of the currently selected camera. 726 * <p> 727 * Used by the {@link Connection.VideoProvider} in response to 728 * {@link VideoCall#requestCameraCapabilities()}. The {@link Connection.VideoProvider} 729 * may also report the camera capabilities after a call to 730 * {@link VideoCall#setCamera(String)}. 731 * <p> 732 * Callback originates from 733 * {@link Connection.VideoProvider#changeCameraCapabilities( 734 * VideoProfile.CameraCapabilities)}. 735 * 736 * @param cameraCapabilities The changed camera capabilities. 737 */ 738 public abstract void onCameraCapabilitiesChanged( 739 VideoProfile.CameraCapabilities cameraCapabilities); 740 } 741 } 742} 743