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.content.res.AssetManager;
20 import android.os.Parcel;
21 import android.os.Process;
22 import android.util.ArrayMap;
23 import android.view.Surface;
24 
25 import androidx.annotation.VisibleForTesting;
26 
27 import com.android.telephony.imsmedia.util.Log;
28 
29 /** JNI interface class to send message to libimsmediajni */
30 public class JNIImsMediaService {
31     private static final String TAG = "JNIImsMediaService";
32     private static final int THREAD_PRIORITY_REALTIME = -20;
33     public static JNIImsMediaService sService = null;
34     private final Object mLock = new Object();
35 
36     /** for media service based on type ex. audio, video, rtt */
37     private static ArrayMap<Integer, JNIImsMediaListener> sListeners =
38             new ArrayMap<Integer, JNIImsMediaListener>();
39 
40     /**
41      * Gets instance object of BaseManager with the corresponding media type
42      *
43      * @param mediatype Audio/Video/Text type
44      * @return the native instance of BaseManager
45      */
getInterface(int mediatype)46     public static native long getInterface(int mediatype);
47 
48     /**
49      * Send message to libimsmediajni to libimsmedia library to operate with corresponding
50      * arguments
51      *
52      * @param nativeObject An unique object identifier of BaseManager to operate
53      * @param sessionId An unique session identifier
54      * @param baData A parameter to operate session
55      */
sendMessage(long nativeObject, int sessionId, byte[] baData)56     public static native void sendMessage(long nativeObject, int sessionId, byte[] baData);
57 
58     /**
59      * Set preview surface to libimsmediajni and it delivers libimsmedia
60      *
61      * @param nativeObject An unique object identifier of BaseManager to operate
62      * @param sessionId An unique session identifier
63      * @param surface A preview surface
64      */
setPreviewSurface(long nativeObject, int sessionId, Surface surface)65     public static native void setPreviewSurface(long nativeObject, int sessionId, Surface surface);
66 
67     /**
68      * Set display surface to libimsmediajni and it delivers libimsmedia
69      *
70      * @param nativeObject An unique object identifier of BaseManager to operate
71      * @param sessionId An unique session identifier
72      * @param surface A display surface
73      */
setDisplaySurface(long nativeObject, int sessionId, Surface surface)74     public static native void setDisplaySurface(long nativeObject, int sessionId, Surface surface);
75 
76     /**
77      * Generates SPROP list for the given set of video configurations.
78      *
79      * @param videoConfig video configuration for which sprop should be generated.
80      * @return returns the generated sprop value.
81      */
generateSprop(byte[] videoConfig)82     public static native String generateSprop(byte[] videoConfig);
83 
84     /**
85      * Passes the application's asset manager reference to native which will be used to access
86      * pause images assets during video call multitasking scenarios.
87      *
88      * @param assetManager Application's asset manager reference.
89      */
setAssetManager(AssetManager assetManager)90     public static native void setAssetManager(AssetManager assetManager);
91 
92     /**
93      * Set the libimsmedia library logging level and mode for debug
94      *
95      * @param logMode The log mode
96      * @param debugLogMode The debug log mode
97      */
setLogMode(int logMode, int debugLogMode)98     public static native void setLogMode(int logMode, int debugLogMode);
99 
100     /**
101      * Gets intance of JNIImsMediaService for jni interface
102      *
103      * @return instance of JNIImsMediaService
104      */
getInstance()105     public static JNIImsMediaService getInstance() {
106         if (sService == null) {
107             sService = new JNIImsMediaService();
108         }
109         return sService;
110     }
111 
112     /**
113      * Sets listener to get callback from libimsmediajni
114      *
115      * @param sessionId An unique object identifier the session to use as a key to acquire a paired
116      * listener
117      * @param listener A listener to set for getting messages
118      */
setListener(final int sessionId, final JNIImsMediaListener listener)119     public static void setListener(final int sessionId, final JNIImsMediaListener listener) {
120         Log.d(TAG, "setListener() - sessionId=" + sessionId);
121         if (listener == null) {
122             Log.e(TAG, "setListener() - null listener");
123             return;
124         }
125         synchronized (sListeners) {
126             sListeners.put(sessionId, listener);
127         }
128     }
129 
130     /**
131      * Gets a listener with the key to match
132      *
133      * @param sessionId An unique key identifier to get the paired listener
134      * @return A JNIImsMediaListener listener
135      */
getListener(final int sessionId)136     public static JNIImsMediaListener getListener(final int sessionId) {
137         JNIImsMediaListener listener = null;
138         synchronized (sListeners) {
139             listener = sListeners.get(sessionId);
140         }
141 
142         return listener;
143     }
144 
145     /**
146      *  Clears listener container
147      */
clearListener()148     public static void clearListener() {
149         synchronized (sListeners) {
150             sListeners.clear();
151         }
152     }
153 
154     @VisibleForTesting
getListenerSize()155     public static int getListenerSize() {
156         return sListeners.size();
157     }
158 
159     /**
160      * Sends callback parcel message from libimsmediajni to java
161      *
162      * @param sessionId An unique key idenfier to find corresponding listener object to send message
163      * @param baData byte array form of data to send
164      * @return 1 if it is success to send data, -1 when it fails
165      */
sendData2Java(final int sessionId, final byte[] baData)166     public static int sendData2Java(final int sessionId, final byte[] baData) {
167         Log.dc(TAG, "sendData2Java() - sessionId=" + sessionId);
168         JNIImsMediaListener listener = getListener(sessionId);
169         if (listener == null) {
170             Log.e(TAG, "No listener :: sessionId=" + sessionId);
171             return -1;
172         }
173         if (baData == null) {
174             return -1;
175         }
176         // retrieve parcel object from pool
177         Parcel parcel = Parcel.obtain();
178         parcel.unmarshall(baData, 0, baData.length);
179         parcel.setDataPosition(0);
180         listener.onMessage(parcel);
181         parcel.recycle();
182 
183         return 1;
184     }
185 
186     /** Elevates the priority of audio thread to THREAD_PRIORITY_REALTIME. Increase in thead
187      * priority will ensure AOC and JitterBuffer calls are made consistent every 20msecs.
188      *
189      * @param threadId is the id of the thread whose priority should to be increased.
190      */
setAudioThreadPriority(int threadId)191     public static void setAudioThreadPriority(int threadId) {
192         Log.d(TAG, "setAudioThreadPriority. tid:" + threadId);
193         Process.setThreadPriority(threadId, THREAD_PRIORITY_REALTIME);
194     }
195 
196     /** local shared libimsmediajni library */
197     static {
198         try {
Log.d(TAG, "libimsmedia :: loading")199             Log.d(TAG, "libimsmedia :: loading");
200             System.loadLibrary("imsmedia");
Log.d(TAG, "libimsmedia :: load completed")201             Log.d(TAG, "libimsmedia :: load completed");
202         } catch (UnsatisfiedLinkError e) {
203             Log.e(TAG, "Loading fail : libimsmedia.so");
204         }
205     }
206 }
207