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

Commit d68bc3a4 authored by Rambo Wang's avatar Rambo Wang Committed by Android (Google) Code Review
Browse files

Merge "Clean up OpenLogicalChannelRecord on SIM removal" into main

parents 7f6ae9b7 5510b021
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -42,3 +42,11 @@ flag {
    description: "This flag controls eSIM available memory feature."
    bug:"318348580"
}

# OWNER=rambowang TARGET=24Q3
flag {
    name: "cleanup_open_logical_channel_record_on_dispose"
    namespace: "telephony"
    description: "This flag cleans up the OpenLogicalChannelRecord once SIM is removed"
    bug:"335046531"
}
+32 −18
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.TelephonyComponentFactory;
import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.telephony.flags.FeatureFlagsImpl;
import com.android.internal.telephony.flags.Flags;
import com.android.telephony.Rlog;

import java.io.FileDescriptor;
@@ -57,8 +58,9 @@ public class UiccPort {
    private int mPortIdx;
    private int mPhysicalSlotIndex;

    // The list of the opened logical channel record. The channels will be closed by us when
    // detecting client died without closing them in advance.
    // The list of the opened logical channel record.
    // The channels will be closed by us when detecting client died without closing them in advance.
    // The same lock should be used to protect both access of the list and the individual record.
    @GuardedBy("mOpenChannelRecords")
    private final List<OpenLogicalChannelRecord> mOpenChannelRecords = new ArrayList<>();

@@ -101,11 +103,13 @@ public class UiccPort {
            }
            mUiccProfile = null;
        }
        cleanupOpenLogicalChannelRecordsIfNeeded();
    }

    @Override
    protected void finalize() {
        if (DBG) log("UiccPort finalized");
        cleanupOpenLogicalChannelRecordsIfNeeded();
    }

    /**
@@ -389,8 +393,10 @@ public class UiccPort {
    public void onLogicalChannelOpened(@NonNull IccLogicalChannelRequest request) {
        OpenLogicalChannelRecord record = new OpenLogicalChannelRecord(request);
        try {
            synchronized (mOpenChannelRecords) {
                request.binder.linkToDeath(record, /*flags=*/ 0);
            addOpenLogicalChannelRecord(record);
                mOpenChannelRecords.add(record);
            }
            if (DBG) log("onLogicalChannelOpened: monitoring client " + record);
        } catch (RemoteException | NullPointerException ex) {
            loge("IccOpenLogicChannel client has died, clean up manually");
@@ -406,11 +412,13 @@ public class UiccPort {
     */
    public void onLogicalChannelClosed(int channelId) {
        OpenLogicalChannelRecord record = getOpenLogicalChannelRecord(channelId);
        synchronized (mOpenChannelRecords) {
            if (record != null && record.mRequest != null && record.mRequest.binder != null) {
                if (DBG) log("onLogicalChannelClosed: stop monitoring client " + record);
                record.mRequest.binder.unlinkToDeath(record, /*flags=*/ 0);
            removeOpenLogicalChannelRecord(record);
                record.mRequest.binder = null;
                mOpenChannelRecords.remove(record);
            }
        }
    }

@@ -428,15 +436,21 @@ public class UiccPort {
        return null;
    }

    private void addOpenLogicalChannelRecord(OpenLogicalChannelRecord record) {
    /**
     * Clean up records when logical channels underneath have been released, in cases like SIM
     * removal or modem reset. The obsoleted records may trigger a redundant release of logical
     * channel that may have been assigned to other client.
     */
    private void cleanupOpenLogicalChannelRecordsIfNeeded() {
        if (Flags.cleanupOpenLogicalChannelRecordOnDispose()) {
            synchronized (mOpenChannelRecords) {
            mOpenChannelRecords.add(record);
                for (OpenLogicalChannelRecord record : mOpenChannelRecords) {
                    if (DBG) log("Clean up " + record);
                    record.mRequest.binder.unlinkToDeath(record, /*flags=*/ 0);
                    record.mRequest.binder = null;
                }
                mOpenChannelRecords.clear();
            }

    private void removeOpenLogicalChannelRecord(OpenLogicalChannelRecord record) {
        synchronized (mOpenChannelRecords) {
            mOpenChannelRecords.remove(record);
        }
    }

+25 −0
Original line number Diff line number Diff line
@@ -20,11 +20,16 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

import android.os.Binder;
import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -33,9 +38,11 @@ import androidx.test.filters.SmallTest;

import com.android.internal.telephony.IccLogicalChannelRequest;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.flags.Flags;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

@@ -54,9 +61,13 @@ public class UiccPortTest extends TelephonyTest {

    private int mPhoneId = 0;

    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    @Before
    public void setUp() throws Exception {
        super.setUp(getClass().getSimpleName());
        mSetFlagsRule.enableFlags(Flags.FLAG_CLEANUP_OPEN_LOGICAL_CHANNEL_RECORD_ON_DISPOSE);
        mUiccCard = mock(UiccCard.class);
        mIccCardStatus = mock(IccCardStatus.class);
        /* initially there are no application available */
@@ -144,6 +155,20 @@ public class UiccPortTest extends TelephonyTest {
        verify(mUiccProfile).iccCloseLogicalChannel(eq(CHANNEL_ID), eq(false), eq(null));
    }

    @Test
    @SmallTest
    public void testOnOpenLogicalChannel_withPortDisposed_noRecordLeft() {
        IccLogicalChannelRequest request = getIccLogicalChannelRequest();

        mUiccPort.onLogicalChannelOpened(request);
        mUiccPort.dispose();

        UiccPort.OpenLogicalChannelRecord record = mUiccPort.getOpenLogicalChannelRecord(
                CHANNEL_ID);
        assertThat(record).isNull();
        verify(mUiccProfile, never()).iccCloseLogicalChannel(anyInt(), anyBoolean(), any());
    }

    private IccLogicalChannelRequest getIccLogicalChannelRequest() {
        IccLogicalChannelRequest request = new IccLogicalChannelRequest();
        request.channel = CHANNEL_ID;