diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp index 87be5f63c4990..d8f30e94d6674 100644 --- a/core/jni/android_media_AudioSystem.cpp +++ b/core/jni/android_media_AudioSystem.cpp @@ -566,10 +566,10 @@ android_media_AudioSystem_handleDeviceConfigChange(JNIEnv *env, jobject thiz, ji return (jint) status; } -static jint -android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state) -{ - return (jint) check_AudioSystem_Command(AudioSystem::setPhoneState((audio_mode_t) state)); +static jint android_media_AudioSystem_setPhoneState(JNIEnv *env, jobject thiz, jint state, + jint uid) { + return (jint)check_AudioSystem_Command( + AudioSystem::setPhoneState((audio_mode_t)state, (uid_t)uid)); } static jint @@ -2434,7 +2434,7 @@ static const JNINativeMethod gMethods[] = (void *)android_media_AudioSystem_getDeviceConnectionState}, {"handleDeviceConfigChange", "(ILjava/lang/String;Ljava/lang/String;I)I", (void *)android_media_AudioSystem_handleDeviceConfigChange}, - {"setPhoneState", "(I)I", (void *)android_media_AudioSystem_setPhoneState}, + {"setPhoneState", "(II)I", (void *)android_media_AudioSystem_setPhoneState}, {"setForceUse", "(II)I", (void *)android_media_AudioSystem_setForceUse}, {"getForceUse", "(I)I", (void *)android_media_AudioSystem_getForceUse}, {"initStreamVolume", "(III)I", (void *)android_media_AudioSystem_initStreamVolume}, diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 0a0f7f643ac9c..53379b8761c42 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -1024,7 +1024,18 @@ public class AudioSystem String device_name, int codecFormat); @UnsupportedAppUsage - public static native int setPhoneState(int state); + public static int setPhoneState(int state) { + Log.w(TAG, "Do not use this method! Use AudioManager.setMode() instead."); + return 0; + } + /** + * @hide + * Send the current audio mode to audio policy manager and audio HAL. + * @param state the audio mode + * @param uid the UID of the app owning the audio mode + * @return command completion status. + */ + public static native int setPhoneState(int state, int uid); @UnsupportedAppUsage public static native int setForceUse(int usage, int config); @UnsupportedAppUsage diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 67d7530fa11e5..f41eeeb11d5a2 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -1001,11 +1001,14 @@ public class AudioService extends IAudioService.Stub mDeviceBroker.onAudioServerDied(); // Restore call state - if (AudioSystem.setPhoneState(mMode) == AudioSystem.AUDIO_STATUS_OK) { - mModeLogger.log(new AudioEventLogger.StringEvent( - "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + ")")); + synchronized (mDeviceBroker.mSetModeLock) { + if (AudioSystem.setPhoneState(mMode, getModeOwnerUid()) + == AudioSystem.AUDIO_STATUS_OK) { + mModeLogger.log(new AudioEventLogger.StringEvent( + "onAudioServerDied causes setPhoneState(" + AudioSystem.modeToString(mMode) + + ", uid=" + getModeOwnerUid() + ")")); + } } - final int forSys; synchronized (mSettingsLock) { forSys = mCameraSoundForced ? @@ -3425,14 +3428,30 @@ public class AudioService extends IAudioService.Stub return modeOwnerPid; } + /** + * Return the uid of the current audio mode owner + * @return 0 if nobody owns the mode + */ + /*package*/ int getModeOwnerUid() { + int modeOwnerUid = 0; + try { + modeOwnerUid = mSetModeDeathHandlers.get(0).getUid(); + } catch (Exception e) { + // nothing to do, modeOwnerUid is not modified + } + return modeOwnerUid; + } + private class SetModeDeathHandler implements IBinder.DeathRecipient { - private IBinder mCb; // To be notified of client's death - private int mPid; + private final IBinder mCb; // To be notified of client's death + private final int mPid; + private final int mUid; private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client - SetModeDeathHandler(IBinder cb, int pid) { + SetModeDeathHandler(IBinder cb, int pid, int uid) { mCb = cb; mPid = pid; + mUid = uid; } public void binderDied() { @@ -3445,7 +3464,7 @@ public class AudioService extends IAudioService.Stub if (index < 0) { Log.w(TAG, "unregistered setMode() client died"); } else { - newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, TAG); + newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, mUid, TAG); } } // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all @@ -3470,6 +3489,10 @@ public class AudioService extends IAudioService.Stub public IBinder getBinder() { return mCb; } + + public int getUid() { + return mUid; + } } /** @see AudioManager#setMode(int) */ @@ -3518,7 +3541,8 @@ public class AudioService extends IAudioService.Stub + " without permission or being mode owner"); return; } - newModeOwnerPid = setModeInt(mode, cb, callingPid, callingPackage); + newModeOwnerPid = setModeInt( + mode, cb, callingPid, Binder.getCallingUid(), callingPackage); } // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all // SCO connections not started by the application changing the mode when pid changes @@ -3530,9 +3554,11 @@ public class AudioService extends IAudioService.Stub // setModeInt() returns a valid PID if the audio mode was successfully set to // any mode other than NORMAL. @GuardedBy("mDeviceBroker.mSetModeLock") - private int setModeInt(int mode, IBinder cb, int pid, String caller) { - if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ", caller=" - + caller + ")"); } + private int setModeInt(int mode, IBinder cb, int pid, int uid, String caller) { + if (DEBUG_MODE) { + Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + + ", uid=" + uid + ", caller=" + caller + ")"); + } int newModeOwnerPid = 0; if (cb == null) { Log.e(TAG, "setModeInt() called with null binder"); @@ -3569,7 +3595,7 @@ public class AudioService extends IAudioService.Stub } } else { if (hdlr == null) { - hdlr = new SetModeDeathHandler(cb, pid); + hdlr = new SetModeDeathHandler(cb, pid, uid); } // Register for client death notification try { @@ -3587,7 +3613,7 @@ public class AudioService extends IAudioService.Stub if (actualMode != mMode) { final long identity = Binder.clearCallingIdentity(); - status = AudioSystem.setPhoneState(actualMode); + status = AudioSystem.setPhoneState(actualMode, getModeOwnerUid()); Binder.restoreCallingIdentity(identity); if (status == AudioSystem.AUDIO_STATUS_OK) { if (DEBUG_MODE) { Log.v(TAG, " mode successfully set to " + actualMode); } @@ -6634,7 +6660,7 @@ public class AudioService extends IAudioService.Stub static final int LOG_NB_EVENTS_DYN_POLICY = 10; final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE, - "phone state (logged after successfull call to AudioSystem.setPhoneState(int))"); + "phone state (logged after successful call to AudioSystem.setPhoneState(int, int))"); // logs for wired + A2DP device connections: // - wired: logged before onSetWiredDeviceConnectionState() is executed