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

Commit 45066127 authored by Hall Liu's avatar Hall Liu
Browse files

Convert Telephony broadcasts to be non-sticky

Convert ACTION_SERVICE_STATE_CHANGED and
ACTION_ANY_DATA_CONNECTION_CHANGED to be non-sticky broadcasts that
require the READ_PHONE_STATE permission to receive. As part of this,
declare READ_PHONE_STATE to be split from READ_PRIVILEGED_PHONE_STATE,
so that system apps holding READ_PRIVILEGED_PHONE_STATE can also receive
these broadcasts.

Also modify affected users to fetch the current value of the broadcast
upon registration instead of relying on the sticky nature of the
broadcast.

Bug: 150155839
Test: manual
Test: atest KeyguardUpdateMonitorTest
Change-Id: I020b1554c4fc59c138d015e787526b4a66c74853
parent 4785a066
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -197,6 +197,9 @@
    <split-permission name="android.permission.WRITE_EXTERNAL_STORAGE">
        <new-permission name="android.permission.READ_EXTERNAL_STORAGE" />
    </split-permission>
    <split-permission name="android.permission.READ_PRIVILEGED_PHONE_STATE">
        <new-permission name="android.permission.READ_PHONE_STATE" />
    </split-permission>
    <split-permission name="android.permission.READ_CONTACTS"
                      targetSdk="16">
        <new-permission name="android.permission.READ_CALL_LOG" />
+9 −0
Original line number Diff line number Diff line
@@ -1664,6 +1664,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
        filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
        mBroadcastDispatcher.registerReceiverWithHandler(mBroadcastReceiver, filter, mHandler);
        // Since ACTION_SERVICE_STATE is being moved to a non-sticky broadcast, trigger the
        // listener now with the service state from the default sub.
        mBackgroundExecutor.execute(() -> {
            int subId = SubscriptionManager.getDefaultSubscriptionId();
            ServiceState serviceState = mContext.getSystemService(TelephonyManager.class)
                    .getServiceStateForSubscriber(subId);
            mHandler.sendMessage(
                    mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState));
        });

        mHandler.post(this::registerRingerTracker);

+14 −1
Original line number Diff line number Diff line
@@ -329,7 +329,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
        return mDataSaverController;
    }

    private void registerListeners() {
    @VisibleForTesting
    void registerListeners() {
        for (int i = 0; i < mMobileSignalControllers.size(); i++) {
            MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
            mobileSignalController.registerListener();
@@ -364,6 +365,18 @@ public class NetworkControllerImpl extends BroadcastReceiver
        // Initial setup of WifiSignalController. Handled as if we had received a sticky broadcast
        // of WifiManager.WIFI_STATE_CHANGED_ACTION or WifiManager.NETWORK_STATE_CHANGED_ACTION
        mReceiverHandler.post(mWifiSignalController::fetchInitialState);

        // Initial setup of mLastServiceState. Only run if there is no service state yet.
        // Each MobileSignalController will also get their corresponding
        mReceiverHandler.post(() -> {
            if (mLastServiceState == null) {
                mLastServiceState = mPhone.getServiceState();
                if (mMobileSignalControllers.size() == 0) {
                    recalculateEmergency();
                }
            }
        });

        updateMobileControllers();

        // Initial setup of emergency information. Handled as if we had received a sticky broadcast
+14 −2
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ import android.testing.TestableLooper;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;

import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.internal.telephony.TelephonyIntents;
import com.android.keyguard.KeyguardUpdateMonitor.BiometricAuthenticated;
import com.android.systemui.SysuiTestCase;
@@ -87,6 +88,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;

import java.util.ArrayList;
import java.util.List;
@@ -134,16 +136,17 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
    @Mock
    private BroadcastDispatcher mBroadcastDispatcher;
    @Mock
    private TelephonyManager mTelephonyManager;
    @Mock
    private RingerModeTracker mRingerModeTracker;
    @Mock
    private LiveData<Integer> mRingerModeLiveData;
    @Mock
    private TelephonyManager mTelephonyManager;
    // Direct executor
    private Executor mBackgroundExecutor = Runnable::run;
    private TestableLooper mTestableLooper;
    private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
    private TestableContext mSpiedContext;
    private MockitoSession mMockitoSession;

    @Before
    public void setup() {
@@ -165,6 +168,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
        when(mStrongAuthTracker
                .isUnlockingWithBiometricAllowed(anyBoolean() /* isStrongBiometric */))
                .thenReturn(true);

        when(mTelephonyManager.getServiceStateForSubscriber(anyInt()))
                .thenReturn(new ServiceState());
        mSpiedContext.addMockSystemService(TrustManager.class, mTrustManager);
        mSpiedContext.addMockSystemService(FingerprintManager.class, mFingerprintManager);
        mSpiedContext.addMockSystemService(BiometricManager.class, mBiometricManager);
@@ -176,6 +182,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {

        when(mRingerModeTracker.getRingerMode()).thenReturn(mRingerModeLiveData);

        mMockitoSession = ExtendedMockito.mockitoSession()
                .spyStatic(SubscriptionManager.class).startMocking();
        ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
                .when(SubscriptionManager::getDefaultSubscriptionId);

        mTestableLooper = TestableLooper.get(this);
        allowTestableLooperAsMainThread();
        mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext);
@@ -183,6 +194,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {

    @After
    public void tearDown() {
        mMockitoSession.finishMocking();
        mKeyguardUpdateMonitor.destroy();
    }

+24 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static org.mockito.Mockito.when;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkCapabilities;
import android.os.Handler;
import android.os.Looper;
import android.telephony.CellSignalStrength;
import android.telephony.ServiceState;
@@ -46,6 +47,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@SmallTest
@@ -67,6 +69,28 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
        verifyLastMobileDataIndicators(false, -1, 0);
    }

    @Test
    public void testServiceStateInitialState() throws Exception {
        // Verify that NetworkControllerImpl pulls the service state from Telephony upon
        // initialization rather than relying on the sticky behavior of ACTION_SERVICE_STATE

        when(mServiceState.isEmergencyOnly()).thenReturn(true);
        when(mMockTm.getServiceState()).thenReturn(mServiceState);
        when(mMockSm.getCompleteActiveSubscriptionInfoList()).thenReturn(Collections.emptyList());

        mNetworkController = new NetworkControllerImpl(mContext, mMockCm, mMockTm, mMockWm,
                mMockNsm, mMockSm, mConfig, Looper.getMainLooper(), mCallbackHandler,
                mock(AccessPointControllerImpl.class), mock(DataUsageController.class),
                mMockSubDefaults, mock(DeviceProvisionedController.class), mMockBd);
        mNetworkController.registerListeners();

        // Wait for the main looper to execute the previous command
        Handler mainThreadHandler = new Handler(Looper.getMainLooper());
        waitForIdleSync(mainThreadHandler);

        verifyEmergencyOnly(true);
    }

    @Test
    public void testNoSimsIconPresent() {
        // No Subscriptions.
Loading