Merge "AudioService: Make suspended apps lose audio focus"
This commit is contained in:
committed by
Android (Google) Code Review
commit
d2d04c6e81
@@ -3409,13 +3409,13 @@ package android.media {
|
||||
|
||||
public final class AudioFocusInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public android.media.AudioAttributes getAttributes();
|
||||
method public String getClientId();
|
||||
method @NonNull public android.media.AudioAttributes getAttributes();
|
||||
method @NonNull public String getClientId();
|
||||
method public int getClientUid();
|
||||
method public int getFlags();
|
||||
method public int getGainRequest();
|
||||
method public int getLossReceived();
|
||||
method public String getPackageName();
|
||||
method @NonNull public String getPackageName();
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field public static final android.os.Parcelable.Creator<android.media.AudioFocusInfo> CREATOR;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package android.media;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.SystemApi;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
@@ -29,10 +30,10 @@ import java.util.Objects;
|
||||
@SystemApi
|
||||
public final class AudioFocusInfo implements Parcelable {
|
||||
|
||||
private final AudioAttributes mAttributes;
|
||||
private final @NonNull AudioAttributes mAttributes;
|
||||
private final int mClientUid;
|
||||
private final String mClientId;
|
||||
private final String mPackageName;
|
||||
private final @NonNull String mClientId;
|
||||
private final @NonNull String mPackageName;
|
||||
private final int mSdkTarget;
|
||||
private int mGainRequest;
|
||||
private int mLossReceived;
|
||||
@@ -80,13 +81,21 @@ public final class AudioFocusInfo implements Parcelable {
|
||||
* The audio attributes for the audio focus request.
|
||||
* @return non-null {@link AudioAttributes}.
|
||||
*/
|
||||
public AudioAttributes getAttributes() { return mAttributes; }
|
||||
public @NonNull AudioAttributes getAttributes() {
|
||||
return mAttributes;
|
||||
}
|
||||
|
||||
public int getClientUid() { return mClientUid; }
|
||||
public int getClientUid() {
|
||||
return mClientUid;
|
||||
}
|
||||
|
||||
public String getClientId() { return mClientId; }
|
||||
public @NonNull String getClientId() {
|
||||
return mClientId;
|
||||
}
|
||||
|
||||
public String getPackageName() { return mPackageName; }
|
||||
public @NonNull String getPackageName() {
|
||||
return mPackageName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of audio focus gain request.
|
||||
|
||||
@@ -225,9 +225,9 @@ public final class AudioFocusRequest {
|
||||
/** @hide */
|
||||
public static final String KEY_ACCESSIBILITY_FORCE_FOCUS_DUCKING = "a11y_force_ducking";
|
||||
|
||||
private final OnAudioFocusChangeListener mFocusListener; // may be null
|
||||
private final Handler mListenerHandler; // may be null
|
||||
private final AudioAttributes mAttr; // never null
|
||||
private final @Nullable OnAudioFocusChangeListener mFocusListener;
|
||||
private final @Nullable Handler mListenerHandler;
|
||||
private final @NonNull AudioAttributes mAttr;
|
||||
private final int mFocusGain;
|
||||
private final int mFlags;
|
||||
|
||||
|
||||
@@ -754,6 +754,7 @@ public class AudioService extends IAudioService.Stub
|
||||
intentFilter.addAction(Intent.ACTION_USER_FOREGROUND);
|
||||
intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
|
||||
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
|
||||
intentFilter.addAction(Intent.ACTION_PACKAGES_SUSPENDED);
|
||||
|
||||
intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
|
||||
mMonitorRotation = SystemProperties.getBoolean("ro.audio.monitorRotation", false);
|
||||
@@ -5183,6 +5184,20 @@ public class AudioService extends IAudioService.Stub
|
||||
} else if (action.equals(AudioEffect.ACTION_OPEN_AUDIO_EFFECT_CONTROL_SESSION) ||
|
||||
action.equals(AudioEffect.ACTION_CLOSE_AUDIO_EFFECT_CONTROL_SESSION)) {
|
||||
handleAudioEffectBroadcast(context, intent);
|
||||
} else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
|
||||
final int[] suspendedUids = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
|
||||
final String[] suspendedPackages =
|
||||
intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
|
||||
if (suspendedPackages == null || suspendedUids == null
|
||||
|| suspendedPackages.length != suspendedUids.length) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < suspendedUids.length; i++) {
|
||||
if (!TextUtils.isEmpty(suspendedPackages[i])) {
|
||||
mMediaFocusControl.noFocusForSuspendedApp(
|
||||
suspendedPackages[i], suspendedUids[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end class AudioServiceBroadcastReceiver
|
||||
@@ -5347,6 +5362,11 @@ public class AudioService extends IAudioService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
if (callingPackageName == null || clientId == null || aa == null) {
|
||||
Log.e(TAG, "Invalid null parameter to request audio focus");
|
||||
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
|
||||
}
|
||||
|
||||
return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
|
||||
clientId, callingPackageName, flags, sdk,
|
||||
forceFocusDuckingForAccessibility(aa, durationHint, Binder.getCallingUid()));
|
||||
|
||||
@@ -45,8 +45,8 @@ public class FocusRequester {
|
||||
private AudioFocusDeathHandler mDeathHandler; // may be null
|
||||
private IAudioFocusDispatcher mFocusDispatcher; // may be null
|
||||
private final IBinder mSourceRef; // may be null
|
||||
private final String mClientId;
|
||||
private final String mPackageName;
|
||||
private final @NonNull String mClientId;
|
||||
private final @NonNull String mPackageName;
|
||||
private final int mCallingUid;
|
||||
private final MediaFocusControl mFocusController; // never null
|
||||
private final int mSdkTarget;
|
||||
@@ -72,7 +72,7 @@ public class FocusRequester {
|
||||
/**
|
||||
* the audio attributes associated with the focus request
|
||||
*/
|
||||
private final AudioAttributes mAttributes;
|
||||
private final @NonNull AudioAttributes mAttributes;
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
@@ -87,9 +87,10 @@ public class FocusRequester {
|
||||
* @param uid
|
||||
* @param ctlr cannot be null
|
||||
*/
|
||||
FocusRequester(AudioAttributes aa, int focusRequest, int grantFlags,
|
||||
IAudioFocusDispatcher afl, IBinder source, String id, AudioFocusDeathHandler hdlr,
|
||||
String pn, int uid, @NonNull MediaFocusControl ctlr, int sdk) {
|
||||
FocusRequester(@NonNull AudioAttributes aa, int focusRequest, int grantFlags,
|
||||
IAudioFocusDispatcher afl, IBinder source, @NonNull String id,
|
||||
AudioFocusDeathHandler hdlr, @NonNull String pn, int uid,
|
||||
@NonNull MediaFocusControl ctlr, int sdk) {
|
||||
mAttributes = aa;
|
||||
mFocusDispatcher = afl;
|
||||
mSourceRef = source;
|
||||
@@ -124,11 +125,7 @@ public class FocusRequester {
|
||||
}
|
||||
|
||||
boolean hasSameClient(String otherClient) {
|
||||
try {
|
||||
return mClientId.compareTo(otherClient) == 0;
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
return mClientId.compareTo(otherClient) == 0;
|
||||
}
|
||||
|
||||
boolean isLockedFocusOwner() {
|
||||
@@ -143,12 +140,8 @@ public class FocusRequester {
|
||||
return (mFocusDispatcher != null) && mFocusDispatcher.equals(fd);
|
||||
}
|
||||
|
||||
boolean hasSamePackage(String pack) {
|
||||
try {
|
||||
return mPackageName.compareTo(pack) == 0;
|
||||
} catch (NullPointerException e) {
|
||||
return false;
|
||||
}
|
||||
boolean hasSamePackage(@NonNull String pack) {
|
||||
return mPackageName.compareTo(pack) == 0;
|
||||
}
|
||||
|
||||
boolean hasSameUid(int uid) {
|
||||
|
||||
@@ -24,7 +24,6 @@ import android.media.AudioFocusInfo;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioSystem;
|
||||
import android.media.IAudioFocusDispatcher;
|
||||
import android.media.audiopolicy.AudioPolicy;
|
||||
import android.media.audiopolicy.IAudioPolicyCallback;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
@@ -35,6 +34,7 @@ import android.util.Log;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.text.DateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@@ -44,7 +44,6 @@ import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.text.DateFormat;
|
||||
|
||||
/**
|
||||
* @hide
|
||||
@@ -138,6 +137,30 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
private static final AudioEventLogger mEventLogger = new AudioEventLogger(50,
|
||||
"focus commands as seen by MediaFocusControl");
|
||||
|
||||
/*package*/ void noFocusForSuspendedApp(@NonNull String packageName, int uid) {
|
||||
synchronized (mAudioFocusLock) {
|
||||
final Iterator<FocusRequester> stackIterator = mFocusStack.iterator();
|
||||
List<String> clientsToRemove = new ArrayList<>();
|
||||
while (stackIterator.hasNext()) {
|
||||
final FocusRequester focusOwner = stackIterator.next();
|
||||
if (focusOwner.hasSameUid(uid) && focusOwner.hasSamePackage(packageName)) {
|
||||
clientsToRemove.add(focusOwner.getClientId());
|
||||
mEventLogger.log((new AudioEventLogger.StringEvent(
|
||||
"focus owner:" + focusOwner.getClientId()
|
||||
+ " in uid:" + uid + " pack: " + packageName
|
||||
+ " getting AUDIOFOCUS_LOSS due to app suspension"))
|
||||
.printLog(TAG));
|
||||
// make the suspended app lose focus through its focus listener (if any)
|
||||
focusOwner.dispatchFocusChange(AudioManager.AUDIOFOCUS_LOSS);
|
||||
}
|
||||
}
|
||||
for (String clientToRemove : clientsToRemove) {
|
||||
// update the stack but don't signal the change.
|
||||
removeFocusStackEntry(clientToRemove, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard the current audio focus owner.
|
||||
* Notify top of audio focus stack that it lost focus (regardless of possibility to reassign
|
||||
@@ -688,9 +711,9 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
|
||||
}
|
||||
|
||||
/** @see AudioManager#requestAudioFocus(AudioManager.OnAudioFocusChangeListener, int, int, int) */
|
||||
protected int requestAudioFocus(AudioAttributes aa, int focusChangeHint, IBinder cb,
|
||||
IAudioFocusDispatcher fd, String clientId, String callingPackageName, int flags,
|
||||
int sdk, boolean forceDuck) {
|
||||
protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb,
|
||||
IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName,
|
||||
int flags, int sdk, boolean forceDuck) {
|
||||
mEventLogger.log((new AudioEventLogger.StringEvent(
|
||||
"requestAudioFocus() from uid/pid " + Binder.getCallingUid()
|
||||
+ "/" + Binder.getCallingPid()
|
||||
|
||||
Reference in New Issue
Block a user