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

Commit 78f8352f authored by Sarah Chin's avatar Sarah Chin Committed by Automerger Merge Worker
Browse files

Merge "Fix APM race conditions in ServiceStateTracker" into tm-d1-dev am: abeaa6e8

parents fd7bd20e abeaa6e8
Loading
Loading
Loading
Loading
+29 −11
Original line number Diff line number Diff line
@@ -1093,7 +1093,7 @@ public class ServiceStateTracker extends Handler {
    /**
     * Turn on or off radio power with option to specify whether it's for emergency call and specify
     * a reason for setting the power state.
     * More details check {@link PhoneInternalInterface#setRadioPower(
     * More details check {@link PhoneInternalInterface#setRadioPowerForReason(
     * boolean, boolean, boolean, boolean, int)}.
     */
    public void setRadioPowerForReason(boolean power, boolean forEmergencyCall,
@@ -1197,8 +1197,8 @@ public class ServiceStateTracker extends Handler {
            case EVENT_SET_RADIO_POWER_OFF:
                synchronized (this) {
                    if (mPhone.isUsingNewDataStack()) {
                        mPendingRadioPowerOffAfterDataOff = false;
                        log("Wait for all data networks torn down timed out. Power off now.");
                        cancelPendingRadioPowerOff();
                        hangupAndPowerOff();
                        return;
                    }
@@ -1494,12 +1494,13 @@ public class ServiceStateTracker extends Handler {
                            areAllDataDisconnectedOnAllPhones = false;
                        }
                    }
                    synchronized (this) {
                        if (areAllDataDisconnectedOnAllPhones) {
                        mPendingRadioPowerOffAfterDataOff = false;
                        removeMessages(EVENT_SET_RADIO_POWER_OFF);
                            if (DBG) log("Data disconnected for all phones, turn radio off now.");
                            cancelPendingRadioPowerOff();
                            hangupAndPowerOff();
                        }
                    }
                    return;
                }
                int dds = SubscriptionManager.getDefaultDataSubscriptionId();
@@ -3135,12 +3136,12 @@ public class ServiceStateTracker extends Handler {
                    && getRadioPowerOffDelayTimeoutForImsRegistration() > 0) {
                if (DBG) log("setPowerStateToDesired: delaying power off until IMS dereg.");
                startDelayRadioOffWaitingForImsDeregTimeout();
                // Return early here as we do not want to hit the cancel timeout code below.
                return;
            } else {
                if (DBG) log("setPowerStateToDesired: powerOffRadioSafely()");
                powerOffRadioSafely();
            }
            // Return early here as we do not want to hit the cancel timeout code below.
            return;
        } else if (mDeviceShuttingDown
                && (mCi.getRadioState() != TelephonyManager.RADIO_POWER_UNAVAILABLE)) {
            // !mDesiredPowerState condition above will happen first if the radio is on, so we will
@@ -3150,6 +3151,23 @@ public class ServiceStateTracker extends Handler {
        }
        // Cancel any pending timeouts because the state has been re-evaluated.
        cancelDelayRadioOffWaitingForImsDeregTimeout();
        cancelPendingRadioPowerOff();
    }

    /**
     * Cancel the pending radio power off request that was sent to force the radio to power off
     * if waiting for all data to disconnect times out.
     */
    private synchronized void cancelPendingRadioPowerOff() {
        if (mPhone.isUsingNewDataStack() && mPendingRadioPowerOffAfterDataOff) {
            if (DBG) log("cancelPendingRadioPowerOff: cancelling.");
            mPendingRadioPowerOffAfterDataOff = false;
            for (Phone phone : PhoneFactory.getPhones()) {
                phone.getDataNetworkController().unregisterDataNetworkControllerCallback(
                        mDataDisconnectedCallback);
            }
            removeMessages(EVENT_SET_RADIO_POWER_OFF);
        }
    }

    /**
+52 −1
Original line number Diff line number Diff line
@@ -417,6 +417,7 @@ public class ServiceStateTrackerTest extends TelephonyTest {
                callback1.capture());
        verify(dataNetworkController_phone2, times(1)).registerDataNetworkControllerCallback(
                callback2.capture());
        assertTrue(sst.hasMessages(38 /* EVENT_SET_RADIO_POWER_OFF */));

        // Data disconnected on sub 2, still waiting for data disconnected on sub 1
        doReturn(true).when(dataNetworkController_phone2).areAllDataDisconnected();
