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

Commit b4d54d93 authored by Vlad Popa's avatar Vlad Popa Committed by Android (Google) Code Review
Browse files

Merge "Use cache for volume getter" into main

parents 3206850a 4f416c50
Loading
Loading
Loading
Loading
+27 −5
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.content.Context.DEVICE_ID_DEFAULT;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
import static android.media.audio.Flags.cacheGetStreamMinMaxVolume;
import static android.media.audio.Flags.cacheGetStreamVolume;
import static android.media.audio.Flags.FLAG_DEPRECATE_STREAM_BT_SCO;
import static android.media.audio.Flags.FLAG_FOCUS_EXCLUSIVE_WITH_RECORDING;
import static android.media.audio.Flags.FLAG_FOCUS_FREEZE_TEST_API;
@@ -1241,7 +1242,12 @@ public class AudioManager {
     * @hide
     **/
    public static final String VOLUME_MAX_CACHING_API = "getStreamMaxVolume";
    private static final int VOLUME_MIN_MAX_CACHING_SIZE = 16;
    /**
     * API string for caching the volume for each stream
     * @hide
     **/
    public static final String VOLUME_CACHING_API = "getStreamVolume";
    private static final int VOLUME_CACHING_SIZE = 16;

    private final IpcDataCache.QueryHandler<VolumeCacheQuery, Integer> mVolQuery =
            new IpcDataCache.QueryHandler<>() {
@@ -1252,6 +1258,7 @@ public class AudioManager {
                        return switch (query.queryCommand) {
                            case QUERY_VOL_MIN -> service.getStreamMinVolume(query.stream);
                            case QUERY_VOL_MAX -> service.getStreamMaxVolume(query.stream);
                            case QUERY_VOL -> service.getStreamVolume(query.stream);
                            default -> {
                                Log.w(TAG, "Not a valid volume cache query: " + query);
                                yield null;
@@ -1265,29 +1272,40 @@ public class AudioManager {
            };

    private final IpcDataCache<VolumeCacheQuery, Integer> mVolMinCache =
            new IpcDataCache<>(VOLUME_MIN_MAX_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
            new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
                    VOLUME_MIN_CACHING_API, VOLUME_MIN_CACHING_API, mVolQuery);

    private final IpcDataCache<VolumeCacheQuery, Integer> mVolMaxCache =
            new IpcDataCache<>(VOLUME_MIN_MAX_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
            new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
                    VOLUME_MAX_CACHING_API, VOLUME_MAX_CACHING_API, mVolQuery);

    private final IpcDataCache<VolumeCacheQuery, Integer> mVolCache =
            new IpcDataCache<>(VOLUME_CACHING_SIZE, IpcDataCache.MODULE_SYSTEM,
                    VOLUME_CACHING_API, VOLUME_CACHING_API, mVolQuery);

    /**
     * Used to invalidate the cache for the given API
     * @hide
     **/
    public static void clearVolumeCache(String api) {
        if (cacheGetStreamMinMaxVolume()) {
        if (cacheGetStreamMinMaxVolume() && (VOLUME_MAX_CACHING_API.equals(api)
                || VOLUME_MIN_CACHING_API.equals(api))) {
            IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, api);
        } else if (cacheGetStreamVolume() && VOLUME_CACHING_API.equals(api)) {
            IpcDataCache.invalidateCache(IpcDataCache.MODULE_SYSTEM, api);
        } else {
            Log.w(TAG, "invalid clearVolumeCache for api " + api);
        }
    }

    private static final int QUERY_VOL_MIN = 1;
    private static final int QUERY_VOL_MAX = 2;
    private static final int QUERY_VOL = 3;
    /** @hide */
    @IntDef(prefix = "QUERY_VOL", value = {
            QUERY_VOL_MIN,
            QUERY_VOL_MAX}
            QUERY_VOL_MAX,
            QUERY_VOL}
    )
    @Retention(RetentionPolicy.SOURCE)
    private @interface QueryVolCommand {}
@@ -1297,6 +1315,7 @@ public class AudioManager {
            return switch (queryCommand) {
                case QUERY_VOL_MIN -> "getStreamMinVolume";
                case QUERY_VOL_MAX -> "getStreamMaxVolume";
                case QUERY_VOL -> "getStreamVolume";
                default -> "invalid command";
            };
        }
@@ -1373,6 +1392,9 @@ public class AudioManager {
     * @see #setStreamVolume(int, int, int)
     */
    public int getStreamVolume(int streamType) {
        if (cacheGetStreamVolume()) {
            return mVolCache.query(new VolumeCacheQuery(streamType, QUERY_VOL));
        }
        final IAudioService service = getService();
        try {
            return service.getStreamVolume(streamType);
+24 −12
Original line number Diff line number Diff line
@@ -67,6 +67,17 @@ public class AudioManagerTest {

    private AudioManager mAudioManager;

    private static final int[] PUBLIC_STREAM_TYPES = {
            STREAM_VOICE_CALL,
            STREAM_SYSTEM,
            STREAM_RING,
            STREAM_MUSIC,
            STREAM_ALARM,
            STREAM_NOTIFICATION,
            STREAM_DTMF,
            STREAM_ACCESSIBILITY,
    };

    @Rule
    public final AudioVolumesTestRule rule = new AudioVolumesTestRule();

@@ -226,18 +237,8 @@ public class AudioManagerTest {
    public void getStreamMinMaxVolume_consistentWithAs() throws Exception {
        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
        IAudioService service = IAudioService.Stub.asInterface(b);
        final int[] streamTypes = {
                STREAM_VOICE_CALL,
                STREAM_SYSTEM,
                STREAM_RING,
                STREAM_MUSIC,
                STREAM_ALARM,
                STREAM_NOTIFICATION,
                STREAM_DTMF,
                STREAM_ACCESSIBILITY,
        };

        for (int streamType : streamTypes) {
        for (int streamType : PUBLIC_STREAM_TYPES) {
            assertEquals(service.getStreamMinVolume(streamType),
                    mAudioManager.getStreamMinVolume(streamType));
            assertEquals(service.getStreamMaxVolume(streamType),
@@ -245,6 +246,17 @@ public class AudioManagerTest {
        }
    }

    @Test
    public void getStreamVolume_consistentWithAs() throws Exception {
        IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
        IAudioService service = IAudioService.Stub.asInterface(b);

        for (int streamType : PUBLIC_STREAM_TYPES) {
            assertEquals(service.getStreamVolume(streamType),
                    mAudioManager.getStreamVolume(streamType));
        }
    }

    //-----------------------------------------------------------------
    // Test Volume per Attributes setter/getters
    //-----------------------------------------------------------------
+13 −0
Original line number Diff line number Diff line
@@ -69,6 +69,8 @@ class AudioManagerShellCommand extends ShellCommand {
                return getMinVolume();
            case "get-max-volume":
                return getMaxVolume();
            case "get-stream-volume":
                return getStreamVolume();
            case "set-device-volume":
                return setDeviceVolume();
            case "adj-mute":
@@ -114,6 +116,8 @@ class AudioManagerShellCommand extends ShellCommand {
        pw.println("    Gets the min volume for STREAM_TYPE");
        pw.println("  get-max-volume STREAM_TYPE");
        pw.println("    Gets the max volume for STREAM_TYPE");
        pw.println("  get-stream-volume STREAM_TYPE");
        pw.println("    Gets the volume for STREAM_TYPE");
        pw.println("  set-device-volume STREAM_TYPE VOLUME_INDEX NATIVE_DEVICE_TYPE");
        pw.println("    Sets for NATIVE_DEVICE_TYPE the STREAM_TYPE volume to VOLUME_INDEX");
        pw.println("  adj-mute STREAM_TYPE");
@@ -322,6 +326,15 @@ class AudioManagerShellCommand extends ShellCommand {
        return 0;
    }

    private int getStreamVolume() {
        final Context context = mService.mContext;
        final AudioManager am = context.getSystemService(AudioManager.class);
        final int stream = readIntArg();
        final int result = am.getStreamVolume(stream);
        getOutPrintWriter().println("AudioManager.getStreamVolume(" + stream + ") -> " + result);
        return 0;
    }

    private int setDeviceVolume() {
        final Context context = mService.mContext;
        final AudioDeviceVolumeManager advm = (AudioDeviceVolumeManager) context.getSystemService(
+39 −2
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import static android.media.AudioManager.STREAM_SYSTEM;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
import static android.media.audio.Flags.cacheGetStreamMinMaxVolume;
import static android.media.audio.Flags.cacheGetStreamVolume;
import static android.media.audio.Flags.concurrentAudioRecordBypassPermission;
import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency;
import static android.media.audio.Flags.focusFreezeTestApi;
@@ -1910,6 +1911,12 @@ public class AudioService extends IAudioService.Stub
            mSpatializerHelper.onRoutingUpdated();
        }
        checkMuteAwaitConnection();
        if (cacheGetStreamVolume()) {
            if (DEBUG_VOL) {
                Log.d(TAG, "Clear volume cache after routing update");
            }
            AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
        }
    }
    //-----------------------------------------------------------------
@@ -4988,6 +4995,8 @@ public class AudioService extends IAudioService.Stub
                + concurrentAudioRecordBypassPermission());
        pw.println("\tandroid.media.audio.Flags.cacheGetStreamMinMaxVolume:"
                + cacheGetStreamMinMaxVolume());
        pw.println("\tandroid.media.audio.Flags.cacheGetStreamVolume:"
                + cacheGetStreamVolume());
    }
    private void dumpAudioMode(PrintWriter pw) {
@@ -7054,6 +7063,13 @@ public class AudioService extends IAudioService.Stub
                    streamState.mIsMuted = false;
                }
            }
            if (cacheGetStreamVolume()) {
                if (DEBUG_VOL) {
                    Log.d(TAG,
                            "Clear volume cache after possibly changing mute in readAudioSettings");
                }
                AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
            }
        }
        readVolumeGroupsSettings(userSwitch);
@@ -9274,11 +9290,23 @@ public class AudioService extends IAudioService.Stub
            public void put(int key, int value) {
                super.put(key, value);
                record("put", key, value);
                if (cacheGetStreamVolume()) {
                    if (DEBUG_VOL) {
                        Log.d(TAG, "Clear volume cache after update index map");
                    }
                    AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
                }
            }
            @Override
            public void setValueAt(int index, int value) {
                super.setValueAt(index, value);
                record("setValueAt", keyAt(index), value);
                if (cacheGetStreamVolume()) {
                    if (DEBUG_VOL) {
                        Log.d(TAG, "Clear volume cache after update index map");
                    }
                    AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
                }
            }
            // Record all changes in the VolumeStreamState
@@ -10008,8 +10036,9 @@ public class AudioService extends IAudioService.Stub
         * @return true if the mute state was changed
         */
        public boolean mute(boolean state, boolean apply, String src) {
            boolean changed;
            synchronized (VolumeStreamState.class) {
                boolean changed = state != mIsMuted;
                changed = state != mIsMuted;
                if (changed) {
                    sMuteLogger.enqueue(
                            new AudioServiceEvents.StreamMuteEvent(mStreamType, state, src));
@@ -10027,8 +10056,16 @@ public class AudioService extends IAudioService.Stub
                        doMute();
                    }
                }
                return changed;
            }
            if (cacheGetStreamVolume() && changed) {
                if (DEBUG_VOL) {
                    Log.d(TAG, "Clear volume cache after changing mute state");
                }
                AudioManager.clearVolumeCache(AudioManager.VOLUME_CACHING_API);
            }
            return changed;
        }
        public void doMute() {