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

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

Merge "AudioDeviceVolumeManager: set volume per device" into tm-qpr-dev

parents 8be2f810 118ca2fc
Loading
Loading
Loading
Loading
+18 −2
Original line number Diff line number Diff line
@@ -61,10 +61,12 @@ public class AudioDeviceVolumeManager {

    private static IAudioService sService;

    private final String mPackageName;
    private final @NonNull String mPackageName;
    private final @Nullable String mAttributionTag;

    public AudioDeviceVolumeManager(Context context) {
        mPackageName = context.getApplicationContext().getOpPackageName();
        mAttributionTag = context.getApplicationContext().getAttributionTag();
    }

    /**
@@ -287,7 +289,6 @@ public class AudioDeviceVolumeManager {
     * @hide
     * Removes a previously added listener of changes to device volume behavior.
     */

    @RequiresPermission(anyOf = {
            android.Manifest.permission.MODIFY_AUDIO_ROUTING,
            android.Manifest.permission.QUERY_AUDIO_STATE
@@ -298,6 +299,21 @@ public class AudioDeviceVolumeManager {
                "removeOnDeviceVolumeBehaviorChangedListener");
    }

    /**
     * @hide
     * Sets the volume on the given audio device
     * @param vi the volume information, only stream-based volumes are supported
     * @param ada the device for which volume is to be modified
     */
    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
    public void setDeviceVolume(@NonNull VolumeInfo vi, @NonNull AudioDeviceAttributes ada) {
        try {
            getService().setDeviceVolume(vi, ada, mPackageName, mAttributionTag);
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
        }
    }

    /**
     * Return human-readable name for volume behavior
     * @param behavior one of the volume behaviors defined in AudioManager
+3 −0
Original line number Diff line number Diff line
@@ -98,6 +98,9 @@ interface IAudioService {
    void setStreamVolumeWithAttribution(int streamType, int index, int flags,
            in String callingPackage, in String attributionTag);

    void setDeviceVolume(in VolumeInfo vi, in AudioDeviceAttributes ada,
            in String callingPackage, in String attributionTag);

    oneway void handleVolumeKey(in KeyEvent event, boolean isOnTv,
            String callingPackage, String caller);

+80 −11
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ import com.android.internal.util.Preconditions;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.audio.AudioServiceEvents.DeviceVolumeEvent;
import com.android.server.audio.AudioServiceEvents.PhoneStateEvent;
import com.android.server.audio.AudioServiceEvents.VolumeEvent;
import com.android.server.pm.UserManagerInternal;
@@ -3584,7 +3585,8 @@ public class AudioService extends IAudioService.Stub
                        + "), do not change associated stream volume");
                continue;
            }
            setStreamVolume(groupedStream, index, flags, callingPackage, callingPackage,
            setStreamVolume(groupedStream, index, flags, /*device*/ null,
                    callingPackage, callingPackage,
                    attributionTag, Binder.getCallingUid(), true /*hasModifyAudioSettings*/);
        }
    }
