Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1035afff authored by Hyunho's avatar Hyunho
Browse files

Add a new api that does not send PUBLISH request with duplicated presence capabilities

Add API that get RcsContactUsCapability when there are changed presence capabilities.
If there is no changed presence capabilities, do not send PUBLISH request.

Test: atest DeviceCapabilityInfoTest, PublishProcessor
Bug: b/215749573
Change-Id: Ifbf9b4f27a51acd89e3472cd8c68cd2659e3ffd6
Merged-In: Ifbf9b4f27a51acd89e3472cd8c68cd2659e3ffd6
parent 4c329e11
Loading
Loading
Loading
Loading
+58 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.util.Log;

import com.android.ims.rcs.uce.util.FeatureTags;
import com.android.ims.rcs.uce.util.UceUtils;
import com.android.internal.annotations.VisibleForTesting;

import java.io.PrintWriter;
import java.util.Arrays;
@@ -104,6 +105,11 @@ public class DeviceCapabilityInfo {
    private boolean mMobileData;
    private boolean mVtSetting;

    // The service description associated with the last publication update.
    private Set<ServiceDescription> mLastSuccessfulCapabilities = new ArraySet<>();
    // The service description to temporarily store the presence capability being sent.
    private Set<ServiceDescription> mPendingPublishCapabilities;

    public DeviceCapabilityInfo(int subId, String[] capToRegistrationMap) {
        mSubId = subId;
        mServiceCapRegTracker = PublishServiceDescTracker.fromCarrierConfig(capToRegistrationMap);
@@ -126,6 +132,8 @@ public class DeviceCapabilityInfo {
        mMmTelCapabilities = new MmTelCapabilities();
        mMmtelAssociatedUris = Collections.EMPTY_LIST;
        mRcsAssociatedUris = Collections.EMPTY_LIST;
        mLastSuccessfulCapabilities.clear();
        mPendingPublishCapabilities = null;
    }

    /**
@@ -173,6 +181,8 @@ public class DeviceCapabilityInfo {
        if (mMmtelRegistered) {
            mMmtelRegistered = false;
        }
        mLastSuccessfulCapabilities.clear();
        mPendingPublishCapabilities = null;
        mMmtelNetworkRegType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
    }

@@ -242,6 +252,8 @@ public class DeviceCapabilityInfo {
            changed = true;
        }
        mRcsNetworkRegType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
        mLastSuccessfulCapabilities.clear();
        mPendingPublishCapabilities = null;
        return changed;
    }

@@ -430,6 +442,52 @@ public class DeviceCapabilityInfo {
        return mPresenceCapable;
    }

    // Get the device's capabilities with the PRESENCE mechanism.
    public RcsContactUceCapability getChangedPresenceCapability(Context context) {
        if (context == null) {
            return null;
        }
        Set<ServiceDescription> capableFromReg =
                mServiceCapRegTracker.copyRegistrationCapabilities();
        if (isPresenceCapabilityChanged(capableFromReg)) {
            RcsContactUceCapability rcsContactUceCapability = getPresenceCapabilities(context);
            if (rcsContactUceCapability != null) {
                mPendingPublishCapabilities = mServiceCapRegTracker.copyRegistrationCapabilities();
            }
            return rcsContactUceCapability;
        }
        return null;
    }

    public void setPresencePublishResult(boolean isSuccess) {
        if (isSuccess) {
            mLastSuccessfulCapabilities = mPendingPublishCapabilities;
        }
        mPendingPublishCapabilities = null;
    }

    public void resetPresenceCapability() {
        mLastSuccessfulCapabilities.clear();
        mPendingPublishCapabilities = null;
    }

    @VisibleForTesting
    public void addLastSuccessfulServiceDescription(ServiceDescription capability) {
        mLastSuccessfulCapabilities.add(capability);
    }

    @VisibleForTesting
    public boolean isPresenceCapabilityChanged(Set<ServiceDescription> capableFromReg) {
        if (mLastSuccessfulCapabilities.isEmpty()) {
            return true;
        }

        if (capableFromReg.equals(mLastSuccessfulCapabilities)) {
            return false;
        }
        return true;
    }

    private boolean isVolteAvailable(int networkRegType, MmTelCapabilities capabilities) {
        return (networkRegType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
                && capabilities.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE);
+18 −3
Original line number Diff line number Diff line
@@ -112,6 +112,8 @@ public class PublishProcessor {
        logi("onRcsDisconnected");
        mRcsFeatureManager = null;
        mProcessorState.onRcsDisconnected();
        // reset the publish capabilities.
        mDeviceCapabilities.resetPresenceCapability();
    }

    /**
@@ -152,10 +154,15 @@ public class PublishProcessor {
        }

        // Get the latest device's capabilities.
        RcsContactUceCapability deviceCapability =
                mDeviceCapabilities.getDeviceCapabilities(CAPABILITY_MECHANISM_PRESENCE, mContext);
        RcsContactUceCapability deviceCapability;
        if (triggerType == PublishController.PUBLISH_TRIGGER_SERVICE) {
            deviceCapability = mDeviceCapabilities.getDeviceCapabilities(
                    CAPABILITY_MECHANISM_PRESENCE, mContext);
        } else {
            deviceCapability = mDeviceCapabilities.getChangedPresenceCapability(mContext);
        }
        if (deviceCapability == null) {
            logw("doPublishInternal: device capability is null");
            logi("doPublishInternal: device capability hasn't changed or is null");
            return false;
        }

@@ -349,6 +356,8 @@ public class PublishProcessor {
        // Increase the retry count
        mProcessorState.increaseRetryCount();

        // reset the last capabilities because of the request is failed
        mDeviceCapabilities.setPresencePublishResult(false);
        // Reset the pending flag because it is going to resend a request.
        clearPendingRequest();

@@ -373,10 +382,14 @@ public class PublishProcessor {
        Instant responseTime = response.getResponseTimestamp();

        // Record the time when the request is successful and reset the retry count.
        boolean publishSuccess = false;
        if (response.isRequestSuccess()) {
            mProcessorState.setLastPublishedTime(responseTime);
            mProcessorState.resetRetryCount();
            publishSuccess = true;
        }
        // set the last capabilities according to the result of request.
        mDeviceCapabilities.setPresencePublishResult(publishSuccess);

        // Update the publish state after the request has finished.
        int publishState = response.getPublishState();
@@ -492,6 +505,8 @@ public class PublishProcessor {
     */
    public void resetState() {
        mProcessorState.resetState();
        // reset the publish capabilities.
        mDeviceCapabilities.resetPresenceCapability();
    }

    /**
+128 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.presence.publish;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import android.telephony.ims.RcsContactPresenceTuple;
import android.util.ArraySet;

import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

import com.android.ims.ImsTestBase;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;

import java.util.Collections;
import java.util.Set;

@RunWith(AndroidJUnit4.class)
public class DeviceCapabilityInfoTest extends ImsTestBase {

    int mSubId = 1;
    @Mock PublishServiceDescTracker mPublishServiceDescTracker;

    @Before
    public void setUp() throws Exception {
        super.setUp();
    }

    @After
    public void tearDown() throws Exception {
        super.tearDown();
    }

    @Test
    @SmallTest
    public void testGetPresenceCapabilityForSameDescription() throws Exception {
        DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo();

        Set<ServiceDescription> mTestCapability = new ArraySet<>();
        mTestCapability.add(getChatDescription());
        mTestCapability.add(getMmtelDescription());
        mTestCapability.add(getUndefinedDescription());

        deviceCapInfo.addLastSuccessfulServiceDescription(getMmtelDescription());
        deviceCapInfo.addLastSuccessfulServiceDescription(getChatDescription());
        deviceCapInfo.addLastSuccessfulServiceDescription(getUndefinedDescription());
        assertFalse(deviceCapInfo.isPresenceCapabilityChanged(mTestCapability));
    }

    @Test
    @SmallTest
    public void testGetPresenceCapabilityForSameSizeOfDescription() throws Exception {
        DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo();

        Set<ServiceDescription> mTestCapability = new ArraySet<>();
        mTestCapability.add(getChatDescription());
        mTestCapability.add(getMmtelDescription());
        mTestCapability.add(getUndefinedDescription());

        deviceCapInfo.addLastSuccessfulServiceDescription(getMmtelDescription());
        deviceCapInfo.addLastSuccessfulServiceDescription(getChatDescription());
        deviceCapInfo.addLastSuccessfulServiceDescription(getUndefined2Description());

        assertTrue(deviceCapInfo.isPresenceCapabilityChanged(mTestCapability));
    }
    private DeviceCapabilityInfo createDeviceCapabilityInfo() {
        DeviceCapabilityInfo deviceCapInfo = new DeviceCapabilityInfo(mSubId, null);
        return deviceCapInfo;
    }

    private ServiceDescription getChatDescription() {
        ServiceDescription SERVICE_DESCRIPTION_CHAT_SESSION =
                new ServiceDescription(
                        RcsContactPresenceTuple.SERVICE_ID_CHAT_V2,
                        "2.0" /*version*/,
                        null /*description*/
                );
        return SERVICE_DESCRIPTION_CHAT_SESSION;
    }

    private ServiceDescription getMmtelDescription() {
        ServiceDescription SERVICE_DESCRIPTION_MMTEL_VOICE = new ServiceDescription(
                RcsContactPresenceTuple.SERVICE_ID_MMTEL,
                "1.0" /*version*/,
                "Voice Service" /*description*/
        );
        return SERVICE_DESCRIPTION_MMTEL_VOICE;
    }

    private ServiceDescription getUndefinedDescription() {
        ServiceDescription SERVICE_DESCRIPTION_TEST = new ServiceDescription(
                "test",
                "1.0" /*version*/,
                "Test_Service" /*description*/
        );
        return SERVICE_DESCRIPTION_TEST;
    }

    private ServiceDescription getUndefined2Description() {
        ServiceDescription SERVICE_DESCRIPTION_TEST2 = new ServiceDescription(
                "test1",
                "1.0" /*version*/,
                "Test_Service" /*description*/
        );
        return SERVICE_DESCRIPTION_TEST2;
    }
}
+8 −1
Original line number Diff line number Diff line
@@ -66,8 +66,8 @@ public class PublishProcessorTest extends ImsTestBase {

        doReturn(true).when(mDeviceCapabilities).isImsRegistered();
        RcsContactUceCapability capability = getRcsContactUceCapability();
        doReturn(capability).when(mDeviceCapabilities).getChangedPresenceCapability(any());
        doReturn(capability).when(mDeviceCapabilities).getDeviceCapabilities(anyInt(), any());

        doReturn(mTaskId).when(mResponseCallback).getTaskId();
    }

