• 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 com.android.telephony.imsmedia;
18 
19 import android.app.Service;
20 import android.content.Intent;
21 import android.os.IBinder;
22 import android.os.Parcel;
23 import android.os.ParcelFileDescriptor;
24 import android.support.annotation.GuardedBy;
25 import android.telephony.imsmedia.IImsAudioSession;
26 import android.telephony.imsmedia.IImsAudioSessionCallback;
27 import android.telephony.imsmedia.IImsMedia;
28 import android.telephony.imsmedia.IImsMediaCallback;
29 import android.telephony.imsmedia.IImsTextSession;
30 import android.telephony.imsmedia.IImsTextSessionCallback;
31 import android.telephony.imsmedia.IImsVideoSession;
32 import android.telephony.imsmedia.IImsVideoSessionCallback;
33 import android.telephony.imsmedia.ImsMediaSession;
34 import android.telephony.imsmedia.RtpConfig;
35 import android.telephony.imsmedia.VideoConfig;
36 import android.util.Log;
37 import android.util.SparseArray;
38 
39 import com.android.telephony.imsmedia.Utils.OpenSessionParams;
40 
41 import java.util.concurrent.atomic.AtomicInteger;
42 
43 /** Controller that maintains all IMS Media sessions */
44 public class ImsMediaController extends Service {
45 
46     private static final String TAG = "ImsMediaController";
47     private AtomicInteger mSessionId = new AtomicInteger();
48     private OpenSessionCallback mCallback = new OpenSessionCallback();
49 
50     @GuardedBy("mSessions")
51     private final SparseArray<IMediaSession> mSessions = new SparseArray();
52 
53     private class ImsMediaBinder extends IImsMedia.Stub {
54         // TODO add permission checks
55         @Override
openSession( final ParcelFileDescriptor rtpFd, final ParcelFileDescriptor rtcpFd, final int sessionType, final RtpConfig rtpConfig, final IBinder callback)56         public void openSession(
57             final ParcelFileDescriptor rtpFd, final ParcelFileDescriptor rtcpFd,
58             final int sessionType, final RtpConfig rtpConfig, final IBinder callback) {
59             final int sessionId = mSessionId.getAndIncrement();
60 
61             IMediaSession session;
62             Log.d(TAG, "openSession: sessionId = " + sessionId
63                     + ", type=" + sessionType + "," + rtpConfig);
64             synchronized (mSessions) {
65                 switch (sessionType) {
66                     case ImsMediaSession.SESSION_TYPE_AUDIO:
67                         session = new AudioSession(sessionId,
68                                 IImsAudioSessionCallback.Stub.asInterface(callback));
69                         break;
70                     case ImsMediaSession.SESSION_TYPE_VIDEO:
71                         JNIImsMediaService.setAssetManager(ImsMediaController.this.getAssets());
72                         session = new VideoSession(sessionId,
73                                 IImsVideoSessionCallback.Stub.asInterface(callback));
74                         break;
75                     case ImsMediaSession.SESSION_TYPE_RTT:
76                         session = new TextSession(sessionId,
77                                 IImsTextSessionCallback.Stub.asInterface(callback));
78                         break;
79                     default:
80                         session = null;
81                 }
82 
83                 if (session != null) {
84                     mSessions.append(sessionId, session);
85                     session.openSession(new OpenSessionParams(rtpFd, rtcpFd, rtpConfig,
86                         mCallback));
87 
88                 }
89             }
90         }
91 
92         @Override
closeSession(IBinder session)93         public void closeSession(IBinder session) {
94             Log.d(TAG, "closeSession: " + session);
95             synchronized (mSessions) {
96                 if (session instanceof AudioSession) {
97                     final AudioSession audioSession =
98                             (AudioSession) IImsAudioSession.Stub.asInterface(session);
99                     audioSession.closeSession();
100                 } else if (session instanceof VideoSession) {
101                     final VideoSession videoSession =
102                             (VideoSession) IImsVideoSession.Stub.asInterface(session);
103                     videoSession.closeSession();
104                 } else if (session instanceof TextSession) {
105                     final TextSession textSession =
106                             (TextSession) IImsTextSession.Stub.asInterface(session);
107                     textSession.closeSession();
108                 }
109             }
110         }
111 
112         @Override
generateVideoSprop(VideoConfig[] videoConfigList, IBinder callback)113         public void generateVideoSprop(VideoConfig[] videoConfigList, IBinder callback) {
114 
115             if (videoConfigList == null || callback == null) {
116                 Log.d(TAG, "[SPROP] Invalid params");
117                 return;
118             }
119 
120             try {
121                 int len = videoConfigList.length;
122                 String[] spropList = new String[len];
123 
124                 int idx = 0;
125                 for (VideoConfig config : videoConfigList) {
126                     Parcel parcel = Parcel.obtain();
127                     config.writeToParcel(parcel, 0);
128                     parcel.setDataPosition(0);
129                     spropList[idx] = JNIImsMediaService.generateSprop(parcel.marshall());
130                     parcel.recycle();
131                     idx++;
132                 }
133                 IImsMediaCallback.Stub.asInterface(callback).onVideoSpropResponse(spropList);
134             } catch (Exception e) {
135                 Log.e(TAG, "[SPROP] Error: " + e.toString());
136             }
137         }
138     }
139 
140     private IImsMedia.Stub mImsMediaBinder = new ImsMediaBinder();
141 
142     @Override
onBind(Intent intent)143     public IBinder onBind(Intent intent) {
144         Log.d(TAG, Thread.currentThread().getName() + " onBind");
145         return mImsMediaBinder;
146     }
147 
148     @Override
onUnbind(Intent intent)149     public boolean onUnbind(Intent intent) {
150         Log.d(TAG, Thread.currentThread().getName() + " onUnbind");
151         try {
152             synchronized (mSessions) {
153                 while (mSessions.size() > 0) {
154                     mImsMediaBinder.closeSession((IBinder) mSessions.valueAt(0));
155                     mSessions.removeAt(0);
156                 }
157                 JNIImsMediaService.clearListener();
158                 mSessions.clear();
159             }
160         } catch (Exception e) {
161             Log.d(TAG, "onUnbind: e=" + e);
162         }
163         return true;
164     }
165 
166     @Override
onCreate()167     public void onCreate() {
168         Log.d(TAG, "onCreate");
169     }
170 
171     @Override
onDestroy()172     public void onDestroy() {
173         Log.d(TAG, "onDestroy");
174     }
175 
getSession(int sessionId)176     private IMediaSession getSession(int sessionId) {
177         synchronized (mSessions) {
178             return mSessions.get(sessionId);
179         }
180     }
181 
182     public class OpenSessionCallback {
onOpenSessionSuccess(int sessionId, Object session)183         public void onOpenSessionSuccess(int sessionId, Object session) {
184             getSession(sessionId).onOpenSessionSuccess(session);
185         }
186 
onOpenSessionFailure(int sessionId, int error)187         public void onOpenSessionFailure(int sessionId, int error) {
188             synchronized (mSessions) {
189                 getSession(sessionId).onOpenSessionFailure(error);
190                 mSessions.remove(sessionId);
191             }
192         }
193 
194         /**
195          * Called when the session is closed.
196          *
197          * @param sessionId identifier of the session
198          */
onSessionClosed(int sessionId)199         public void onSessionClosed(int sessionId) {
200             synchronized (mSessions) {
201                 getSession(sessionId).onSessionClosed();
202                 Log.d(TAG, "onSessionClosed: sessionId = " + sessionId);
203                 mSessions.remove(sessionId);
204             }
205         }
206     }
207 }
208