Merge changes from topic "fix-flake" into udc-dev am: 334b55d700

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

Change-Id: I2ea2e5c21f74d9d6bf8fc9982671d5d43df7f1aa
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Ajinkya Chalke
2023-03-06 16:49:41 +00:00
committed by Automerger Merge Worker
14 changed files with 119 additions and 112 deletions

View File

@@ -23,9 +23,9 @@ import com.android.systemui.hdmi.HdmiCecSetMenuLanguageActivity;
import com.android.systemui.keyguard.WorkLockActivity; import com.android.systemui.keyguard.WorkLockActivity;
import com.android.systemui.people.PeopleSpaceActivity; import com.android.systemui.people.PeopleSpaceActivity;
import com.android.systemui.people.widget.LaunchConversationActivity; import com.android.systemui.people.widget.LaunchConversationActivity;
import com.android.systemui.screenshot.AppClipsActivity;
import com.android.systemui.screenshot.AppClipsTrampolineActivity;
import com.android.systemui.screenshot.LongScreenshotActivity; import com.android.systemui.screenshot.LongScreenshotActivity;
import com.android.systemui.screenshot.appclips.AppClipsActivity;
import com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity;
import com.android.systemui.sensorprivacy.SensorUseStartedActivity; import com.android.systemui.sensorprivacy.SensorUseStartedActivity;
import com.android.systemui.sensorprivacy.television.TvSensorPrivacyChangedActivity; import com.android.systemui.sensorprivacy.television.TvSensorPrivacyChangedActivity;
import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity; import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity;

View File

