am 7a6ccb87: Merge "Remote volume changes" into klp-dev

* commit '7a6ccb87290f12203e00cbddcffc2fbee35cebd3':
  Remote volume changes
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 680e73a..d652cae 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1572,6 +1572,24 @@
 
     /**
      * @hide
+     * Checks whether any local or remote media playback is active.
+     * Local playback refers to playback for instance on the device's speakers or wired headphones.
+     * Remote playback refers to playback for instance on a wireless display mirroring the
+     *    devices's, or on a device using a Cast-like protocol.
+     * @return true if media playback, from which the device is aware, is active.
+     */
+    public boolean isLocalOrRemoteMusicActive() {
+        IAudioService service = getService();
+        try {
+            return service.isLocalOrRemoteMusicActive();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Dead object in isLocalOrRemoteMusicActive()", e);
+            return false;
+        }
+    }
+
+    /**
+     * @hide
      * Checks whether the current audio focus is exclusive.
      * @return true if the top of the audio focus stack requested focus
      *     with {@link #AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 79814d1..1f5fefd 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -751,6 +751,26 @@
     ///////////////////////////////////////////////////////////////////////////
     // IPC methods
     ///////////////////////////////////////////////////////////////////////////
+    /** @see AudioManager#isLocalOrRemoteMusicActive() */
+    public boolean isLocalOrRemoteMusicActive() {
+        if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
+            // local / wired / BT playback active
+            if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): local");
+            return true;
+        }
+        if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) {
+            // remote "cast-like" playback active
+            if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): has PLAYBACK_TYPE_REMOTE");
+            return true;
+        }
+        if (AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, 0)) {
+            // remote submix playback active
+            if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): remote submix");
+            return true;
+        }
+        if (DEBUG_VOL) Log.d(TAG, "isLocalOrRemoteMusicActive(): no");
+        return false;
+    }
 
     /** @see AudioManager#adjustVolume(int, int) */
     public void adjustVolume(int direction, int flags, String callingPackage) {
@@ -763,10 +783,10 @@
     public void adjustLocalOrRemoteStreamVolume(int streamType, int direction,
             String callingPackage) {
         if (DEBUG_VOL) Log.d(TAG, "adjustLocalOrRemoteStreamVolume(dir="+direction+")");
-        if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) {
-            mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, 0);
-        } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
+        if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
             adjustStreamVolume(AudioSystem.STREAM_MUSIC, direction, 0, callingPackage);
+        } else if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) {
+            mMediaFocusControl.adjustRemoteVolume(AudioSystem.STREAM_MUSIC, direction, 0);
         }
     }
 
@@ -2612,6 +2632,17 @@
         return (isOffhook || getMode() == AudioManager.MODE_IN_COMMUNICATION);
     }
 
+    /**
+     * For code clarity for getActiveStreamType(int)
+     * @param delay_ms max time since last STREAM_MUSIC activity to consider
+     * @return true if STREAM_MUSIC is active in streams handled by AudioFlinger now or
+     *     in the last "delay_ms" ms.
+     */
+    private boolean isAfMusicActiveRecently(int delay_ms) {
+        return AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, delay_ms)
+                || AudioSystem.isStreamActiveRemotely(AudioSystem.STREAM_MUSIC, delay_ms);
+    }
+
     private int getActiveStreamType(int suggestedStreamType) {
         if (mVoiceCapable) {
             if (isInCommunication()) {
@@ -2624,23 +2655,22 @@
                     return AudioSystem.STREAM_VOICE_CALL;
                 }
             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
-                // Having the suggested stream be USE_DEFAULT_STREAM_TYPE is how remote control
-                // volume can have priority over STREAM_MUSIC
-                if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) {
-                    if (DEBUG_VOL)
-                        Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
-                    return STREAM_REMOTE_MUSIC;
-                } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC,
-                            DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
+                if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
                     if (DEBUG_VOL)
                         Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
                     return AudioSystem.STREAM_MUSIC;
-                } else {
-                    if (DEBUG_VOL)
-                        Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default");
-                    return AudioSystem.STREAM_RING;
+                } else
+                    if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC))
+                    {
+                        if (DEBUG_VOL)
+                            Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
+                        return STREAM_REMOTE_MUSIC;
+                    } else {
+                        if (DEBUG_VOL)
+                            Log.v(TAG, "getActiveStreamType: Forcing STREAM_RING b/c default");
+                        return AudioSystem.STREAM_RING;
                 }
