Merge "Fix setting camera op restriction on reboot" into sc-qpr1-dev am: 395f43dd6f
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15983492 Change-Id: Id37dddc45836bb75f911f93da71f11f49a843e83
This commit is contained in:
@@ -39,6 +39,7 @@ import static android.hardware.SensorPrivacyManager.Sources.OTHER;
|
||||
import static android.hardware.SensorPrivacyManager.Sources.QS_TILE;
|
||||
import static android.hardware.SensorPrivacyManager.Sources.SETTINGS;
|
||||
import static android.hardware.SensorPrivacyManager.Sources.SHELL;
|
||||
import static android.os.UserHandle.USER_NULL;
|
||||
import static android.os.UserHandle.USER_SYSTEM;
|
||||
import static android.service.SensorPrivacyIndividualEnabledSensorProto.UNKNOWN;
|
||||
|
||||
@@ -195,7 +196,7 @@ public final class SensorPrivacyService extends SystemService {
|
||||
private EmergencyCallHelper mEmergencyCallHelper;
|
||||
private KeyguardManager mKeyguardManager;
|
||||
|
||||
private int mCurrentUser = -1;
|
||||
private int mCurrentUser = USER_NULL;
|
||||
|
||||
public SensorPrivacyService(Context context) {
|
||||
super(context);
|
||||
@@ -228,9 +229,9 @@ public final class SensorPrivacyService extends SystemService {
|
||||
|
||||
@Override
|
||||
public void onUserStarting(TargetUser user) {
|
||||
if (mCurrentUser == -1) {
|
||||
if (mCurrentUser == USER_NULL) {
|
||||
mCurrentUser = user.getUserIdentifier();
|
||||
mSensorPrivacyServiceImpl.userSwitching(-1, user.getUserIdentifier());
|
||||
mSensorPrivacyServiceImpl.userSwitching(USER_NULL, user.getUserIdentifier());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1294,13 +1295,13 @@ public final class SensorPrivacyService extends SystemService {
|
||||
micState = isIndividualSensorPrivacyEnabledLocked(to, MICROPHONE);
|
||||
camState = isIndividualSensorPrivacyEnabledLocked(to, CAMERA);
|
||||
}
|
||||
if (prevMicState != micState) {
|
||||
if (from == USER_NULL || prevMicState != micState) {
|
||||
mHandler.onUserGlobalSensorPrivacyChanged(MICROPHONE, micState);
|
||||
setGlobalRestriction(MICROPHONE, micState);
|
||||
}
|
||||
if (prevCamState != camState) {
|
||||
if (from == USER_NULL || prevCamState != camState) {
|
||||
mHandler.onUserGlobalSensorPrivacyChanged(CAMERA, camState);
|
||||
setGlobalRestriction(CAMERA, micState);
|
||||
setGlobalRestriction(CAMERA, camState);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||
<sensor-privacy persistence-version="1" version="1">
|
||||
<user id="0" enabled="false">
|
||||
<individual-sensor-privacy sensor="1" enabled="true" />
|
||||
<individual-sensor-privacy sensor="2" enabled="true" />
|
||||
</user>
|
||||
</sensor-privacy>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||
<sensor-privacy persistence-version="1" version="1">
|
||||
<user id="0" enabled="false">
|
||||
<individual-sensor-privacy sensor="1" enabled="true" />
|
||||
<individual-sensor-privacy sensor="2" enabled="false" />
|
||||
</user>
|
||||
</sensor-privacy>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||
<sensor-privacy persistence-version="1" version="1">
|
||||
<user id="0" enabled="false">
|
||||
<individual-sensor-privacy sensor="1" enabled="false" />
|
||||
<individual-sensor-privacy sensor="2" enabled="true" />
|
||||
</user>
|
||||
</sensor-privacy>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
|
||||
<sensor-privacy persistence-version="1" version="1">
|
||||
<user id="0" enabled="false">
|
||||
<individual-sensor-privacy sensor="1" enabled="false" />
|
||||
<individual-sensor-privacy sensor="2" enabled="false" />
|
||||
</user>
|
||||
</sensor-privacy>
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package com.android.server.sensorprivacy;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.AppOpsManager;
|
||||
import android.app.AppOpsManagerInternal;
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.Environment;
|
||||
@@ -33,8 +39,10 @@ import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import com.android.dx.mockito.inline.extended.ExtendedMockito;
|
||||
import com.android.server.LocalServices;
|
||||
import com.android.server.SensorPrivacyService;
|
||||
import com.android.server.SystemService;
|
||||
import com.android.server.pm.UserManagerInternal;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -44,6 +52,7 @@ import org.mockito.quality.Strictness;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@RunWith(AndroidTestingRunner.class)
|
||||
public class SensorPrivacyServiceMockingTest {
|
||||
@@ -63,10 +72,21 @@ public class SensorPrivacyServiceMockingTest {
|
||||
public static final String PERSISTENCE_FILE6 =
|
||||
String.format(PERSISTENCE_FILE_PATHS_TEMPLATE, 6);
|
||||
|
||||
public static final String PERSISTENCE_FILE_MIC_MUTE_CAM_MUTE =
|
||||
"SensorPrivacyServiceMockingTest/persisted_file_micMute_camMute.xml";
|
||||
public static final String PERSISTENCE_FILE_MIC_MUTE_CAM_UNMUTE =
|
||||
"SensorPrivacyServiceMockingTest/persisted_file_micMute_camUnmute.xml";
|
||||
public static final String PERSISTENCE_FILE_MIC_UNMUTE_CAM_MUTE =
|
||||
"SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camMute.xml";
|
||||
public static final String PERSISTENCE_FILE_MIC_UNMUTE_CAM_UNMUTE =
|
||||
"SensorPrivacyServiceMockingTest/persisted_file_micUnmute_camUnmute.xml";
|
||||
|
||||
private Context mContext;
|
||||
@Mock
|
||||
private AppOpsManager mMockedAppOpsManager;
|
||||
@Mock
|
||||
private AppOpsManagerInternal mMockedAppOpsManagerInternal;
|
||||
@Mock
|
||||
private UserManagerInternal mMockedUserManagerInternal;
|
||||
@Mock
|
||||
private ActivityManager mMockedActivityManager;
|
||||
@@ -134,13 +154,103 @@ public class SensorPrivacyServiceMockingTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceInit_AppOpsRestricted_micMute_camMute() throws IOException {
|
||||
testServiceInit_AppOpsRestricted(PERSISTENCE_FILE_MIC_MUTE_CAM_MUTE, true, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceInit_AppOpsRestricted_micMute_camUnmute() throws IOException {
|
||||
testServiceInit_AppOpsRestricted(PERSISTENCE_FILE_MIC_MUTE_CAM_UNMUTE, true, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceInit_AppOpsRestricted_micUnmute_camMute() throws IOException {
|
||||
testServiceInit_AppOpsRestricted(PERSISTENCE_FILE_MIC_UNMUTE_CAM_MUTE, false, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testServiceInit_AppOpsRestricted_micUnmute_camUnmute() throws IOException {
|
||||
testServiceInit_AppOpsRestricted(PERSISTENCE_FILE_MIC_UNMUTE_CAM_UNMUTE, false, false);
|
||||
}
|
||||
|
||||
private void testServiceInit_AppOpsRestricted(String persistenceFileMicMuteCamMute,
|
||||
boolean expectedMicState, boolean expectedCamState)
|
||||
throws IOException {
|
||||
MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
|
||||
.initMocks(this)
|
||||
.strictness(Strictness.WARN)
|
||||
.spyStatic(LocalServices.class)
|
||||
.spyStatic(Environment.class)
|
||||
.startMocking();
|
||||
|
||||
try {
|
||||
mContext = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
spyOn(mContext);
|
||||
|
||||
doReturn(mMockedAppOpsManager).when(mContext).getSystemService(AppOpsManager.class);
|
||||
doReturn(mMockedAppOpsManagerInternal)
|
||||
.when(() -> LocalServices.getService(AppOpsManagerInternal.class));
|
||||
doReturn(mMockedUserManagerInternal)
|
||||
.when(() -> LocalServices.getService(UserManagerInternal.class));
|
||||
doReturn(mMockedActivityManager).when(mContext).getSystemService(ActivityManager.class);
|
||||
doReturn(mMockedActivityTaskManager)
|
||||
.when(mContext).getSystemService(ActivityTaskManager.class);
|
||||
doReturn(mMockedTelephonyManager).when(mContext).getSystemService(
|
||||
TelephonyManager.class);
|
||||
|
||||
String dataDir = mContext.getApplicationInfo().dataDir;
|
||||
doReturn(new File(dataDir)).when(() -> Environment.getDataSystemDirectory());
|
||||
|
||||
File onDeviceFile = new File(dataDir, "sensor_privacy.xml");
|
||||
onDeviceFile.delete();
|
||||
|
||||
doReturn(new int[]{0}).when(mMockedUserManagerInternal).getUserIds();
|
||||
doReturn(ExtendedMockito.mock(UserInfo.class)).when(mMockedUserManagerInternal)
|
||||
.getUserInfo(0);
|
||||
|
||||
CompletableFuture<Boolean> micState = new CompletableFuture<>();
|
||||
CompletableFuture<Boolean> camState = new CompletableFuture<>();
|
||||
doAnswer(invocation -> {
|
||||
int code = invocation.getArgument(0);
|
||||
boolean restricted = invocation.getArgument(1);
|
||||
if (code == AppOpsManager.OP_RECORD_AUDIO) {
|
||||
micState.complete(restricted);
|
||||
} else if (code == AppOpsManager.OP_CAMERA) {
|
||||
camState.complete(restricted);
|
||||
}
|
||||
return null;
|
||||
}).when(mMockedAppOpsManagerInternal).setGlobalRestriction(anyInt(), anyBoolean(),
|
||||
any());
|
||||
|
||||
initServiceWithPersistenceFile(onDeviceFile, persistenceFileMicMuteCamMute, 0);
|
||||
|
||||
Assert.assertTrue(micState.join() == expectedMicState);
|
||||
Assert.assertTrue(camState.join() == expectedCamState);
|
||||
|
||||
} finally {
|
||||
mockitoSession.finishMocking();
|
||||
}
|
||||
}
|
||||
|
||||
private void initServiceWithPersistenceFile(File onDeviceFile,
|
||||
String persistenceFilePath) throws IOException {
|
||||
initServiceWithPersistenceFile(onDeviceFile, persistenceFilePath, -1);
|
||||
}
|
||||
|
||||
private void initServiceWithPersistenceFile(File onDeviceFile,
|
||||
String persistenceFilePath, int startingUserId) throws IOException {
|
||||
if (persistenceFilePath != null) {
|
||||
Files.copy(mContext.getAssets().open(persistenceFilePath),
|
||||
onDeviceFile.toPath());
|
||||
}
|
||||
new SensorPrivacyService(mContext);
|
||||
SensorPrivacyService service = new SensorPrivacyService(mContext);
|
||||
if (startingUserId != -1) {
|
||||
SystemService.TargetUser mockedTargetUser =
|
||||
ExtendedMockito.mock(SystemService.TargetUser.class);
|
||||
doReturn(startingUserId).when(mockedTargetUser).getUserIdentifier();
|
||||
service.onUserStarting(mockedTargetUser);
|
||||
}
|
||||
onDeviceFile.delete();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user