Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c795b8f6 authored by Ajinkya Chalke's avatar Ajinkya Chalke
Browse files

Implements basic version of Backlinks

- Updated existing and backlinks logic to perform screenshot of and
  query tasks on display that is showing the app clips flow.
- Backlinks changes are guarded behind trunk stable flag.

Bug: 300307759
Test: atest AppClipsActivityTest AppClipsViewModelTest
Flag: com.android.systemui.app_clips_backlinks
Change-Id: I2105164fc6a0af051f545c047a64f1b2f3481bed
parent 98c094c2
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -51,6 +51,15 @@
        app:layout_constraintStart_toEndOf="@id/save"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/backlinks_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:visibility="gone"
        app:layout_constraintStart_toEndOf="@id/cancel"
        app:layout_constraintTop_toTopOf="parent" />

    <ImageView
        android:id="@+id/preview"
        android:layout_width="0px"
+2 −0
Original line number Diff line number Diff line
@@ -269,6 +269,8 @@
    <string name="screenshot_detected_multiple_template"><xliff:g id="appName" example="Google Chrome">%1$s</xliff:g> and other open apps detected this screenshot.</string>
    <!-- Add to note button used in App Clips flow to return the saved screenshot image to notes app. [CHAR LIMIT=NONE] -->
    <string name="app_clips_save_add_to_note">Add to note</string>
    <!-- TODO(b/300307759): Temporary string for text view that displays backlinks data. [CHAR LIMIT=NONE] -->
    <string name="backlinks_string" translatable="false">Open <xliff:g id="appName" example="Google Chrome">%1$s</xliff:g></string>

    <!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
    <string name="screenrecord_title">Screen Recorder</string>
+31 −6
Original line number Diff line number Diff line
@@ -16,16 +16,20 @@

package com.android.systemui.screenshot.appclips;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;

import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_ACCEPTED;
import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_CANCELLED;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.ACTION_FINISH_FROM_TRAMPOLINE;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_CALLING_PACKAGE_NAME;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_CALLING_PACKAGE_TASK_ID;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_RESULT_RECEIVER;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.PERMISSION_SELF;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -43,6 +47,7 @@ import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.activity.ComponentActivity;
import androidx.annotation.Nullable;
@@ -51,10 +56,13 @@ import androidx.lifecycle.ViewModelProvider;
import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.UiEventLogger.UiEventEnum;
import com.android.settingslib.Utils;
import com.android.systemui.Flags;
import com.android.systemui.res.R;
import com.android.systemui.screenshot.scroll.CropView;
import com.android.systemui.settings.UserTracker;

import java.util.Set;

import javax.inject.Inject;

/**
@@ -73,8 +81,6 @@ import javax.inject.Inject;
 *
 * <p>This {@link Activity} runs in its own separate process to isolate memory intensive image
 * editing from SysUI process.
 *
 * TODO(b/267309532): Polish UI and animations.
 */
