Launcher3: Add Google Lens scan button to recents
And a squash of:
Launcher3: Restart launcher on changing google search/lens app
Launcher3: Make lens available without lens package
* Google search package is capable of lens functionality. Who knew? :)
idoybh (YAAP): Keep clear all rightmost
Co-authored-by: Pranav Vashi <neobuddy89@gmail.com>
Co-authored-by: hundeva <hundeva@gmail.com>
Change-Id: I8ba82c0d33b704d4a9d4fd20ab6552d054caa8eb
Signed-off-by: Pranav <npv12@iitbbs.ac.in>
diff --git a/.gitignore b/.gitignore
index 694b40c..85bd93a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,4 @@
build/
gradlew*
.DS_Store
+.settings
diff --git a/quickstep/res/drawable/ic_lens.xml b/quickstep/res/drawable/ic_lens.xml
new file mode 100644
index 0000000..e372e83
--- /dev/null
+++ b/quickstep/res/drawable/ic_lens.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector android:height="24.0dip" android:width="24.0dip" android:viewportWidth="24.0" android:viewportHeight="24.0"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#ff000000" android:pathData="M8.4445,5.7778C6.9689,5.7778 5.7778,6.9689 5.7778,8.4445L5.7778,10.2222L4,10.2222L4,8.4445C4,5.9911 5.9911,4 8.4445,4L10.2222,4v1.7778zM17.3333,17.3333m-1.7778,0a1.7778,1.7778 0,1 1,3.5555 0,1.7778 1.7778,0 1,1 -3.5555,0M12,12m-3.1111,0a3.1111,3.1111 0,1 1,6.2222 0,3.1111 3.1111,0 1,1 -6.2222,0M8.4444,18.2222c-1.4755,0 -2.6667,-1.1911 -2.6667,-2.6667L5.7777,13.7778L4,13.7778v1.7778C4,18.0089 5.9911,20 8.4445,20L10.2222,20L10.2222,18.2222ZM15.5555,5.7778c1.4755,0 2.6667,1.1911 2.6667,2.6667L18.2222,10.2222L20,10.2222L20,8.4445C20,5.9911 18.0089,4 15.5555,4h-1.7778v1.7778z" />
+</vector>
\ No newline at end of file
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index fcd2e54..36b37e5 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -45,6 +45,22 @@
android:theme="@style/ThemeControlHighlightWorkspaceColor"
android:visibility="gone" />
+ <Button
+ android:drawableStart="@drawable/ic_lens"
+ style="@style/OverviewActionButton"
+ android:id="@+id/action_lens"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/action_lens"
+ android:theme="@style/ThemeControlHighlightWorkspaceColor"
+ android:visibility="gone" />
+
+ <Space
+ android:id="@+id/lens_space"
+ android:layout_width="0dp"
+ android:layout_height="1dp"
+ android:layout_weight="1"
+ android:visibility="gone" />
</LinearLayout>
<!-- Currently, the only "group action button" is this save app pair button. If more are added,
@@ -59,4 +75,4 @@
android:layout_gravity="bottom|center_horizontal"
android:visibility="gone" />
-</com.android.quickstep.views.OverviewActionsView>
\ No newline at end of file
+</com.android.quickstep.views.OverviewActionsView>
diff --git a/quickstep/src/com/android/quickstep/ImageActionsApi.java b/quickstep/src/com/android/quickstep/ImageActionsApi.java
index 2273806..b7acd29 100644
--- a/quickstep/src/com/android/quickstep/ImageActionsApi.java
+++ b/quickstep/src/com/android/quickstep/ImageActionsApi.java
@@ -31,6 +31,7 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
+import android.view.View;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@@ -108,6 +109,11 @@
ImageActionUtils.startShareActivity(mContext, mBitmapSupplier, crop, null, TAG);
}
+ @UiThread
+ public void startLensActivity() {
+ ImageActionUtils.startLensActivity(mContext, mBitmapSupplier, null, null, TAG);
+ }
+
/**
* @param screenshot to be saved to the media store.
* @param screenshotBounds the location of where the bitmap was laid out on the screen in
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index b183ae3..128a3c1 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -331,6 +331,14 @@
public void onSaveAppPair() {
endLiveTileMode(TaskOverlay.this::saveAppPair);
}
+
+ public void onLens() {
+ if (mIsAllowedByPolicy) {
+ endLiveTileMode(() -> mImageApi.startLensActivity());
+ } else {
+ showBlockedByPolicyMessage();
+ }
+ }
}
}
@@ -347,5 +355,7 @@
/** User wants to save an app pair with current group of apps. */
void onSaveAppPair();
+
+ void onLens();
}
}
diff --git a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
index 3a1c99b..b39c93e 100644
--- a/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
+++ b/quickstep/src/com/android/quickstep/util/ImageActionUtils.java
@@ -45,12 +45,14 @@
import android.util.Log;
import android.view.View;
+import androidx.annotation.UiThread;
import androidx.annotation.WorkerThread;
import androidx.core.content.FileProvider;
import com.android.internal.app.ChooserActivity;
import com.android.internal.util.ScreenshotRequest;
import com.android.launcher3.BuildConfig;
+import com.android.launcher3.Utilities;
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.recents.model.Task;
@@ -159,6 +161,19 @@
});
}
+ @UiThread
+ public static void startLensActivity(Context context, Supplier<Bitmap> bitmapSupplier,
+ Rect crop, Intent intent, String tag) {
+ if (bitmapSupplier.get() == null) {
+ Log.e(tag, "No snapshot available, not starting share.");
+ return;
+ }
+
+ UI_HELPER_EXECUTOR.execute(() -> persistBitmapAndStartActivity(context,
+ bitmapSupplier.get(), crop, intent, ImageActionUtils::getLensIntentForImageUri,
+ tag));
+ }
+
/**
* Starts activity based on given intent created from image uri.
*/
@@ -299,6 +314,24 @@
return new Intent[]{Intent.createChooser(intent, null).addFlags(FLAG_ACTIVITY_NEW_TASK)};
}
+ @WorkerThread
+ private static Intent[] getLensIntentForImageUri(Uri uri, Intent intent) {
+ if (intent == null) {
+ intent = new Intent();
+ }
+ ClipData clipdata = new ClipData(new ClipDescription("content",
+ new String[]{"image/png"}),
+ new ClipData.Item(uri));
+ intent.setAction(Intent.ACTION_SEND)
+ .setComponent(new ComponentName(Utilities.GSA_PACKAGE, Utilities.LENS_SHARE_ACTIVITY))
+ .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .addFlags(FLAG_GRANT_READ_URI_PERMISSION)
+ .setType("image/png")
+ .putExtra(Intent.EXTRA_STREAM, uri)
+ .setClipData(clipdata);
+ return new Intent[]{Intent.createChooser(intent, null).addFlags(FLAG_ACTIVITY_NEW_TASK)};
+ }
+
private static void clearOldCacheFiles(Context context) {
THREAD_POOL_EXECUTOR.execute(() -> {
File parent = new File(context.getCacheDir(), SUB_FOLDER);
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index d9468c7..4285787 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -33,6 +33,7 @@
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
import com.android.launcher3.Insettable;
+import com.android.launcher3.Utilities;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.util.DisplayController;
@@ -181,6 +182,13 @@
mSplitButton = findViewById(R.id.action_split);
mSplitButton.setOnClickListener(this);
mSaveAppPairButton.setOnClickListener(this);
+
+ if (Utilities.isGSAEnabled(getContext())) {
+ View lens = findViewById(R.id.action_lens);
+ findViewById(R.id.action_lens).setOnClickListener(this);
+ lens.setVisibility(VISIBLE);
+ findViewById(R.id.lens_space).setVisibility(VISIBLE);
+ }
}
/**
@@ -204,6 +212,8 @@
mCallbacks.onSplit();
} else if (id == R.id.action_save_app_pair) {
mCallbacks.onSaveAppPair();
+ } else if (id == R.id.action_lens) {
+ mCallbacks.onLens();
}
}
diff --git a/res/values/leaf_strings.xml b/res/values/leaf_strings.xml
new file mode 100644
index 0000000..d0c8f5c
--- /dev/null
+++ b/res/values/leaf_strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2022 The LeafOS 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.
+*/
+-->
+<resources>
+ <!-- Recents -->
+ <string name="action_lens">Lens</string>
+</resources>
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 19a3002..fb737da 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -24,6 +24,7 @@
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
+import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
@@ -31,6 +32,7 @@
import android.app.Person;
import android.app.WallpaperManager;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.content.pm.ShortcutInfo;
@@ -138,6 +140,8 @@
public static final boolean ATLEAST_V = Build.VERSION.SDK_INT
>= VERSION_CODES.VANILLA_ICE_CREAM;
+ private static final long WAIT_BEFORE_RESTART = 250;
+
/**
* Set on a motion event dispatched from the nav bar. See {@link MotionEvent#setEdgeFlags(int)}.
*/
@@ -162,6 +166,9 @@
@IntDef({TRANSLATE_UP, TRANSLATE_DOWN, TRANSLATE_LEFT, TRANSLATE_RIGHT})
public @interface AdjustmentDirection{}
+ public static final String GSA_PACKAGE = "com.google.android.googlequicksearchbox";
+ public static final String LENS_SHARE_ACTIVITY = "com.google.android.apps.search.lens.LensShareEntryPointActivity";
+
/**
* Returns true if theme is dark.
*/
@@ -864,4 +871,22 @@
}
return null;
}
+
+ public static void restart(final Context context) {
+ MODEL_EXECUTOR.execute(() -> {
+ try {
+ Thread.sleep(WAIT_BEFORE_RESTART);
+ } catch (Exception ignored) {
+ }
+ android.os.Process.killProcess(android.os.Process.myPid());
+ });
+ }
+
+ public static boolean isGSAEnabled(Context context) {
+ try {
+ return context.getPackageManager().getApplicationInfo(GSA_PACKAGE, 0).enabled;
+ } catch (PackageManager.NameNotFoundException e) {
+ return false;
+ }
+ }
}
diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java
index 079987b..8754ade 100644
--- a/src/com/android/launcher3/model/PackageUpdatedTask.java
+++ b/src/com/android/launcher3/model/PackageUpdatedTask.java
@@ -39,6 +39,7 @@
import com.android.launcher3.LauncherModel.ModelUpdateTask;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LauncherSettings.Favorites;
+import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.logging.FileLog;
@@ -117,6 +118,7 @@
: ItemInfoMatcher.ofPackages(packageSet, mUser);
final HashSet<ComponentName> removedComponents = new HashSet<>();
final HashMap<String, List<LauncherActivityInfo>> activitiesLists = new HashMap<>();
+ boolean needsRestart = false;
if (DEBUG) {
Log.d(TAG, "Package updated: mOp=" + getOpString()
+ " packages=" + Arrays.toString(packages));
@@ -124,6 +126,9 @@
switch (mOp) {
case OP_ADD: {
for (int i = 0; i < N; i++) {
+ if (isTargetPackage(packages[i])) {
+ needsRestart = true;
+ }
iconCache.updateIconsForPkg(packages[i], mUser);
if (FeatureFlags.PROMISE_APPS_IN_ALL_APPS.get()) {
if (DEBUG) {
@@ -158,6 +163,9 @@
case OP_REMOVE: {
for (int i = 0; i < N; i++) {
iconCache.removeIconsForPkg(packages[i], mUser);
+ if (isTargetPackage(packages[i])) {
+ needsRestart = true;
+ }
}
// Fall through
}
@@ -175,6 +183,11 @@
flagOp = FlagOp.NO_OP.setFlag(
WorkspaceItemInfo.FLAG_DISABLED_SUSPENDED, mOp == OP_SUSPEND);
appsList.updateDisabledFlags(matcher, flagOp);
+ for (int i = 0; i < N; i++) {
+ if (isTargetPackage(packages[i])) {
+ needsRestart = true;
+ }
+ }
break;
case OP_USER_AVAILABILITY_CHANGE: {
UserManagerState ums = new UserManagerState();
@@ -428,6 +441,10 @@
}
taskController.bindUpdatedWidgets(dataModel);
}
+
+ if (needsRestart) {
+ Utilities.restart(context);
+ }
}
/**
@@ -464,5 +481,9 @@
case OP_USER_AVAILABILITY_CHANGE -> "USER_AVAILABILITY_CHANGE";
default -> "UNKNOWN";
};
+ }
+
+ private boolean isTargetPackage(String packageName) {
+ return packageName.equals(Utilities.GSA_PACKAGE);
}
}