@@ -3627,15 +3629,73 @@ public class AudioService extends IAudioService.Stub
        return AudioSystem.getMinVolumeIndexForAttributes(attr);
    }
    /** @see AudioDeviceVolumeManager#setDeviceVolume(VolumeInfo, AudioDeviceAttributes)
     * Part of service interface, check permissions and parameters here */
    public void setDeviceVolume(@NonNull VolumeInfo vi, @NonNull AudioDeviceAttributes ada,
            @NonNull String callingPackage, @Nullable String attributionTag) {
        enforceModifyAudioRoutingPermission();
        Objects.requireNonNull(vi);
        Objects.requireNonNull(ada);
        Objects.requireNonNull(callingPackage);
        if (!vi.hasStreamType()) {
            Log.e(TAG, "Unsupported non-stream type based VolumeInfo", new Exception());
            return;
        }
        int index = vi.getVolumeIndex();
        if (index == VolumeInfo.INDEX_NOT_SET) {
            throw new IllegalArgumentException("changing device volume requires a volume index");
        }
        if (vi.getMinVolumeIndex() == VolumeInfo.INDEX_NOT_SET
                || vi.getMaxVolumeIndex() == VolumeInfo.INDEX_NOT_SET) {
            // assume index meant to be in stream type range, validate
            if ((index * 10) < mStreamStates[vi.getStreamType()].getMinIndex()
                    || (index * 10) > mStreamStates[vi.getStreamType()].getMaxIndex()) {
                throw new IllegalArgumentException("invalid volume index " + index
                        + " not between min/max for stream " + vi.getStreamType());
            }
        } else {
            // check if index needs to be rescaled
            final int min = (mStreamStates[vi.getStreamType()].getMinIndex() + 5) / 10;
            final int max = (mStreamStates[vi.getStreamType()].getMaxIndex() + 5) / 10;
            if (vi.getMinVolumeIndex() != min || vi.getMaxVolumeIndex() != max) {
                index = rescaleIndex(index,
                        /*srcMin*/ vi.getMinVolumeIndex(), /*srcMax*/ vi.getMaxVolumeIndex(),
                        /*dstMin*/ min, /*dstMax*/ max);
            }
        }
        setStreamVolumeWithAttributionInt(vi.getStreamType(), index, /*flags*/ 0,
                ada, callingPackage, attributionTag);
    }
    /** Retain API for unsupported app usage */
    public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
        setStreamVolumeWithAttribution(streamType, index, flags, callingPackage, null);
        setStreamVolumeWithAttribution(streamType, index, flags,
                callingPackage, /*attributionTag*/ null);
    }
    /** @see AudioManager#setStreamVolume(int, int, int)
     * Part of service interface, check permissions here */
    public void setStreamVolumeWithAttribution(int streamType, int index, int flags,
            String callingPackage, String attributionTag) {
        setStreamVolumeWithAttributionInt(streamType, index, flags, /*device*/ null,
                callingPackage, attributionTag);
    }
    /**
     * Internal method for a stream type volume change. Can be used to change the volume on a
     * given device only
     * @param streamType the stream type whose volume is to be changed
     * @param index the volume index
     * @param flags options for volume handling
     * @param device null when controlling volume for the current routing, otherwise the device
     *               for which volume is being changed
     * @param callingPackage client side-provided package name of caller, not to be trusted
     * @param attributionTag client side-provided attribution name, not to be trusted
     */
    protected void setStreamVolumeWithAttributionInt(int streamType, int index, int flags,
            @Nullable AudioDeviceAttributes device,
            String callingPackage, String attributionTag) {
        if ((streamType == AudioManager.STREAM_ACCESSIBILITY) && !canChangeAccessibilityVolume()) {
            Log.w(TAG, "Trying to call setStreamVolume() for a11y without"
                    + " CHANGE_ACCESSIBILITY_VOLUME  callingPackage=" + callingPackage);
@@ -3658,10 +3718,14 @@ public class AudioService extends IAudioService.Stub
            return;
        }
        sVolumeLogger.log(new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
                index/*val1*/, flags/*val2*/, callingPackage));
        setStreamVolume(streamType, index, flags, callingPackage, callingPackage,
                attributionTag, Binder.getCallingUid(), callingOrSelfHasAudioSettingsPermission());
        final AudioEventLogger.Event event = (device == null)
                ? new VolumeEvent(VolumeEvent.VOL_SET_STREAM_VOL, streamType,
                    index/*val1*/, flags/*val2*/, callingPackage)
                : new DeviceVolumeEvent(streamType, index, device, callingPackage);
        sVolumeLogger.log(event);
        setStreamVolume(streamType, index, flags, device,
                callingPackage, callingPackage, attributionTag,
                Binder.getCallingUid(), callingOrSelfHasAudioSettingsPermission());
    }
    /** @see AudioManager#isUltrasoundSupported() */
