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