1 /**
2  * Copyright (C) 2022 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.telephony.imsmedia;
18 
19 import android.os.Binder;
20 import android.os.IBinder;
21 import android.telephony.ims.RtpHeaderExtension;
22 
23 import java.util.List;
24 import java.util.concurrent.Executor;
25 
26 /**
27  * Video session callback APIs
28  *
29  * @hide
30  */
31 public class VideoSessionCallback extends ImsMediaManager.SessionCallback {
32 
33     private final CallbackBinder mCallbackBinder = new CallbackBinder(this);
34 
35     /** @hide */
36     @Override
getBinder()37     public IBinder getBinder() {
38         return mCallbackBinder;
39     }
40 
41     /** @hide */
42     @Override
setExecutor(final Executor executor)43     public void setExecutor(final Executor executor) {
44         mCallbackBinder.setExecutor(executor);
45     }
46 
47     private static class CallbackBinder extends IImsVideoSessionCallback.Stub {
48         private final VideoSessionCallback mLocalCallback;
49         private Executor mExecutor;
50 
CallbackBinder(final VideoSessionCallback localCallback)51         CallbackBinder(final VideoSessionCallback localCallback) {
52             mLocalCallback = localCallback;
53         }
54 
55         @Override
onOpenSessionSuccess(final IImsVideoSession session)56         public void onOpenSessionSuccess(final IImsVideoSession session) {
57             if (mLocalCallback == null) return;
58 
59             final long callingIdentity = Binder.clearCallingIdentity();
60             try {
61                 mExecutor.execute(()
62                         -> mLocalCallback.onOpenSessionSuccess(new ImsVideoSession(session)));
63             } finally {
64                 restoreCallingIdentity(callingIdentity);
65             }
66         }
67 
68         @Override
onOpenSessionFailure(final int error)69         public void onOpenSessionFailure(final int error) {
70             if (mLocalCallback == null) return;
71 
72             final long callingIdentity = Binder.clearCallingIdentity();
73             try {
74                 mExecutor.execute(() -> mLocalCallback.onOpenSessionFailure(error));
75             } finally {
76                 restoreCallingIdentity(callingIdentity);
77             }
78         }
79 
80         @Override
onSessionClosed()81         public void onSessionClosed() {
82             if (mLocalCallback == null) return;
83 
84             final long callingIdentity = Binder.clearCallingIdentity();
85             try {
86                 mExecutor.execute(() -> mLocalCallback.onSessionClosed());
87             } finally {
88                 restoreCallingIdentity(callingIdentity);
89             }
90         }
91 
92         @Override
onModifySessionResponse(final VideoConfig config, final @ImsMediaSession.SessionOperationResult int result)93         public void onModifySessionResponse(final VideoConfig config,
94                 final @ImsMediaSession.SessionOperationResult int result) {
95             if (mLocalCallback == null) return;
96 
97             final long callingIdentity = Binder.clearCallingIdentity();
98             try {
99                 mExecutor.execute(() -> mLocalCallback.onModifySessionResponse(config, result));
100             } finally {
101                 restoreCallingIdentity(callingIdentity);
102             }
103         }
104 
105         @Override
onFirstMediaPacketReceived(final VideoConfig config)106         public void onFirstMediaPacketReceived(final VideoConfig config) {
107             if (mLocalCallback == null) return;
108 
109             final long callingIdentity = Binder.clearCallingIdentity();
110             try {
111                 mExecutor.execute(() -> mLocalCallback.onFirstMediaPacketReceived(config));
112             } finally {
113                 restoreCallingIdentity(callingIdentity);
114             }
115         }
116 
117         @Override
onPeerDimensionChanged(final int width, final int height)118         public void onPeerDimensionChanged(final int width, final int height) {
119             if (mLocalCallback == null) return;
120 
121             final long callingIdentity = Binder.clearCallingIdentity();
122             try {
123                 mExecutor.execute(() -> mLocalCallback.onPeerDimensionChanged(width, height));
124             } finally {
125                 restoreCallingIdentity(callingIdentity);
126             }
127         }
128 
129         @Override
onHeaderExtensionReceived(final List<RtpHeaderExtension> extensions)130         public void onHeaderExtensionReceived(final List<RtpHeaderExtension> extensions) {
131             if (mLocalCallback == null) return;
132 
133             final long callingIdentity = Binder.clearCallingIdentity();
134             try {
135                 mExecutor.execute(() -> mLocalCallback.onHeaderExtensionReceived(extensions));
136             } finally {
137                 restoreCallingIdentity(callingIdentity);
138             }
139         }
140 
141         @Override
notifyMediaInactivity(final int packetType)142         public void notifyMediaInactivity(final int packetType) {
143             if (mLocalCallback == null) return;
144 
145             final long callingIdentity = Binder.clearCallingIdentity();
146             try {
147                 mExecutor.execute(() -> mLocalCallback.notifyMediaInactivity(packetType));
148             } finally {
149                 restoreCallingIdentity(callingIdentity);
150             }
151         }
152 
153         @Override
notifyBitrate(final int bitrate)154         public void notifyBitrate(final int bitrate) {
155             if (mLocalCallback == null) return;
156 
157             final long callingIdentity = Binder.clearCallingIdentity();
158             try {
159                 mExecutor.execute(() -> mLocalCallback.notifyBitrate(bitrate));
160             } finally {
161                 restoreCallingIdentity(callingIdentity);
162             }
163         }
164 
165         @Override
notifyVideoDataUsage(final long bytes)166         public void notifyVideoDataUsage(final long bytes) {
167             if (mLocalCallback == null) return;
168 
169             final long callingIdentity = Binder.clearCallingIdentity();
170             try {
171                 mExecutor.execute(() -> mLocalCallback.notifyVideoDataUsage(bytes));
172             } finally {
173                 restoreCallingIdentity(callingIdentity);
174             }
175         }
176 
setExecutor(final Executor executor)177         private void setExecutor(final Executor executor) {
178             mExecutor = executor;
179         }
180     }
181 
182     /**
183      * Called when ImsMediaSession#modifySession() API is handled
184      *
185      * @param config The VideoConfig passed in ImsMediaSession#modifySession()
186      * @param result The result of modify session
187      */
onModifySessionResponse(final VideoConfig config, final @ImsMediaSession.SessionOperationResult int result)188     public void onModifySessionResponse(final VideoConfig config,
189             final @ImsMediaSession.SessionOperationResult int result) {
190         // Base Implementation
191     }
192 
193     /**
194      * Indicates when the first Rtp media packet is received by the UE
195      * during ring back, call hold or early media scenarios. This is
196      * sent only if the packet is received on the active remote
197      * configuration.
198      *
199      * In case of early media scenarios, the implementation shall play
200      * the RTP packets from the most recently added config.
201      *
202      * @param config the remote config where media packet is received
203      */
onFirstMediaPacketReceived(final VideoConfig config)204     public void onFirstMediaPacketReceived(final VideoConfig config) {
205         // Base Implementation
206     }
207 
208     /**
209      * Notify when the received video frame resolution is different with the current resolution.
210      * @param width width of resolution changed.
211      * @param height height of resolution changed.
212      */
onPeerDimensionChanged(final int width, final int height)213     public void onPeerDimensionChanged(final int width, final int height) {
214         // Base Implementation
215     }
216 
217     /**
218      * RTP header extension received from the other party
219      *
220      * @param extensions List of received RTP header extensions
221      */
onHeaderExtensionReceived(final List<RtpHeaderExtension> extensions)222     public void onHeaderExtensionReceived(final List<RtpHeaderExtension> extensions){
223         // Base Implementation
224     }
225 
226     /**
227      * Notifies media inactivity observed as per thresholds set by
228      * setMediaQualityThreshold() API
229      *
230      * @param packetType either RTP or RTCP
231      */
notifyMediaInactivity(final int packetType)232     public void notifyMediaInactivity(final int packetType) {
233          // Base Implementation
234     }
235 
236     /**
237      * Notifies when the video bitrate decreased below the threshold set by
238      * setMediaQualityThreshold() API
239      *
240      * @param bitrate The bitrate of sending video packets in bps unit
241      */
notifyBitrate(final int bitrate)242     public void notifyBitrate(final int bitrate) {
243         // Base Implementation
244     }
245 
246     /**
247      * Notify accumulated video data usage in the current session.
248      * @param bytes bytes of send and received rtp data.
249      */
notifyVideoDataUsage(final long bytes)250     public void notifyVideoDataUsage(final long bytes) {
251         // Base Implementation
252     }
253 }
254