-            } else if (AudioSystem.isStreamActive(AudioSystem.STREAM_MUSIC, 0)) {
+            } else if (isAfMusicActiveRecently(0)) {
                 if (DEBUG_VOL)
                     Log.v(TAG, "getActiveStreamType: Forcing STREAM_MUSIC stream active");
                 return AudioSystem.STREAM_MUSIC;
@@ -2666,14 +2696,17 @@
                 if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_NOTIFICATION");
                 return AudioSystem.STREAM_NOTIFICATION;
             } else if (suggestedStreamType == AudioManager.USE_DEFAULT_STREAM_TYPE) {
-                if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC)) {
-                    // Having the suggested stream be USE_DEFAULT_STREAM_TYPE is how remote control
-                    // volume can have priority over STREAM_MUSIC
-                    if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
-                    return STREAM_REMOTE_MUSIC;
+                if (isAfMusicActiveRecently(DEFAULT_STREAM_TYPE_OVERRIDE_DELAY_MS)) {
+                    if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: forcing STREAM_MUSIC");
+                    return AudioSystem.STREAM_MUSIC;
+                } else
+                    if (mMediaFocusControl.checkUpdateRemoteStateIfActive(AudioSystem.STREAM_MUSIC))
+                    {
+                        if (DEBUG_VOL)
+                            Log.v(TAG, "getActiveStreamType: Forcing STREAM_REMOTE_MUSIC");
+                        return STREAM_REMOTE_MUSIC;
                 } else {
-                    if (DEBUG_VOL)
-                        Log.v(TAG, "getActiveStreamType: using STREAM_MUSIC as default");
+                    if (DEBUG_VOL) Log.v(TAG, "getActiveStreamType: using STREAM_MUSIC as default");
                     return AudioSystem.STREAM_MUSIC;
                 }
             } else {
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 8c05089..2f08325 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -37,6 +37,8 @@
 
     void adjustVolume(int direction, int flags, String callingPackage);
 
+    boolean isLocalOrRemoteMusicActive();
+
     oneway void adjustLocalOrRemoteStreamVolume(int streamType, int direction,
             String callingPackage);
 
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 448925b..ec70314 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -42,6 +42,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.media.AudioManager;
+import android.media.AudioSystem;
 import android.media.IAudioService;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -3647,7 +3648,9 @@
     }
 
     /**
-     * @return Whether music is being played right now.
+     * @return Whether music is being played right now "locally" (e.g. on the device's speakers
+     *    or wired headphones) or "remotely" (e.g. on a device using the Cast protocol and
+     *    controlled by this device, or through remote submix).
      */
     boolean isMusicActive() {
         final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
@@ -3655,7 +3658,7 @@
             Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
             return false;
         }
-        return am.isMusicActive();
+        return am.isLocalOrRemoteMusicActive();
     }
 
     /**
@@ -3668,19 +3671,28 @@
             return;
         }
         try {
-            // since audio is playing, we shouldn't have to hold a wake lock
+            // when audio is playing locally, we shouldn't have to hold a wake lock
             // during the call, but we do it as a precaution for the rare possibility
-            // that the music stops right before we call this
+            // that the music stops right before we call this.
+            // Otherwise we might also be in a remote playback case.
             // TODO: Actually handle MUTE.
             mBroadcastWakeLock.acquire();
-            audioService.adjustStreamVolume(stream,
-                keycode == KeyEvent.KEYCODE_VOLUME_UP
-                            ? AudioManager.ADJUST_RAISE
-                            : AudioManager.ADJUST_LOWER,
-                    0,
-                    mContext.getOpPackageName());
+            if (stream == AudioSystem.STREAM_MUSIC) {
+                audioService.adjustLocalOrRemoteStreamVolume(stream,
+                        keycode == KeyEvent.KEYCODE_VOLUME_UP
+                                ? AudioManager.ADJUST_RAISE
+                                : AudioManager.ADJUST_LOWER,
+                        mContext.getOpPackageName());
+            } else {
+                audioService.adjustStreamVolume(stream,
+                        keycode == KeyEvent.KEYCODE_VOLUME_UP
+                                ? AudioManager.ADJUST_RAISE
+                                : AudioManager.ADJUST_LOWER,
+                        0,
+                        mContext.getOpPackageName());
+            }
         } catch (RemoteException e) {
-            Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
+            Log.w(TAG, "IAudioService.adjust*StreamVolume() threw RemoteException " + e);
         } finally {
             mBroadcastWakeLock.release();
         }