• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.telecom;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.SdkConstant;
22 import android.annotation.SystemApi;
23 import android.app.Service;
24 import android.content.Intent;
25 import android.os.Handler;
26 import android.os.IBinder;
27 import android.os.Looper;
28 import android.os.Message;
29 import android.os.RemoteException;
30 
31 import androidx.annotation.Nullable;
32 
33 import com.android.internal.telecom.ICallStreamingService;
34 import com.android.internal.telecom.IStreamingCallAdapter;
35 
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 
39 /**
40  * This service is implemented by an app that wishes to provide functionality for a general call
41  * streaming sender for voip calls.
42  * <p>
43  * Below is an example manifest registration for a {@code CallStreamingService}.
44  * <pre>
45  * {@code
46  * <service android:name=".EgCallStreamingService"
47  *     android:permission="android.permission.BIND_CALL_STREAMING_SERVICE" >
48  *     ...
49  *     <intent-filter>
50  *         <action android:name="android.telecom.CallStreamingService" />
51  *     </intent-filter>
52  * </service>
53  * }
54  * </pre>
55  *
56  * @hide
57  */
58 @SystemApi
59 public abstract class CallStreamingService extends Service {
60     /**
61      * The {@link android.content.Intent} that must be declared as handled by the service.
62      */
63     @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
64     public static final String SERVICE_INTERFACE = "android.telecom.CallStreamingService";
65 
66     private static final int MSG_SET_STREAMING_CALL_ADAPTER = 1;
67     private static final int MSG_CALL_STREAMING_STARTED = 2;
68     private static final int MSG_CALL_STREAMING_STOPPED = 3;
69     private static final int MSG_CALL_STREAMING_STATE_CHANGED = 4;
70 
71     /** Default Handler used to consolidate binder method calls onto a single thread. */
72     private final Handler mHandler = new Handler(Looper.getMainLooper()) {
73         @Override
74         public void handleMessage(Message msg) {
75             if (mStreamingCallAdapter == null && msg.what != MSG_SET_STREAMING_CALL_ADAPTER) {
76                 Log.i(this, "handleMessage: null adapter!");
77                 return;
78             }
79 
80             switch (msg.what) {
81                 case MSG_SET_STREAMING_CALL_ADAPTER:
82                     if (msg.obj != null) {
83                         Log.i(this, "MSG_SET_STREAMING_CALL_ADAPTER");
84                         mStreamingCallAdapter = new StreamingCallAdapter(
85                                 (IStreamingCallAdapter) msg.obj);
86                     }
87                     break;
88                 case MSG_CALL_STREAMING_STARTED:
89                     Log.i(this, "MSG_CALL_STREAMING_STARTED");
90                     mCall = (StreamingCall) msg.obj;
91                     mCall.setAdapter(mStreamingCallAdapter);
92                     CallStreamingService.this.onCallStreamingStarted(mCall);
93                     break;
94                 case MSG_CALL_STREAMING_STOPPED:
95                     Log.i(this, "MSG_CALL_STREAMING_STOPPED");
96                     mCall = null;
97                     mStreamingCallAdapter = null;
98                     CallStreamingService.this.onCallStreamingStopped();
99                     break;
100                 case MSG_CALL_STREAMING_STATE_CHANGED:
101                     int state = (int) msg.obj;
102                     if (mStreamingCallAdapter != null) {
103                         mCall.requestStreamingState(state);
104                         CallStreamingService.this.onCallStreamingStateChanged(state);
105                     }
106                     break;
107                 default:
108                     break;
109             }
110         }
111     };
112 
113     @Nullable
114     @Override
onBind(@onNull Intent intent)115     public IBinder onBind(@NonNull Intent intent) {
116         Log.i(this, "onBind");
117         return new CallStreamingServiceBinder();
118     }
119 
120     /** Manages the binder calls so that the implementor does not need to deal with it. */
121     private final class CallStreamingServiceBinder extends ICallStreamingService.Stub {
122         @Override
setStreamingCallAdapter(IStreamingCallAdapter streamingCallAdapter)123         public void setStreamingCallAdapter(IStreamingCallAdapter streamingCallAdapter)
124                 throws RemoteException {
125             Log.i(this, "setCallStreamingAdapter");
126             mHandler.obtainMessage(MSG_SET_STREAMING_CALL_ADAPTER, streamingCallAdapter)
127                     .sendToTarget();
128         }
129 
130         @Override
onCallStreamingStarted(StreamingCall call)131         public void onCallStreamingStarted(StreamingCall call) throws RemoteException {
132             Log.i(this, "onCallStreamingStarted");
133             mHandler.obtainMessage(MSG_CALL_STREAMING_STARTED, call).sendToTarget();
134         }
135 
136         @Override
onCallStreamingStopped()137         public void onCallStreamingStopped() throws RemoteException {
138             mHandler.obtainMessage(MSG_CALL_STREAMING_STOPPED).sendToTarget();
139         }
140 
141         @Override
onCallStreamingStateChanged(int state)142         public void onCallStreamingStateChanged(int state) throws RemoteException {
143             mHandler.obtainMessage(MSG_CALL_STREAMING_STATE_CHANGED, state).sendToTarget();
144         }
145     }
146 
147     /**
148      * Call streaming request reject reason used with
149      * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
150      * call streaming request due to unknown reason.
151      */
152     public static final int STREAMING_FAILED_UNKNOWN = 0;
153 
154     /**
155      * Call streaming request reject reason used with
156      * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
157      * call streaming request because there's an ongoing streaming call on this device.
158      */
159     public static final int STREAMING_FAILED_ALREADY_STREAMING = 1;
160 
161     /**
162      * Call streaming request reject reason used with
163      * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
164      * call streaming request because telecom can't find existing general streaming sender on this
165      * device.
166      */
167     public static final int STREAMING_FAILED_NO_SENDER = 2;
168 
169     /**
170      * Call streaming request reject reason used with
171      * {@link CallEventCallback#onCallStreamingFailed(int)} to indicate that telecom is rejecting a
172      * call streaming request because telecom can't bind to the general streaming sender app.
173      */
174     public static final int STREAMING_FAILED_SENDER_BINDING_ERROR = 3;
175 
176     private StreamingCallAdapter mStreamingCallAdapter;
177     private StreamingCall mCall;
178 
179     /**
180      * @hide
181      */
182     @IntDef(prefix = {"STREAMING_FAILED"},
183             value = {
184                     STREAMING_FAILED_UNKNOWN,
185                     STREAMING_FAILED_ALREADY_STREAMING,
186                     STREAMING_FAILED_NO_SENDER,
187                     STREAMING_FAILED_SENDER_BINDING_ERROR
188             })
189     @Retention(RetentionPolicy.SOURCE)
190     public @interface StreamingFailedReason {
191     }
192 
193     ;
194 
195     /**
196      * Called when a {@code StreamingCall} has been added to this call streaming session. The call
197      * streaming sender should start to intercept the device audio using audio records and audio
198      * tracks from Audio frameworks.
199      *
200      * @param call a newly added {@code StreamingCall}.
201      */
onCallStreamingStarted(@onNull StreamingCall call)202     public void onCallStreamingStarted(@NonNull StreamingCall call) {
203     }
204 
205     /**
206      * Called when a current {@code StreamingCall} has been removed from this call streaming
207      * session. The call streaming sender should notify the streaming receiver that the call is
208      * stopped streaming and stop the device audio interception.
209      */
onCallStreamingStopped()210     public void onCallStreamingStopped() {
211     }
212 
213     /**
214      * Called when the streaming state of current {@code StreamingCall} changed. General streaming
215      * sender usually get notified of the holding/unholding from the original owner voip app of the
216      * call.
217      */
onCallStreamingStateChanged(@treamingCall.StreamingCallState int state)218     public void onCallStreamingStateChanged(@StreamingCall.StreamingCallState int state) {
219     }
220 }
221