Merge "Only honor passed-in userid value if work profile flag enabled" into tm-qpr-dev am: 6af3a82437

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/20303911

Change-Id: I851608aa817489e917af9b7aad7157ac3e695755
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Matt Casey
2022-11-01 15:34:57 +00:00
committed by Automerger Merge Worker
4 changed files with 82 additions and 11 deletions

View File

@@ -38,6 +38,8 @@ import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.exifinterface.media.ExifInterface; import androidx.exifinterface.media.ExifInterface;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
@@ -85,10 +87,12 @@ class ImageExporter {
private final ContentResolver mResolver; private final ContentResolver mResolver;
private CompressFormat mCompressFormat = CompressFormat.PNG; private CompressFormat mCompressFormat = CompressFormat.PNG;
private int mQuality = 100; private int mQuality = 100;
private final FeatureFlags mFlags;
@Inject @Inject
ImageExporter(ContentResolver resolver) { ImageExporter(ContentResolver resolver, FeatureFlags flags) {
mResolver = resolver; mResolver = resolver;
mFlags = flags;
} }
/** /**
@@ -161,7 +165,7 @@ class ImageExporter {
ZonedDateTime captureTime, UserHandle owner) { ZonedDateTime captureTime, UserHandle owner) {
final Task task = new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat, final Task task = new Task(mResolver, requestId, bitmap, captureTime, mCompressFormat,
mQuality, /* publish */ true, owner); mQuality, /* publish */ true, owner, mFlags);
return CallbackToFutureAdapter.getFuture( return CallbackToFutureAdapter.getFuture(
(completer) -> { (completer) -> {
@@ -209,9 +213,11 @@ class ImageExporter {
private final UserHandle mOwner; private final UserHandle mOwner;
private final String mFileName; private final String mFileName;
private final boolean mPublish; private final boolean mPublish;
private final FeatureFlags mFlags;
Task(ContentResolver resolver, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime, Task(ContentResolver resolver, UUID requestId, Bitmap bitmap, ZonedDateTime captureTime,
CompressFormat format, int quality, boolean publish, UserHandle owner) { CompressFormat format, int quality, boolean publish, UserHandle owner,
FeatureFlags flags) {
mResolver = resolver; mResolver = resolver;
mRequestId = requestId; mRequestId = requestId;
mBitmap = bitmap; mBitmap = bitmap;
@@ -221,6 +227,7 @@ class ImageExporter {
mOwner = owner; mOwner = owner;
mFileName = createFilename(mCaptureTime, mFormat); mFileName = createFilename(mCaptureTime, mFormat);
mPublish = publish; mPublish = publish;
mFlags = flags;
} }
public Result execute() throws ImageExportException, InterruptedException { public Result execute() throws ImageExportException, InterruptedException {
@@ -234,7 +241,7 @@ class ImageExporter {
start = Instant.now(); start = Instant.now();
} }
uri = createEntry(mResolver, mFormat, mCaptureTime, mFileName, mOwner); uri = createEntry(mResolver, mFormat, mCaptureTime, mFileName, mOwner, mFlags);
throwIfInterrupted(); throwIfInterrupted();
writeImage(mResolver, mBitmap, mFormat, mQuality, uri); writeImage(mResolver, mBitmap, mFormat, mQuality, uri);
@@ -278,13 +285,15 @@ class ImageExporter {
} }
private static Uri createEntry(ContentResolver resolver, CompressFormat format, private static Uri createEntry(ContentResolver resolver, CompressFormat format,
ZonedDateTime time, String fileName, UserHandle owner) throws ImageExportException { ZonedDateTime time, String fileName, UserHandle owner, FeatureFlags flags)
throws ImageExportException {
Trace.beginSection("ImageExporter_createEntry"); Trace.beginSection("ImageExporter_createEntry");
try { try {
final ContentValues values = createMetadata(time, format, fileName); final ContentValues values = createMetadata(time, format, fileName);
Uri baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; Uri baseUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
if (UserHandle.myUserId() != owner.getIdentifier()) { if (flags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY)
&& UserHandle.myUserId() != owner.getIdentifier()) {
baseUri = ContentProvider.maybeAddUserId(baseUri, owner.getIdentifier()); baseUri = ContentProvider.maybeAddUserId(baseUri, owner.getIdentifier());
} }
Uri uri = resolver.insert(baseUri, values); Uri uri = resolver.insert(baseUri, values);

View File

@@ -1043,8 +1043,13 @@ public class ScreenshotController {
} }
private boolean isUserSetupComplete(UserHandle owner) { private boolean isUserSetupComplete(UserHandle owner) {
return Settings.Secure.getInt(mContext.createContextAsUser(owner, 0) if (mFlags.isEnabled(SCREENSHOT_WORK_PROFILE_POLICY)) {
.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1; return Settings.Secure.getInt(mContext.createContextAsUser(owner, 0)
.getContentResolver(), SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
} else {
return Settings.Secure.getInt(mContext.getContentResolver(),
SETTINGS_SECURE_USER_SETUP_COMPLETE, 0) == 1;
}
} }
/** /**

View File

@@ -23,6 +23,7 @@ import static org.junit.Assert.assertTrue;
import static java.nio.charset.StandardCharsets.US_ASCII; import static java.nio.charset.StandardCharsets.US_ASCII;
import android.content.ContentProvider;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.ContentValues; import android.content.ContentValues;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@@ -31,9 +32,11 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Paint; import android.graphics.Paint;
import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.Process; import android.os.Process;
import android.os.UserHandle;
import android.provider.MediaStore; import android.provider.MediaStore;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
@@ -41,11 +44,18 @@ import androidx.exifinterface.media.ExifInterface;
import androidx.test.filters.MediumTest; import androidx.test.filters.MediumTest;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.Flags;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
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.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
@@ -60,7 +70,6 @@ import java.util.concurrent.Executor;
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
@MediumTest // file I/O @MediumTest // file I/O
public class ImageExporterTest extends SysuiTestCase { public class ImageExporterTest extends SysuiTestCase {
/** Executes directly in the caller's thread */ /** Executes directly in the caller's thread */
private static final Executor DIRECT_EXECUTOR = Runnable::run; private static final Executor DIRECT_EXECUTOR = Runnable::run;
private static final byte[] EXIF_FILE_TAG = "Exif\u0000\u0000".getBytes(US_ASCII); private static final byte[] EXIF_FILE_TAG = "Exif\u0000\u0000".getBytes(US_ASCII);
@@ -68,6 +77,15 @@ public class ImageExporterTest extends SysuiTestCase {
private static final ZonedDateTime CAPTURE_TIME = private static final ZonedDateTime CAPTURE_TIME =
ZonedDateTime.of(LocalDateTime.of(2020, 12, 15, 13, 15), ZoneId.of("EST")); ZonedDateTime.of(LocalDateTime.of(2020, 12, 15, 13, 15), ZoneId.of("EST"));
private FakeFeatureFlags mFeatureFlags = new FakeFeatureFlags();
@Mock
private ContentResolver mMockContentResolver;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Test @Test
public void testImageFilename() { public void testImageFilename() {
assertEquals("image file name", "Screenshot_20201215-131500.png", assertEquals("image file name", "Screenshot_20201215-131500.png",
@@ -92,7 +110,8 @@ public class ImageExporterTest extends SysuiTestCase {
@Test @Test
public void testImageExport() throws ExecutionException, InterruptedException, IOException { public void testImageExport() throws ExecutionException, InterruptedException, IOException {
ContentResolver contentResolver = mContext.getContentResolver(); ContentResolver contentResolver = mContext.getContentResolver();
ImageExporter exporter = new ImageExporter(contentResolver); mFeatureFlags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, true);
ImageExporter exporter = new ImageExporter(contentResolver, mFeatureFlags);
UUID requestId = UUID.fromString("3c11da99-9284-4863-b1d5-6f3684976814"); UUID requestId = UUID.fromString("3c11da99-9284-4863-b1d5-6f3684976814");
Bitmap original = createCheckerBitmap(10, 10, 10); Bitmap original = createCheckerBitmap(10, 10, 10);
@@ -168,6 +187,44 @@ public class ImageExporterTest extends SysuiTestCase {
values.getAsLong(MediaStore.MediaColumns.DATE_EXPIRES)); values.getAsLong(MediaStore.MediaColumns.DATE_EXPIRES));
} }
@Test
public void testSetUser() {
mFeatureFlags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, true);
ImageExporter exporter = new ImageExporter(mMockContentResolver, mFeatureFlags);
UserHandle imageUserHande = UserHandle.of(10);
ArgumentCaptor<Uri> uriCaptor = ArgumentCaptor.forClass(Uri.class);
// Capture the URI and then return null to bail out of export.
Mockito.when(mMockContentResolver.insert(uriCaptor.capture(), Mockito.any())).thenReturn(
null);
exporter.export(DIRECT_EXECUTOR, UUID.fromString("3c11da99-9284-4863-b1d5-6f3684976814"),
null, CAPTURE_TIME, imageUserHande);
Uri expected = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
expected = ContentProvider.maybeAddUserId(expected, imageUserHande.getIdentifier());
assertEquals(expected, uriCaptor.getValue());
}
@Test
public void testSetUser_noWorkProfile() {
mFeatureFlags.set(Flags.SCREENSHOT_WORK_PROFILE_POLICY, false);
ImageExporter exporter = new ImageExporter(mMockContentResolver, mFeatureFlags);
UserHandle imageUserHandle = UserHandle.of(10);
ArgumentCaptor<Uri> uriCaptor = ArgumentCaptor.forClass(Uri.class);
// Capture the URI and then return null to bail out of export.
Mockito.when(mMockContentResolver.insert(uriCaptor.capture(), Mockito.any())).thenReturn(
null);
exporter.export(DIRECT_EXECUTOR, UUID.fromString("3c11da99-9284-4863-b1d5-6f3684976814"),
null, CAPTURE_TIME, imageUserHandle);
// The user handle should be ignored here since the flag is off.
assertEquals(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, uriCaptor.getValue());
}
@SuppressWarnings("SameParameterValue") @SuppressWarnings("SameParameterValue")
private Bitmap createCheckerBitmap(int tileSize, int w, int h) { private Bitmap createCheckerBitmap(int tileSize, int w, int h) {
Bitmap bitmap = Bitmap.createBitmap(w * tileSize, h * tileSize, Bitmap.Config.ARGB_8888); Bitmap bitmap = Bitmap.createBitmap(w * tileSize, h * tileSize, Bitmap.Config.ARGB_8888);

View File

@@ -62,7 +62,7 @@ import org.mockito.Mockito.verifyZeroInteractions
import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.`when` as whenever
private const val USER_ID = 1 private const val USER_ID = 1
private const val TASK_ID = 1 private const val TASK_ID = 11
@RunWith(AndroidTestingRunner::class) @RunWith(AndroidTestingRunner::class)
@SmallTest @SmallTest