OSDN Git Service

Merge "Do not perform forceVolumeControlStream in master volume mode" into lmp-mr1-dev
[android-x86/frameworks-base.git] / media / java / android / media / AudioManager.java
index febb979..e61b563 100644 (file)
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.Manifest;
+import android.annotation.NonNull;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
@@ -469,6 +470,49 @@ public class AudioManager {
     public static final int FLAG_SHOW_UI_WARNINGS = 1 << 10;
 
     /**
+     * Adjusting the volume down from vibrated was prevented, display a hint in the UI.
+     * @hide
+     */
+    public static final int FLAG_SHOW_VIBRATE_HINT = 1 << 11;
+
+    private static final String[] FLAG_NAMES = {
+        "FLAG_SHOW_UI",
+        "FLAG_ALLOW_RINGER_MODES",
+        "FLAG_PLAY_SOUND",
+        "FLAG_REMOVE_SOUND_AND_VIBRATE",
+        "FLAG_VIBRATE",
+        "FLAG_FIXED_VOLUME",
+        "FLAG_BLUETOOTH_ABS_VOLUME",
+        "FLAG_SHOW_SILENT_HINT",
+        "FLAG_HDMI_SYSTEM_AUDIO_VOLUME",
+        "FLAG_ACTIVE_MEDIA_ONLY",
+        "FLAG_SHOW_UI_WARNINGS",
+        "FLAG_SHOW_VIBRATE_HINT",
+    };
+
+    /** @hide */
+    public static String flagsToString(int flags) {
+        final StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < FLAG_NAMES.length; i++) {
+            final int flag = 1 << i;
+            if ((flags & flag) != 0) {
+                if (sb.length() > 0) {
+                    sb.append(',');
+                }
+                sb.append(FLAG_NAMES[i]);
+                flags &= ~flag;
+            }
+        }
+        if (flags != 0) {
+            if (sb.length() > 0) {
+                sb.append(',');
+            }
+            sb.append(flags);
+        }
+        return sb.toString();
+    }
+
+    /**
      * Ringer mode that will be silent and will not vibrate. (This overrides the
      * vibrate setting.)
      *
@@ -856,7 +900,7 @@ public class AudioManager {
     public int getRingerMode() {
         IAudioService service = getService();
         try {
-            return service.getRingerMode();
+            return service.getRingerModeExternal();
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in getRingerMode", e);
             return RINGER_MODE_NORMAL;
@@ -976,21 +1020,12 @@ public class AudioManager {
      * @see #isVolumeFixed()
      */
     public void setRingerMode(int ringerMode) {
-        setRingerMode(ringerMode, true /*checkZen*/);
-    }
-
-    /**
-     * @see #setRingerMode(int)
-     * @param checkZen  Update zen mode if necessary to compensate.
-     * @hide
-     */
-    public void setRingerMode(int ringerMode, boolean checkZen) {
         if (!isValidRingerMode(ringerMode)) {
             return;
         }
         IAudioService service = getService();
         try {
-            service.setRingerMode(ringerMode, checkZen);
+            service.setRingerModeExternal(ringerMode, mContext.getOpPackageName());
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in setRingerMode", e);
         }
@@ -2321,14 +2356,25 @@ public class AudioManager {
         return status;
     }
 
-    // when adding new flags, add them to AUDIOFOCUS_FLAGS_ALL
+    // when adding new flags, add them to the relevant AUDIOFOCUS_FLAGS_APPS or SYSTEM masks
     /** @hide */
+    @SystemApi
     public static final int AUDIOFOCUS_FLAG_DELAY_OK = 0x1 << 0;
     /** @hide */
-    public static final int AUDIOFOCUS_FLAGS_ALL = AUDIOFOCUS_FLAG_DELAY_OK;
+    @SystemApi
+    public static final int AUDIOFOCUS_FLAG_LOCK     = 0x1 << 1;
+    /** @hide */
+    public static final int AUDIOFOCUS_FLAGS_APPS = AUDIOFOCUS_FLAG_DELAY_OK;
+    /** @hide */
+    public static final int AUDIOFOCUS_FLAGS_SYSTEM = AUDIOFOCUS_FLAG_DELAY_OK
+            | AUDIOFOCUS_FLAG_LOCK;
 
     /**
      * @hide
+     * Request audio focus.
+     * Send a request to obtain the audio focus. This method differs from
+     * {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)} in that it can express
+     * that the requester accepts delayed grants of audio focus.
      * @param l the listener to be notified of audio focus changes. It is not allowed to be null
      *     when the request is flagged with {@link #AUDIOFOCUS_FLAG_DELAY_OK}.
      * @param requestAttributes non null {@link AudioAttributes} describing the main reason for
@@ -2343,24 +2389,70 @@ public class AudioManager {
      *      usecases such as voice memo recording, or speech recognition.
      *      Use {@link #AUDIOFOCUS_GAIN} for a focus request of unknown duration such
      *      as the playback of a song or a video.
-     * @param flags use 0 when not using any flags for the request, which behaves like
-     *      {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio
-     *      focus is granted immediately, or the grant request fails because the system is in a
-     *      state where focus cannot change (e.g. a phone call).
-     *      Use {link #AUDIOFOCUS_FLAG_DELAY_OK} if it is ok for the requester to not be granted
-     *      audio focus immediately (as indicated by {@link #AUDIOFOCUS_REQUEST_DELAYED}) when
-     *      the system is in a state where focus cannot change, but be granted focus later when
-     *      this condition ends.
+     * @param flags 0 or {link #AUDIOFOCUS_FLAG_DELAY_OK}.
+     *     <br>Use 0 when not using any flags for the request, which behaves like
+     *     {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio
+     *     focus is granted immediately, or the grant request fails because the system is in a
+     *     state where focus cannot change (e.g. a phone call).
+     *     <br>Use {link #AUDIOFOCUS_FLAG_DELAY_OK} if it is ok for the requester to not be granted
+     *     audio focus immediately (as indicated by {@link #AUDIOFOCUS_REQUEST_DELAYED}) when
+     *     the system is in a state where focus cannot change, but be granted focus later when
+     *     this condition ends.
      * @return {@link #AUDIOFOCUS_REQUEST_FAILED}, {@link #AUDIOFOCUS_REQUEST_GRANTED}
      *     or {@link #AUDIOFOCUS_REQUEST_DELAYED}.
      *     The return value is never {@link #AUDIOFOCUS_REQUEST_DELAYED} when focus is requested
      *     without the {@link #AUDIOFOCUS_FLAG_DELAY_OK} flag.
      * @throws IllegalArgumentException
      */
+    @SystemApi
     public int requestAudioFocus(OnAudioFocusChangeListener l,
-            AudioAttributes requestAttributes,
+            @NonNull AudioAttributes requestAttributes,
             int durationHint,
             int flags) throws IllegalArgumentException {
+        if (flags != (flags & AUDIOFOCUS_FLAGS_APPS)) {
+            throw new IllegalArgumentException("Invalid flags 0x"
+                    + Integer.toHexString(flags).toUpperCase());
+        }
+        return requestAudioFocus(l, requestAttributes, durationHint,
+                flags & AUDIOFOCUS_FLAGS_APPS,
+                null /* no AudioPolicy*/);
+    }
+
+    /**
+     * @hide
+     * Request or lock audio focus.
+     * This method is to be used by system components that have registered an
+     * {@link android.media.audiopolicy.AudioPolicy} to request audio focus, but also to "lock" it
+     * so focus granting is temporarily disabled.
+     * @param l see the description of the same parameter in
+     *     {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
+     * @param requestAttributes non null {@link AudioAttributes} describing the main reason for
+     *     requesting audio focus.
+     * @param durationHint see the description of the same parameter in
+     *     {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
+     * @param flags 0 or a combination of {link #AUDIOFOCUS_FLAG_DELAY_OK},
+     *     {@link #AUDIOFOCUS_FLAG_LOCK}
+     *     <br>Use 0 when not using any flags for the request, which behaves like
+     *     {@link #requestAudioFocus(OnAudioFocusChangeListener, int, int)}, where either audio
+     *     focus is granted immediately, or the grant request fails because the system is in a
+     *     state where focus cannot change (e.g. a phone call).
+     *     <br>Use {link #AUDIOFOCUS_FLAG_DELAY_OK} if it is ok for the requester to not be granted
+     *     audio focus immediately (as indicated by {@link #AUDIOFOCUS_REQUEST_DELAYED}) when
+     *     the system is in a state where focus cannot change, but be granted focus later when
+     *     this condition ends.
+     *     <br>Use {@link #AUDIOFOCUS_FLAG_LOCK} when locking audio focus so granting is
+     *     temporarily disabled.
+     * @param ap a registered {@link android.media.audiopolicy.AudioPolicy} instance when locking
+     *     focus, or null.
+     * @return see the description of the same return value in
+     *     {@link #requestAudioFocus(OnAudioFocusChangeListener, AudioAttributes, int, int)}
+     * @throws IllegalArgumentException
+     */
+    public int requestAudioFocus(OnAudioFocusChangeListener l,
+            @NonNull AudioAttributes requestAttributes,
+            int durationHint,
+            int flags,
+            AudioPolicy ap) throws IllegalArgumentException {
         // parameter checking
         if (requestAttributes == null) {
             throw new IllegalArgumentException("Illegal null AudioAttributes argument");
@@ -2369,7 +2461,7 @@ public class AudioManager {
                 (durationHint > AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE)) {
             throw new IllegalArgumentException("Invalid duration hint");
         }
-        if (flags != (flags & AUDIOFOCUS_FLAGS_ALL)) {
+        if (flags != (flags & AUDIOFOCUS_FLAGS_SYSTEM)) {
             throw new IllegalArgumentException("Illegal flags 0x"
                 + Integer.toHexString(flags).toUpperCase());
         }
@@ -2377,6 +2469,10 @@ public class AudioManager {
             throw new IllegalArgumentException(
                     "Illegal null focus listener when flagged as accepting delayed focus grant");
         }
+        if (((flags & AUDIOFOCUS_FLAG_LOCK) == AUDIOFOCUS_FLAG_LOCK) && (ap == null)) {
+            throw new IllegalArgumentException(
+                    "Illegal null audio policy when locking audio focus");
+        }
 
         int status = AUDIOFOCUS_REQUEST_FAILED;
         registerAudioFocusListener(l);
@@ -2384,9 +2480,10 @@ public class AudioManager {
         try {
             status = service.requestAudioFocus(requestAttributes, durationHint, mICallBack,
                     mAudioFocusDispatcher, getIdForAudioFocusListener(l),
-                    mContext.getOpPackageName() /* package name */, flags);
+                    mContext.getOpPackageName() /* package name */, flags,
+                    ap != null ? ap.token() : null);
         } catch (RemoteException e) {
-            Log.e(TAG, "Can't call requestAudioFocus() on AudioService due to "+e);
+            Log.e(TAG, "Can't call requestAudioFocus() on AudioService:", e);
         }
         return status;
     }
@@ -2408,9 +2505,11 @@ public class AudioManager {
                         .setInternalLegacyStreamType(streamType).build(),
                     durationHint, mICallBack, null,
                     MediaFocusControl.IN_VOICE_COMM_FOCUS_ID,
-                    mContext.getOpPackageName(), 0 /* flags, legacy behavior*/ );
+                    mContext.getOpPackageName(),
+                    AUDIOFOCUS_FLAG_LOCK,
+                    null /* policy token */);
         } catch (RemoteException e) {
-            Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService due to "+e);
+            Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService:", e);
         }
     }
 