public class AppClipsActivity extends ComponentActivity {

@@ -94,6 +100,7 @@ public class AppClipsActivity extends ComponentActivity {
    private CropView mCropView;
    private Button mSave;
    private Button mCancel;
    private TextView mBacklinksData;
    private AppClipsViewModel mViewModel;

    private ResultReceiver mResultReceiver;
@@ -153,11 +160,10 @@ public class AppClipsActivity extends ComponentActivity {
        mCancel = mLayout.findViewById(R.id.cancel);
        mSave.setOnClickListener(this::onClick);
        mCancel.setOnClickListener(this::onClick);


        mCropView = mLayout.findViewById(R.id.crop_view);

        mBacklinksData = mLayout.findViewById(R.id.backlinks_data);
        mPreview = mLayout.findViewById(R.id.preview);

        mPreview.addOnLayoutChangeListener(
                (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
                        updateImageDimensions());
@@ -166,9 +172,19 @@ public class AppClipsActivity extends ComponentActivity {
        mViewModel.getScreenshot().observe(this, this::setScreenshot);
        mViewModel.getResultLiveData().observe(this, this::setResultThenFinish);
        mViewModel.getErrorLiveData().observe(this, this::setErrorThenFinish);
        mViewModel.getBacklinksLiveData().observe(this, this::setBacklinksData);

        if (savedInstanceState == null) {
            mViewModel.performScreenshot();
            int displayId = getDisplayId();
            mViewModel.performScreenshot(displayId);

            if (Flags.appClipsBacklinks()) {
                int appClipsTaskId = getTaskId();
                int callingPackageTaskId = intent.getIntExtra(EXTRA_CALLING_PACKAGE_TASK_ID,
                        INVALID_TASK_ID);
                Set<Integer> taskIdsToIgnore = Set.of(appClipsTaskId, callingPackageTaskId);
                mViewModel.triggerBacklinks(taskIdsToIgnore, displayId);
            }
        }
    }

@@ -281,6 +297,15 @@ public class AppClipsActivity extends ComponentActivity {
        finish();
    }

    private void setBacklinksData(ClipData clipData) {
        if (mBacklinksData.getVisibility() == View.GONE) {
            mBacklinksData.setVisibility(View.VISIBLE);
        }

        mBacklinksData.setText(String.format(getString(R.string.backlinks_string),
                clipData.getDescription().getLabel()));
    }

    private void setError(int errorCode) {
        if (mResultReceiver == null) {
            return;
+8 −8
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.UserHandle;
import android.util.Log;

import androidx.annotation.Nullable;

@@ -27,19 +28,18 @@ import com.android.internal.infra.AndroidFuture;
import com.android.internal.infra.ServiceConnector;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Application;
import com.android.systemui.settings.DisplayTracker;

import javax.inject.Inject;

/** An intermediary singleton object to help communicating with the cross process service. */
@SysUISingleton
class AppClipsCrossProcessHelper {
    private static final String TAG = AppClipsCrossProcessHelper.class.getSimpleName();

    private final ServiceConnector<IAppClipsScreenshotHelperService> mProxyConnector;
    private final DisplayTracker mDisplayTracker;

    @Inject
    AppClipsCrossProcessHelper(@Application Context context, DisplayTracker displayTracker) {
    AppClipsCrossProcessHelper(@Application Context context) {
        // Start a service as main user so that even if the app clips activity is running as work
        // profile user the service is able to use correct instance of Bubbles to grab a screenshot
        // excluding the bubble layer.
@@ -48,7 +48,6 @@ class AppClipsCrossProcessHelper {
                Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
                        | Context.BIND_NOT_VISIBLE, UserHandle.USER_SYSTEM,
                IAppClipsScreenshotHelperService.Stub::asInterface);
        mDisplayTracker = displayTracker;
    }

    /**
@@ -58,15 +57,16 @@ class AppClipsCrossProcessHelper {
     * pass around but not a {@link Bitmap}.
     */
    @Nullable
    Bitmap takeScreenshot() {
    Bitmap takeScreenshot(int displayId) {
        try {
            AndroidFuture<ScreenshotHardwareBufferInternal> future =
                    mProxyConnector.postForResult(
                            service ->
                                    // Take a screenshot of the default display of the user.
                                    service.takeScreenshot(mDisplayTracker.getDefaultDisplayId()));
                            service -> service.takeScreenshot(displayId));
            return future.get().createBitmapThenCloseBuffer();
        } catch (Exception e) {
            Log.e(TAG,
                    String.format("Error while capturing a screenshot of displayId %d", displayId),
                    e);
            return null;
        }
    }
+4 −1
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ public class AppClipsTrampolineActivity extends Activity {
    static final String ACTION_FINISH_FROM_TRAMPOLINE = TAG + "FINISH_FROM_TRAMPOLINE";
    static final String EXTRA_RESULT_RECEIVER = TAG + "RESULT_RECEIVER";
    static final String EXTRA_CALLING_PACKAGE_NAME = TAG + "CALLING_PACKAGE_NAME";
    static final String EXTRA_CALLING_PACKAGE_TASK_ID = TAG + "CALLING_PACKAGE_TASK_ID";
    private static final ApplicationInfoFlags APPLICATION_INFO_FLAGS = ApplicationInfoFlags.of(0);

    private final NoteTaskController mNoteTaskController;
@@ -193,12 +194,14 @@ public class AppClipsTrampolineActivity extends Activity {
        ComponentName componentName = ComponentName.unflattenFromString(
                    getString(R.string.config_screenshotAppClipsActivityComponent));
        String callingPackageName = getCallingPackage();
        int callingPackageTaskId = getTaskId();

        Intent intent = new Intent()
                .setComponent(componentName)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                .putExtra(EXTRA_RESULT_RECEIVER, mResultReceiver)
                .putExtra(EXTRA_CALLING_PACKAGE_NAME, callingPackageName);
                .putExtra(EXTRA_CALLING_PACKAGE_NAME, callingPackageName)
                .putExtra(EXTRA_CALLING_PACKAGE_TASK_ID, callingPackageTaskId);
        try {
            startActivity(intent);

Loading