blob: c609909797aa2e61e60b88486e290a20eb92d2c9 [file] [log] [blame]
/*
* Copyright (C) 2020 The Android Open Source 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.ims.rcs.uce;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.content.Context;
import android.net.Uri;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.RemoteException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsContactUceCapability.CapabilityMechanism;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.RcsUceAdapter.PublishState;
import android.telephony.ims.RcsUceAdapter.StackPublishTriggerType;
import android.telephony.ims.aidl.IOptionsRequestCallback;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import android.util.IndentingPrintWriter;
import android.util.LocalLog;
import android.util.Log;
import com.android.ims.RcsFeatureManager;
import com.android.ims.rcs.uce.UceDeviceState.DeviceStateResult;
import com.android.ims.rcs.uce.eab.EabCapabilityResult;
import com.android.ims.rcs.uce.eab.EabController;
import com.android.ims.rcs.uce.eab.EabControllerImpl;
import com.android.ims.rcs.uce.options.OptionsController;
import com.android.ims.rcs.uce.options.OptionsControllerImpl;
import com.android.ims.rcs.uce.presence.publish.PublishController;
import com.android.ims.rcs.uce.presence.publish.PublishControllerImpl;
import com.android.ims.rcs.uce.presence.subscribe.SubscribeController;
import com.android.ims.rcs.uce.presence.subscribe.SubscribeControllerImpl;
import com.android.ims.rcs.uce.request.UceRequestManager;
import com.android.ims.rcs.uce.util.UceUtils;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.SomeArgs;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* The UceController will manage the RCS UCE requests on a per subscription basis. When it receives
* the UCE requests from the RCS applications and from the ImsService, it will coordinate the
* cooperation between the publish/subscribe/options components to complete the requests.
*/
public class UceController {
private static final String LOG_TAG = UceUtils.getLogPrefix() + "UceController";
/**
* The callback interface is called by the internal controllers to receive information from
* others controllers.
*/
public interface UceControllerCallback {
/**
* Retrieve the capabilities associated with the given uris from the cache.
*/
List<EabCapabilityResult> getCapabilitiesFromCache(@NonNull List<Uri> uris);
/**
* Retrieve the contact's capabilities from the availability cache.
*/
EabCapabilityResult getAvailabilityFromCache(@NonNull Uri uri);
/**
* Store the given capabilities to the cache.
*/
void saveCapabilities(List<RcsContactUceCapability> contactCapabilities);
/**
* Retrieve the device's capabilities.
*/
RcsContactUceCapability getDeviceCapabilities(@CapabilityMechanism int mechanism);
/**
* Refresh the device state. It is called when receive the UCE request response.
* @param sipCode The SIP code of the request response.
* @param reason The reason from the network response.
* @param type The type of the request
*/
void refreshDeviceState(int sipCode, String reason, @RequestType int type);
/**
* Reset the device state when then device disallowed state is expired.
*/
void resetDeviceState();
/**
* Get the current device state to check if the device is allowed to send UCE requests.
*/
DeviceStateResult getDeviceState();
/**
* Setup timer to exit device disallowed state.
*/
void setupResetDeviceStateTimer(long resetAfterSec);
/**
* The device state is already reset, clear the timer.
*/
void clearResetDeviceStateTimer();
/**
* The method is called when the given contacts' capabilities are expired and need to be
* refreshed.
*/
void refreshCapabilities(@NonNull List<Uri> contactNumbers,
@NonNull IRcsUceControllerCallback callback) throws RemoteException;
}
/**
* Used to inject RequestManger instances for testing.
*/
@VisibleForTesting
public interface RequestManagerFactory {
UceRequestManager createRequestManager(Context context, int subId, Looper looper,
UceControllerCallback callback);
}
private RequestManagerFactory mRequestManagerFactory = (context, subId, looper, callback) ->
new UceRequestManager(context, subId, looper, callback);
/**
* Used to inject Controller instances for testing.
*/
@VisibleForTesting
public interface ControllerFactory {
/**
* @return an {@link EabController} associated with the subscription id specified.
*/
EabController createEabController(Context context, int subId, UceControllerCallback c,
Looper looper);
/**
* @return an {@link PublishController} associated with the subscription id specified.
*/
PublishController createPublishController(Context context, int subId,
UceControllerCallback c, Looper looper);
/**
* @return an {@link SubscribeController} associated with the subscription id specified.
*/
SubscribeController createSubscribeController(Context context, int subId);
/**
* @return an {@link OptionsController} associated with the subscription id specified.
*/
OptionsController createOptionsController(Context context, int subId);
}
private ControllerFactory mControllerFactory = new ControllerFactory() {
@Override
public EabController createEabController(Context context, int subId,
UceControllerCallback c, Looper looper) {
return new EabControllerImpl(context, subId, c, looper);
}
@Override
public PublishController createPublishController(Context context, int subId,
UceControllerCallback c, Looper looper) {
return new PublishControllerImpl(context, subId, c, looper);
}
@Override
public SubscribeController createSubscribeController(Context context, int subId) {
return new SubscribeControllerImpl(context, subId);
}
@Override
public OptionsController createOptionsController(Context context, int subId) {
return new OptionsControllerImpl(context, subId);
}
};
/**
* Cache the capabilities events triggered by the ImsService during the RCS connected procedure.
*/
private static class CachedCapabilityEvent {
private Optional<Integer> mRequestPublishCapabilitiesEvent;
private Optional<Boolean> mUnpublishEvent;
private Optional<SomeArgs> mRemoteCapabilityRequestEvent;
public CachedCapabilityEvent() {
mRequestPublishCapabilitiesEvent = Optional.empty();
mUnpublishEvent = Optional.empty();
mRemoteCapabilityRequestEvent = Optional.empty();
}
/**
* Cache the publish capabilities request event triggered by the ImsService.
*/
public synchronized void setRequestPublishCapabilitiesEvent(int triggerType) {
mRequestPublishCapabilitiesEvent = Optional.of(triggerType);
}
/**
* Cache the unpublish event triggered by the ImsService.
*/
public synchronized void setOnUnpublishEvent() {
mUnpublishEvent = Optional.of(Boolean.TRUE);
}
/**
* Cache the remote capability request event triggered by the ImsService.
*/
public synchronized void setRemoteCapabilityRequestEvent(Uri contactUri,
List<String> remoteCapabilities, IOptionsRequestCallback callback) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = contactUri;
args.arg2 = remoteCapabilities;
args.arg3 = callback;
mRemoteCapabilityRequestEvent = Optional.of(args);
}
/** @Return the cached publish request event */
public synchronized Optional<Integer> getRequestPublishEvent() {
return mRequestPublishCapabilitiesEvent;
}
/** @Return the cached unpublish event */
public synchronized Optional<Boolean> getUnpublishEvent() {
return mUnpublishEvent;
}
/** @Return the cached remote capability request event */
public synchronized Optional<SomeArgs> getRemoteCapabilityRequestEvent() {
return mRemoteCapabilityRequestEvent;
}
/** Clear the cached */
public synchronized void clear() {
mRequestPublishCapabilitiesEvent = Optional.empty();
mUnpublishEvent = Optional.empty();
mRemoteCapabilityRequestEvent.ifPresent(args -> args.recycle());
mRemoteCapabilityRequestEvent = Optional.empty();
}
}
/**
* The request type is PUBLISH.
*/
public static final int REQUEST_TYPE_PUBLISH = 1;
/**
* The request type is CAPABILITY.
*/
public static final int REQUEST_TYPE_CAPABILITY = 2;
@IntDef(value = {
REQUEST_TYPE_PUBLISH,
REQUEST_TYPE_CAPABILITY,
}, prefix="REQUEST_TYPE_")
@Retention(RetentionPolicy.SOURCE)
public @interface RequestType {}
public static final Map<Integer, String> REQUEST_TYPE_DESCRIPTION = new HashMap<>();
static {
REQUEST_TYPE_DESCRIPTION.put(REQUEST_TYPE_PUBLISH, "REQUEST_TYPE_PUBLISH");
REQUEST_TYPE_DESCRIPTION.put(REQUEST_TYPE_CAPABILITY, "REQUEST_TYPE_CAPABILITY");
}
/** The RCS state is disconnected */
private static final int RCS_STATE_DISCONNECTED = 0;
/** The RCS state is connecting */
private static final int RCS_STATE_CONNECTING = 1;
/** The RCS state is connected */
private static final int RCS_STATE_CONNECTED = 2;
@IntDef(value = {
RCS_STATE_DISCONNECTED,
RCS_STATE_CONNECTING,
RCS_STATE_CONNECTED,
}, prefix="RCS_STATE_")
@Retention(RetentionPolicy.SOURCE)
@interface RcsConnectedState {}
private final int mSubId;
private final Context mContext;
private final LocalLog mLocalLog = new LocalLog(UceUtils.LOG_SIZE);
private volatile Looper mLooper;
private volatile boolean mIsDestroyedFlag;
private volatile @RcsConnectedState int mRcsConnectedState;
private RcsFeatureManager mRcsFeatureManager;
private EabController mEabController;
private PublishController mPublishController;
private SubscribeController mSubscribeController;
private OptionsController mOptionsController;
private UceRequestManager mRequestManager;
// The device state to execute UCE requests.
private UceDeviceState mDeviceState;
// The cache of the capability request event triggered by ImsService
private final CachedCapabilityEvent mCachedCapabilityEvent;
public UceController(Context context, int subId) {
mSubId = subId;
mContext = context;
mCachedCapabilityEvent = new CachedCapabilityEvent();
mRcsConnectedState = RCS_STATE_DISCONNECTED;
logi("create");
initLooper();
initControllers();
initRequestManager();
initUceDeviceState();
}
@VisibleForTesting
public UceController(Context context, int subId, UceDeviceState deviceState,
ControllerFactory controllerFactory, RequestManagerFactory requestManagerFactory) {
mSubId = subId;
mContext = context;
mDeviceState = deviceState;
mControllerFactory = controllerFactory;
mRequestManagerFactory = requestManagerFactory;
mCachedCapabilityEvent = new CachedCapabilityEvent();
mRcsConnectedState = RCS_STATE_DISCONNECTED;
initLooper();
initControllers();
initRequestManager();
}
private void initLooper() {
// Init the looper, it will be passed to each controller.
HandlerThread handlerThread = new HandlerThread("UceControllerHandlerThread");
handlerThread.start();
mLooper = handlerThread.getLooper();
}
private void initControllers() {
mEabController = mControllerFactory.createEabController(mContext, mSubId, mCtrlCallback,
mLooper);
mPublishController = mControllerFactory.createPublishController(mContext, mSubId,
mCtrlCallback, mLooper);
mSubscribeController = mControllerFactory.createSubscribeController(mContext, mSubId);
mOptionsController = mControllerFactory.createOptionsController(mContext, mSubId);
}
private void initRequestManager() {
mRequestManager = mRequestManagerFactory.createRequestManager(mContext, mSubId, mLooper,
mCtrlCallback);
mRequestManager.setSubscribeController(mSubscribeController);
mRequestManager.setOptionsController(mOptionsController);
}
private void initUceDeviceState() {
mDeviceState = new UceDeviceState(mSubId, mContext, mCtrlCallback);
mDeviceState.checkSendResetDeviceStateTimer();
}
/**
* The RcsFeature has been connected to the framework. This method runs on main thread.
*/
public void onRcsConnected(RcsFeatureManager manager) {
logi("onRcsConnected");
// Set the RCS is connecting flag
mRcsConnectedState = RCS_STATE_CONNECTING;
// Listen to the capability exchange event which is triggered by the ImsService
mRcsFeatureManager = manager;
mRcsFeatureManager.addCapabilityEventCallback(mCapabilityEventListener);
// Notify each controllers that RCS is connected.
mEabController.onRcsConnected(manager);
mPublishController.onRcsConnected(manager);
mSubscribeController.onRcsConnected(manager);
mOptionsController.onRcsConnected(manager);
// Set the RCS is connected flag and check if there is any capability event received during
// the connecting process.
mRcsConnectedState = RCS_STATE_CONNECTED;
handleCachedCapabilityEvent();
}
/**
* The framework has lost the binding to the RcsFeature. This method runs on main thread.
*/
public void onRcsDisconnected() {
logi("onRcsDisconnected");
mRcsConnectedState = RCS_STATE_DISCONNECTED;
// Remove the listener because RCS is disconnected.
if (mRcsFeatureManager != null) {
mRcsFeatureManager.removeCapabilityEventCallback(mCapabilityEventListener);
mRcsFeatureManager = null;
}
// Notify each controllers that RCS is disconnected.
mEabController.onRcsDisconnected();
mPublishController.onRcsDisconnected();
mSubscribeController.onRcsDisconnected();
mOptionsController.onRcsDisconnected();
}
/**
* Notify to destroy this instance. This instance is unusable after destroyed.
*/
public void onDestroy() {
logi("onDestroy");
mIsDestroyedFlag = true;
// Remove the listener because the UceController instance is destroyed.
if (mRcsFeatureManager != null) {
mRcsFeatureManager.removeCapabilityEventCallback(mCapabilityEventListener);
mRcsFeatureManager = null;
}
// Destroy all the controllers
mRequestManager.onDestroy();
mEabController.onDestroy();
mPublishController.onDestroy();
mSubscribeController.onDestroy();
mOptionsController.onDestroy();
// Execute all the existing requests before quitting the looper.
mLooper.quitSafely();
}
/**
* Notify all associated classes that the carrier configuration has changed for the subId.
*/
public void onCarrierConfigChanged() {
mEabController.onCarrierConfigChanged();
mPublishController.onCarrierConfigChanged();
mSubscribeController.onCarrierConfigChanged();
mOptionsController.onCarrierConfigChanged();
}
private void handleCachedCapabilityEvent() {
Optional<Integer> requestPublishEvent = mCachedCapabilityEvent.getRequestPublishEvent();
requestPublishEvent.ifPresent(triggerType ->
onRequestPublishCapabilitiesFromService(triggerType));
Optional<Boolean> unpublishEvent = mCachedCapabilityEvent.getUnpublishEvent();
unpublishEvent.ifPresent(unpublish -> onUnpublish());
Optional<SomeArgs> remoteRequest = mCachedCapabilityEvent.getRemoteCapabilityRequestEvent();
remoteRequest.ifPresent(args -> {
Uri contactUri = (Uri) args.arg1;
List<String> remoteCapabilities = (List<String>) args.arg2;
IOptionsRequestCallback callback = (IOptionsRequestCallback) args.arg3;
retrieveOptionsCapabilitiesForRemote(contactUri, remoteCapabilities, callback);
});
mCachedCapabilityEvent.clear();
}
/*
* The implementation of the interface UceControllerCallback. These methods are called by other
* controllers.
*/
private UceControllerCallback mCtrlCallback = new UceControllerCallback() {
@Override
public List<EabCapabilityResult> getCapabilitiesFromCache(List<Uri> uris) {
return mEabController.getCapabilities(uris);
}
@Override
public EabCapabilityResult getAvailabilityFromCache(Uri contactUri) {
return mEabController.getAvailability(contactUri);
}
@Override
public void saveCapabilities(List<RcsContactUceCapability> contactCapabilities) {
mEabController.saveCapabilities(contactCapabilities);
}
@Override
public RcsContactUceCapability getDeviceCapabilities(@CapabilityMechanism int mechanism) {
return mPublishController.getDeviceCapabilities(mechanism);
}
@Override
public void refreshDeviceState(int sipCode, String reason, @RequestType int type) {
mDeviceState.refreshDeviceState(sipCode, reason, type);
}
@Override
public void resetDeviceState() {
mDeviceState.resetDeviceState();
}
@Override
public DeviceStateResult getDeviceState() {
return mDeviceState.getCurrentState();
}
@Override
public void setupResetDeviceStateTimer(long resetAfterSec) {
mPublishController.setupResetDeviceStateTimer(resetAfterSec);
}
@Override
public void clearResetDeviceStateTimer() {
mPublishController.clearResetDeviceStateTimer();
}
@Override
public void refreshCapabilities(@NonNull List<Uri> contactNumbers,
@NonNull IRcsUceControllerCallback callback) throws RemoteException{
logd("refreshCapabilities: " + contactNumbers.size());
UceController.this.requestCapabilitiesInternal(contactNumbers, true, callback);
}
};
@VisibleForTesting
public void setUceControllerCallback(UceControllerCallback callback) {
mCtrlCallback = callback;
}
/*
* Setup the listener to listen to the requests and updates from ImsService.
*/
private RcsFeatureManager.CapabilityExchangeEventCallback mCapabilityEventListener =
new RcsFeatureManager.CapabilityExchangeEventCallback() {
@Override
public void onRequestPublishCapabilities(
@StackPublishTriggerType int triggerType) {
if (isRcsConnecting()) {
mCachedCapabilityEvent.setRequestPublishCapabilitiesEvent(triggerType);
return;
}
onRequestPublishCapabilitiesFromService(triggerType);
}
@Override
public void onUnpublish() {
if (isRcsConnecting()) {
mCachedCapabilityEvent.setOnUnpublishEvent();
return;
}
UceController.this.onUnpublish();
}
@Override
public void onRemoteCapabilityRequest(Uri contactUri,
List<String> remoteCapabilities, IOptionsRequestCallback cb) {
if (contactUri == null || remoteCapabilities == null || cb == null) {
logw("onRemoteCapabilityRequest: parameter cannot be null");
return;
}
if (isRcsConnecting()) {
mCachedCapabilityEvent.setRemoteCapabilityRequestEvent(contactUri,
remoteCapabilities, cb);
return;
}
retrieveOptionsCapabilitiesForRemote(contactUri, remoteCapabilities, cb);
}
};
/**
* Request to get the contacts' capabilities. This method will retrieve the capabilities from
* the cache If the capabilities are out of date, it will trigger another request to get the
* latest contact's capabilities from the network.
*/
public void requestCapabilities(@NonNull List<Uri> uriList,
@NonNull IRcsUceControllerCallback c) throws RemoteException {
requestCapabilitiesInternal(uriList, false, c);
}
private void requestCapabilitiesInternal(@NonNull List<Uri> uriList, boolean skipFromCache,
@NonNull IRcsUceControllerCallback c) throws RemoteException {
if (uriList == null || uriList.isEmpty() || c == null) {
logw("requestCapabilities: parameter is empty");
if (c != null) {
c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
}
return;
}
if (isUnavailable()) {
logw("requestCapabilities: controller is unavailable");
c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
return;
}
// Return if the device is not allowed to execute UCE requests.
DeviceStateResult deviceStateResult = mDeviceState.getCurrentState();
if (deviceStateResult.isRequestForbidden()) {
int deviceState = deviceStateResult.getDeviceState();
int errorCode = deviceStateResult.getErrorCode()
.orElse(RcsUceAdapter.ERROR_GENERIC_FAILURE);
long retryAfterMillis = deviceStateResult.getRequestRetryAfterMillis();
logw("requestCapabilities: The device is disallowed, deviceState= " + deviceState +
", errorCode=" + errorCode + ", retryAfterMillis=" + retryAfterMillis);
c.onError(errorCode, retryAfterMillis);
return;
}
// Trigger the capabilities request task
logd("requestCapabilities: size=" + uriList.size());
mRequestManager.sendCapabilityRequest(uriList, skipFromCache, c);
}
/**
* Request to get the contact's capabilities. It will check the availability cache first. If
* the capability in the availability cache is expired then it will retrieve the capability
* from the network.
*/
public void requestAvailability(@NonNull Uri uri, @NonNull IRcsUceControllerCallback c)
throws RemoteException {
if (uri == null || c == null) {
logw("requestAvailability: parameter is empty");
if (c != null) {
c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
}
return;
}
if (isUnavailable()) {
logw("requestAvailability: controller is unavailable");
c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
return;
}
// Return if the device is not allowed to execute UCE requests.
DeviceStateResult deviceStateResult = mDeviceState.getCurrentState();
if (deviceStateResult.isRequestForbidden()) {
int deviceState = deviceStateResult.getDeviceState();
int errorCode = deviceStateResult.getErrorCode()
.orElse(RcsUceAdapter.ERROR_GENERIC_FAILURE);
long retryAfterMillis = deviceStateResult.getRequestRetryAfterMillis();
logw("requestAvailability: The device is disallowed, deviceState= " + deviceState +
", errorCode=" + errorCode + ", retryAfterMillis=" + retryAfterMillis);
c.onError(errorCode, retryAfterMillis);
return;
}
// Trigger the availability request task
logd("requestAvailability");
mRequestManager.sendAvailabilityRequest(uri, c);
}
/**
* Publish the device's capabilities. This request is triggered from the ImsService.
*/
public void onRequestPublishCapabilitiesFromService(@StackPublishTriggerType int triggerType) {
logd("onRequestPublishCapabilitiesFromService: " + triggerType);
// Reset the device state when the service triggers to publish the device's capabilities
mDeviceState.resetDeviceState();
// Send the publish request.
mPublishController.requestPublishCapabilitiesFromService(triggerType);
}
/**
* This method is triggered by the ImsService to notify framework that the device's
* capabilities has been unpublished from the network.
*/
public void onUnpublish() {
logi("onUnpublish");
mPublishController.onUnpublish();
}
/**
* Request publish the device's capabilities. This request is from the ImsService to send the
* capabilities to the remote side.
*/
public void retrieveOptionsCapabilitiesForRemote(@NonNull Uri contactUri,
@NonNull List<String> remoteCapabilities, @NonNull IOptionsRequestCallback c) {
logi("retrieveOptionsCapabilitiesForRemote");
mRequestManager.retrieveCapabilitiesForRemote(contactUri, remoteCapabilities, c);
}
/**
* Register a {@link PublishStateCallback} to receive the published state changed.
*/
public void registerPublishStateCallback(@NonNull IRcsUcePublishStateCallback c) {
mPublishController.registerPublishStateCallback(c);
}
/**
* Removes an existing {@link PublishStateCallback}.
*/
public void unregisterPublishStateCallback(@NonNull IRcsUcePublishStateCallback c) {
mPublishController.unregisterPublishStateCallback(c);
}
/**
* Get the UCE publish state if the PUBLISH is supported by the carrier.
*/
public @PublishState int getUcePublishState() {
return mPublishController.getUcePublishState();
}
/**
* Add new feature tags to the Set used to calculate the capabilities in PUBLISH.
* <p>
* Used for testing ONLY.
* @return the new capabilities that will be used for PUBLISH.
*/
public RcsContactUceCapability addRegistrationOverrideCapabilities(Set<String> featureTags) {
return mPublishController.addRegistrationOverrideCapabilities(featureTags);
}
/**
* Remove existing feature tags to the Set used to calculate the capabilities in PUBLISH.
* <p>
* Used for testing ONLY.
* @return the new capabilities that will be used for PUBLISH.
*/
public RcsContactUceCapability removeRegistrationOverrideCapabilities(Set<String> featureTags) {
return mPublishController.removeRegistrationOverrideCapabilities(featureTags);
}
/**
* Clear all overrides in the Set used to calculate the capabilities in PUBLISH.
* <p>
* Used for testing ONLY.
* @return the new capabilities that will be used for PUBLISH.
*/
public RcsContactUceCapability clearRegistrationOverrideCapabilities() {
return mPublishController.clearRegistrationOverrideCapabilities();
}
/**
* @return current RcsContactUceCapability instance that will be used for PUBLISH.
*/
public RcsContactUceCapability getLatestRcsContactUceCapability() {
return mPublishController.getLatestRcsContactUceCapability();
}
/**
* Get the PIDF XML associated with the last successful publish or null if not PUBLISHed to the
* network.
*/
public String getLastPidfXml() {
return mPublishController.getLastPidfXml();
}
/**
* Remove the device disallowed state.
* <p>
* Used for testing ONLY.
*/
public void removeRequestDisallowedStatus() {
logd("removeRequestDisallowedStatus");
mDeviceState.resetDeviceState();
}
/**
* Set the milliseconds of capabilities request timeout.
* <p>
* Used for testing ONLY.
*/
public void setCapabilitiesRequestTimeout(long timeoutAfterMs) {
logd("setCapabilitiesRequestTimeout: " + timeoutAfterMs);
UceUtils.setCapRequestTimeoutAfterMillis(timeoutAfterMs);
}
/**
* Get the subscription ID.
*/
public int getSubId() {
return mSubId;
}
/**
* Check if the UceController is available.
* @return true if RCS is connected without destroyed.
*/
public boolean isUnavailable() {
if (!isRcsConnected() || mIsDestroyedFlag) {
return true;
}
return false;
}
private boolean isRcsConnecting() {
return mRcsConnectedState == RCS_STATE_CONNECTING;
}
private boolean isRcsConnected() {
return mRcsConnectedState == RCS_STATE_CONNECTED;
}
public void dump(PrintWriter printWriter) {
IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
pw.println("UceController" + "[subId: " + mSubId + "]:");
pw.increaseIndent();
pw.println("Log:");
pw.increaseIndent();
mLocalLog.dump(pw);
pw.decreaseIndent();
pw.println("---");
mPublishController.dump(pw);
pw.decreaseIndent();
}
private void logd(String log) {
Log.d(LOG_TAG, getLogPrefix().append(log).toString());
mLocalLog.log("[D] " + log);
}
private void logi(String log) {
Log.i(LOG_TAG, getLogPrefix().append(log).toString());
mLocalLog.log("[I] " + log);
}
private void logw(String log) {
Log.w(LOG_TAG, getLogPrefix().append(log).toString());
mLocalLog.log("[W] " + log);
}
private StringBuilder getLogPrefix() {
StringBuilder builder = new StringBuilder("[");
builder.append(mSubId);
builder.append("] ");
return builder;
}
}