summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/AppOpsManager.java33
-rw-r--r--core/java/android/permission/PermissionUsageHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt4
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java3
-rw-r--r--services/core/java/com/android/server/appop/DiscreteRegistry.java3
-rw-r--r--services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java15
-rw-r--r--services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java18
-rw-r--r--services/core/java/com/android/server/policy/AppOpsPolicy.java8
-rw-r--r--services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java5
-rw-r--r--services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java19
11 files changed, 101 insertions, 14 deletions
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 3b1943bf86f6..a216021fc66b 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1335,9 +1335,17 @@ public class AppOpsManager {
public static final int OP_ACCESS_RESTRICTED_SETTINGS =
AppProtoEnums.APP_OP_ACCESS_RESTRICTED_SETTINGS;
+ /**
+ * Receive microphone audio from an ambient sound detection event
+ *
+ * @hide
+ */
+ public static final int OP_RECEIVE_AMBIENT_TRIGGER_AUDIO =
+ AppProtoEnums.APP_OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
+
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public static final int _NUM_OP = 120;
+ public static final int _NUM_OP = 121;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1800,6 +1808,14 @@ public class AppOpsManager {
public static final String OPSTR_ACCESS_RESTRICTED_SETTINGS =
"android:access_restricted_settings";
+ /**
+ * Receive microphone audio from an ambient sound detection event
+ *
+ * @hide
+ */
+ public static final String OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO =
+ "android:receive_ambient_trigger_audio";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -2021,6 +2037,7 @@ public class AppOpsManager {
OP_ESTABLISH_VPN_SERVICE, // OP_ESTABLISH_VPN_SERVICE
OP_ESTABLISH_VPN_MANAGER, // OP_ESTABLISH_VPN_MANAGER
OP_ACCESS_RESTRICTED_SETTINGS, // OP_ACCESS_RESTRICTED_SETTINGS
+ OP_RECEIVE_AMBIENT_TRIGGER_AUDIO, // RECEIVE_SOUNDTRIGGER_AUDIO
};
/**
@@ -2147,6 +2164,7 @@ public class AppOpsManager {
OPSTR_ESTABLISH_VPN_SERVICE,
OPSTR_ESTABLISH_VPN_MANAGER,
OPSTR_ACCESS_RESTRICTED_SETTINGS,
+ OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
};
/**
@@ -2274,6 +2292,7 @@ public class AppOpsManager {
"ESTABLISH_VPN_SERVICE",
"ESTABLISH_VPN_MANAGER",
"ACCESS_RESTRICTED_SETTINGS",
+ "RECEIVE_SOUNDTRIGGER_AUDIO",
};
/**
@@ -2402,6 +2421,7 @@ public class AppOpsManager {
null, // no permission for OP_ESTABLISH_VPN_SERVICE
null, // no permission for OP_ESTABLISH_VPN_MANAGER
null, // no permission for OP_ACCESS_RESTRICTED_SETTINGS,
+ null, // no permission for OP_RECEIVE_SOUNDTRIGGER_AUDIO
};
/**
@@ -2529,7 +2549,8 @@ public class AppOpsManager {
null, // NEARBY_WIFI_DEVICES
null, // ESTABLISH_VPN_SERVICE
null, // ESTABLISH_VPN_MANAGER
- null, // ACCESS_RESTRICTED_SETTINGS,
+ null, // ACCESS_RESTRICTED_SETTINGS
+ null, // RECEIVE_SOUNDTRIGGER_AUDIO
};
/**
@@ -2656,7 +2677,8 @@ public class AppOpsManager {
null, // NEARBY_WIFI_DEVICES
null, // ESTABLISH_VPN_SERVICE
null, // ESTABLISH_VPN_MANAGER
- null, // ACCESS_RESTRICTED_SETTINGS,
+ null, // ACCESS_RESTRICTED_SETTINGS
+ null, // RECEIVE_SOUNDTRIGGER_AUDIO
};
/**
@@ -2765,7 +2787,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ERRORED, // OP_NO_ISOLATED_STORAGE
AppOpsManager.MODE_ALLOWED, // PHONE_CALL_MICROPHONE
AppOpsManager.MODE_ALLOWED, // PHONE_CALL_CAMERA
- AppOpsManager.MODE_ALLOWED, // OP_RECORD_AUDIO_HOTWORD
+ AppOpsManager.MODE_ALLOWED, // RECORD_AUDIO_HOTWORD
AppOpsManager.MODE_DEFAULT, // MANAGE_ONGOING_CALLS
AppOpsManager.MODE_DEFAULT, // MANAGE_CREDENTIALS
AppOpsManager.MODE_DEFAULT, // USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER
@@ -2783,6 +2805,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_SERVICE
AppOpsManager.MODE_ALLOWED, // ESTABLISH_VPN_MANAGER
AppOpsManager.MODE_ALLOWED, // ACCESS_RESTRICTED_SETTINGS,
+ AppOpsManager.MODE_ALLOWED, // RECEIVE_SOUNDTRIGGER_AUDIO
};
/**
@@ -2913,6 +2936,7 @@ public class AppOpsManager {
false, // OP_ESTABLISH_VPN_SERVICE
false, // OP_ESTABLISH_VPN_MANAGER
true, // ACCESS_RESTRICTED_SETTINGS
+ false, // RECEIVE_SOUNDTRIGGER_AUDIO
};
/**
@@ -3040,6 +3064,7 @@ public class AppOpsManager {
false, // OP_ESTABLISH_VPN_SERVICE
false, // OP_ESTABLISH_VPN_MANAGER
true, // ACCESS_RESTRICTED_SETTINGS
+ false, // RECEIVE_SOUNDTRIGGER_AUDIO
};
/**
diff --git a/core/java/android/permission/PermissionUsageHelper.java b/core/java/android/permission/PermissionUsageHelper.java
index 4ed939c48bd7..f5f1c374b636 100644
--- a/core/java/android/permission/PermissionUsageHelper.java
+++ b/core/java/android/permission/PermissionUsageHelper.java
@@ -30,6 +30,7 @@ import static android.app.AppOpsManager.OPSTR_COARSE_LOCATION;
import static android.app.AppOpsManager.OPSTR_FINE_LOCATION;
import static android.app.AppOpsManager.OPSTR_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OPSTR_PHONE_CALL_MICROPHONE;
+import static android.app.AppOpsManager.OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO;
import static android.app.AppOpsManager.OPSTR_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_FLAGS_ALL_TRUSTED;
@@ -137,6 +138,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
private static final List<String> MIC_OPS = List.of(
OPSTR_PHONE_CALL_MICROPHONE,
+ OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO,
OPSTR_RECORD_AUDIO
);
@@ -147,6 +149,7 @@ public class PermissionUsageHelper implements AppOpsManager.OnOpActiveChangedLis
private static @NonNull String getGroupForOp(String op) {
switch (op) {
+ case OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO:
case OPSTR_RECORD_AUDIO:
return MICROPHONE;
case OPSTR_CAMERA:
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index c10fafeac8b4..6b859763eb6f 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -102,6 +102,7 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
AppOpsManager.OP_PHONE_CALL_CAMERA,
AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO,
AppOpsManager.OP_PHONE_CALL_MICROPHONE,
AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION
@@ -535,7 +536,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
}
private boolean isOpMicrophone(int op) {
- return op == AppOpsManager.OP_RECORD_AUDIO || op == AppOpsManager.OP_PHONE_CALL_MICROPHONE;
+ return op == AppOpsManager.OP_RECORD_AUDIO || op == AppOpsManager.OP_PHONE_CALL_MICROPHONE
+ || op == AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
}
protected class H extends Handler {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index dbdb9d268aab..cd6eb99e259e 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -58,7 +58,8 @@ class PrivacyItemController @Inject constructor(
internal companion object {
val OPS_MIC_CAMERA = intArrayOf(AppOpsManager.OP_CAMERA,
AppOpsManager.OP_PHONE_CALL_CAMERA, AppOpsManager.OP_RECORD_AUDIO,
- AppOpsManager.OP_PHONE_CALL_MICROPHONE)
+ AppOpsManager.OP_PHONE_CALL_MICROPHONE,
+ AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO)
val OPS_LOCATION = intArrayOf(
AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION)
@@ -315,6 +316,7 @@ class PrivacyItemController @Inject constructor(
AppOpsManager.OP_COARSE_LOCATION,
AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION
AppOpsManager.OP_PHONE_CALL_MICROPHONE,
+ AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO,
AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
else -> return null
}
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 8cef0b0130f6..b9da144713cd 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -43,6 +43,7 @@ import static android.app.AppOpsManager.OP_FLAG_SELF;
import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
+import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD;
import static android.app.AppOpsManager.OnOpStartedListener.START_TYPE_FAILED;
@@ -3849,7 +3850,7 @@ public class AppOpsService extends IAppOpsService.Stub {
// the data gated by OP_RECORD_AUDIO.
//
// TODO: Revert this change before Android 12.
- if (code == OP_RECORD_AUDIO_HOTWORD) {
+ if (code == OP_RECORD_AUDIO_HOTWORD || code == OP_RECEIVE_AMBIENT_TRIGGER_AUDIO) {
int result = checkOperation(OP_RECORD_AUDIO, uid, packageName);
if (result != AppOpsManager.MODE_ALLOWED) {
return new SyncNotedAppOp(result, code, attributionTag, packageName);
diff --git a/services/core/java/com/android/server/appop/DiscreteRegistry.java b/services/core/java/com/android/server/appop/DiscreteRegistry.java
index 8de515d4d3e5..158092f33ee3 100644
--- a/services/core/java/com/android/server/appop/DiscreteRegistry.java
+++ b/services/core/java/com/android/server/appop/DiscreteRegistry.java
@@ -34,6 +34,7 @@ import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXY;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE;
+import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.flagsToString;
import static android.app.AppOpsManager.getUidStateName;
@@ -133,7 +134,7 @@ final class DiscreteRegistry {
private static final String PROPERTY_DISCRETE_OPS_LIST = "discrete_history_ops_cslist";
private static final String DEFAULT_DISCRETE_OPS = OP_FINE_LOCATION + "," + OP_COARSE_LOCATION
+ "," + OP_CAMERA + "," + OP_RECORD_AUDIO + "," + OP_PHONE_CALL_MICROPHONE + ","
- + OP_PHONE_CALL_CAMERA;
+ + OP_PHONE_CALL_CAMERA + "," + OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
private static final long DEFAULT_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(7).toMillis();
private static final long MAXIMUM_DISCRETE_HISTORY_CUTOFF = Duration.ofDays(30).toMillis();
private static final long DEFAULT_DISCRETE_HISTORY_QUANTIZATION =
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java
index 446e20b70279..6c2354f1b3e6 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerInternal.java
@@ -17,6 +17,7 @@
package com.android.server.pm.permission;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
/**
@@ -105,6 +106,20 @@ public interface LegacyPermissionManagerInternal {
void scheduleReadDefaultPermissionExceptions();
/**
+ * Check whether a particular package should have access to the microphone data from the
+ * SoundTrigger.
+ *
+ * @param uid the uid of the package you are checking against
+ * @param packageName the name of the package you are checking against
+ * @param attributionTag the attributionTag to attach to the app op transaction
+ * @param reason the reason to attach to the app op transaction
+ * @return {@code PERMISSION_GRANTED} if the permission is granted,
+ * or {@code PERMISSION_SOFT/HARD DENIED otherwise
+ */
+ int checkSoundTriggerRecordAudioPermissionForDataDelivery(int uid,
+ @NonNull String packageName, @Nullable String attributionTag, @NonNull String reason);
+
+ /**
* Provider for package names.
*/
interface PackagesProvider {
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
index 360a04f7e9bc..88b4a94f7027 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
@@ -16,12 +16,15 @@
package com.android.server.pm.permission;
+import static android.Manifest.permission.RECORD_AUDIO;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
+import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
@@ -399,6 +402,21 @@ public class LegacyPermissionManagerService extends ILegacyPermissionManager.Stu
public void scheduleReadDefaultPermissionExceptions() {
mDefaultPermissionGrantPolicy.scheduleReadDefaultPermissionExceptions();
}
+
+ @Override
+ public int checkSoundTriggerRecordAudioPermissionForDataDelivery(int uid,
+ @NonNull String packageName, @Nullable String attributionTag,
+ @NonNull String reason) {
+ int result = PermissionChecker.checkPermissionForPreflight(mContext, RECORD_AUDIO, -1,
+ uid, packageName);
+ if (result != PermissionChecker.PERMISSION_GRANTED) {
+ return result;
+ }
+ mContext.getSystemService(AppOpsManager.class).noteOpNoThrow(
+ AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO, uid, packageName,
+ attributionTag, reason);
+ return result;
+ }
}
/**
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index e157a277366f..a6d148c824c9 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -87,8 +87,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
private final VoiceInteractionManagerInternal mVoiceInteractionManagerInternal;
/**
- * Whether this device allows only the HotwordDetectionService to use OP_RECORD_AUDIO_HOTWORD
- * which doesn't incur the privacy indicator.
+ * Whether this device allows only the HotwordDetectionService to use
+ * OP_RECORD_AUDIO_HOTWORD which doesn't incur the privacy indicator.
*/
private final boolean mIsHotwordDetectionServiceRequired;
@@ -428,8 +428,8 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat
if (!mIsHotwordDetectionServiceRequired) {
return code;
}
- // Only the HotwordDetectionService can use the HOTWORD op which doesn't incur the
- // privacy indicator. Downgrade to standard RECORD_AUDIO for other processes.
+ // Only the HotwordDetectionService can use the RECORD_AUDIO_HOTWORD op which doesn't
+ // incur the privacy indicator. Downgrade to standard RECORD_AUDIO for other processes.
final HotwordDetectionServiceIdentity hotwordDetectionServiceIdentity =
mVoiceInteractionManagerInternal.getHotwordDetectionServiceIdentity();
if (hotwordDetectionServiceIdentity != null
diff --git a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
index 3c779f387673..c354f116af5f 100644
--- a/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/sensorprivacy/SensorPrivacyService.java
@@ -25,6 +25,7 @@ import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_PHONE_CALL_CAMERA;
import static android.app.AppOpsManager.OP_PHONE_CALL_MICROPHONE;
+import static android.app.AppOpsManager.OP_RECEIVE_AMBIENT_TRIGGER_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.content.Intent.EXTRA_PACKAGE_NAME;
import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
@@ -1067,6 +1068,10 @@ public final class SensorPrivacyService extends SystemService {
mAppOpsRestrictionToken);
mAppOpsManagerInternal.setGlobalRestriction(OP_PHONE_CALL_MICROPHONE, enabled,
mAppOpsRestrictionToken);
+ // We don't show the dialog for RECEIVE_SOUNDTRIGGER_AUDIO, but still want to
+ // restrict it when the microphone is disabled
+ mAppOpsManagerInternal.setGlobalRestriction(OP_RECEIVE_AMBIENT_TRIGGER_AUDIO,
+ enabled, mAppOpsRestrictionToken);
break;
case CAMERA:
mAppOpsManagerInternal.setGlobalRestriction(OP_CAMERA, enabled,
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
index f3d151fe5cc4..13fe14caa1f9 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerMiddlewarePermission.java
@@ -41,6 +41,9 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
+import com.android.server.LocalServices;
+import com.android.server.pm.permission.LegacyPermissionManagerInternal;
+
import java.io.PrintWriter;
import java.util.Objects;
@@ -120,8 +123,7 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
* Throws a {@link SecurityException} iff the originator has permission to receive data.
*/
void enforcePermissionsForDataDelivery(@NonNull Identity identity, @NonNull String reason) {
- enforcePermissionForDataDelivery(mContext, identity, RECORD_AUDIO,
- reason);
+ enforceSoundTriggerRecordAudioPermissionForDataDelivery(identity, reason);
enforcePermissionForDataDelivery(mContext, identity, CAPTURE_AUDIO_HOTWORD,
reason);
}
@@ -147,6 +149,19 @@ public class SoundTriggerMiddlewarePermission implements ISoundTriggerMiddleware
}
}
+ private static void enforceSoundTriggerRecordAudioPermissionForDataDelivery(
+ @NonNull Identity identity, @NonNull String reason) {
+ LegacyPermissionManagerInternal lpmi =
+ LocalServices.getService(LegacyPermissionManagerInternal.class);
+ final int status = lpmi.checkSoundTriggerRecordAudioPermissionForDataDelivery(identity.uid,
+ identity.packageName, identity.attributionTag, reason);
+ if (status != PermissionChecker.PERMISSION_GRANTED) {
+ throw new SecurityException(
+ String.format("Failed to obtain permission RECORD_AUDIO for identity %s",
+ ObjectPrinter.print(identity, 16)));
+ }
+ }
+
/**
* Throws a {@link SecurityException} if originator permanently doesn't have the given
* permission.