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

Commit eff96487 authored by Neil Fuller's avatar Neil Fuller
Browse files

Deflake ServiceStateTracker test and others

Switching MccTable over to using TelephonyComponentFactory
in commit 42e5c2cc
appears to have made an existing flakiness problem worse:
Evidence from Treehugger suggests that
MccTable.updateMccMncConfiguration() (which started using
TelephonyComponentFactory to obtain a TimeServiceHelper) is
called in various places while a test may be running.
TelephonyTest's replacement of the static
TelephonyComponentFactory instance used by MccTable is probably
leading to spurious NullPointerExceptions.

This change allows logic to be shared while side-stepping
the test infrastructure issue implied.

This change also moves the replacement of static instances
of various fundamental telephony classes until after they have
been baseline configured: it's not a solution but reduces the
time window where there may be unconfigured mocks replacing
real instances.

Bug: 63743683
Test: atest FrameworksTelephonyTests
Test: Treehugger

Change-Id: Ib93a87ab87464af93f8092434e971f09326973a4
parent 467c5502
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -358,13 +358,11 @@ public final class MccTable {
     * @param mcc Mobile Country Code of the SIM or SIM-like entity (build prop on CDMA)
     */
    private static void setTimezoneFromMccIfNeeded(Context context, int mcc) {
        TimeServiceHelper timeServiceHelper =
                TelephonyComponentFactory.getInstance().makeTimeServiceHelper(context);
        if (!timeServiceHelper.isTimeZoneSettingInitialized()) {
        if (!TimeServiceHelper.isTimeZoneSettingInitializedStatic()) {
            String zoneId = defaultTimeZoneForMcc(mcc);
            if (zoneId != null && zoneId.length() > 0) {
                // Set time zone based on MCC
                timeServiceHelper.setDeviceTimeZone(zoneId);
                TimeServiceHelper.setDeviceTimeZoneStatic(context, zoneId);
                Slog.d(LOG_TAG, "timezone set to " + zoneId);
            }
        }
+35 −15
Original line number Diff line number Diff line
@@ -94,16 +94,8 @@ public class TimeServiceHelper {
     * Returns true if the device has an explicit time zone set.
     */
    public boolean isTimeZoneSettingInitialized() {
        // timezone.equals("GMT") will be true and only true if the timezone was
        // set to a default value by the system server (when starting, system server
        // sets the persist.sys.timezone to "GMT" if it's not set). "GMT" is not used by
        // any code that sets it explicitly (in case where something sets GMT explicitly,
        // "Etc/GMT" Olsen ID would be used).
        // TODO(b/64056758): Remove "timezone.equals("GMT")" hack when there's a
        // better way of telling if the value has been defaulted.
        return isTimeZoneSettingInitializedStatic();

        String timeZoneId = SystemProperties.get(TIMEZONE_PROPERTY);
        return timeZoneId != null && timeZoneId.length() > 0 && !timeZoneId.equals("GMT");
    }

    /**
@@ -135,12 +127,7 @@ public class TimeServiceHelper {
     * @param zoneId timezone set by carrier
     */
    public void setDeviceTimeZone(String zoneId) {
        AlarmManager alarm = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
        alarm.setTimeZone(zoneId);
        Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
        intent.putExtra("time-zone", zoneId);
        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
        setDeviceTimeZoneStatic(mContext, zoneId);
    }

    /**
@@ -156,4 +143,37 @@ public class TimeServiceHelper {
        intent.putExtra("time", time);
        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
    }

    /**
     * Static implementation of isTimeZoneSettingInitialized() for use from {@link MccTable}. This
     * is a hack to deflake TelephonyTests when running on a device with a real SIM: in that
     * situation real service events may come in while a TelephonyTest is running, leading to flakes
     * as the real / fake instance of TimeServiceHelper is swapped in and out from
     * {@link TelephonyComponentFactory}.
     */
    static boolean isTimeZoneSettingInitializedStatic() {
        // timezone.equals("GMT") will be true and only true if the timezone was
        // set to a default value by the system server (when starting, system server
        // sets the persist.sys.timezone to "GMT" if it's not set). "GMT" is not used by
        // any code that sets it explicitly (in case where something sets GMT explicitly,
        // "Etc/GMT" Olsen ID would be used).
        // TODO(b/64056758): Remove "timezone.equals("GMT")" hack when there's a
        // better way of telling if the value has been defaulted.

        String timeZoneId = SystemProperties.get(TIMEZONE_PROPERTY);
        return timeZoneId != null && timeZoneId.length() > 0 && !timeZoneId.equals("GMT");
    }

    /**
     * Static method for use by MccTable. See {@link #isTimeZoneSettingInitializedStatic()} for
     * explanation.
     */
    static void setDeviceTimeZoneStatic(Context context, String zoneId) {
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.setTimeZone(zoneId);
        Intent intent = new Intent(TelephonyIntents.ACTION_NETWORK_SET_TIMEZONE);
        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
        intent.putExtra("time-zone", zoneId);
        context.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
    }
}
+22 −23
Original line number Diff line number Diff line
@@ -299,26 +299,6 @@ public abstract class TelephonyTest {
        TAG = tag;
        MockitoAnnotations.initMocks(this);

        //Use reflection to mock singletons
        replaceInstance(CallManager.class, "INSTANCE", null, mCallManager);
        replaceInstance(TelephonyComponentFactory.class, "sInstance", null,
                mTelephonyComponentFactory);
        replaceInstance(UiccController.class, "mInstance", null, mUiccController);
        replaceInstance(CdmaSubscriptionSourceManager.class, "sInstance", null, mCdmaSSM);
        replaceInstance(ImsManager.class, "sImsManagerInstances", null, mImsManagerInstances);
        replaceInstance(SubscriptionController.class, "sInstance", null, mSubscriptionController);
        replaceInstance(ProxyController.class, "sProxyController", null, mProxyController);
        replaceInstance(ActivityManager.class, "IActivityManagerSingleton", null,
                mIActivityManagerSingleton);
        replaceInstance(CdmaSubscriptionSourceManager.class,
                "mCdmaSubscriptionSourceChangedRegistrants", mCdmaSSM, mRegistrantList);
        replaceInstance(SimulatedCommandsVerifier.class, "sInstance", null,
                mSimulatedCommandsVerifier);
        replaceInstance(Singleton.class, "mInstance", mIActivityManagerSingleton,
                mIActivityManager);
        replaceInstance(ServiceManager.class, "sCache", null, mServiceManagerMockedServices);
        replaceInstance(IntentBroadcaster.class, "sIntentBroadcaster", null, mIntentBroadcaster);

        mSimulatedCommands = new SimulatedCommands();
        mContextFixture = new ContextFixture();
        mContext = mContextFixture.getTestDouble();
@@ -333,9 +313,6 @@ public abstract class TelephonyTest {
        mEuiccManager = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE);
        mPackageManager = mContext.getPackageManager();

        replaceInstance(TelephonyManager.class, "sInstance", null,
                mContext.getSystemService(Context.TELEPHONY_SERVICE));

        //mTelephonyComponentFactory
        doReturn(mSST).when(mTelephonyComponentFactory)
                .makeServiceStateTracker(nullable(GsmCdmaPhone.class),
@@ -464,6 +441,28 @@ public abstract class TelephonyTest {
        //SIM
        doReturn(1).when(mTelephonyManager).getSimCount();

        //Use reflection to mock singletons
        replaceInstance(CallManager.class, "INSTANCE", null, mCallManager);
        replaceInstance(TelephonyComponentFactory.class, "sInstance", null,
                mTelephonyComponentFactory);
        replaceInstance(UiccController.class, "mInstance", null, mUiccController);
        replaceInstance(CdmaSubscriptionSourceManager.class, "sInstance", null, mCdmaSSM);
        replaceInstance(ImsManager.class, "sImsManagerInstances", null, mImsManagerInstances);
        replaceInstance(SubscriptionController.class, "sInstance", null, mSubscriptionController);
        replaceInstance(ProxyController.class, "sProxyController", null, mProxyController);
        replaceInstance(ActivityManager.class, "IActivityManagerSingleton", null,
                mIActivityManagerSingleton);
        replaceInstance(CdmaSubscriptionSourceManager.class,
                "mCdmaSubscriptionSourceChangedRegistrants", mCdmaSSM, mRegistrantList);
        replaceInstance(SimulatedCommandsVerifier.class, "sInstance", null,
                mSimulatedCommandsVerifier);
        replaceInstance(Singleton.class, "mInstance", mIActivityManagerSingleton,
                mIActivityManager);
        replaceInstance(ServiceManager.class, "sCache", null, mServiceManagerMockedServices);
        replaceInstance(IntentBroadcaster.class, "sIntentBroadcaster", null, mIntentBroadcaster);
        replaceInstance(TelephonyManager.class, "sInstance", null,
                mContext.getSystemService(Context.TELEPHONY_SERVICE));

        setReady(false);
    }