Merge "[DO NOT MERGE] Keep track of audio recordings that are silenced" into rvc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ac81a5725d
@@ -25,7 +25,9 @@ public class AppOpItem {
|
|||||||
private int mUid;
|
private int mUid;
|
||||||
private String mPackageName;
|
private String mPackageName;
|
||||||
private long mTimeStarted;
|
private long mTimeStarted;
|
||||||
private String mState;
|
private StringBuilder mState;
|
||||||
|
// This is only used for items with mCode == AppOpsManager.OP_RECORD_AUDIO
|
||||||
|
private boolean mSilenced;
|
||||||
|
|
||||||
public AppOpItem(int code, int uid, String packageName, long timeStarted) {
|
public AppOpItem(int code, int uid, String packageName, long timeStarted) {
|
||||||
this.mCode = code;
|
this.mCode = code;
|
||||||
@@ -36,9 +38,8 @@ public class AppOpItem {
|
|||||||
.append("AppOpItem(")
|
.append("AppOpItem(")
|
||||||
.append("Op code=").append(code).append(", ")
|
.append("Op code=").append(code).append(", ")
|
||||||
.append("UID=").append(uid).append(", ")
|
.append("UID=").append(uid).append(", ")
|
||||||
.append("Package name=").append(packageName)
|
.append("Package name=").append(packageName).append(", ")
|
||||||
.append(")")
|
.append("Paused=");
|
||||||
.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getCode() {
|
public int getCode() {
|
||||||
@@ -57,8 +58,16 @@ public class AppOpItem {
|
|||||||
return mTimeStarted;
|
return mTimeStarted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setSilenced(boolean silenced) {
|
||||||
|
mSilenced = silenced;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSilenced() {
|
||||||
|
return mSilenced;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return mState;
|
return mState.append(mSilenced).append(")").toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,12 +19,15 @@ package com.android.systemui.appops;
|
|||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.media.AudioRecordingConfiguration;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.ArraySet;
|
import android.util.ArraySet;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
|
||||||
import androidx.annotation.WorkerThread;
|
import androidx.annotation.WorkerThread;
|
||||||
|
|
||||||
@@ -62,6 +65,7 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
private static final boolean DEBUG = false;
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private final AppOpsManager mAppOps;
|
private final AppOpsManager mAppOps;
|
||||||
|
private final AudioManager mAudioManager;
|
||||||
private H mBGHandler;
|
private H mBGHandler;
|
||||||
private final List<AppOpsController.Callback> mCallbacks = new ArrayList<>();
|
private final List<AppOpsController.Callback> mCallbacks = new ArrayList<>();
|
||||||
private final ArrayMap<Integer, Set<Callback>> mCallbacksByCode = new ArrayMap<>();
|
private final ArrayMap<Integer, Set<Callback>> mCallbacksByCode = new ArrayMap<>();
|
||||||
@@ -72,6 +76,9 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
private final List<AppOpItem> mActiveItems = new ArrayList<>();
|
private final List<AppOpItem> mActiveItems = new ArrayList<>();
|
||||||
@GuardedBy("mNotedItems")
|
@GuardedBy("mNotedItems")
|
||||||
private final List<AppOpItem> mNotedItems = new ArrayList<>();
|
private final List<AppOpItem> mNotedItems = new ArrayList<>();
|
||||||
|
@GuardedBy("mActiveItems")
|
||||||
|
private final SparseArray<ArrayList<AudioRecordingConfiguration>> mRecordingsByUid =
|
||||||
|
new SparseArray<>();
|
||||||
|
|
||||||
protected static final int[] OPS = new int[] {
|
protected static final int[] OPS = new int[] {
|
||||||
AppOpsManager.OP_CAMERA,
|
AppOpsManager.OP_CAMERA,
|
||||||
@@ -86,7 +93,8 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
Context context,
|
Context context,
|
||||||
@Background Looper bgLooper,
|
@Background Looper bgLooper,
|
||||||
DumpManager dumpManager,
|
DumpManager dumpManager,
|
||||||
PermissionFlagsCache cache
|
PermissionFlagsCache cache,
|
||||||
|
AudioManager audioManager
|
||||||
) {
|
) {
|
||||||
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
|
||||||
mFlagsCache = cache;
|
mFlagsCache = cache;
|
||||||
@@ -95,6 +103,7 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
for (int i = 0; i < numOps; i++) {
|
for (int i = 0; i < numOps; i++) {
|
||||||
mCallbacksByCode.put(OPS[i], new ArraySet<>());
|
mCallbacksByCode.put(OPS[i], new ArraySet<>());
|
||||||
}
|
}
|
||||||
|
mAudioManager = audioManager;
|
||||||
dumpManager.registerDumpable(TAG, this);
|
dumpManager.registerDumpable(TAG, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,12 +118,19 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
if (listening) {
|
if (listening) {
|
||||||
mAppOps.startWatchingActive(OPS, this);
|
mAppOps.startWatchingActive(OPS, this);
|
||||||
mAppOps.startWatchingNoted(OPS, this);
|
mAppOps.startWatchingNoted(OPS, this);
|
||||||
|
mAudioManager.registerAudioRecordingCallback(mAudioRecordingCallback, mBGHandler);
|
||||||
|
mBGHandler.post(() -> mAudioRecordingCallback.onRecordingConfigChanged(
|
||||||
|
mAudioManager.getActiveRecordingConfigurations()));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
mAppOps.stopWatchingActive(this);
|
mAppOps.stopWatchingActive(this);
|
||||||
mAppOps.stopWatchingNoted(this);
|
mAppOps.stopWatchingNoted(this);
|
||||||
|
mAudioManager.unregisterAudioRecordingCallback(mAudioRecordingCallback);
|
||||||
|
|
||||||
mBGHandler.removeCallbacksAndMessages(null); // null removes all
|
mBGHandler.removeCallbacksAndMessages(null); // null removes all
|
||||||
synchronized (mActiveItems) {
|
synchronized (mActiveItems) {
|
||||||
mActiveItems.clear();
|
mActiveItems.clear();
|
||||||
|
mRecordingsByUid.clear();
|
||||||
}
|
}
|
||||||
synchronized (mNotedItems) {
|
synchronized (mNotedItems) {
|
||||||
mNotedItems.clear();
|
mNotedItems.clear();
|
||||||
@@ -187,9 +203,12 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
AppOpItem item = getAppOpItemLocked(mActiveItems, code, uid, packageName);
|
AppOpItem item = getAppOpItemLocked(mActiveItems, code, uid, packageName);
|
||||||
if (item == null && active) {
|
if (item == null && active) {
|
||||||
item = new AppOpItem(code, uid, packageName, System.currentTimeMillis());
|
item = new AppOpItem(code, uid, packageName, System.currentTimeMillis());
|
||||||
|
if (code == AppOpsManager.OP_RECORD_AUDIO) {
|
||||||
|
item.setSilenced(isAnyRecordingPausedLocked(uid));
|
||||||
|
}
|
||||||
mActiveItems.add(item);
|
mActiveItems.add(item);
|
||||||
if (DEBUG) Log.w(TAG, "Added item: " + item.toString());
|
if (DEBUG) Log.w(TAG, "Added item: " + item.toString());
|
||||||
return true;
|
return !item.isSilenced();
|
||||||
} else if (item != null && !active) {
|
} else if (item != null && !active) {
|
||||||
mActiveItems.remove(item);
|
mActiveItems.remove(item);
|
||||||
if (DEBUG) Log.w(TAG, "Removed item: " + item.toString());
|
if (DEBUG) Log.w(TAG, "Removed item: " + item.toString());
|
||||||
@@ -213,7 +232,7 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
active = getAppOpItemLocked(mActiveItems, code, uid, packageName) != null;
|
active = getAppOpItemLocked(mActiveItems, code, uid, packageName) != null;
|
||||||
}
|
}
|
||||||
if (!active) {
|
if (!active) {
|
||||||
notifySuscribers(code, uid, packageName, false);
|
notifySuscribersWorker(code, uid, packageName, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +340,7 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
AppOpItem item = mActiveItems.get(i);
|
AppOpItem item = mActiveItems.get(i);
|
||||||
if ((userId == UserHandle.USER_ALL
|
if ((userId == UserHandle.USER_ALL
|
||||||
|| UserHandle.getUserId(item.getUid()) == userId)
|
|| UserHandle.getUserId(item.getUid()) == userId)
|
||||||
&& isUserVisible(item)) {
|
&& isUserVisible(item) && !item.isSilenced()) {
|
||||||
list.add(item);
|
list.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -340,6 +359,10 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void notifySuscribers(int code, int uid, String packageName, boolean active) {
|
||||||
|
mBGHandler.post(() -> notifySuscribersWorker(code, uid, packageName, active));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
|
public void onOpActiveChanged(int code, int uid, String packageName, boolean active) {
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
@@ -357,7 +380,7 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
// If active is false, we only send the update if the op is not actively noted (prevent
|
// If active is false, we only send the update if the op is not actively noted (prevent
|
||||||
// early removal)
|
// early removal)
|
||||||
if (!alsoNoted) {
|
if (!alsoNoted) {
|
||||||
mBGHandler.post(() -> notifySuscribers(code, uid, packageName, active));
|
notifySuscribers(code, uid, packageName, active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,11 +398,11 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
alsoActive = getAppOpItemLocked(mActiveItems, code, uid, packageName) != null;
|
alsoActive = getAppOpItemLocked(mActiveItems, code, uid, packageName) != null;
|
||||||
}
|
}
|
||||||
if (!alsoActive) {
|
if (!alsoActive) {
|
||||||
mBGHandler.post(() -> notifySuscribers(code, uid, packageName, true));
|
notifySuscribers(code, uid, packageName, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifySuscribers(int code, int uid, String packageName, boolean active) {
|
private void notifySuscribersWorker(int code, int uid, String packageName, boolean active) {
|
||||||
if (mCallbacksByCode.containsKey(code) && isUserVisible(code, uid, packageName)) {
|
if (mCallbacksByCode.containsKey(code) && isUserVisible(code, uid, packageName)) {
|
||||||
if (DEBUG) Log.d(TAG, "Notifying of change in package " + packageName);
|
if (DEBUG) Log.d(TAG, "Notifying of change in package " + packageName);
|
||||||
for (Callback cb: mCallbacksByCode.get(code)) {
|
for (Callback cb: mCallbacksByCode.get(code)) {
|
||||||
@@ -405,6 +428,61 @@ public class AppOpsControllerImpl implements AppOpsController,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isAnyRecordingPausedLocked(int uid) {
|
||||||
|
List<AudioRecordingConfiguration> configs = mRecordingsByUid.get(uid);
|
||||||
|
if (configs == null) return false;
|
||||||
|
int configsNum = configs.size();
|
||||||
|
for (int i = 0; i < configsNum; i++) {
|
||||||
|
AudioRecordingConfiguration config = configs.get(i);
|
||||||
|
if (config.isClientSilenced()) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateRecordingPausedStatus() {
|
||||||
|
synchronized (mActiveItems) {
|
||||||
|
int size = mActiveItems.size();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
AppOpItem item = mActiveItems.get(i);
|
||||||
|
if (item.getCode() == AppOpsManager.OP_RECORD_AUDIO) {
|
||||||
|
boolean paused = isAnyRecordingPausedLocked(item.getUid());
|
||||||
|
if (item.isSilenced() != paused) {
|
||||||
|
item.setSilenced(paused);
|
||||||
|
notifySuscribers(
|
||||||
|
item.getCode(),
|
||||||
|
item.getUid(),
|
||||||
|
item.getPackageName(),
|
||||||
|
!item.isSilenced()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AudioManager.AudioRecordingCallback mAudioRecordingCallback =
|
||||||
|
new AudioManager.AudioRecordingCallback() {
|
||||||
|
@Override
|
||||||
|
public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {
|
||||||
|
synchronized (mActiveItems) {
|
||||||
|
mRecordingsByUid.clear();
|
||||||
|
final int recordingsCount = configs.size();
|
||||||
|
for (int i = 0; i < recordingsCount; i++) {
|
||||||
|
AudioRecordingConfiguration recording = configs.get(i);
|
||||||
|
|
||||||
|
ArrayList<AudioRecordingConfiguration> recordings = mRecordingsByUid.get(
|
||||||
|
recording.getClientUid());
|
||||||
|
if (recordings == null) {
|
||||||
|
recordings = new ArrayList<>();
|
||||||
|
mRecordingsByUid.put(recording.getClientUid(), recordings);
|
||||||
|
}
|
||||||
|
recordings.add(recording);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateRecordingPausedStatus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
protected class H extends Handler {
|
protected class H extends Handler {
|
||||||
H(Looper looper) {
|
H(Looper looper) {
|
||||||
super(looper);
|
super(looper);
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
|||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
import static org.mockito.ArgumentMatchers.anyString;
|
import static org.mockito.ArgumentMatchers.anyString;
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.inOrder;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
@@ -34,6 +37,8 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
import android.media.AudioManager;
|
||||||
|
import android.media.AudioRecordingConfiguration;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.testing.AndroidTestingRunner;
|
import android.testing.AndroidTestingRunner;
|
||||||
@@ -47,9 +52,11 @@ import com.android.systemui.dump.DumpManager;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InOrder;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -73,6 +80,12 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
|||||||
private PermissionFlagsCache mFlagsCache;
|
private PermissionFlagsCache mFlagsCache;
|
||||||
@Mock
|
@Mock
|
||||||
private PackageManager mPackageManager;
|
private PackageManager mPackageManager;
|
||||||
|
@Mock(stubOnly = true)
|
||||||
|
private AudioManager mAudioManager;
|
||||||
|
@Mock(stubOnly = true)
|
||||||
|
private AudioManager.AudioRecordingCallback mRecordingCallback;
|
||||||
|
@Mock(stubOnly = true)
|
||||||
|
private AudioRecordingConfiguration mPausedMockRecording;
|
||||||
|
|
||||||
private AppOpsControllerImpl mController;
|
private AppOpsControllerImpl mController;
|
||||||
private TestableLooper mTestableLooper;
|
private TestableLooper mTestableLooper;
|
||||||
@@ -94,11 +107,20 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
|||||||
when(mFlagsCache.getPermissionFlags(anyString(), anyString(),
|
when(mFlagsCache.getPermissionFlags(anyString(), anyString(),
|
||||||
eq(TEST_UID_NON_USER_SENSITIVE))).thenReturn(0);
|
eq(TEST_UID_NON_USER_SENSITIVE))).thenReturn(0);
|
||||||
|
|
||||||
|
doAnswer((invocation) -> mRecordingCallback = invocation.getArgument(0))
|
||||||
|
.when(mAudioManager).registerAudioRecordingCallback(any(), any());
|
||||||
|
when(mPausedMockRecording.getClientUid()).thenReturn(TEST_UID);
|
||||||
|
when(mPausedMockRecording.isClientSilenced()).thenReturn(true);
|
||||||
|
|
||||||
|
when(mAudioManager.getActiveRecordingConfigurations())
|
||||||
|
.thenReturn(List.of(mPausedMockRecording));
|
||||||
|
|
||||||
mController = new AppOpsControllerImpl(
|
mController = new AppOpsControllerImpl(
|
||||||
mContext,
|
mContext,
|
||||||
mTestableLooper.getLooper(),
|
mTestableLooper.getLooper(),
|
||||||
mDumpManager,
|
mDumpManager,
|
||||||
mFlagsCache
|
mFlagsCache,
|
||||||
|
mAudioManager
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,6 +385,89 @@ public class AppOpsControllerTest extends SysuiTestCase {
|
|||||||
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPausedRecordingIsRetrievedOnCreation() {
|
||||||
|
mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
mController.onOpActiveChanged(
|
||||||
|
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
verify(mCallback, never())
|
||||||
|
.onActiveStateChanged(anyInt(), anyInt(), anyString(), anyBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPausedRecordingFilteredOut() {
|
||||||
|
mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
mController.onOpActiveChanged(
|
||||||
|
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
assertTrue(mController.getActiveAppOps().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOnlyRecordAudioPaused() {
|
||||||
|
mController.addCallback(new int[]{
|
||||||
|
AppOpsManager.OP_RECORD_AUDIO,
|
||||||
|
AppOpsManager.OP_CAMERA
|
||||||
|
}, mCallback);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
mController.onOpActiveChanged(
|
||||||
|
AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
verify(mCallback).onActiveStateChanged(
|
||||||
|
AppOpsManager.OP_CAMERA, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||||
|
List<AppOpItem> list = mController.getActiveAppOps();
|
||||||
|
|
||||||
|
assertEquals(1, list.size());
|
||||||
|
assertEquals(AppOpsManager.OP_CAMERA, list.get(0).getCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnpausedRecordingSentActive() {
|
||||||
|
mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
mController.onOpActiveChanged(
|
||||||
|
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||||
|
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
mRecordingCallback.onRecordingConfigChanged(Collections.emptyList());
|
||||||
|
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
verify(mCallback).onActiveStateChanged(
|
||||||
|
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAudioPausedSentInactive() {
|
||||||
|
mController.addCallback(new int[]{AppOpsManager.OP_RECORD_AUDIO}, mCallback);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
mController.onOpActiveChanged(
|
||||||
|
AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
AudioRecordingConfiguration mockARC = mock(AudioRecordingConfiguration.class);
|
||||||
|
when(mockARC.getClientUid()).thenReturn(TEST_UID_OTHER);
|
||||||
|
when(mockARC.isClientSilenced()).thenReturn(true);
|
||||||
|
|
||||||
|
mRecordingCallback.onRecordingConfigChanged(List.of(mockARC));
|
||||||
|
mTestableLooper.processAllMessages();
|
||||||
|
|
||||||
|
InOrder inOrder = inOrder(mCallback);
|
||||||
|
inOrder.verify(mCallback).onActiveStateChanged(
|
||||||
|
AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
|
||||||
|
inOrder.verify(mCallback).onActiveStateChanged(
|
||||||
|
AppOpsManager.OP_RECORD_AUDIO, TEST_UID_OTHER, TEST_PACKAGE_NAME, false);
|
||||||
|
}
|
||||||
|
|
||||||
private class TestHandler extends AppOpsControllerImpl.H {
|
private class TestHandler extends AppOpsControllerImpl.H {
|
||||||
TestHandler(Looper looper) {
|
TestHandler(Looper looper) {
|
||||||
mController.super(looper);
|
mController.super(looper);
|
||||||
|
|||||||
Reference in New Issue
Block a user