@@ -17,7 +17,7 @@ package com.android.systemui.notetask
import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceConfig import com.android.systemui.notetask.quickaffordance.NoteTaskQuickAffordanceConfig
import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity import com.android.systemui.notetask.shortcut.LaunchNoteTaskActivity
import com.android.systemui.screenshot.AppClipsTrampolineActivity import com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity
/** /**
* Supported entry points for [NoteTaskController.showNoteTask]. * Supported entry points for [NoteTaskController.showNoteTask].

View File

@@ -57,7 +57,8 @@ import java.util.concurrent.Executor;
import javax.inject.Inject; import javax.inject.Inject;
class ImageExporter { /** A class to help with exporting screenshot to storage. */
public class ImageExporter {
private static final String TAG = LogConfig.logTag(ImageExporter.class); private static final String TAG = LogConfig.logTag(ImageExporter.class);
static final Duration PENDING_ENTRY_TTL = Duration.ofHours(24); static final Duration PENDING_ENTRY_TTL = Duration.ofHours(24);
@@ -90,7 +91,7 @@ class ImageExporter {
private final FeatureFlags mFlags; private final FeatureFlags mFlags;
@Inject @Inject
ImageExporter(ContentResolver resolver, FeatureFlags flags) { public ImageExporter(ContentResolver resolver, FeatureFlags flags) {
mResolver = resolver; mResolver = resolver;
mFlags = flags; mFlags = flags;
} }
@@ -148,7 +149,7 @@ class ImageExporter {
* *
* @return a listenable future result * @return a listenable future result
*/ */
ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap, public ListenableFuture<Result> export(Executor executor, UUID requestId, Bitmap bitmap,
UserHandle owner) { UserHandle owner) {
return export(executor, requestId, bitmap, ZonedDateTime.now(), owner); return export(executor, requestId, bitmap, ZonedDateTime.now(), owner);
} }
@@ -181,13 +182,14 @@ class ImageExporter {
); );
} }
static class Result { /** The result returned by the task exporting screenshots to storage. */
Uri uri; public static class Result {
UUID requestId; public Uri uri;
String fileName; public UUID requestId;
long timestamp; public String fileName;
CompressFormat format; public long timestamp;
boolean published; public CompressFormat format;
public boolean published;
@Override @Override
public String toString() { public String toString() {

View File

@@ -93,13 +93,7 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "User has discarded the result of a long screenshot") @UiEvent(doc = "User has discarded the result of a long screenshot")
SCREENSHOT_LONG_SCREENSHOT_EXIT(911), SCREENSHOT_LONG_SCREENSHOT_EXIT(911),
@UiEvent(doc = "A screenshot has been taken and saved to work profile") @UiEvent(doc = "A screenshot has been taken and saved to work profile")
SCREENSHOT_SAVED_TO_WORK_PROFILE(1240), SCREENSHOT_SAVED_TO_WORK_PROFILE(1240);
@UiEvent(doc = "Notes application triggered the screenshot for notes")
SCREENSHOT_FOR_NOTE_TRIGGERED(1308),
@UiEvent(doc = "User accepted the screenshot to be sent to the notes app")
SCREENSHOT_FOR_NOTE_ACCEPTED(1309),
@UiEvent(doc = "User cancelled the screenshot for notes app flow")
SCREENSHOT_FOR_NOTE_CANCELLED(1310);
private final int mId; private final int mId;

View File

@@ -14,15 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.systemui.screenshot; package com.android.systemui.screenshot.appclips;
import static com.android.systemui.screenshot.AppClipsTrampolineActivity.ACTION_FINISH_FROM_TRAMPOLINE; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_ACCEPTED;
import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_CALLING_PACKAGE_NAME; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_CANCELLED;
import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_RESULT_RECEIVER; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.ACTION_FINISH_FROM_TRAMPOLINE;
import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_CALLING_PACKAGE_NAME;
import static com.android.systemui.screenshot.AppClipsTrampolineActivity.PERMISSION_SELF; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_RESULT_RECEIVER;
import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_ACCEPTED; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_CANCELLED; import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.PERMISSION_SELF;
import android.app.Activity; import android.app.Activity;
import android.content.BroadcastReceiver; import android.content.BroadcastReceiver;
@@ -52,6 +52,8 @@ import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLogger.UiEventEnum; import com.android.internal.logging.UiEventLogger.UiEventEnum;
import com.android.settingslib.Utils; import com.android.settingslib.Utils;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.screenshot.CropView;
import com.android.systemui.screenshot.MagnifierView;
import com.android.systemui.settings.UserTracker; import com.android.systemui.settings.UserTracker;
import javax.inject.Inject; import javax.inject.Inject;

View File

@@ -32,12 +32,12 @@ import javax.inject.Inject;
/** An intermediary singleton object to help communicating with the cross process service. */ /** An intermediary singleton object to help communicating with the cross process service. */
@SysUISingleton @SysUISingleton
public class AppClipsCrossProcessHelper { class AppClipsCrossProcessHelper {
private final ServiceConnector<IAppClipsScreenshotHelperService> mProxyConnector; private final ServiceConnector<IAppClipsScreenshotHelperService> mProxyConnector;
@Inject @Inject
public AppClipsCrossProcessHelper(@Application Context context) { AppClipsCrossProcessHelper(@Application Context context) {
mProxyConnector = new ServiceConnector.Impl<IAppClipsScreenshotHelperService>(context, mProxyConnector = new ServiceConnector.Impl<IAppClipsScreenshotHelperService>(context,
new Intent(context, AppClipsScreenshotHelperService.class), new Intent(context, AppClipsScreenshotHelperService.class),
Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
@@ -52,7 +52,7 @@ public class AppClipsCrossProcessHelper {
* pass around but not a {@link Bitmap}. * pass around but not a {@link Bitmap}.
*/ */
@Nullable @Nullable
public Bitmap takeScreenshot() { Bitmap takeScreenshot() {
try { try {
AndroidFuture<ScreenshotHardwareBufferInternal> future = AndroidFuture<ScreenshotHardwareBufferInternal> future =
mProxyConnector.postForResult( mProxyConnector.postForResult(

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.screenshot.appclips;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
enum AppClipsEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "Notes application triggered the screenshot for notes")
SCREENSHOT_FOR_NOTE_TRIGGERED(1308),
@UiEvent(doc = "User accepted the screenshot to be sent to the notes app")
SCREENSHOT_FOR_NOTE_ACCEPTED(1309),
@UiEvent(doc = "User cancelled the screenshot for notes app flow")
SCREENSHOT_FOR_NOTE_CANCELLED(1310);
private final int mId;
AppClipsEvent(int id) {
mId = id;
}
@Override
public int getId() {
return mId;
}
}

View File

@@ -24,7 +24,6 @@ import android.window.ScreenCapture.ScreenshotSync;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import com.android.systemui.screenshot.AppClipsActivity;
import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.bubbles.Bubbles;
import java.util.Optional; import java.util.Optional;

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.systemui.screenshot; package com.android.systemui.screenshot.appclips;
import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN; import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_BLOCKED_BY_ADMIN;
import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED; import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
@@ -24,7 +24,7 @@ import static android.content.Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE;
import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION; import static android.content.Intent.FLAG_GRANT_READ_URI_PERMISSION;
import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS; import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_TRIGGERED; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_TRIGGERED;
import android.app.Activity; import android.app.Activity;
import android.app.admin.DevicePolicyManager; import android.app.admin.DevicePolicyManager;

View File

@@ -14,12 +14,10 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.systemui.screenshot; package com.android.systemui.screenshot.appclips;
import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED; import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
import static androidx.annotation.VisibleForTesting.PACKAGE_PRIVATE;
import android.content.Intent; import android.content.Intent;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.HardwareRenderer; import android.graphics.HardwareRenderer;
@@ -31,7 +29,6 @@ import android.net.Uri;
import android.os.Process; import android.os.Process;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.LiveData; import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel; import androidx.lifecycle.ViewModel;
@@ -39,11 +36,10 @@ import androidx.lifecycle.ViewModelProvider;
import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.screenshot.appclips.AppClipsCrossProcessHelper; import com.android.systemui.screenshot.ImageExporter;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import java.time.ZonedDateTime;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@@ -52,8 +48,7 @@ import java.util.concurrent.Executor;
import javax.inject.Inject; import javax.inject.Inject;
/** A {@link ViewModel} to help with the App Clips screenshot flow. */ /** A {@link ViewModel} to help with the App Clips screenshot flow. */
@VisibleForTesting(otherwise = PACKAGE_PRIVATE) final class AppClipsViewModel extends ViewModel {
public final class AppClipsViewModel extends ViewModel {
private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
private final ImageExporter mImageExporter; private final ImageExporter mImageExporter;
@@ -80,8 +75,7 @@ public final class AppClipsViewModel extends ViewModel {
} }
/** Grabs a screenshot and updates the {@link Bitmap} set in screenshot {@link LiveData}. */ /** Grabs a screenshot and updates the {@link Bitmap} set in screenshot {@link LiveData}. */
@VisibleForTesting(otherwise = PACKAGE_PRIVATE) void performScreenshot() {
public void performScreenshot() {
mBgExecutor.execute(() -> { mBgExecutor.execute(() -> {
Bitmap screenshot = mAppClipsCrossProcessHelper.takeScreenshot(); Bitmap screenshot = mAppClipsCrossProcessHelper.takeScreenshot();
mMainExecutor.execute(() -> { mMainExecutor.execute(() -> {
@@ -95,14 +89,12 @@ public final class AppClipsViewModel extends ViewModel {
} }
/** Returns a {@link LiveData} that holds the captured screenshot. */ /** Returns a {@link LiveData} that holds the captured screenshot. */
@VisibleForTesting(otherwise = PACKAGE_PRIVATE) LiveData<Bitmap> getScreenshot() {
public LiveData<Bitmap> getScreenshot() {
return mScreenshotLiveData; return mScreenshotLiveData;
} }
/** Returns a {@link LiveData} that holds the {@link Uri} where screenshot is saved. */ /** Returns a {@link LiveData} that holds the {@link Uri} where screenshot is saved. */
@VisibleForTesting(otherwise = PACKAGE_PRIVATE) LiveData<Uri> getResultLiveData() {
public LiveData<Uri> getResultLiveData() {
return mResultLiveData; return mResultLiveData;
} }
@@ -110,8 +102,7 @@ public final class AppClipsViewModel extends ViewModel {
* Returns a {@link LiveData} that holds the error codes for * Returns a {@link LiveData} that holds the error codes for
* {@link Intent#EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE}. * {@link Intent#EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE}.
*/ */
@VisibleForTesting(otherwise = PACKAGE_PRIVATE) LiveData<Integer> getErrorLiveData() {
public LiveData<Integer> getErrorLiveData() {
return mErrorLiveData; return mErrorLiveData;
} }
@@ -119,8 +110,7 @@ public final class AppClipsViewModel extends ViewModel {
* Saves the provided {@link Drawable} to storage then informs the result {@link Uri} to * Saves the provided {@link Drawable} to storage then informs the result {@link Uri} to
* {@link LiveData}. * {@link LiveData}.
*/ */
@VisibleForTesting(otherwise = PACKAGE_PRIVATE) void saveScreenshotThenFinish(Drawable screenshotDrawable, Rect bounds) {
public void saveScreenshotThenFinish(Drawable screenshotDrawable, Rect bounds) {
mBgExecutor.execute(() -> { mBgExecutor.execute(() -> {
// Render the screenshot bitmap in background. // Render the screenshot bitmap in background.
Bitmap screenshotBitmap = renderBitmap(screenshotDrawable, bounds); Bitmap screenshotBitmap = renderBitmap(screenshotDrawable, bounds);
@@ -128,7 +118,7 @@ public final class AppClipsViewModel extends ViewModel {
// Export and save the screenshot in background. // Export and save the screenshot in background.
// TODO(b/267310185): Save to work profile UserHandle. // TODO(b/267310185): Save to work profile UserHandle.
ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export( ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
mBgExecutor, UUID.randomUUID(), screenshotBitmap, ZonedDateTime.now(), mBgExecutor, UUID.randomUUID(), screenshotBitmap,
Process.myUserHandle()); Process.myUserHandle());
// Get the result and update state on main thread. // Get the result and update state on main thread.
@@ -160,8 +150,7 @@ public final class AppClipsViewModel extends ViewModel {
} }
/** Helper factory to help with injecting {@link AppClipsViewModel}. */ /** Helper factory to help with injecting {@link AppClipsViewModel}. */
@VisibleForTesting(otherwise = PACKAGE_PRIVATE) static final class Factory implements ViewModelProvider.Factory {
public static final class Factory implements ViewModelProvider.Factory {
private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; private final AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
private final ImageExporter mImageExporter; private final ImageExporter mImageExporter;

View File

@@ -28,7 +28,7 @@ import android.window.ScreenCapture.ScreenshotHardwareBuffer;
* An internal version of {@link ScreenshotHardwareBuffer} that helps with parceling the information * An internal version of {@link ScreenshotHardwareBuffer} that helps with parceling the information
* necessary for creating a {@link Bitmap}. * necessary for creating a {@link Bitmap}.
*/ */
public class ScreenshotHardwareBufferInternal implements Parcelable { class ScreenshotHardwareBufferInternal implements Parcelable {
public static final Creator<ScreenshotHardwareBufferInternal> CREATOR = public static final Creator<ScreenshotHardwareBufferInternal> CREATOR =
new Creator<>() { new Creator<>() {
@@ -45,7 +45,7 @@ public class ScreenshotHardwareBufferInternal implements Parcelable {
private final HardwareBuffer mHardwareBuffer; private final HardwareBuffer mHardwareBuffer;
private final ParcelableColorSpace mParcelableColorSpace; private final ParcelableColorSpace mParcelableColorSpace;
public ScreenshotHardwareBufferInternal( ScreenshotHardwareBufferInternal(
ScreenshotHardwareBuffer screenshotHardwareBuffer) { ScreenshotHardwareBuffer screenshotHardwareBuffer) {
mHardwareBuffer = screenshotHardwareBuffer.getHardwareBuffer(); mHardwareBuffer = screenshotHardwareBuffer.getHardwareBuffer();
mParcelableColorSpace = new ParcelableColorSpace( mParcelableColorSpace = new ParcelableColorSpace(
@@ -65,7 +65,7 @@ public class ScreenshotHardwareBufferInternal implements Parcelable {
* {@link Bitmap#wrapHardwareBuffer(HardwareBuffer, ColorSpace)} and * {@link Bitmap#wrapHardwareBuffer(HardwareBuffer, ColorSpace)} and
* {@link HardwareBuffer#close()} for more information. * {@link HardwareBuffer#close()} for more information.
*/ */
public Bitmap createBitmapThenCloseBuffer() { Bitmap createBitmapThenCloseBuffer() {
Bitmap bitmap = Bitmap.wrapHardwareBuffer(mHardwareBuffer, Bitmap bitmap = Bitmap.wrapHardwareBuffer(mHardwareBuffer,
mParcelableColorSpace.getColorSpace()); mParcelableColorSpace.getColorSpace());
mHardwareBuffer.close(); mHardwareBuffer.close();

View File

@@ -18,14 +18,14 @@ package com.android.systemui.screenshot.appclips;
import static android.app.Activity.RESULT_OK; import static android.app.Activity.RESULT_OK;
import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_ACCEPTED; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_ACCEPTED;
import static com.android.systemui.screenshot.ScreenshotEvent.SCREENSHOT_FOR_NOTE_CANCELLED; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_CANCELLED;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static com.google.common.util.concurrent.MoreExecutors.directExecutor;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -34,36 +34,35 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.ApplicationInfoFlags; import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Parcel; import android.os.Parcel;
import android.os.ResultReceiver; import android.os.ResultReceiver;
import android.os.UserHandle;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.lifecycle.MutableLiveData;
import androidx.test.rule.ActivityTestRule; import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.intercepting.SingleActivityFactory; import androidx.test.runner.intercepting.SingleActivityFactory;
import com.android.internal.logging.UiEventLogger; import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R; import com.android.systemui.R;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.screenshot.AppClipsActivity; import com.android.systemui.screenshot.ImageExporter;
import com.android.systemui.screenshot.AppClipsTrampolineActivity;
import com.android.systemui.screenshot.AppClipsViewModel;
import com.android.systemui.settings.UserTracker; import com.android.systemui.settings.UserTracker;
import com.google.common.util.concurrent.Futures;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.util.UUID;
import java.util.concurrent.Executor;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@RunWith(AndroidTestingRunner.class) @RunWith(AndroidTestingRunner.class)
@@ -78,18 +77,16 @@ public final class AppClipsActivityTest extends SysuiTestCase {
private static final String TEST_CALLING_PACKAGE = "test-calling-package"; private static final String TEST_CALLING_PACKAGE = "test-calling-package";
@Mock @Mock
private AppClipsViewModel.Factory mViewModelFactory; private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
@Mock
private ImageExporter mImageExporter;
@Mock @Mock
private PackageManager mPackageManager; private PackageManager mPackageManager;
@Mock @Mock
private UserTracker mUserTracker; private UserTracker mUserTracker;
@Mock @Mock
private UiEventLogger mUiEventLogger; private UiEventLogger mUiEventLogger;
@Mock
private AppClipsViewModel mViewModel;
private MutableLiveData<Bitmap> mScreenshotLiveData;
private MutableLiveData<Uri> mResultLiveData;
private AppClipsActivity mActivity; private AppClipsActivity mActivity;
// Using the deprecated ActivityTestRule and SingleActivityFactory to help with injecting mocks. // Using the deprecated ActivityTestRule and SingleActivityFactory to help with injecting mocks.
@@ -97,8 +94,11 @@ public final class AppClipsActivityTest extends SysuiTestCase {
new SingleActivityFactory<>(AppClipsActivityTestable.class) { new SingleActivityFactory<>(AppClipsActivityTestable.class) {
@Override @Override
protected AppClipsActivityTestable create(Intent unUsed) { protected AppClipsActivityTestable create(Intent unUsed) {
return new AppClipsActivityTestable(mViewModelFactory, mPackageManager, return new AppClipsActivityTestable(
mUserTracker, mUiEventLogger); new AppClipsViewModel.Factory(mAppClipsCrossProcessHelper,
mImageExporter, getContext().getMainExecutor(),
directExecutor()), mPackageManager, mUserTracker,
mUiEventLogger);
} }
}; };
@@ -110,29 +110,17 @@ public final class AppClipsActivityTest extends SysuiTestCase {
public void setUp() throws PackageManager.NameNotFoundException { public void setUp() throws PackageManager.NameNotFoundException {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mScreenshotLiveData = new MutableLiveData<>();
mResultLiveData = new MutableLiveData<>();
MutableLiveData<Integer> errorLiveData = new MutableLiveData<>();
when(mViewModelFactory.create(any(Class.class))).thenReturn(mViewModel);
when(mViewModel.getScreenshot()).thenReturn(mScreenshotLiveData);
when(mViewModel.getResultLiveData()).thenReturn(mResultLiveData);
when(mViewModel.getErrorLiveData()).thenReturn(errorLiveData);
when(mUserTracker.getUserId()).thenReturn(TEST_USER_ID); when(mUserTracker.getUserId()).thenReturn(TEST_USER_ID);
ApplicationInfo applicationInfo = new ApplicationInfo(); ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.uid = TEST_UID; applicationInfo.uid = TEST_UID;
when(mPackageManager.getApplicationInfoAsUser(eq(TEST_CALLING_PACKAGE), when(mPackageManager.getApplicationInfoAsUser(eq(TEST_CALLING_PACKAGE),
any(ApplicationInfoFlags.class), eq(TEST_USER_ID))).thenReturn(applicationInfo); any(ApplicationInfoFlags.class), eq(TEST_USER_ID))).thenReturn(applicationInfo);
doAnswer(invocation -> { when(mAppClipsCrossProcessHelper.takeScreenshot()).thenReturn(TEST_BITMAP);
runOnMainThread(() -> mScreenshotLiveData.setValue(TEST_BITMAP)); ImageExporter.Result result = new ImageExporter.Result();
return null; result.uri = TEST_URI;
}).when(mViewModel).performScreenshot(); when(mImageExporter.export(any(Executor.class), any(UUID.class), any(Bitmap.class),
doAnswer(invocation -> { any(UserHandle.class))).thenReturn(Futures.immediateFuture(result));
runOnMainThread(() -> mResultLiveData.setValue(TEST_URI));
return null;
}).when(mViewModel).saveScreenshotThenFinish(any(Drawable.class), any(Rect.class));
} }
@After @After
@@ -140,7 +128,6 @@ public final class AppClipsActivityTest extends SysuiTestCase {
mActivityRule.finishActivity(); mActivityRule.finishActivity();
} }
@Ignore("b/269403503")
@Test @Test
public void appClipsLaunched_screenshotDisplayed() { public void appClipsLaunched_screenshotDisplayed() {
launchActivity(); launchActivity();
@@ -148,7 +135,6 @@ public final class AppClipsActivityTest extends SysuiTestCase {
assertThat(((ImageView) mActivity.findViewById(R.id.preview)).getDrawable()).isNotNull(); assertThat(((ImageView) mActivity.findViewById(R.id.preview)).getDrawable()).isNotNull();
} }
@Ignore("b/269403503")
@Test @Test
public void screenshotDisplayed_userConsented_screenshotExportedSuccessfully() { public void screenshotDisplayed_userConsented_screenshotExportedSuccessfully() {
ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> { ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
@@ -168,7 +154,6 @@ public final class AppClipsActivityTest extends SysuiTestCase {
verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_ACCEPTED, TEST_UID, TEST_CALLING_PACKAGE); verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_ACCEPTED, TEST_UID, TEST_CALLING_PACKAGE);
} }
@Ignore("b/269403503")
@Test @Test
public void screenshotDisplayed_userDeclined() { public void screenshotDisplayed_userDeclined() {
ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> { ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {

View File

@@ -25,7 +25,8 @@ import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_WINDOW_MODE_UNSUPP
import static android.content.Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE; import static android.content.Intent.EXTRA_CAPTURE_CONTENT_FOR_NOTE_STATUS_CODE;
import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS; import static com.android.systemui.flags.Flags.SCREENSHOT_APP_CLIPS;
import static com.android.systemui.screenshot.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI; import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_TRIGGERED;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
@@ -59,8 +60,6 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags; import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.notetask.NoteTaskController; import com.android.systemui.notetask.NoteTaskController;
import com.android.systemui.screenshot.AppClipsTrampolineActivity;
import com.android.systemui.screenshot.ScreenshotEvent;
import com.android.systemui.settings.UserTracker; import com.android.systemui.settings.UserTracker;
import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.bubbles.Bubbles;
@@ -262,8 +261,7 @@ public final class AppClipsTrampolineActivityTest extends SysuiTestCase {
mActivityRule.launchActivity(mActivityIntent); mActivityRule.launchActivity(mActivityIntent);
waitForIdleSync(); waitForIdleSync();
verify(mUiEventLogger).log(ScreenshotEvent.SCREENSHOT_FOR_NOTE_TRIGGERED, TEST_UID, verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_TRIGGERED, TEST_UID, TEST_CALLING_PACKAGE);
TEST_CALLING_PACKAGE);
} }
private void mockToSatisfyAllPrerequisites() throws NameNotFoundException { private void mockToSatisfyAllPrerequisites() throws NameNotFoundException {

View File

@@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.android.systemui.screenshot; package com.android.systemui.screenshot.appclips;
import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED; import static android.content.Intent.CAPTURE_CONTENT_FOR_NOTE_FAILED;
@@ -36,7 +36,7 @@ import android.os.UserHandle;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.screenshot.appclips.AppClipsCrossProcessHelper; import com.android.systemui.screenshot.ImageExporter;
import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.Futures;
@@ -46,7 +46,6 @@ import org.junit.runner.RunWith;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.time.ZonedDateTime;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -62,7 +61,7 @@ public final class AppClipsViewModelTest extends SysuiTestCase {
@Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper; @Mock private AppClipsCrossProcessHelper mAppClipsCrossProcessHelper;
@Mock private ImageExporter mImageExporter; @Mock private ImageExporter mImageExporter;
private com.android.systemui.screenshot.AppClipsViewModel mViewModel; private AppClipsViewModel mViewModel;
@Before @Before
public void setUp() { public void setUp() {
@@ -99,8 +98,8 @@ public final class AppClipsViewModelTest extends SysuiTestCase {
@Test @Test
public void saveScreenshot_throwsError_shouldUpdateErrorWithFailed() { public void saveScreenshot_throwsError_shouldUpdateErrorWithFailed() {
when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any( when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null),
ZonedDateTime.class), any(UserHandle.class))).thenReturn( any(UserHandle.class))).thenReturn(
Futures.immediateFailedFuture(new ExecutionException(new Throwable()))); Futures.immediateFailedFuture(new ExecutionException(new Throwable())));
mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT); mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
@@ -113,8 +112,8 @@ public final class AppClipsViewModelTest extends SysuiTestCase {
@Test @Test
public void saveScreenshot_failsSilently_shouldUpdateErrorWithFailed() { public void saveScreenshot_failsSilently_shouldUpdateErrorWithFailed() {
when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any( when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null),
ZonedDateTime.class), any(UserHandle.class))).thenReturn( any(UserHandle.class))).thenReturn(
Futures.immediateFuture(new ImageExporter.Result())); Futures.immediateFuture(new ImageExporter.Result()));
mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT); mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
@@ -129,9 +128,8 @@ public final class AppClipsViewModelTest extends SysuiTestCase {
public void saveScreenshot_succeeds_shouldUpdateResultWithUri() { public void saveScreenshot_succeeds_shouldUpdateResultWithUri() {
ImageExporter.Result result = new ImageExporter.Result(); ImageExporter.Result result = new ImageExporter.Result();
result.uri = FAKE_URI; result.uri = FAKE_URI;
when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null), any( when(mImageExporter.export(any(Executor.class), any(UUID.class), eq(null),
ZonedDateTime.class), any(UserHandle.class))).thenReturn( any(UserHandle.class))).thenReturn(Futures.immediateFuture(result));
Futures.immediateFuture(result));
mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT); mViewModel.saveScreenshotThenFinish(FAKE_DRAWABLE, FAKE_RECT);
waitForIdleSync(); waitForIdleSync();