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

Commit ba4e8149 authored by Vlad Popa's avatar Vlad Popa
Browse files

Add check when persisting AdiDeviceStates

When persisting the AdiDeviceStates we need to make sure that the
Settings limit will not be exceeded. Calculating the max number of
devices we can have in the inventory based on the max String length that
the Secure Settings can persist

Test: trivial
Bug: 314856304
Change-Id: Id51fd2a668a8711db2024898ff6297410edb78e6
parent be9ba7e9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -95,7 +95,9 @@ final class SettingsState {

    static final int SETTINGS_VERSION_NEW_ENCODING = 121;

    // LINT.IfChange
    public static final int MAX_LENGTH_PER_STRING = 32768;
    // LINT.ThenChange(/services/core/java/com/android/server/audio/AudioDeviceInventory.java:settings_max_length_per_string)
    private static final long WRITE_SETTINGS_DELAY_MILLIS = 200;
    private static final long MAX_WRITE_SETTINGS_DELAY_MILLIS = 2000;

+3 −2
Original line number Diff line number Diff line
@@ -235,9 +235,10 @@ public final class AdiDeviceState {
     * {@link AdiDeviceState#toPersistableString()}.
     */
    public static int getPeristedMaxSize() {
        return 36;  /* (mDeviceType)2 + (mDeviceAddress)17 + (mInternalDeviceType)9 + (mSAEnabled)1
        return 39;  /* (mDeviceType)2 + (mDeviceAddress)17 + (mInternalDeviceType)9 + (mSAEnabled)1
                           + (mHasHeadTracker)1 + (mHasHeadTrackerEnabled)1
                           + (SETTINGS_FIELD_SEPARATOR)5 */
                           + (mAudioDeviceCategory)1 + (SETTINGS_FIELD_SEPARATOR)6
                           + (SETTING_DEVICE_SEPARATOR)1 */
    }

    @Nullable
+9 −5
Original line number Diff line number Diff line
@@ -2687,12 +2687,16 @@ public class AudioDeviceBroker {
            return;
        }
        final SettingsAdapter settingsAdapter = mAudioService.getSettings();
        try {
            boolean res = settingsAdapter.putSecureStringForUser(mAudioService.getContentResolver(),
                    Settings.Secure.AUDIO_DEVICE_INVENTORY,
                    deviceSettings, UserHandle.USER_CURRENT);
            if (!res) {
                Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings);
            }
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "error saving AdiDeviceState: " + deviceSettings, e);
        }
    }

    private String readDeviceSettings() {
+27 −4
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import static android.media.AudioSystem.isBluetoothOutDevice;
import static android.media.AudioSystem.isBluetoothScoOutDevice;
import static android.media.audio.Flags.automaticBtDeviceType;


import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;

import android.annotation.NonNull;
@@ -81,7 +80,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -104,6 +102,14 @@ public class AudioDeviceInventory {
    private static final String SETTING_DEVICE_SEPARATOR_CHAR = "|";
    private static final String SETTING_DEVICE_SEPARATOR = "\\|";

    /** Max String length that can be persisted within the Settings. */
    // LINT.IfChange(settings_max_length_per_string)
    private static final int MAX_SETTINGS_LENGTH_PER_STRING = 32768;
    // LINT.ThenChange(/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java)

    private static final int MAX_DEVICE_INVENTORY_ENTRIES =
            MAX_SETTINGS_LENGTH_PER_STRING / AdiDeviceState.getPeristedMaxSize();

    // lock to synchronize all access to mConnectedDevices and mApmConnectedDevices
    private final Object mDevicesLock = new Object();

@@ -113,7 +119,8 @@ public class AudioDeviceInventory {
    private final Object mDeviceInventoryLock = new Object();

    @GuardedBy("mDeviceInventoryLock")
    private final HashMap<Pair<Integer, String>, AdiDeviceState> mDeviceInventory = new HashMap<>();
    private final LinkedHashMap<Pair<Integer, String>, AdiDeviceState> mDeviceInventory =
            new LinkedHashMap<>();

    Collection<AdiDeviceState> getImmutableDeviceInventory() {
        final List<AdiDeviceState> newList;
@@ -136,6 +143,7 @@ public class AudioDeviceInventory {
                oldState.setSAEnabled(newState.isSAEnabled());
                return oldState;
            });
            checkDeviceInventorySize_l();
        }
        mDeviceBroker.postSynchronizeAdiDevicesInInventory(deviceState);
    }
@@ -173,6 +181,8 @@ public class AudioDeviceInventory {
            ads.setAudioDeviceCategory(category);

            mDeviceInventory.put(ads.getDeviceId(), ads);
            checkDeviceInventorySize_l();

            mDeviceBroker.postUpdatedAdiDeviceState(ads);
            mDeviceBroker.postPersistAudioDeviceSettings();
        }
@@ -200,6 +210,7 @@ public class AudioDeviceInventory {
                        }
                        return oldState;
                    });
            checkDeviceInventorySize_l();
        }
        if (updatedCategory.get()) {
            mDeviceBroker.postUpdatedAdiDeviceState(deviceState);
@@ -272,6 +283,18 @@ public class AudioDeviceInventory {
        }
    }

    @GuardedBy("mDeviceInventoryLock")
    private void checkDeviceInventorySize_l() {
        if (mDeviceInventory.size() > MAX_DEVICE_INVENTORY_ENTRIES) {
            // remove the first element
            Iterator<Entry<Pair<Integer, String>, AdiDeviceState>> iterator =
                    mDeviceInventory.entrySet().iterator();
            if (iterator.hasNext()) {
                iterator.remove();
            }
        }
    }

    @GuardedBy({"mDevicesLock", "mDeviceInventoryLock"})
    private boolean synchronizeBleDeviceInInventory(AdiDeviceState updatedDevice) {
        for (DeviceInfo di : mConnectedDevices.values()) {