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

Commit 208dc551 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 11916113 from 722013c0 to 24Q4-release

Change-Id: I09f0c57303629b3d3603bad69d0b07a3a3eb770f
parents 13bc6d43 722013c0
Loading
Loading
Loading
Loading
+159 −62
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
@@ -85,13 +86,13 @@ import java.util.concurrent.CountDownLatch;
// FOR ACONFIGD TEST MISSION AND ROLLOUT
import java.io.DataInputStream;
import java.io.DataOutputStream;
import android.net.LocalSocketAddress;
import android.net.LocalSocket;
import android.util.proto.ProtoInputStream;
import android.aconfigd.Aconfigd.StorageRequestMessage;
import android.aconfigd.Aconfigd.StorageRequestMessages;
import android.aconfigd.Aconfigd.StorageReturnMessage;
import android.aconfigd.Aconfigd.StorageReturnMessages;
import android.aconfigd.AconfigdClientSocket;
import android.aconfigd.AconfigdFlagInfo;
import android.aconfigd.AconfigdJavaUtils;
import static com.android.aconfig_new_storage.Flags.enableAconfigStorageDaemon;
/**
@@ -265,6 +266,10 @@ final class SettingsState {
    @NonNull
    private Map<String, Map<String, String>> mNamespaceDefaults;

    // TOBO(b/312444587): remove the comparison logic after Test Mission 2.
    @NonNull
    private Map<String, AconfigdFlagInfo> mAconfigDefaultFlags;

    public static final int SETTINGS_TYPE_GLOBAL = 0;
    public static final int SETTINGS_TYPE_SYSTEM = 1;
    public static final int SETTINGS_TYPE_SECURE = 2;
@@ -334,8 +339,13 @@ final class SettingsState {
                + settingTypeToString(getTypeFromKey(key)) + "]";
    }

    public SettingsState(Context context, Object lock, File file, int key,
            int maxBytesPerAppPackage, Looper looper) {
    public SettingsState(
            Context context,
            Object lock,
            File file,
            int key,
            int maxBytesPerAppPackage,
            Looper looper) {
        // It is important that we use the same lock as the settings provider
        // to ensure multiple mutations on this state are atomically persisted
        // as the async persistence should be blocked while we make changes.
@@ -353,12 +363,15 @@ final class SettingsState {
            mPackageToMemoryUsage = null;
        }

        mHistoricalOperations = Build.IS_DEBUGGABLE
                ? new ArrayList<>(HISTORICAL_OPERATION_COUNT) : null;
        mHistoricalOperations =
                Build.IS_DEBUGGABLE ? new ArrayList<>(HISTORICAL_OPERATION_COUNT) : null;

        mNamespaceDefaults = new HashMap<>();
        mAconfigDefaultFlags = new HashMap<>();

        ProtoOutputStream requests = null;
        Map<String, AconfigdFlagInfo> aconfigFlagMap = new HashMap<>();

        synchronized (mLock) {
            readStateSyncLocked();

@@ -375,37 +388,112 @@ final class SettingsState {
                }
            }

            if (enableAconfigStorageDaemon()) {
                if (isConfigSettingsKey(mKey)) {
                    aconfigFlagMap = getAllAconfigFlagsFromSettings();
                }
            }

            if (isConfigSettingsKey(mKey)) {
                requests = handleBulkSyncToNewStorage();
                requests = handleBulkSyncToNewStorage(aconfigFlagMap);
            }
        }

        if (enableAconfigStorageDaemon()) {
            if (isConfigSettingsKey(mKey)){
                AconfigdClientSocket localSocket = AconfigdJavaUtils.getAconfigdClientSocket();
                if (requests != null) {
            LocalSocket client = new LocalSocket();
            try{
                client.connect(new LocalSocketAddress(
                    "aconfigd", LocalSocketAddress.Namespace.RESERVED));
                Slog.d(LOG_TAG, "connected to aconfigd socket");
            } catch (IOException ioe) {
                Slog.e(LOG_TAG, "failed to connect to aconfigd socket", ioe);
                return;
                    InputStream res = localSocket.send(requests.getBytes());
                    if (res == null) {
                        Slog.w(LOG_TAG, "Bulk sync request to acongid failed.");
                    }
                }
                // TOBO(b/312444587): remove the comparison logic after Test Mission 2.
                if (mSettings.get("aconfigd_marker/bulk_synced").value.equals("true")
                        && requests == null) {
                    Map<String, AconfigdFlagInfo> aconfigdFlagMap =
                            AconfigdJavaUtils.listFlagsValueInNewStorage(localSocket);
                    compareFlagValueInNewStorage(
                            aconfigFlagMap,
                            mAconfigDefaultFlags,
                            aconfigdFlagMap);
                }
            }
            AconfigdJavaUtils.sendAconfigdRequests(client, requests);
        }
    }

    // TODO(b/341764371): migrate aconfig flag push to GMS core
    public static class FlagOverrideToSync {
        public String packageName;
        public String flagName;
        public String flagValue;
        public boolean isLocal;
    // TOBO(b/312444587): remove the comparison logic after Test Mission 2.
    public int compareFlagValueInNewStorage(
            Map<String, AconfigdFlagInfo> settingFlagMap,
            Map<String, AconfigdFlagInfo> defaultFlagMap,
            Map<String, AconfigdFlagInfo> aconfigdFlagMap) {

        // Get all defaults from the default map. The mSettings may not contain
        // all flags, since it only contains updated flags.
        int diffNum = 0;
        for (Map.Entry<String, AconfigdFlagInfo> entry : defaultFlagMap.entrySet()) {
            String key = entry.getKey();
            AconfigdFlagInfo flag = entry.getValue();
            if (settingFlagMap.containsKey(key)) {
                flag.merge(settingFlagMap.get(key));
            }

            AconfigdFlagInfo aconfigdFlag = aconfigdFlagMap.get(key);
            if (aconfigdFlag == null) {
                Slog.w(LOG_TAG, String.format("Flag %s is missing from aconfigd", key));
                diffNum++;
                continue;
            }
            String diff = flag.dumpDiff(aconfigdFlag);
            if (!diff.isEmpty()) {
                Slog.w(
                        LOG_TAG,
                        String.format(
                                "Flag %s is different in Settings and aconfig: %s", key, diff));
                diffNum++;
            }
        }

        for (String key : aconfigdFlagMap.keySet()) {
            if (defaultFlagMap.containsKey(key)) continue;
            Slog.w(LOG_TAG, String.format("Flag %s is missing from Settings", key));
            diffNum++;
        }

        if (diffNum == 0) {
            Slog.i(LOG_TAG, "Settings and new storage have same flags.");
        }
        return diffNum;
    }

    @GuardedBy("mLock")
    public Map<String, AconfigdFlagInfo> getAllAconfigFlagsFromSettings() {
        Map<String, AconfigdFlagInfo> ret = new HashMap<>();
        int numSettings = mSettings.size();
        int num_requests = 0;
        for (int i = 0; i < numSettings; i++) {
            String name = mSettings.keyAt(i);
            Setting setting = mSettings.valueAt(i);
            AconfigdFlagInfo flag =
                    getFlagOverrideToSync(name, setting.getValue());
            if (flag == null) {
                continue;
            }
            String fullFlagName = flag.getFullFlagName();
            AconfigdFlagInfo prev = ret.putIfAbsent(fullFlagName,flag);
            if (prev != null) {
                prev.merge(flag);
            }
            ++num_requests;
        }
        Slog.i(LOG_TAG, num_requests + " flag override requests created");
        return ret;
    }

    // TODO(b/341764371): migrate aconfig flag push to GMS core
    @VisibleForTesting
    @GuardedBy("mLock")
    public FlagOverrideToSync getFlagOverrideToSync(String name, String value) {
    public AconfigdFlagInfo getFlagOverrideToSync(String name, String value) {
        int slashIdx = name.indexOf("/");
        if (slashIdx <= 0 || slashIdx >= name.length() - 1) {
            Slog.e(LOG_TAG, "invalid flag name " + name);
@@ -430,7 +518,8 @@ final class SettingsState {
        }

        String aconfigName = namespace + "/" + fullFlagName;
        boolean isAconfig = mNamespaceDefaults.containsKey(namespace)
        boolean isAconfig =
                mNamespaceDefaults.containsKey(namespace)
                        && mNamespaceDefaults.get(namespace).containsKey(aconfigName);
        if (!isAconfig) {
            return null;
@@ -443,25 +532,30 @@ final class SettingsState {
            return null;
        }

        FlagOverrideToSync flag = new FlagOverrideToSync();
        flag.packageName = fullFlagName.substring(0, dotIdx);
        flag.flagName = fullFlagName.substring(dotIdx + 1);
        flag.isLocal = isLocal;
        flag.flagValue = value;
        return flag;
        AconfigdFlagInfo.Builder builder = AconfigdFlagInfo.newBuilder()
                        .setPackageName(fullFlagName.substring(0, dotIdx))
                        .setFlagName(fullFlagName.substring(dotIdx + 1))
                        .setDefaultFlagValue(mNamespaceDefaults.get(namespace).get(aconfigName));

        if (isLocal) {
            builder.setHasLocalOverride(isLocal).setBootFlagValue(value).setLocalFlagValue(value);
        } else {
            builder.setHasServerOverride(true).setServerFlagValue(value).setBootFlagValue(value);
        }
        return builder.build();
    }


    // TODO(b/341764371): migrate aconfig flag push to GMS core
    @VisibleForTesting
    @GuardedBy("mLock")
    public ProtoOutputStream handleBulkSyncToNewStorage() {
    public ProtoOutputStream handleBulkSyncToNewStorage(
            Map<String, AconfigdFlagInfo> aconfigFlagMap) {
        // get marker or add marker if it does not exist
        final String bulkSyncMarkerName = new String("aconfigd_marker/bulk_synced");
        Setting markerSetting = mSettings.get(bulkSyncMarkerName);
        if (markerSetting == null) {
            markerSetting = new Setting(
                bulkSyncMarkerName, "false", false, "aconfig", "aconfig");
            markerSetting = new Setting(bulkSyncMarkerName, "false", false, "aconfig", "aconfig");
            mSettings.put(bulkSyncMarkerName, markerSetting);
        }

@@ -479,24 +573,19 @@ final class SettingsState {
                AconfigdJavaUtils.writeResetStorageRequest(requests);

                // loop over all settings and add flag override requests
                final int numSettings = mSettings.size();
                int num_requests = 0;
                for (int i = 0; i < numSettings; i++) {
                    String name = mSettings.keyAt(i);
                    Setting setting = mSettings.valueAt(i);
                    FlagOverrideToSync flag =
                            getFlagOverrideToSync(name, setting.getValue());
                    if (flag == null) {
                        continue;
                    }
                    ++num_requests;
                for (AconfigdFlagInfo flag : aconfigFlagMap.values()) {
                    String value =
                            flag.getHasLocalOverride()
                                    ? flag.getLocalFlagValue()
                                    : flag.getServerFlagValue();
                    AconfigdJavaUtils.writeFlagOverrideRequest(
                        requests, flag.packageName, flag.flagName, flag.flagValue,
                        flag.isLocal);
                            requests,
                            flag.getPackageName(),
                            flag.getFlagName(),
                            value,
                            flag.getHasLocalOverride());
                }

                Slog.i(LOG_TAG, num_requests + " flag override requests created");

                // mark sync has been done
                markerSetting.value = "true";
                scheduleWriteIfNeededLocked();
@@ -513,14 +602,14 @@ final class SettingsState {
                return null;
            }
        }

    }

    @GuardedBy("mLock")
    private void loadAconfigDefaultValuesLocked(List<String> filePaths) {
        for (String fileName : filePaths) {
            try (FileInputStream inputStream = new FileInputStream(fileName)) {
                loadAconfigDefaultValues(inputStream.readAllBytes(), mNamespaceDefaults);
                loadAconfigDefaultValues(
                        inputStream.readAllBytes(), mNamespaceDefaults, mAconfigDefaultFlags);
            } catch (IOException e) {
                Slog.e(LOG_TAG, "failed to read protobuf", e);
            }
@@ -566,21 +655,30 @@ final class SettingsState {

    @VisibleForTesting
    @GuardedBy("mLock")
    public static void loadAconfigDefaultValues(byte[] fileContents,
            @NonNull Map<String, Map<String, String>> defaultMap) {
    public static void loadAconfigDefaultValues(
            byte[] fileContents,
            @NonNull Map<String, Map<String, String>> defaultMap,
            @NonNull Map<String, AconfigdFlagInfo> flagInfoDefault) {
        try {
            parsed_flags parsedFlags =
                    parsed_flags.parseFrom(fileContents);
            parsed_flags parsedFlags = parsed_flags.parseFrom(fileContents);
            for (parsed_flag flag : parsedFlags.getParsedFlagList()) {
                if (!defaultMap.containsKey(flag.getNamespace())) {
                    Map<String, String> defaults = new HashMap<>();
                    defaultMap.put(flag.getNamespace(), defaults);
                }
                String flagName = flag.getNamespace()
                        + "/" + flag.getPackage() + "." + flag.getName();
                String flagValue = flag.getState() == flag_state.ENABLED
                        ? "true" : "false";
                String fullFlagName = flag.getPackage() + "." + flag.getName();
                String flagName = flag.getNamespace() + "/" + fullFlagName;
                String flagValue = flag.getState() == flag_state.ENABLED ? "true" : "false";
                defaultMap.get(flag.getNamespace()).put(flagName, flagValue);
                if (!flagInfoDefault.containsKey(fullFlagName)) {
                    flagInfoDefault.put(
                            fullFlagName,
                            AconfigdFlagInfo.newBuilder()
                                    .setPackageName(flag.getPackage())
                                    .setFlagName(flag.getName())
                                    .setDefaultFlagValue(flagValue)
                                    .build());
                }
            }
        } catch (IOException e) {
            Slog.e(LOG_TAG, "failed to parse protobuf", e);
@@ -1646,7 +1744,6 @@ final class SettingsState {
                        }
                    }
                }

                mSettings.put(name, new Setting(name, value, defaultValue, packageName, tag,
                        fromSystem, id, isPreservedInRestore));

+244 −21

File changed.

Preview size limit exceeded, changes collapsed.

+7 −0
Original line number Diff line number Diff line
@@ -1000,6 +1000,13 @@ flag {
  bug: "339667383"
}

flag {
  name: "glanceable_hub_allow_keyguard_when_dreaming"
  namespace: "systemui"
  description: "Allows users to exit dream to keyguard with glanceable hub enabled"
  bug: "343505271"
}

flag {
  name: "new_touchpad_gestures_tutorial"
  namespace: "systemui"
+32 −16
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.kosmos.testScope
import com.android.systemui.qs.qsTileFactory
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.TestScope
@@ -41,6 +42,7 @@ class QSLongPressEffectTest : SysuiTestCase() {

    private val kosmos = testKosmos()
    private val vibratorHelper = kosmos.vibratorHelper
    private val qsTile = kosmos.qsTileFactory.createTile("Test Tile")

    private val effectDuration = 400
    private val lowTickDuration = 12
@@ -61,6 +63,7 @@ class QSLongPressEffectTest : SysuiTestCase() {
                vibratorHelper,
                kosmos.keyguardInteractor,
            )
        longPressEffect.qsTile = qsTile
    }

    @Test
@@ -91,8 +94,10 @@ class QSLongPressEffectTest : SysuiTestCase() {
        // GIVEN an action down event occurs
        longPressEffect.handleActionDown()

        // THEN the effect moves to the TIMEOUT_WAIT state
        // THEN the effect moves to the TIMEOUT_WAIT state and starts the wait
        val action by collectLastValue(longPressEffect.actionType)
        assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
        assertThat(action).isEqualTo(QSLongPressEffect.ActionType.WAIT_TAP_TIMEOUT)
    }

    @Test
@@ -106,20 +111,6 @@ class QSLongPressEffectTest : SysuiTestCase() {
            assertEffectDidNotStart()
        }

    @Test
    fun onActionUp_whileWaiting_performsClick() =
        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
            // GIVEN an action is being collected
            val action by collectLastValue(longPressEffect.actionType)

            // GIVEN an action up occurs
            longPressEffect.handleActionUp()

            // THEN the action to invoke is the click action and the effect does not start
            assertThat(action).isEqualTo(QSLongPressEffect.ActionType.CLICK)
            assertEffectDidNotStart()
        }

    @Test
    fun onWaitComplete_whileWaiting_beginsEffect() =
        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
@@ -221,8 +212,10 @@ class QSLongPressEffectTest : SysuiTestCase() {
            // GIVEN that the animator was cancelled
            longPressEffect.handleAnimationCancel()

            // THEN the state goes to the timeout wait
            // THEN the state goes to the timeout wait and the wait is posted
            val action by collectLastValue(longPressEffect.actionType)
            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.TIMEOUT_WAIT)
            assertThat(action).isEqualTo(QSLongPressEffect.ActionType.WAIT_TAP_TIMEOUT)
        }

    @Test
@@ -238,6 +231,29 @@ class QSLongPressEffectTest : SysuiTestCase() {
            assertThat(longPressEffect.state).isEqualTo(QSLongPressEffect.State.IDLE)
        }

    @Test
    fun onTileClick_whileWaiting_withQSTile_clicks() =
        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
            // GIVEN that a click was detected
            val couldClick = longPressEffect.onTileClick()

            // THEN the click is successful
            assertThat(couldClick).isTrue()
        }

    @Test
    fun onTileClick_whileWaiting_withoutQSTile_cannotClick() =
        testWhileInState(QSLongPressEffect.State.TIMEOUT_WAIT) {
            // GIVEN that no QSTile has been set
            longPressEffect.qsTile = null

            // GIVEN that a click was detected
            val couldClick = longPressEffect.onTileClick()

            // THEN the click is not successful
            assertThat(couldClick).isFalse()
        }

    private fun testWithScope(initialize: Boolean = true, test: suspend TestScope.() -> Unit) =
        with(kosmos) {
            testScope.runTest {
+7 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.flags

import android.app.Activity
import android.content.pm.PackageManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -35,6 +36,7 @@ class FlagManager constructor(
) : FlagListenable {
    companion object {
        const val RECEIVING_PACKAGE = "com.android.systemui"
        const val RECEIVING_PACKAGE_WATCH = "com.google.android.apps.wearable.systemui"
        const val ACTION_SET_FLAG = "com.android.systemui.action.SET_FLAG"
        const val ACTION_GET_FLAGS = "com.android.systemui.action.GET_FLAGS"
        const val FLAGS_PERMISSION = "com.android.systemui.permission.FLAGS"
@@ -62,7 +64,7 @@ class FlagManager constructor(

    fun getFlagsFuture(): ListenableFuture<Collection<Flag<*>>> {
        val intent = Intent(ACTION_GET_FLAGS)
        intent.setPackage(RECEIVING_PACKAGE)
        intent.setPackage(if (isWatch()) RECEIVING_PACKAGE_WATCH else RECEIVING_PACKAGE)

        return CallbackToFutureAdapter.getFuture {
                completer: CallbackToFutureAdapter.Completer<Collection<Flag<*>>> ->
@@ -193,6 +195,10 @@ class FlagManager constructor(
        restartAction?.accept(suppressRestart)
    }

    private fun isWatch(): Boolean {
        return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH)
    }

    private data class PerFlagListener(val name: String, val listener: FlagListenable.Listener)
}

Loading