blob: 6066bbac32831304d5b62a252a061c53cca78979 [file] [log] [blame]
/*
* Copyright (C) 2018 The Android Open Source Project
* Copyright (C) 2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.incallui;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.telecom.Call.RttCall;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.rtt.RttTranscript;
import com.android.incallui.InCallPresenter.InCallState;
import com.android.incallui.InCallPresenter.InCallStateListener;
import com.android.incallui.call.CallList;
import com.android.incallui.call.DialerCall;
import com.android.incallui.rtt.protocol.RttCallScreen;
import com.android.incallui.rtt.protocol.RttCallScreenDelegate;
import java.io.IOException;
/**
* Logic related to the {@link RttCallScreen} and for managing changes to the RTT calling surfaces
* based on other user interface events and incoming events.
*/
public class RttCallPresenter implements RttCallScreenDelegate, InCallStateListener {
private RttCallScreen rttCallScreen;
private RttCall rttCall;
private HandlerThread handlerThread;
private RemoteMessageHandler remoteMessageHandler;
@Override
public void initRttCallScreenDelegate(RttCallScreen rttCallScreen) {
this.rttCallScreen = rttCallScreen;
}
@Override
public void onLocalMessage(String message) {
if (rttCall == null) {
LogUtil.w("RttCallPresenter.onLocalMessage", "Rtt Call is not started yet");
return;
}
remoteMessageHandler.writeMessage(message);
}
@Override
public void onRttCallScreenUiReady() {
LogUtil.enterBlock("RttCallPresenter.onRttCallScreenUiReady");
InCallPresenter.getInstance().addListener(this);
startListenOnRemoteMessage();
DialerCall call = CallList.getInstance().getCallById(rttCallScreen.getCallId());
if (call != null) {
rttCallScreen.onRestoreRttChat(call.getRttTranscript());
}
}
@Override
public void onSaveRttTranscript() {
LogUtil.enterBlock("RttCallPresenter.onSaveRttTranscript");
DialerCall call = CallList.getInstance().getCallById(rttCallScreen.getCallId());
if (call != null) {
saveTranscript(call);
}
}
@Override
public void onRttCallScreenUiUnready() {
LogUtil.enterBlock("RttCallPresenter.onRttCallScreenUiUnready");
InCallPresenter.getInstance().removeListener(this);
stopListenOnRemoteMessage();
onSaveRttTranscript();
}
private void saveTranscript(DialerCall dialerCall) {
LogUtil.enterBlock("RttCallPresenter.saveTranscript");
RttTranscript.Builder builder = RttTranscript.newBuilder();
builder
.setId(String.valueOf(dialerCall.getCreationTimeMillis()))
.setTimestamp(dialerCall.getCreationTimeMillis())
.setNumber(dialerCall.getNumber())
.addAllMessages(rttCallScreen.getRttTranscriptMessageList());
dialerCall.setRttTranscript(builder.build());
}
@Override
public void onStateChange(InCallState oldState, InCallState newState, CallList callList) {
LogUtil.enterBlock("RttCallPresenter.onStateChange");
if (newState == InCallState.INCALL) {
startListenOnRemoteMessage();
}
}
private void startListenOnRemoteMessage() {
DialerCall call = CallList.getInstance().getCallById(rttCallScreen.getCallId());
if (call == null) {
LogUtil.i("RttCallPresenter.startListenOnRemoteMessage", "call does not exist");
return;
}
rttCall = call.getRttCall();
if (rttCall == null) {
LogUtil.i("RttCallPresenter.startListenOnRemoteMessage", "RTT Call is not started yet");
return;
}
if (handlerThread != null && handlerThread.isAlive()) {
LogUtil.i("RttCallPresenter.startListenOnRemoteMessage", "already running");
return;
}
handlerThread = new HandlerThread("RttCallRemoteMessageHandler");
handlerThread.start();
remoteMessageHandler =
new RemoteMessageHandler(handlerThread.getLooper(), rttCall, rttCallScreen);
remoteMessageHandler.start();
}
private void stopListenOnRemoteMessage() {
if (handlerThread != null && handlerThread.isAlive()) {
handlerThread.quit();
}
}
private static class RemoteMessageHandler extends Handler {
private static final int START = 1;
private static final int READ_MESSAGE = 2;
private static final int WRITE_MESSAGE = 3;
private final RttCall rttCall;
private final RttCallScreen rttCallScreen;
RemoteMessageHandler(Looper looper, RttCall rttCall, RttCallScreen rttCallScreen) {
super(looper);
this.rttCall = rttCall;
this.rttCallScreen = rttCallScreen;
}
@Override
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case START:
sendEmptyMessage(READ_MESSAGE);
break;
case READ_MESSAGE:
try {
final String message = rttCall.readImmediately();
if (message != null) {
ThreadUtil.postOnUiThread(() -> rttCallScreen.onRemoteMessage(message));
}
} catch (IOException e) {
LogUtil.e("RttCallPresenter.RemoteMessageHandler.handleMessage", "read message", e);
}
sendEmptyMessageDelayed(READ_MESSAGE, 200);
break;
case WRITE_MESSAGE:
try {
rttCall.write((String) msg.obj);
} catch (IOException e) {
LogUtil.e("RttCallPresenter.RemoteMessageHandler.handleMessage", "write message", e);
}
break;
default: // fall out
}
}
void start() {
sendEmptyMessage(START);
}
void writeMessage(String message) {
sendMessage(obtainMessage(WRITE_MESSAGE, message));
}
}
}