summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/system-current.txt1
-rw-r--r--core/java/android/app/ActivityManager.java15
-rw-r--r--core/java/android/app/AppOpsManager.java6
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java13
-rw-r--r--services/core/java/com/android/server/am/ProcessServiceRecord.java6
-rw-r--r--services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java5
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java44
-rw-r--r--services/core/java/com/android/server/audio/HardeningEnforcer.java83
-rw-r--r--services/core/java/com/android/server/audio/MediaFocusControl.java12
-rw-r--r--services/core/java/com/android/server/utils/EventLogger.java46
10 files changed, 207 insertions, 24 deletions
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e86c5129496a..e0e5c54582cc 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -592,6 +592,7 @@ package android.app {
field public static final int FOREGROUND_SERVICE_API_TYPE_MICROPHONE = 6; // 0x6
field public static final int FOREGROUND_SERVICE_API_TYPE_PHONE_CALL = 7; // 0x7
field public static final int FOREGROUND_SERVICE_API_TYPE_USB = 8; // 0x8
+ field @FlaggedApi("android.media.audio.foreground_audio_control") public static final int PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL = 64; // 0x40
field public static final int PROCESS_CAPABILITY_FOREGROUND_CAMERA = 2; // 0x2
field public static final int PROCESS_CAPABILITY_FOREGROUND_LOCATION = 1; // 0x1
field public static final int PROCESS_CAPABILITY_FOREGROUND_MICROPHONE = 4; // 0x4
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index a8d183a1d6dd..237d31c67fe2 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.activityTypeToString;
import static android.app.WindowConfiguration.windowingModeToString;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.media.audio.Flags.FLAG_FOREGROUND_AUDIO_CONTROL;
import android.Manifest;
import android.annotation.ColorInt;
@@ -794,6 +795,7 @@ public class ActivityManager {
PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK,
PROCESS_CAPABILITY_BFSL,
PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK,
+ PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ProcessCapability {}
@@ -943,6 +945,14 @@ public class ActivityManager {
public static final int PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK = 1 << 5;
/**
+ * @hide
+ * Process can access volume APIs and can request audio focus with GAIN.
+ */
+ @FlaggedApi(FLAG_FOREGROUND_AUDIO_CONTROL)
+ @SystemApi
+ public static final int PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL = 1 << 6;
+
+ /**
* @hide all capabilities, the ORing of all flags in {@link ProcessCapability}.
*
* Don't expose it as TestApi -- we may add new capabilities any time, which could
@@ -953,7 +963,8 @@ public class ActivityManager {
| PROCESS_CAPABILITY_FOREGROUND_MICROPHONE
| PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK
| PROCESS_CAPABILITY_BFSL
- | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK;
+ | PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK
+ | PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
/**
* All implicit capabilities. There are capabilities that process automatically have.
@@ -975,6 +986,7 @@ public class ActivityManager {
pw.print((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
pw.print((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
pw.print((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
+ pw.print((caps & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0 ? 'A' : '-');
}
/** @hide */
@@ -986,6 +998,7 @@ public class ActivityManager {
sb.append((caps & PROCESS_CAPABILITY_POWER_RESTRICTED_NETWORK) != 0 ? 'N' : '-');
sb.append((caps & PROCESS_CAPABILITY_BFSL) != 0 ? 'F' : '-');
sb.append((caps & PROCESS_CAPABILITY_USER_RESTRICTED_NETWORK) != 0 ? 'U' : '-');
+ sb.append((caps & PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL) != 0 ? 'A' : '-');
}
/**
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 2100425a6771..409badb347c4 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -16,7 +16,9 @@
package android.app;
+
import static android.location.flags.Flags.FLAG_LOCATION_BYPASS;
+import static android.media.audio.Flags.foregroundAudioControl;
import static android.permission.flags.Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER;
import static android.view.contentprotection.flags.Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED;
import static android.view.contentprotection.flags.Flags.FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED;
@@ -3229,6 +3231,10 @@ public class AppOpsManager {
* @hide
*/
public static @Mode int opToDefaultMode(int op) {
+ if (op == OP_TAKE_AUDIO_FOCUS && foregroundAudioControl()) {
+ // when removing the flag, change the entry in sAppOpInfos for OP_TAKE_AUDIO_FOCUS
+ return AppOpsManager.MODE_FOREGROUND;
+ }
return sAppOpInfos[op].defaultMode;
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 7d82f0c2a63e..df46e5dafce8 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -19,6 +19,7 @@ package com.android.server.am;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL_IMPLICIT;
import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
@@ -67,7 +68,10 @@ import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_UNBIND_SERVICE;
import static android.content.Context.BIND_TREAT_LIKE_VISIBLE_FOREGROUND_SERVICE;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_LOCATION;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK;
import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE;
+import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL;
+import static android.media.audio.Flags.foregroundAudioControl;
import static android.os.Process.SCHED_OTHER;
import static android.os.Process.THREAD_GROUP_BACKGROUND;
import static android.os.Process.THREAD_GROUP_DEFAULT;
@@ -2266,6 +2270,15 @@ public class OomAdjuster {
(fgsType & FOREGROUND_SERVICE_TYPE_LOCATION)
!= 0 ? PROCESS_CAPABILITY_FOREGROUND_LOCATION : 0;
+ if (foregroundAudioControl()) { // flag check
+ final int fgsAudioType = FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
+ | FOREGROUND_SERVICE_TYPE_CAMERA
+ | FOREGROUND_SERVICE_TYPE_MICROPHONE
+ | FOREGROUND_SERVICE_TYPE_PHONE_CALL;
+ capabilityFromFGS |= (psr.getForegroundServiceTypes() & fgsAudioType) != 0
+ ? PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL : 0;
+ }
+
final boolean enabled = state.getCachedCompatChange(
CACHED_COMPAT_CHANGE_CAMERA_MICROPHONE_CAPABILITY);
if (enabled) {
diff --git a/services/core/java/com/android/server/am/ProcessServiceRecord.java b/services/core/java/com/android/server/am/ProcessServiceRecord.java
index 57d233e7c503..562beaf50a7f 100644
--- a/services/core/java/com/android/server/am/ProcessServiceRecord.java
+++ b/services/core/java/com/android/server/am/ProcessServiceRecord.java
@@ -205,10 +205,10 @@ final class ProcessServiceRecord {
}
/**
- * Returns the FGS typps, but it doesn't tell if the types include "NONE" or not, so
- * do not use it outside of this class.
+ * Returns the FGS types, but it doesn't tell if the types include "NONE" or not, use
+ * {@link #hasForegroundServices()}
*/
- private int getForegroundServiceTypes() {
+ int getForegroundServiceTypes() {
return mHasForegroundServices ? mFgServiceTypes : 0;
}
diff --git a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
index 23a384ff5d3b..bc6ef2005584 100644
--- a/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
+++ b/services/core/java/com/android/server/appop/AppOpsUidStateTrackerImpl.java
@@ -16,6 +16,7 @@
package com.android.server.appop;
+import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_CAMERA;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION;
import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
@@ -30,6 +31,7 @@ import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_TAKE_AUDIO_FOCUS;
import static android.app.AppOpsManager.UID_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.UID_STATE_MAX_LAST_NON_RESTRICTED;
import static android.app.AppOpsManager.UID_STATE_TOP;
@@ -139,7 +141,6 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
}
private int evalModeInternal(int uid, int code, int uidState, int uidCapability) {
-
if (getUidAppWidgetVisible(uid) || mActivityManagerInternal.isPendingTopUid(uid)
|| mActivityManagerInternal.isTempAllowlistedForFgsWhileInUse(uid)) {
return MODE_ALLOWED;
@@ -173,6 +174,8 @@ class AppOpsUidStateTrackerImpl implements AppOpsUidStateTracker {
case OP_RECORD_AUDIO:
case OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO:
return PROCESS_CAPABILITY_FOREGROUND_MICROPHONE;
+ case OP_TAKE_AUDIO_FOCUS:
+ return PROCESS_CAPABILITY_FOREGROUND_AUDIO_CONTROL;
default:
return PROCESS_CAPABILITY_NONE;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c59f4f7888ce..559a1d647ea4 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -34,6 +34,7 @@ import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import static android.media.audio.Flags.automaticBtDeviceType;
import static android.media.audio.Flags.featureSpatialAudioHeadtrackingLowLatency;
import static android.media.audio.Flags.focusFreezeTestApi;
+import static android.media.audio.Flags.foregroundAudioControl;
import static android.media.audiopolicy.Flags.enableFadeManagerConfiguration;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.INVALID_UID;
@@ -1356,7 +1357,8 @@ public class AudioService extends IAudioService.Stub
mMusicFxHelper = new MusicFxHelper(mContext, mAudioHandler);
- mHardeningEnforcer = new HardeningEnforcer(mContext, isPlatformAutomotive());
+ mHardeningEnforcer = new HardeningEnforcer(mContext, isPlatformAutomotive(), mAppOps,
+ context.getPackageManager());
}
private void initVolumeStreamStates() {
@@ -4517,7 +4519,8 @@ public class AudioService extends IAudioService.Stub
}
private void dumpFlags(PrintWriter pw) {
- pw.println("\nFun with Flags: ");
+
+ pw.println("\nFun with Flags:");
pw.println("\tandroid.media.audio.autoPublicVolumeApiHardening:"
+ autoPublicVolumeApiHardening());
pw.println("\tandroid.media.audio.Flags.automaticBtDeviceType:"
@@ -4528,8 +4531,8 @@ public class AudioService extends IAudioService.Stub
+ focusFreezeTestApi());
pw.println("\tcom.android.media.audio.disablePrescaleAbsoluteVolume:"
+ disablePrescaleAbsoluteVolume());
- pw.println("\tandroid.media.audiopolicy.enableFadeManagerConfiguration:"
- + enableFadeManagerConfiguration());
+ pw.println("\tandroid.media.audio.foregroundAudioControl:"
+ + foregroundAudioControl());
}
private void dumpAudioMode(PrintWriter pw) {
@@ -10175,10 +10178,38 @@ public class AudioService extends IAudioService.Stub
.record();
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
}
+
+ // does caller have system privileges to bypass HardeningEnforcer
+ boolean permissionOverridesCheck = false;
+ if ((mContext.checkCallingOrSelfPermission(
+ Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED)
+ == PackageManager.PERMISSION_GRANTED)
+ || (mContext.checkCallingOrSelfPermission(Manifest.permission.MODIFY_AUDIO_ROUTING)
+ == PackageManager.PERMISSION_GRANTED)) {
+ permissionOverridesCheck = true;
+ } else if (uid < UserHandle.AID_APP_START) {
+ permissionOverridesCheck = true;
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ if (!permissionOverridesCheck && mHardeningEnforcer.blockFocusMethod(uid,
+ HardeningEnforcer.METHOD_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS,
+ clientId, durationHint, callingPackageName)) {
+ final String reason = "Audio focus request blocked by hardening";
+ Log.w(TAG, reason);
+ mmi.set(MediaMetrics.Property.EARLY_RETURN, reason).record();
+ return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
mmi.record();
return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
clientId, callingPackageName, attributionTag, flags, sdk,
- forceFocusDuckingForAccessibility(aa, durationHint, uid), -1 /*testUid, ignored*/);
+ forceFocusDuckingForAccessibility(aa, durationHint, uid), -1 /*testUid, ignored*/,
+ permissionOverridesCheck);
}
/** see {@link AudioManager#requestAudioFocusForTest(AudioFocusRequest, String, int, int)} */
@@ -10195,7 +10226,7 @@ public class AudioService extends IAudioService.Stub
}
return mMediaFocusControl.requestAudioFocus(aa, durationHint, cb, fd,
clientId, callingPackageName, null, flags,
- sdk, false /*forceDuck*/, fakeUid);
+ sdk, false /*forceDuck*/, fakeUid, true /*permissionOverridesCheck*/);
}
public int abandonAudioFocus(IAudioFocusDispatcher fd, String clientId, AudioAttributes aa,
@@ -11639,6 +11670,7 @@ public class AudioService extends IAudioService.Stub
pw.println("\nMessage handler is null");
}
dumpFlags(pw);
+ mHardeningEnforcer.dump(pw);
mMediaFocusControl.dump(pw);
dumpStreamStates(pw);
dumpVolumeGroups(pw);
diff --git a/services/core/java/com/android/server/audio/HardeningEnforcer.java b/services/core/java/com/android/server/audio/HardeningEnforcer.java
index 4ceb83b2e1c9..409ed17001b7 100644
--- a/services/core/java/com/android/server/audio/HardeningEnforcer.java
+++ b/services/core/java/com/android/server/audio/HardeningEnforcer.java
@@ -18,13 +18,21 @@ package com.android.server.audio;
import static android.media.audio.Flags.autoPublicVolumeApiHardening;
import android.Manifest;
+import android.annotation.NonNull;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.os.Binder;
import android.os.UserHandle;
import android.text.TextUtils;
-import android.util.Log;
+import android.util.Slog;
+
+import com.android.server.utils.EventLogger;
+
+import java.io.PrintWriter;
/**
* Class to encapsulate all audio API hardening operations
@@ -32,10 +40,19 @@ import android.util.Log;
public class HardeningEnforcer {
private static final String TAG = "AS.HardeningEnforcer";
+ private static final boolean DEBUG = false;
+ private static final int LOG_NB_EVENTS = 20;
final Context mContext;
+ final AppOpsManager mAppOps;
final boolean mIsAutomotive;
+ final ActivityManager mActivityManager;
+ final PackageManager mPackageManager;
+
+ final EventLogger mEventLogger = new EventLogger(LOG_NB_EVENTS,
+ "Hardening enforcement");
+
/**
* Matches calls from {@link AudioManager#setStreamVolume(int, int, int)}
*/
@@ -56,10 +73,24 @@ public class HardeningEnforcer {
* Matches calls from {@link AudioManager#setRingerMode(int)}
*/
public static final int METHOD_AUDIO_MANAGER_SET_RINGER_MODE = 200;
+ /**
+ * Matches calls from {@link AudioManager#requestAudioFocus(AudioFocusRequest)}
+ * and legacy variants
+ */
+ public static final int METHOD_AUDIO_MANAGER_REQUEST_AUDIO_FOCUS = 300;
- public HardeningEnforcer(Context ctxt, boolean isAutomotive) {
+ public HardeningEnforcer(Context ctxt, boolean isAutomotive, AppOpsManager appOps,
+ PackageManager pm) {
mContext = ctxt;
mIsAutomotive = isAutomotive;
+ mAppOps = appOps;
+ mActivityManager = ctxt.getSystemService(ActivityManager.class);
+ mPackageManager = pm;
+ }
+
+ protected void dump(PrintWriter pw) {
+ // log
+ mEventLogger.dump(pw);
}
/**
@@ -84,7 +115,7 @@ public class HardeningEnforcer {
}
// TODO metrics?
// TODO log for audio dumpsys?
- Log.e(TAG, "Preventing volume method " + volumeMethod + " for "
+ Slog.e(TAG, "Preventing volume method " + volumeMethod + " for "
+ getPackNameForUid(Binder.getCallingUid()));
return true;
}
@@ -92,10 +123,40 @@ public class HardeningEnforcer {
return false;
}
+ /**
+ * Checks whether the call in the current thread should be allowed or blocked
+ * @param focusMethod name of the method to check, for logging purposes
+ * @param clientId id of the requester
+ * @param durationHint focus type being requested
+ * @return false if the method call is allowed, true if it should be a no-op
+ */
+ protected boolean blockFocusMethod(int callingUid, int focusMethod, @NonNull String clientId,
+ int durationHint, @NonNull String packageName) {
+ if (packageName.isEmpty()) {
+ packageName = getPackNameForUid(callingUid);
+ }
+
+ if (checkAppOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, callingUid, packageName)) {
+ if (DEBUG) {
+ Slog.i(TAG, "blockFocusMethod pack:" + packageName + " NOT blocking");
+ }
+ return false;
+ }
+
+ String errorMssg = "Focus request DENIED for uid:" + callingUid
+ + " clientId:" + clientId + " req:" + durationHint
+ + " procState:" + mActivityManager.getUidProcessState(callingUid);
+
+ // TODO metrics
+ mEventLogger.enqueueAndSlog(errorMssg, EventLogger.Event.ALOGI, TAG);
+
+ return true;
+ }
+
private String getPackNameForUid(int uid) {
final long token = Binder.clearCallingIdentity();
try {
- final String[] names = mContext.getPackageManager().getPackagesForUid(uid);
+ final String[] names = mPackageManager.getPackagesForUid(uid);
if (names == null
|| names.length == 0
|| TextUtils.isEmpty(names[0])) {
@@ -106,4 +167,18 @@ public class HardeningEnforcer {
Binder.restoreCallingIdentity(token);
}
}
+
+ /**
+ * Checks the given op without throwing
+ * @param op the appOp code
+ * @param uid the calling uid
+ * @param packageName the package name of the caller
+ * @return return false if the operation is not allowed
+ */
+ private boolean checkAppOp(int op, int uid, @NonNull String packageName) {
+ if (mAppOps.checkOpNoThrow(op, uid, packageName) != AppOpsManager.MODE_ALLOWED) {
+ return false;
+ }
+ return true;
+ }
}
diff --git a/services/core/java/com/android/server/audio/MediaFocusControl.java b/services/core/java/com/android/server/audio/MediaFocusControl.java
index 1376bde2fb71..35d38e2373f5 100644
--- a/services/core/java/com/android/server/audio/MediaFocusControl.java
+++ b/services/core/java/com/android/server/audio/MediaFocusControl.java
@@ -1090,11 +1090,14 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
* accessibility.
* @param testUid ignored if flags doesn't contain AudioManager.AUDIOFOCUS_FLAG_TEST
* otherwise the UID being injected for testing
+ * @param permissionOverridesCheck true if permission checks guaranteed that the call should
+ * go through, false otherwise (e.g. non-privileged caller)
* @return
*/
protected int requestAudioFocus(@NonNull AudioAttributes aa, int focusChangeHint, IBinder cb,
IAudioFocusDispatcher fd, @NonNull String clientId, @NonNull String callingPackageName,
- String attributionTag, int flags, int sdk, boolean forceDuck, int testUid) {
+ String attributionTag, int flags, int sdk, boolean forceDuck, int testUid,
+ boolean permissionOverridesCheck) {
new MediaMetrics.Item(mMetricsId)
.setUid(Binder.getCallingUid())
.set(MediaMetrics.Property.CALLING_PACKAGE, callingPackageName)
@@ -1126,10 +1129,9 @@ public class MediaFocusControl implements PlayerFocusEnforcer {
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
}
- if ((flags != AudioManager.AUDIOFOCUS_FLAG_TEST)
- // note we're using the real uid for appOp evaluation
- && (mAppOps.noteOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, Binder.getCallingUid(),
- callingPackageName, attributionTag, null) != AppOpsManager.MODE_ALLOWED)) {
+ final int res = mAppOps.noteOp(AppOpsManager.OP_TAKE_AUDIO_FOCUS, Binder.getCallingUid(),
+ callingPackageName, attributionTag, null);
+ if (!permissionOverridesCheck && res != AppOpsManager.MODE_ALLOWED) {
return AudioManager.AUDIOFOCUS_REQUEST_FAILED;
}
diff --git a/services/core/java/com/android/server/utils/EventLogger.java b/services/core/java/com/android/server/utils/EventLogger.java
index 4772bbfe97dd..2e1049b9ea32 100644
--- a/services/core/java/com/android/server/utils/EventLogger.java
+++ b/services/core/java/com/android/server/utils/EventLogger.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Log;
+import android.util.Slog;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -84,6 +85,17 @@ public class EventLogger {
enqueue(event.printLog(logType, tag));
}
+ /**
+ * Add a string-based event to the system log, and print it to the log with a specific severity.
+ * @param msg the message to appear in the log
+ * @param logType the log severity (verbose/info/warning/error)
+ * @param tag the tag under which the log entry will appear
+ */
+ public synchronized void enqueueAndSlog(String msg, @Event.LogType int logType, String tag) {
+ final Event event = new StringEvent(msg);
+ enqueue(event.printSlog(logType, tag));
+ }
+
/** Dumps events into the given {@link DumpSink}. */
public synchronized void dump(DumpSink dumpSink) {
dumpSink.sink(mTag, new ArrayList<>(mEvents));
@@ -138,7 +150,7 @@ public class EventLogger {
/**
* Causes the string message for the event to appear in the logcat.
* Here is an example of how to create a new event (a StringEvent), adding it to the logger
- * (an instance of AudioEventLogger) while also making it show in the logcat:
+ * (an instance of EventLogger) while also making it show in the logcat:
* <pre>
* myLogger.log(
* (new StringEvent("something for logcat and logger")).printLog(MyClass.TAG) );
@@ -167,9 +179,9 @@ public class EventLogger {
/**
* Same as {@link #printLog(String)} with a log type
- * @param type one of {@link #ALOGI}, {@link #ALOGE}, {@link #ALOGV}
- * @param tag
- * @return
+ * @param type one of {@link #ALOGI}, {@link #ALOGE}, {@link #ALOGV}, {@link #ALOGW}
+ * @param tag the tag the log entry will be printed under
+ * @return the event itself
*/
public Event printLog(@LogType int type, String tag) {
switch (type) {
@@ -191,6 +203,32 @@ public class EventLogger {
}
/**
+ * Causes the string message for the event to appear in the system log.
+ * @param type one of {@link #ALOGI}, {@link #ALOGE}, {@link #ALOGV}, {@link #ALOGW}
+ * @param tag the tag the log entry will be printed under
+ * @return the event itself
+ * @see #printLog(int, String)
+ */
+ public Event printSlog(@LogType int type, String tag) {
+ switch (type) {
+ case ALOGI:
+ Slog.i(tag, eventToString());
+ break;
+ case ALOGE:
+ Slog.e(tag, eventToString());
+ break;
+ case ALOGW:
+ Slog.w(tag, eventToString());
+ break;
+ case ALOGV:
+ default:
+ Slog.v(tag, eventToString());
+ break;
+ }
+ return this;
+ }
+
+ /**
* Convert event to String.
* This method is only called when the logger history is about to the dumped,
* so this method is where expensive String conversions should be made, not when the Event