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