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

Commit 0dac35af authored by RoboErik's avatar RoboErik
Browse files

Pipe caller's identity through volume methods

setStreamVolume and adjustStreamVolume were always being called
from the session service's uid/package. This adds the plumbing to
allow the original app's info to be passed in to the audio service
when volume is changed.

Change-Id: Ib36639dab1e518b435161dc453c8ba9351df3e9b
parent b3cca876
Loading
Loading
Loading
Loading
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package android.media;

import com.android.server.LocalServices;

/**
 * Class for system services to access extra AudioManager functionality. The
 * AudioService is responsible for registering an implementation with
 * {@link LocalServices}.
 *
 * @hide
 */
public abstract class AudioManagerInternal {

    public abstract void adjustStreamVolumeForUid(int streamType, int direction, int flags,
            String callingPackage, int uid);

    public abstract void setStreamVolumeForUid(int streamType, int direction, int flags,
            String callingPackage, int uid);
}
+34 −4
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ import android.view.WindowManager;

import com.android.internal.telephony.ITelephony;
import com.android.internal.util.XmlUtils;
import com.android.server.LocalServices;

import org.xmlpull.v1.XmlPullParserException;

@@ -635,6 +636,7 @@ public class AudioService extends IAudioService.Stub {
        mMasterVolumeRamp = context.getResources().getIntArray(
                com.android.internal.R.array.config_masterVolumeRamp);

        LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal());
    }

    public void systemReady() {
@@ -956,6 +958,11 @@ public class AudioService extends IAudioService.Stub {
    /** @see AudioManager#adjustStreamVolume(int, int, int) */
    public void adjustStreamVolume(int streamType, int direction, int flags,
            String callingPackage) {
        adjustStreamVolume(streamType, direction, flags, callingPackage, Binder.getCallingUid());
    }

    private void adjustStreamVolume(int streamType, int direction, int flags,
            String callingPackage, int uid) {
        if (mUseFixedVolume) {
            return;
        }
@@ -984,8 +991,8 @@ public class AudioService extends IAudioService.Stub {
            return;
        }

        if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
        if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
                != AppOpsManager.MODE_ALLOWED) {
            return;
        }

@@ -1161,6 +1168,11 @@ public class AudioService extends IAudioService.Stub {

    /** @see AudioManager#setStreamVolume(int, int, int) */
    public void setStreamVolume(int streamType, int index, int flags, String callingPackage) {
        setStreamVolume(streamType, index, flags, callingPackage, Binder.getCallingUid());
    }

    private void setStreamVolume(int streamType, int index, int flags, String callingPackage,
            int uid) {
        if (mUseFixedVolume) {
            return;
        }
@@ -1179,8 +1191,8 @@ public class AudioService extends IAudioService.Stub {
            return;
        }

        if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], Binder.getCallingUid(),
                callingPackage) != AppOpsManager.MODE_ALLOWED) {
        if (mAppOps.noteOp(STEAM_VOLUME_OPS[streamTypeAlias], uid, callingPackage)
                != AppOpsManager.MODE_ALLOWED) {
            return;
        }

@@ -5347,6 +5359,24 @@ public class AudioService extends IAudioService.Stub {
        }
    }

    /**
     * Interface for system components to get some extra functionality through
     * LocalServices.
     */
    final class AudioServiceInternal extends AudioManagerInternal {
        @Override
        public void adjustStreamVolumeForUid(int streamType, int direction, int flags,
                String callingPackage, int uid) {
            adjustStreamVolume(streamType, direction, flags, callingPackage, uid);
        }

        @Override
        public void setStreamVolumeForUid(int streamType, int direction, int flags,
                String callingPackage, int uid) {
            setStreamVolume(streamType, direction, flags, callingPackage, uid);
        }
    }

    //==========================================================================================
    // Audio policy management
    //==========================================================================================
+2 −2
Original line number Diff line number Diff line
@@ -48,8 +48,8 @@ interface ISessionController {
    PendingIntent getLaunchPendingIntent();
    long getFlags();
    ParcelableVolumeInfo getVolumeAttributes();
    void adjustVolume(int direction, int flags);
    void setVolumeTo(int value, int flags);
    void adjustVolume(int direction, int flags, String packageName);
    void setVolumeTo(int value, int flags, String packageName);

    IMediaRouterDelegate createMediaRouterDelegate(IMediaRouterStateCallback callback);

+2 −2
Original line number Diff line number Diff line
@@ -310,7 +310,7 @@ public final class MediaController {
     */
    public void setVolumeTo(int value, int flags) {
        try {
            mSessionBinder.setVolumeTo(value, flags);
            mSessionBinder.setVolumeTo(value, flags, mContext.getPackageName());
        } catch (RemoteException e) {
            Log.wtf(TAG, "Error calling setVolumeTo.", e);
        }
@@ -331,7 +331,7 @@ public final class MediaController {
     */
    public void adjustVolume(int direction, int flags) {
        try {
            mSessionBinder.adjustVolume(direction, flags);
            mSessionBinder.adjustVolume(direction, flags, mContext.getPackageName());
        } catch (RemoteException e) {
            Log.wtf(TAG, "Error calling adjustVolumeBy.", e);
        }
+16 −8
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
import android.media.AudioManager;
import android.media.AudioManagerInternal;
import android.media.MediaMetadata;
import android.media.Rating;
import android.media.VolumeProvider;
@@ -52,6 +53,8 @@ import android.util.Log;
import android.util.Slog;
import android.view.KeyEvent;

import com.android.server.LocalServices;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.UUID;
@@ -111,6 +114,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
    // Volume handling fields
    private AudioAttributes mAudioAttrs;
    private AudioManager mAudioManager;
    private AudioManagerInternal mAudioManagerInternal;
    private int mVolumeType = MediaSession.PLAYBACK_TYPE_LOCAL;
    private int mVolumeControlType = VolumeProvider.VOLUME_CONTROL_ABSOLUTE;
    private int mMaxVolume = 0;
@@ -134,6 +138,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
        mService = service;
        mHandler = new MessageHandler(handler.getLooper());
        mAudioManager = (AudioManager) service.getContext().getSystemService(Context.AUDIO_SERVICE);
        mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
        mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
    }

@@ -227,7 +232,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
     *
     * @param direction The direction to adjust volume in.
     */
    public void adjustVolume(int direction, int flags) {
    public void adjustVolume(int direction, int flags, String packageName, int uid) {
        if (isPlaybackActive(false)) {
            flags &= ~AudioManager.FLAG_PLAY_SOUND;
        }
@@ -238,7 +243,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
        }
        if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
            int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
            mAudioManager.adjustStreamVolume(stream, direction, flags);
            mAudioManagerInternal.adjustStreamVolumeForUid(stream, direction, flags, packageName,
                    uid);
        } else {
            if (mVolumeControlType == VolumeProvider.VOLUME_CONTROL_FIXED) {
                // Nothing to do, the volume cannot be changed
@@ -262,10 +268,10 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
        }
    }

    public void setVolumeTo(int value, int flags) {
    public void setVolumeTo(int value, int flags, String packageName, int uid) {
        if (mVolumeType == MediaSession.PLAYBACK_TYPE_LOCAL) {
            int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
            mAudioManager.setStreamVolume(stream, value, flags);
            mAudioManagerInternal.setStreamVolumeForUid(stream, value, flags, packageName, uid);
        } else {
            if (mVolumeControlType != VolumeProvider.VOLUME_CONTROL_ABSOLUTE) {
                // Nothing to do. The volume can't be set directly.
@@ -984,20 +990,22 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
        }

        @Override
        public void adjustVolume(int direction, int flags) {
        public void adjustVolume(int direction, int flags, String packageName) {
            int uid = Binder.getCallingUid();
            final long token = Binder.clearCallingIdentity();
            try {
                MediaSessionRecord.this.adjustVolume(direction, flags);
                MediaSessionRecord.this.adjustVolume(direction, flags, packageName, uid);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void setVolumeTo(int value, int flags) {
        public void setVolumeTo(int value, int flags, String packageName) {
            int uid = Binder.getCallingUid();
            final long token = Binder.clearCallingIdentity();
            try {
                MediaSessionRecord.this.setVolumeTo(value, flags);
                MediaSessionRecord.this.setVolumeTo(value, flags, packageName, uid);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
Loading