@@ -430,10 +431,60 @@ public class ServiceStateTrackerTest extends TelephonyTest {
        doReturn(true).when(mDataNetworkController).areAllDataDisconnected();
        callback1.getValue().onAnyDataNetworkExistingChanged(false);
        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
        verify(mDataNetworkController, times(1)).unregisterDataNetworkControllerCallback(any());
        verify(mDataNetworkController, times(2)).unregisterDataNetworkControllerCallback(any());
        assertEquals(TelephonyManager.RADIO_POWER_OFF, mSimulatedCommands.getRadioState());
    }

    @Test
    public void testSetRadioPowerCancelWaitForAllDataDisconnected() throws Exception {
        // Set up DSDS environment
        GsmCdmaPhone phone2 = Mockito.mock(GsmCdmaPhone.class);
        DataNetworkController dataNetworkController_phone2 =
                Mockito.mock(DataNetworkController.class);
        mPhones = new Phone[] {mPhone, phone2};
        replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
        doReturn(dataNetworkController_phone2).when(phone2).getDataNetworkController();
        doReturn(mSST).when(phone2).getServiceStateTracker();
        doReturn(true).when(phone2).isUsingNewDataStack();
        doReturn(false).when(mDataNetworkController).areAllDataDisconnected();
        doReturn(false).when(dataNetworkController_phone2).areAllDataDisconnected();
        doReturn(1).when(mPhone).getSubId();
        doReturn(2).when(phone2).getSubId();

        // Start with radio on
        sst.setRadioPower(true);
        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());

        // Turn on APM and verify that both subs are waiting for all data disconnected
        sst.setRadioPower(false);
        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());
        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());
        verify(mDataNetworkController).tearDownAllDataNetworks(
                eq(3 /* TEAR_DOWN_REASON_AIRPLANE_MODE_ON */));
        verify(dataNetworkController_phone2, never()).tearDownAllDataNetworks(anyInt());
        ArgumentCaptor<DataNetworkController.DataNetworkControllerCallback> callback1 =
                ArgumentCaptor.forClass(DataNetworkController.DataNetworkControllerCallback.class);
        ArgumentCaptor<DataNetworkController.DataNetworkControllerCallback> callback2 =
                ArgumentCaptor.forClass(DataNetworkController.DataNetworkControllerCallback.class);
        verify(mDataNetworkController, times(1)).registerDataNetworkControllerCallback(
                callback1.capture());
        verify(dataNetworkController_phone2, times(1)).registerDataNetworkControllerCallback(
                callback2.capture());
        assertTrue(sst.hasMessages(38 /* EVENT_SET_RADIO_POWER_OFF */));

        // Turn off APM while waiting for data to disconnect
        sst.setRadioPower(true);
        waitForLastHandlerAction(mSSTTestHandler.getThreadHandler());

        // Check that radio is on and pending power off messages were cleared
        assertFalse(sst.hasMessages(38 /* EVENT_SET_RADIO_POWER_OFF */));
        verify(mDataNetworkController, times(1)).unregisterDataNetworkControllerCallback(any());
        verify(dataNetworkController_phone2, times(1)).unregisterDataNetworkControllerCallback(
                any());
        assertEquals(TelephonyManager.RADIO_POWER_ON, mSimulatedCommands.getRadioState());
    }

    @Test
    @SmallTest
    public void testSetRadioPowerOnForEmergencyCall() {