Fix long screenshots actions for work profile.

Use the ActionIntentExecutor for edit/share there as well.

Logic changes are flagged (everything outside of that is just parameter
passing).

Shared element transition from work profile long screenshots -> markup
wasn't working, so I've omitted it for now.

Bug: 231957192
Test: Manual testing with and without the flag, work and personal
profile long screenshots.

Change-Id: I6d035bfd1838900f8004dbb5bc8f9ae5411e960d
This commit is contained in:
Matt Casey
2022-10-18 19:22:56 +00:00
parent ad23a83ccf
commit 789872fb45
3 changed files with 85 additions and 55 deletions

View File

@@ -32,7 +32,7 @@ import android.view.WindowManagerGlobal
import com.android.internal.infra.ServiceConnector
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import javax.inject.Inject
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.CoroutineDispatcher
@@ -45,7 +45,7 @@ class ActionIntentExecutor
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
@Background private val bgDispatcher: CoroutineDispatcher,
@Main private val mainDispatcher: CoroutineDispatcher,
private val context: Context,
) {
/**
@@ -70,23 +70,21 @@ constructor(
userId: Int,
overrideTransition: Boolean,
) {
withContext(bgDispatcher) {
dismissKeyguard()
dismissKeyguard()
if (userId == UserHandle.myUserId()) {
context.startActivity(intent, bundle)
} else {
launchCrossProfileIntent(userId, intent, bundle)
}
if (userId == UserHandle.myUserId()) {
withContext(mainDispatcher) { context.startActivity(intent, bundle) }
} else {
launchCrossProfileIntent(userId, intent, bundle)
}
if (overrideTransition) {
val runner = RemoteAnimationAdapter(SCREENSHOT_REMOTE_RUNNER, 0, 0)
try {
WindowManagerGlobal.getWindowManagerService()
.overridePendingAppTransitionRemote(runner, Display.DEFAULT_DISPLAY)
} catch (e: Exception) {
Log.e(TAG, "Error overriding screenshot app transition", e)
}
if (overrideTransition) {
val runner = RemoteAnimationAdapter(SCREENSHOT_REMOTE_RUNNER, 0, 0)
try {
WindowManagerGlobal.getWindowManagerService()
.overridePendingAppTransitionRemote(runner, Display.DEFAULT_DISPLAY)
} catch (e: Exception) {
Log.e(TAG, "Error overriding screenshot app transition", e)
}
}
}

View File

@@ -46,6 +46,8 @@ import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.screenshot.ScrollCaptureController.LongScreenshot;
import com.google.common.util.concurrent.ListenableFuture;
@@ -67,6 +69,7 @@ public class LongScreenshotActivity extends Activity {
private static final String TAG = LogConfig.logTag(LongScreenshotActivity.class);
public static final String EXTRA_CAPTURE_RESPONSE = "capture-response";
public static final String EXTRA_SCREENSHOT_USER_HANDLE = "screenshot-userhandle";
private static final String KEY_SAVED_IMAGE_PATH = "saved-image-path";
private final UiEventLogger mUiEventLogger;
@@ -74,6 +77,8 @@ public class LongScreenshotActivity extends Activity {
private final Executor mBackgroundExecutor;
private final ImageExporter mImageExporter;
private final LongScreenshotData mLongScreenshotHolder;
private final ActionIntentExecutor mActionExecutor;
private final FeatureFlags mFeatureFlags;
private ImageView mPreview;
private ImageView mTransitionView;
@@ -85,6 +90,7 @@ public class LongScreenshotActivity extends Activity {
private CropView mCropView;
private MagnifierView mMagnifierView;
private ScrollCaptureResponse mScrollCaptureResponse;
private UserHandle mScreenshotUserHandle;
private File mSavedImagePath;
private ListenableFuture<File> mCacheSaveFuture;
@@ -103,12 +109,15 @@ public class LongScreenshotActivity extends Activity {
@Inject
public LongScreenshotActivity(UiEventLogger uiEventLogger, ImageExporter imageExporter,
@Main Executor mainExecutor, @Background Executor bgExecutor,
LongScreenshotData longScreenshotHolder) {
LongScreenshotData longScreenshotHolder, ActionIntentExecutor actionExecutor,
FeatureFlags featureFlags) {
mUiEventLogger = uiEventLogger;
mUiExecutor = mainExecutor;
mBackgroundExecutor = bgExecutor;
mImageExporter = imageExporter;
mLongScreenshotHolder = longScreenshotHolder;
mActionExecutor = actionExecutor;
mFeatureFlags = featureFlags;
}
@@ -139,6 +148,11 @@ public class LongScreenshotActivity extends Activity {
Intent intent = getIntent();
mScrollCaptureResponse = intent.getParcelableExtra(EXTRA_CAPTURE_RESPONSE);
mScreenshotUserHandle = intent.getParcelableExtra(EXTRA_SCREENSHOT_USER_HANDLE,
UserHandle.class);
if (mScreenshotUserHandle == null) {
mScreenshotUserHandle = Process.myUserHandle();
}
if (savedInstanceState != null) {
String savedImagePath = savedInstanceState.getString(KEY_SAVED_IMAGE_PATH);
@@ -318,36 +332,51 @@ public class LongScreenshotActivity extends Activity {
}
private void doEdit(Uri uri) {
String editorPackage = getString(R.string.config_screenshotEditor);
Intent intent = new Intent(Intent.ACTION_EDIT);
if (!TextUtils.isEmpty(editorPackage)) {
intent.setComponent(ComponentName.unflattenFromString(editorPackage));
}
intent.setDataAndType(uri, "image/png");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
if (mFeatureFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY) && mScreenshotUserHandle
!= Process.myUserHandle()) {
// TODO: Fix transition for work profile. Omitting it in the meantime.
mActionExecutor.launchIntentAsync(
ActionIntentCreator.INSTANCE.createEditIntent(uri, this),
null,
mScreenshotUserHandle.getIdentifier(), false);
} else {
String editorPackage = getString(R.string.config_screenshotEditor);
Intent intent = new Intent(Intent.ACTION_EDIT);
if (!TextUtils.isEmpty(editorPackage)) {
intent.setComponent(ComponentName.unflattenFromString(editorPackage));
}
intent.setDataAndType(uri, "image/png");
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
mTransitionView.setImageBitmap(mOutputBitmap);
mTransitionView.setVisibility(View.VISIBLE);
mTransitionView.setTransitionName(
ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
// TODO: listen for transition completing instead of finishing onStop
mTransitionStarted = true;
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this, mTransitionView,
ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle());
mTransitionView.setImageBitmap(mOutputBitmap);
mTransitionView.setVisibility(View.VISIBLE);
mTransitionView.setTransitionName(
ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME);
// TODO: listen for transition completing instead of finishing onStop
mTransitionStarted = true;
startActivity(intent,
ActivityOptions.makeSceneTransitionAnimation(this, mTransitionView,
ChooserActivity.FIRST_IMAGE_PREVIEW_TRANSITION_NAME).toBundle());
}
}
private void doShare(Uri uri) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent sharingChooserIntent = Intent.createChooser(intent, null)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
if (mFeatureFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY)) {
Intent shareIntent = ActionIntentCreator.INSTANCE.createShareIntent(uri, null);
mActionExecutor.launchIntentAsync(shareIntent, null,
mScreenshotUserHandle.getIdentifier(), false);
} else {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("image/png");
intent.putExtra(Intent.EXTRA_STREAM, uri);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
| Intent.FLAG_GRANT_READ_URI_PERMISSION);
Intent sharingChooserIntent = Intent.createChooser(intent, null)
.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
}
}
private void onClicked(View v) {
@@ -389,8 +418,8 @@ public class LongScreenshotActivity extends Activity {
mOutputBitmap = renderBitmap(drawable, bounds);
ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
mBackgroundExecutor, UUID.randomUUID(), mOutputBitmap, ZonedDateTime.now(),
// TODO: Owner must match the owner of the captured window.
Process.myUserHandle());
mFeatureFlags.isEnabled(Flags.SCREENSHOT_WORK_PROFILE_POLICY)
? mScreenshotUserHandle : Process.myUserHandle());
exportFuture.addListener(() -> onExportCompleted(action, exportFuture), mUiExecutor);
}

View File

@@ -587,7 +587,7 @@ public class ScreenshotController {
// Wait until this window is attached to request because it is
// the reference used to locate the target window (below).
withWindowAttached(() -> {
requestScrollCapture();
requestScrollCapture(owner);
mWindow.peekDecorView().getViewRootImpl().setActivityConfigCallback(
new ViewRootImpl.ActivityConfigCallback() {
@Override
@@ -599,11 +599,11 @@ public class ScreenshotController {
mScreenshotView.hideScrollChip();
// Delay scroll capture eval a bit to allow the underlying activity
// to set up in the new orientation.
mScreenshotHandler.postDelayed(
ScreenshotController.this::requestScrollCapture, 150);
mScreenshotHandler.postDelayed(() -> {
requestScrollCapture(owner);
}, 150);
mScreenshotView.updateInsets(
mWindowManager.getCurrentWindowMetrics()
.getWindowInsets());
mWindowManager.getCurrentWindowMetrics().getWindowInsets());
// Screenshot animation calculations won't be valid anymore,
// so just end
if (mScreenshotAnimation != null
@@ -651,7 +651,7 @@ public class ScreenshotController {
mScreenshotHandler.cancelTimeout(); // restarted after animation
}
private void requestScrollCapture() {
private void requestScrollCapture(UserHandle owner) {
if (!allowLongScreenshots()) {
Log.d(TAG, "Long screenshots not supported on this device");
return;
@@ -664,10 +664,11 @@ public class ScreenshotController {
mScrollCaptureClient.request(DEFAULT_DISPLAY);
mLastScrollCaptureRequest = future;
mLastScrollCaptureRequest.addListener(() ->
onScrollCaptureResponseReady(future), mMainExecutor);
onScrollCaptureResponseReady(future, owner), mMainExecutor);
}
private void onScrollCaptureResponseReady(Future<ScrollCaptureResponse> responseFuture) {
private void onScrollCaptureResponseReady(Future<ScrollCaptureResponse> responseFuture,
UserHandle owner) {
try {
if (mLastScrollCaptureResponse != null) {
mLastScrollCaptureResponse.close();
@@ -697,7 +698,7 @@ public class ScreenshotController {
mScreenshotView.prepareScrollingTransition(response, mScreenBitmap, newScreenshot,
mScreenshotTakenInPortrait);
// delay starting scroll capture to make sure the scrim is up before the app moves
mScreenshotView.post(() -> runBatchScrollCapture(response));
mScreenshotView.post(() -> runBatchScrollCapture(response, owner));
});
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, "requestScrollCapture failed", e);
@@ -706,7 +707,7 @@ public class ScreenshotController {
ListenableFuture<ScrollCaptureController.LongScreenshot> mLongScreenshotFuture;
private void runBatchScrollCapture(ScrollCaptureResponse response) {
private void runBatchScrollCapture(ScrollCaptureResponse response, UserHandle owner) {
// Clear the reference to prevent close() in dismissScreenshot
mLastScrollCaptureResponse = null;
@@ -740,6 +741,8 @@ public class ScreenshotController {
longScreenshot));
final Intent intent = new Intent(mContext, LongScreenshotActivity.class);
intent.putExtra(LongScreenshotActivity.EXTRA_SCREENSHOT_USER_HANDLE,
owner);
intent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);