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

Commit cf10a2b1 authored by Ajinkya Chalke's avatar Ajinkya Chalke Committed by Android (Google) Code Review
Browse files

Merge "Implements basic version of Backlinks" into main

parents 3a02a369 c795b8f6
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -51,6 +51,15 @@
        app:layout_constraintStart_toEndOf="@id/save"
        app:layout_constraintStart_toEndOf="@id/save"
        app:layout_constraintTop_toTopOf="parent" />
        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
    <ImageView
        android:id="@+id/preview"
        android:id="@+id/preview"
        android:layout_width="0px"
        android:layout_width="0px"
+2 −0
Original line number Original line 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>
    <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] -->
    <!-- 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>
    <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]-->
    <!-- Notification title displayed for screen recording [CHAR LIMIT=50]-->
    <string name="screenrecord_title">Screen Recorder</string>
    <string name="screenrecord_title">Screen Recorder</string>
+31 −6
Original line number Original line Diff line number Diff line
@@ -16,16 +16,20 @@


package com.android.systemui.screenshot.appclips;
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_ACCEPTED;
import static com.android.systemui.screenshot.appclips.AppClipsEvent.SCREENSHOT_FOR_NOTE_CANCELLED;
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.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_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_RESULT_RECEIVER;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.EXTRA_SCREENSHOT_URI;
import static com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity.PERMISSION_SELF;
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;
import android.content.ClipData;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentFilter;
@@ -43,6 +47,7 @@ import android.util.Log;
import android.view.View;
import android.view.View;
import android.widget.Button;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ImageView;
import android.widget.TextView;


import androidx.activity.ComponentActivity;
import androidx.activity.ComponentActivity;
import androidx.annotation.Nullable;
import androidx.annotation.Nullable;
@@ -51,10 +56,13 @@ import androidx.lifecycle.ViewModelProvider;
import com.android.internal.logging.UiEventLogger;
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.Flags;
import com.android.systemui.res.R;
import com.android.systemui.res.R;
import com.android.systemui.screenshot.scroll.CropView;
import com.android.systemui.screenshot.scroll.CropView;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.settings.UserTracker;


import java.util.Set;

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


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


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


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

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

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


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


import androidx.annotation.Nullable;
import androidx.annotation.Nullable;


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


import javax.inject.Inject;
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
class AppClipsCrossProcessHelper {
class AppClipsCrossProcessHelper {
    private static final String TAG = AppClipsCrossProcessHelper.class.getSimpleName();


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


    @Inject
    @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
        // 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
        // profile user the service is able to use correct instance of Bubbles to grab a screenshot
        // excluding the bubble layer.
        // excluding the bubble layer.
@@ -48,7 +48,6 @@ class AppClipsCrossProcessHelper {
                Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
                Context.BIND_AUTO_CREATE | Context.BIND_WAIVE_PRIORITY
                        | Context.BIND_NOT_VISIBLE, UserHandle.USER_SYSTEM,
                        | Context.BIND_NOT_VISIBLE, UserHandle.USER_SYSTEM,
                IAppClipsScreenshotHelperService.Stub::asInterface);
                IAppClipsScreenshotHelperService.Stub::asInterface);
        mDisplayTracker = displayTracker;
    }
    }


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


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


        Intent intent = new Intent()
        Intent intent = new Intent()
                .setComponent(componentName)
                .setComponent(componentName)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                .putExtra(EXTRA_RESULT_RECEIVER, mResultReceiver)
                .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 {
        try {
            startActivity(intent);
            startActivity(intent);


Loading