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.os.Handler; 20 import android.os.Looper; 21 import android.os.Message; 22 import android.os.RemoteException; 23 import android.support.annotation.VisibleForTesting; 24 import android.telephony.imsmedia.IImsTextSession; 25 import android.telephony.imsmedia.IImsTextSessionCallback; 26 import android.telephony.imsmedia.ImsMediaSession; 27 import android.telephony.imsmedia.MediaQualityThreshold; 28 import android.telephony.imsmedia.RtpConfig; 29 import android.telephony.imsmedia.TextConfig; 30 31 import androidx.annotation.NonNull; 32 import androidx.annotation.Nullable; 33 34 import com.android.telephony.imsmedia.Utils.OpenSessionParams; 35 import com.android.telephony.imsmedia.util.Log; 36 37 /** 38 * Text session binder implementation which handles all text session APIs from the text service. 39 */ 40 public final class TextSession extends IImsTextSession.Stub implements IMediaSession { 41 private static final String TAG = "TextSession"; 42 43 public static final int CMD_OPEN_SESSION = 101; 44 public static final int CMD_CLOSE_SESSION = 102; 45 public static final int CMD_MODIFY_SESSION = 103; 46 public static final int CMD_SET_MEDIA_QUALITY_THRESHOLD = 104; 47 public static final int CMD_SEND_RTT = 105; 48 49 public static final int EVENT_OPEN_SESSION_SUCCESS = 201; 50 public static final int EVENT_OPEN_SESSION_FAILURE = 202; 51 public static final int EVENT_MODIFY_SESSION_RESPONSE = 203; 52 public static final int EVENT_MEDIA_INACTIVITY_IND = 204; 53 public static final int EVENT_RTT_RECEIVED = 205; 54 public static final int EVENT_SESSION_CLOSED = 206; 55 56 private int mSessionId; 57 private IImsTextSessionCallback mCallback; 58 private TextSessionHandler mHandler; 59 private TextService mTextService; 60 private TextListener mTextListener; 61 private TextLocalSession mLocalSession; 62 TextSession(final int sessionId, final IImsTextSessionCallback callback)63 TextSession(final int sessionId, final IImsTextSessionCallback callback) { 64 mSessionId = sessionId; 65 mCallback = callback; 66 mHandler = new TextSessionHandler(Looper.getMainLooper()); 67 Log.d(TAG, "Initialize local text service"); 68 mTextService = new TextService(); 69 mTextListener = new TextListener(mHandler); 70 mTextService.setListener(mTextListener); 71 mTextListener.setNativeObject(mTextService.getNativeObject()); 72 } 73 74 @VisibleForTesting TextSession(final int sessionId, final @NonNull IImsTextSessionCallback callback, final @Nullable TextService textService, final @Nullable TextLocalSession localSession, Looper looper)75 TextSession(final int sessionId, 76 final @NonNull IImsTextSessionCallback callback, 77 final @Nullable TextService textService, 78 final @Nullable TextLocalSession localSession, Looper looper) { 79 mSessionId = sessionId; 80 mCallback = callback; 81 mHandler = new TextSessionHandler(looper); 82 mTextService = textService; 83 mLocalSession = localSession; 84 mTextListener = new TextListener(mHandler); 85 } 86 87 @VisibleForTesting getTextSessionHandler()88 TextSessionHandler getTextSessionHandler() { 89 return mHandler; 90 } 91 92 @VisibleForTesting getTextListener()93 TextListener getTextListener() { 94 return mTextListener; 95 } 96 97 @Override openSession(OpenSessionParams sessionParams)98 public void openSession(OpenSessionParams sessionParams) { 99 Utils.sendMessage(mHandler, CMD_OPEN_SESSION, sessionParams); 100 RtpConfig rtpConfig = sessionParams.getRtpConfig(); 101 if (rtpConfig != null) { 102 WakeLockManager.getInstance().manageWakeLockOnMediaDirectionUpdate( 103 mSessionId, rtpConfig.getMediaDirection()); 104 } 105 } 106 107 @Override closeSession()108 public void closeSession() { 109 Utils.sendMessage(mHandler, CMD_CLOSE_SESSION); 110 WakeLockManager.getInstance().manageWakeLockOnMediaDirectionUpdate( 111 mSessionId, RtpConfig.MEDIA_DIRECTION_NO_FLOW); 112 } 113 114 @Override getSessionId()115 public int getSessionId() { 116 return mSessionId; 117 } 118 119 @Override modifySession(TextConfig config)120 public void modifySession(TextConfig config) { 121 Log.d(TAG, "modifySession: " + Log.hidePii(String.valueOf(config))); 122 Utils.sendMessage(mHandler, CMD_MODIFY_SESSION, config); 123 WakeLockManager.getInstance().manageWakeLockOnMediaDirectionUpdate( 124 mSessionId, config.getMediaDirection()); 125 } 126 127 @Override setMediaQualityThreshold(MediaQualityThreshold threshold)128 public void setMediaQualityThreshold(MediaQualityThreshold threshold) { 129 Log.d(TAG, "setMediaQualityThreshold: " + Log.hidePii(String.valueOf(threshold))); 130 Utils.sendMessage(mHandler, CMD_SET_MEDIA_QUALITY_THRESHOLD, threshold); 131 } 132 133 @Override sendRtt(String text)134 public void sendRtt(String text) { 135 Log.dc(TAG, "sendRtt: "); 136 Utils.sendMessage(mHandler, CMD_SEND_RTT, text); 137 } 138 139 @Override onOpenSessionSuccess(Object session)140 public void onOpenSessionSuccess(Object session) { 141 Utils.sendMessage(mHandler, EVENT_OPEN_SESSION_SUCCESS, session); 142 } 143 144 @Override onOpenSessionFailure(int error)145 public void onOpenSessionFailure(int error) { 146 Utils.sendMessage(mHandler, EVENT_OPEN_SESSION_FAILURE, error); 147 } 148 149 @Override onSessionClosed()150 public void onSessionClosed() { 151 Utils.sendMessage(mHandler, EVENT_SESSION_CLOSED); 152 } 153 154 /** 155 * Text session message mHandler 156 */ 157 class TextSessionHandler extends Handler { TextSessionHandler(Looper looper)158 TextSessionHandler(Looper looper) { 159 super(looper); 160 } 161 162 @Override handleMessage(Message msg)163 public void handleMessage(Message msg) { 164 Log.dc(TAG, "handleMessage() -" + TextSessionHandler.this + ", " + msg.what); 165 switch (msg.what) { 166 case CMD_OPEN_SESSION: 167 handleOpenSession((OpenSessionParams) msg.obj); 168 break; 169 case CMD_CLOSE_SESSION: 170 handleCloseSession(); 171 break; 172 case CMD_MODIFY_SESSION: 173 handleModifySession((TextConfig) msg.obj); 174 break; 175 case CMD_SET_MEDIA_QUALITY_THRESHOLD: 176 handleSetMediaQualityThreshold((MediaQualityThreshold) msg.obj); 177 break; 178 case CMD_SEND_RTT: 179 handleSendRtt((String) msg.obj); 180 break; 181 case EVENT_OPEN_SESSION_SUCCESS: 182 handleOpenSuccess(msg.obj); 183 break; 184 case EVENT_OPEN_SESSION_FAILURE: 185 handleOpenFailure((int) msg.obj); 186 break; 187 case EVENT_SESSION_CLOSED: 188 handleSessionClosed(); 189 break; 190 case EVENT_MODIFY_SESSION_RESPONSE: 191 handleModifySessionRespose((TextConfig) msg.obj, msg.arg1); 192 break; 193 case EVENT_MEDIA_INACTIVITY_IND: 194 handleNotifyMediaInactivityInd(msg.arg1); 195 break; 196 case EVENT_RTT_RECEIVED: 197 handleRttReceived((String) msg.obj); 198 break; 199 default: 200 } 201 } 202 } 203 handleOpenSession(OpenSessionParams sessionParams)204 private void handleOpenSession(OpenSessionParams sessionParams) { 205 mTextListener.setMediaCallback(sessionParams.getCallback()); 206 Log.d(TAG, "handleOpenSession"); 207 int result = mTextService.openSession(mSessionId, sessionParams); 208 if (result != ImsMediaSession.RESULT_SUCCESS) { 209 handleOpenFailure(result); 210 } 211 } 212 handleCloseSession()213 private void handleCloseSession() { 214 mTextService.closeSession(mSessionId); 215 } 216 handleModifySession(TextConfig config)217 private void handleModifySession(TextConfig config) { 218 mLocalSession.modifySession(config); 219 } 220 handleSetMediaQualityThreshold(MediaQualityThreshold threshold)221 private void handleSetMediaQualityThreshold(MediaQualityThreshold threshold) { 222 mLocalSession.setMediaQualityThreshold(threshold); 223 } 224 handleSendRtt(String text)225 private void handleSendRtt(String text) { 226 mLocalSession.sendRtt(text); 227 } 228 handleOpenSuccess(Object session)229 private void handleOpenSuccess(Object session) { 230 mLocalSession = (TextLocalSession) session; 231 try { 232 mCallback.onOpenSessionSuccess(this); 233 } catch (RemoteException e) { 234 Log.e(TAG, "Failed to notify openSuccess: " + e); 235 } 236 } 237 handleOpenFailure(int error)238 private void handleOpenFailure(int error) { 239 try { 240 mCallback.onOpenSessionFailure(error); 241 } catch (RemoteException e) { 242 Log.e(TAG, "Failed to notify openFailure: " + e); 243 } finally { 244 WakeLockManager.getInstance().manageWakeLockOnMediaDirectionUpdate( 245 mSessionId, RtpConfig.MEDIA_DIRECTION_NO_FLOW); 246 } 247 } 248 handleSessionClosed()249 private void handleSessionClosed() { 250 try { 251 mCallback.onSessionClosed(); 252 } catch (RemoteException e) { 253 Log.e(TAG, "Failed to notify SessionClosed: " + e); 254 } 255 } 256 handleModifySessionRespose(TextConfig config, int error)257 private void handleModifySessionRespose(TextConfig config, int error) { 258 try { 259 if (error != ImsMediaSession.RESULT_SUCCESS) { 260 Log.e(TAG, "modifySession failed with error: " + error); 261 } 262 mCallback.onModifySessionResponse(config, error); 263 } catch (RemoteException e) { 264 Log.e(TAG, "Failed to notify modifySessionResponse: " + e); 265 } 266 } 267 handleNotifyMediaInactivityInd(int packetType)268 private void handleNotifyMediaInactivityInd(int packetType) { 269 try { 270 mCallback.notifyMediaInactivity(packetType); 271 } catch (RemoteException e) { 272 Log.e(TAG, "Failed to notify media timeout: " + e); 273 } 274 } 275 handleRttReceived(String text)276 private void handleRttReceived(String text) { 277 try { 278 mCallback.onRttReceived(text); 279 } catch (RemoteException e) { 280 Log.e(TAG, "Failed to notify rtt received: " + e); 281 } 282 } 283 } 284