@@ -97,6 +97,7 @@ public class PublishProcessorTest extends ImsTestBase {

        publishProcessor.doPublish(PublishController.PUBLISH_TRIGGER_RETRY);

        verify(mDeviceCapabilities).getChangedPresenceCapability(any());
        verify(mProcessorState, never()).resetRetryCount();
    }

@@ -155,6 +156,7 @@ public class PublishProcessorTest extends ImsTestBase {

        publishProcessor.onCommandError(mResponseCallback);

        verify(mDeviceCapabilities).setPresencePublishResult(false);
        verify(mProcessorState).increaseRetryCount();
        verify(mPublishCtrlCallback).requestPublishFromInternal(
                eq(PublishController.PUBLISH_TRIGGER_RETRY));
@@ -172,10 +174,12 @@ public class PublishProcessorTest extends ImsTestBase {
        doReturn(mTaskId).when(mProcessorState).getCurrentTaskId();
        doReturn(mTaskId).when(mResponseCallback).getTaskId();
        doReturn(false).when(mResponseCallback).needRetry();
        doReturn(true).when(mResponseCallback).isRequestSuccess();
        PublishProcessor publishProcessor = getPublishProcessor();

        publishProcessor.onCommandError(mResponseCallback);

        verify(mDeviceCapabilities).setPresencePublishResult(true);
        verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any());
        verify(mResponseCallback).onDestroy();
        verify(mProcessorState).setPublishingFlag(false);
@@ -193,6 +197,7 @@ public class PublishProcessorTest extends ImsTestBase {

        publishProcessor.onNetworkResponse(mResponseCallback);

        verify(mDeviceCapabilities).setPresencePublishResult(false);
        verify(mProcessorState).increaseRetryCount();
        verify(mPublishCtrlCallback).requestPublishFromInternal(
                eq(PublishController.PUBLISH_TRIGGER_RETRY));
@@ -214,6 +219,7 @@ public class PublishProcessorTest extends ImsTestBase {

        publishProcessor.onNetworkResponse(mResponseCallback);

        verify(mDeviceCapabilities).setPresencePublishResult(true);
        verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any());
        verify(mResponseCallback).onDestroy();
        verify(mProcessorState).setPublishingFlag(false);
@@ -248,6 +254,7 @@ public class PublishProcessorTest extends ImsTestBase {

        publishProcessor.publishUpdated(mResponseCallback);

        verify(mDeviceCapabilities).setPresencePublishResult(true);
        verify(mProcessorState).setLastPublishedTime(any());
        verify(mProcessorState).resetRetryCount();
        verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any());