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

Commit 3f4b5d08 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add handling of NativeRescueParty resets to RescueParty."

parents 60998a59 93075f45
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -38,9 +38,11 @@ import android.util.StatsLog;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.server.am.SettingsToPropertiesMapper;
import com.android.server.utils.FlagNamespaceUtils;
import com.android.server.utils.FlagNamespaceUtils;


import java.io.File;
import java.io.File;
import java.util.Arrays;


/**
/**
 * Utilities to help rescue the system from crash loops. Callers are expected to
 * Utilities to help rescue the system from crash loops. Callers are expected to
@@ -158,6 +160,7 @@ public class RescueParty {
     * opportunity to reset any settings depending on our rescue level.
     * opportunity to reset any settings depending on our rescue level.
     */
     */
    public static void onSettingsProviderPublished(Context context) {
    public static void onSettingsProviderPublished(Context context) {
        handleNativeRescuePartyResets();
        executeRescueLevel(context);
        executeRescueLevel(context);
    }
    }


@@ -176,6 +179,13 @@ public class RescueParty {
        return SystemClock.elapsedRealtime();
        return SystemClock.elapsedRealtime();
    }
    }


    private static void handleNativeRescuePartyResets() {
        if (SettingsToPropertiesMapper.isNativeFlagsResetPerformed()) {
            FlagNamespaceUtils.resetDeviceConfig(Settings.RESET_MODE_TRUSTED_DEFAULTS,
                    Arrays.asList(SettingsToPropertiesMapper.getResetNativeCategories()));
        }
    }

    /**
    /**
     * Escalate to the next rescue level. After incrementing the level you'll
     * Escalate to the next rescue level. After incrementing the level you'll
     * probably want to call {@link #executeRescueLevel(Context)}.
     * probably want to call {@link #executeRescueLevel(Context)}.
+2 −1
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.server.am;
package com.android.server.am;


import android.annotation.NonNull;
import android.content.ContentResolver;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.ContentObserver;
import android.net.Uri;
import android.net.Uri;
@@ -167,7 +168,7 @@ public class SettingsToPropertiesMapper {
     * booting.
     * booting.
     * @return
     * @return
     */
     */
    public static String[] getResetNativeCategories() {
    public static @NonNull String[] getResetNativeCategories() {
        if (!isNativeFlagsResetPerformed()) {
        if (!isNativeFlagsResetPerformed()) {
            return new String[0];
            return new String[0];
        }
        }
+24 −6
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.utils;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig;


import com.android.internal.annotations.VisibleForTesting;
import com.android.server.RescueParty;
import com.android.server.RescueParty;


import java.util.ArrayList;
import java.util.ArrayList;
@@ -41,20 +42,23 @@ public final class FlagNamespaceUtils {
    /**
    /**
     * Name of the special namespace in DeviceConfig table used for communicating resets.
     * Name of the special namespace in DeviceConfig table used for communicating resets.
     */
     */
    private static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace";
    @VisibleForTesting
    public static final String NAMESPACE_RESCUE_PARTY = "rescue_party_namespace";
    /**
    /**
     * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY}, holding all known {@link
     * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY}, holding all known {@link
     * DeviceConfig} namespaces, as a {@link #DELIMITER} separated String. It's updated after the
     * DeviceConfig} namespaces, as a {@link #DELIMITER} separated String. It's updated after the
     * first time flags are written to the new namespace in the {@link DeviceConfig}.
     * first time flags are written to the new namespace in the {@link DeviceConfig}.
     */
     */
    private static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces";
    @VisibleForTesting
    public static final String ALL_KNOWN_NAMESPACES_FLAG = "all_known_namespaces";
    /**
    /**
     * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY} with integer counter
     * Flag in the {@link DeviceConfig} in {@link #NAMESPACE_RESCUE_PARTY} with integer counter
     * suffix added to it, holding {@link DeviceConfig} namespace value whose flags were recently
     * suffix added to it, holding {@link DeviceConfig} namespace value whose flags were recently
     * reset by the {@link RescueParty}. It's updated by {@link RescueParty} every time given
     * reset by the {@link RescueParty}. It's updated by {@link RescueParty} every time given
     * namespace flags are reset.
     * namespace flags are reset.
     */
     */
    private static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package";
    @VisibleForTesting
    public static final String RESET_PLATFORM_PACKAGE_FLAG = "reset_platform_package";
    private static final String DELIMITER = ":";
    private static final String DELIMITER = ":";
    /**
    /**
     * Maximum value of the counter used in combination with {@link #RESET_PLATFORM_PACKAGE_FLAG}
     * Maximum value of the counter used in combination with {@link #RESET_PLATFORM_PACKAGE_FLAG}
@@ -97,11 +101,25 @@ public final class FlagNamespaceUtils {
     * Reset all namespaces in DeviceConfig with consumed resetMode.
     * Reset all namespaces in DeviceConfig with consumed resetMode.
     */
     */
    public static void resetDeviceConfig(int resetMode) {
    public static void resetDeviceConfig(int resetMode) {
        List<String> allKnownNamespaces = getAllKnownDeviceConfigNamespacesList();
        resetDeviceConfig(resetMode, getAllKnownDeviceConfigNamespacesList());
        for (String namespace : allKnownNamespaces) {
    }

    /**
     * Reset all consumed namespaces in DeviceConfig with consumed resetMode.
     */
    public static void resetDeviceConfig(int resetMode, List<String> namespacesList) {
        for (String namespace : namespacesList) {
            DeviceConfig.resetToDefaults(resetMode, namespace);
            DeviceConfig.resetToDefaults(resetMode, namespace);
        }
        }
        addToKnownResetNamespaces(allKnownNamespaces);
        addToKnownResetNamespaces(namespacesList);
    }

    /**
     * Resets known reset namespaces flag counter for tests only.
     */
    @VisibleForTesting
    public static void resetKnownResetNamespacesFlagCounterForTest() {
        sKnownResetNamespacesFlagCounter = -1;
    }
    }


    /**
    /**
+42 −2
Original line number Original line Diff line number Diff line
@@ -35,9 +35,12 @@ import android.content.Context;
import android.os.RecoverySystem;
import android.os.RecoverySystem;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings;


import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.am.SettingsToPropertiesMapper;
import com.android.server.utils.FlagNamespaceUtils;


import org.junit.After;
import org.junit.After;
import org.junit.Before;
import org.junit.Before;
@@ -56,6 +59,10 @@ import java.util.HashMap;
public class RescuePartyTest {
public class RescuePartyTest {
    private static final int PERSISTENT_APP_UID = 12;
    private static final int PERSISTENT_APP_UID = 12;
    private static final long CURRENT_NETWORK_TIME_MILLIS = 0L;
    private static final long CURRENT_NETWORK_TIME_MILLIS = 0L;
    private static final String FAKE_NATIVE_NAMESPACE1 = "native1";
    private static final String FAKE_NATIVE_NAMESPACE2 = "native2";
    private static final String[] FAKE_RESET_NATIVE_NAMESPACES =
            {FAKE_NATIVE_NAMESPACE1, FAKE_NATIVE_NAMESPACE2};


    private MockitoSession mSession;
    private MockitoSession mSession;


@@ -73,9 +80,11 @@ public class RescuePartyTest {
                ExtendedMockito.mockitoSession().initMocks(
                ExtendedMockito.mockitoSession().initMocks(
                        this)
                        this)
                        .strictness(Strictness.LENIENT)
                        .strictness(Strictness.LENIENT)
                        .spyStatic(DeviceConfig.class)
                        .spyStatic(SystemProperties.class)
                        .spyStatic(SystemProperties.class)
                        .spyStatic(Settings.Global.class)
                        .spyStatic(Settings.Global.class)
                        .spyStatic(Settings.Secure.class)
                        .spyStatic(Settings.Secure.class)
                        .spyStatic(SettingsToPropertiesMapper.class)
                        .spyStatic(RecoverySystem.class)
                        .spyStatic(RecoverySystem.class)
                        .spyStatic(RescueParty.class)
                        .spyStatic(RescueParty.class)
                        .startMocking();
                        .startMocking();
@@ -121,8 +130,17 @@ public class RescuePartyTest {
                }
                }
        ).when(() -> SystemProperties.getLong(anyString(), anyLong()));
        ).when(() -> SystemProperties.getLong(anyString(), anyLong()));


        // Mock DeviceConfig
        doAnswer((Answer<Boolean>) invocationOnMock -> true)
                .when(() -> DeviceConfig.setProperty(anyString(), anyString(), anyString(),
                        anyBoolean()));
        doAnswer((Answer<Void>) invocationOnMock -> null)
                .when(() -> DeviceConfig.resetToDefaults(anyInt(), anyString()));


        doReturn(CURRENT_NETWORK_TIME_MILLIS).when(() -> RescueParty.getElapsedRealtime());
        doReturn(CURRENT_NETWORK_TIME_MILLIS).when(() -> RescueParty.getElapsedRealtime());
        RescueParty.resetAllThresholds();
        RescueParty.resetAllThresholds();
        FlagNamespaceUtils.resetKnownResetNamespacesFlagCounterForTest();


        SystemProperties.set(RescueParty.PROP_RESCUE_LEVEL,
        SystemProperties.set(RescueParty.PROP_RESCUE_LEVEL,
                Integer.toString(RescueParty.LEVEL_NONE));
                Integer.toString(RescueParty.LEVEL_NONE));
@@ -278,10 +296,32 @@ public class RescuePartyTest {
                SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
                SystemProperties.getInt(RescueParty.PROP_RESCUE_LEVEL, RescueParty.LEVEL_NONE));
    }
    }


    @Test
    public void testNativeRescuePartyResets() {
        doReturn(true).when(() -> SettingsToPropertiesMapper.isNativeFlagsResetPerformed());
        doReturn(FAKE_RESET_NATIVE_NAMESPACES).when(
                () -> SettingsToPropertiesMapper.getResetNativeCategories());

        RescueParty.onSettingsProviderPublished(mMockContext);

        verify(() -> DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS,
                FAKE_NATIVE_NAMESPACE1));
        verify(() -> DeviceConfig.resetToDefaults(Settings.RESET_MODE_TRUSTED_DEFAULTS,
                FAKE_NATIVE_NAMESPACE2));

        ExtendedMockito.verify(
                () -> DeviceConfig.setProperty(FlagNamespaceUtils.NAMESPACE_RESCUE_PARTY,
                        FlagNamespaceUtils.RESET_PLATFORM_PACKAGE_FLAG + 0,
                        FAKE_NATIVE_NAMESPACE1, /*makeDefault=*/true));
        ExtendedMockito.verify(
                () -> DeviceConfig.setProperty(FlagNamespaceUtils.NAMESPACE_RESCUE_PARTY,
                        FlagNamespaceUtils.RESET_PLATFORM_PACKAGE_FLAG + 1,
                        FAKE_NATIVE_NAMESPACE2, /*makeDefault=*/true));
    }

    private void verifySettingsResets(int resetMode) {
    private void verifySettingsResets(int resetMode) {
        verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null,
        verify(() -> Settings.Global.resetToDefaultsAsUser(mMockContentResolver, null,
                resetMode,
                resetMode, UserHandle.USER_SYSTEM));
                UserHandle.USER_SYSTEM));
        verify(() -> Settings.Secure.resetToDefaultsAsUser(eq(mMockContentResolver), isNull(),
        verify(() -> Settings.Secure.resetToDefaultsAsUser(eq(mMockContentResolver), isNull(),
                eq(resetMode), anyInt()));
                eq(resetMode), anyInt()));
    }
    }