@@ -3900,11 +3964,13 @@ public class AudioService extends IAudioService.Stub
        }
    }
    private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
            String caller, String attributionTag, int uid,
    private void setStreamVolume(int streamType, int index, int flags,
            @Nullable AudioDeviceAttributes ada,
            String callingPackage, String caller, String attributionTag, int uid,
            boolean hasModifyAudioSettings) {
        if (DEBUG_VOL) {
            Log.d(TAG, "setStreamVolume(stream=" + streamType+", index=" + index
                    + ", dev=" + ada
                    + ", calling=" + callingPackage + ")");
        }
        if (mUseFixedVolume) {
@@ -3915,7 +3981,9 @@ public class AudioService extends IAudioService.Stub
        int streamTypeAlias = mStreamVolumeAlias[streamType];
        VolumeStreamState streamState = mStreamStates[streamTypeAlias];
        final int device = getDeviceForStream(streamType);
        final int device = (ada == null)
                ? getDeviceForStream(streamType)
                : ada.getInternalType();
        int oldIndex;
        // skip a2dp absolute volume control request when the device
@@ -5419,7 +5487,8 @@ public class AudioService extends IAudioService.Stub
            throw new SecurityException("Should only be called from system process");
        }
        setStreamVolume(streamType, index, flags, packageName, packageName, null, uid,
        setStreamVolume(streamType, index, flags, /*device*/ null,
                packageName, packageName, null, uid,
                hasAudioSettingsPermission(uid, pid));
    }
@@ -7562,7 +7631,7 @@ public class AudioService extends IAudioService.Stub
                    && !isFullyMuted()) {
                index = 1;
            }
            AudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
            mAudioSystem.setStreamVolumeIndexAS(mStreamType, index, device);
        }
        // must be called while synchronized VolumeStreamState.class
+39 −0
Original line number Diff line number Diff line
@@ -16,7 +16,9 @@

package com.android.server.audio;

import android.annotation.NonNull;
import android.media.AudioAttributes;
import android.media.AudioDeviceAttributes;
import android.media.AudioManager;
import android.media.AudioSystem;
import android.media.MediaMetrics;
@@ -145,6 +147,43 @@ public class AudioServiceEvents {
        }
    }

    static final class DeviceVolumeEvent extends AudioEventLogger.Event {
        final int mStream;
        final int mVolIndex;
        final String mDeviceNativeType;
        final String mDeviceAddress;
        final String mCaller;

        DeviceVolumeEvent(int streamType, int index, @NonNull AudioDeviceAttributes device,
                String callingPackage) {
            mStream = streamType;
            mVolIndex = index;
            mDeviceNativeType = "0x" + Integer.toHexString(device.getInternalType());
            mDeviceAddress = device.getAddress();
            mCaller = callingPackage;
            // log metrics
            new MediaMetrics.Item(MediaMetrics.Name.AUDIO_VOLUME_EVENT)
                    .set(MediaMetrics.Property.EVENT, "setDeviceVolume")
                    .set(MediaMetrics.Property.STREAM_TYPE,
                            AudioSystem.streamToString(mStream))
                    .set(MediaMetrics.Property.INDEX, mVolIndex)
                    .set(MediaMetrics.Property.DEVICE, mDeviceNativeType)
                    .set(MediaMetrics.Property.ADDRESS, mDeviceAddress)
                    .set(MediaMetrics.Property.CALLING_PACKAGE, mCaller)
                    .record();
        }

        @Override
        public String eventToString() {
            return new StringBuilder("setDeviceVolume(stream:")
                    .append(AudioSystem.streamToString(mStream))
                    .append(" index:").append(mVolIndex)
                    .append(" device:").append(mDeviceNativeType)
                    .append(" addr:").append(mDeviceAddress)
                    .append(") from ").append(mCaller).toString();
        }
    }

    final static class VolumeEvent extends AudioEventLogger.Event {
        static final int VOL_ADJUST_SUGG_VOL = 0;
        static final int VOL_ADJUST_STREAM_VOL = 1;
+11 −0
Original line number Diff line number Diff line
@@ -386,6 +386,17 @@ public class AudioSystemAdapter implements AudioSystem.RoutingUpdateCallback,
        return AudioSystem.isStreamActiveRemotely(stream, inPastMs);
    }

    /**
     * Same as {@link AudioSystem#setStreamVolumeIndexAS(int, int, int)}
     * @param stream
     * @param index
     * @param device
     * @return
     */
    public int setStreamVolumeIndexAS(int stream, int index, int device) {
        return AudioSystem.setStreamVolumeIndexAS(stream, index, device);
    }

    /**
     * Same as {@link AudioSystem#setPhoneState(int, int)}
     * @param state
Loading