Merge "AudioService: Make suspended apps lose audio focus"

This commit is contained in:
TreeHugger Robot
2019-02-16 03:30:26 +00:00
committed by Android (Google) Code Review
6 changed files with 80 additions and 35 deletions

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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;

View File

@@ -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()));

View File

@@ -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) {

View File

@@ -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()