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