@@ -2423,9 +2522,10 @@ public class AudioManager {
     public void abandonAudioFocusForCall() {
         IAudioService service = getService();
         try {
-            service.abandonAudioFocus(null, MediaFocusControl.IN_VOICE_COMM_FOCUS_ID);
+            service.abandonAudioFocus(null, MediaFocusControl.IN_VOICE_COMM_FOCUS_ID,
+                    null /*AudioAttributes, legacy behavior*/);
         } catch (RemoteException e) {
-            Log.e(TAG, "Can't call abandonAudioFocusForCall() on AudioService due to "+e);
+            Log.e(TAG, "Can't call abandonAudioFocusForCall() on AudioService:", e);
         }
     }
 
@@ -2435,19 +2535,30 @@ public class AudioManager {
      *  @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
      */
     public int abandonAudioFocus(OnAudioFocusChangeListener l) {
+        return abandonAudioFocus(l, null /*AudioAttributes, legacy behavior*/);
+    }
+
+    /**
+     * @hide
+     * Abandon audio focus. Causes the previous focus owner, if any, to receive focus.
+     *  @param l the listener with which focus was requested.
+     * @param aa the {@link AudioAttributes} with which audio focus was requested
+     * @return {@link #AUDIOFOCUS_REQUEST_FAILED} or {@link #AUDIOFOCUS_REQUEST_GRANTED}
+     */
+    @SystemApi
+    public int abandonAudioFocus(OnAudioFocusChangeListener l, AudioAttributes aa) {
         int status = AUDIOFOCUS_REQUEST_FAILED;
         unregisterAudioFocusListener(l);
         IAudioService service = getService();
         try {
             status = service.abandonAudioFocus(mAudioFocusDispatcher,
-                    getIdForAudioFocusListener(l));
+                    getIdForAudioFocusListener(l), aa);
         } catch (RemoteException e) {
-            Log.e(TAG, "Can't call abandonAudioFocus() on AudioService due to "+e);
+            Log.e(TAG, "Can't call abandonAudioFocus() on AudioService:", e);
         }
         return status;
     }
 
-
     //====================================================================
     // Remote Control
     /**
@@ -3234,6 +3345,31 @@ public class AudioManager {
     }
 
     /**
+     * Only useful for volume controllers.
+     * @hide
+     */
+    public void setRingerModeInternal(int ringerMode) {
+        try {
+            getService().setRingerModeInternal(ringerMode, mContext.getOpPackageName());
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error calling setRingerModeInternal", e);
+        }
+    }
+
+    /**
+     * Only useful for volume controllers.
+     * @hide
+     */
+    public int getRingerModeInternal() {
+        try {
+            return getService().getRingerModeInternal();
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error calling getRingerModeInternal", e);
+            return RINGER_MODE_NORMAL;
+        }
+    }
+
+    /**
      * Set Hdmi Cec system audio mode.
      *
      * @param on whether to be on system audio mode