Merge "Adding all-apps onboarding popup for 2-button mode"
diff --git a/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java b/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
index 9ce196e..3343cf5 100644
--- a/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
+++ b/quickstep/src/com/android/launcher3/search/DeviceSearchAdapterProvider.java
@@ -23,6 +23,8 @@
import android.view.LayoutInflater;
import android.view.ViewGroup;
+import com.android.app.search.LayoutType;
+import com.android.app.search.ResultType;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsContainerView;
@@ -78,10 +80,10 @@
SearchTargetHandler
payloadResultView =
(SearchTargetHandler) holder.itemView;
- if (FeatureFlags.SEARCH_TARGET_LEGACY.get()) {
+ if (!FeatureFlags.USE_SEARCH_API.get()) {
payloadResultView.applySearchTarget(item.getSearchTargetLegacy());
} else {
- payloadResultView.applySearchTarget(item.getSearchTarget());
+ payloadResultView.applySearchTarget(item.getSearchTarget(), item.getInlineItems());
}
}
@@ -123,9 +125,24 @@
* Returns -1 if viewType is not found
*/
public int getViewTypeForSearchTarget(SearchTarget t) {
- //TODO: Replace with values from :SearchUi
- if (t.getResultType() == 1 && t.getLayoutType().equals("icon")) {
- return VIEW_TYPE_SEARCH_ICON;
+ if (t.getLayoutType().equals(LayoutType.TEXT_HEADER)) {
+ return VIEW_TYPE_SEARCH_CORPUS_TITLE;
+ }
+ switch (t.getResultType()) {
+ case ResultType.APPLICATION:
+ if (t.getLayoutType().equals(LayoutType.ICON_SINGLE_VERTICAL_TEXT)) {
+ return VIEW_TYPE_SEARCH_ICON;
+ }
+ break;
+ case ResultType.SETTING:
+ if (t.getLayoutType().equals(LayoutType.ICON_SLICE)) {
+ return VIEW_TYPE_SEARCH_SLICE;
+ }
+ return VIEW_TYPE_SEARCH_ROW;
+ case ResultType.SHORTCUT:
+ return VIEW_TYPE_SEARCH_ICON_ROW;
+ case ResultType.PLAY:
+ return VIEW_TYPE_SEARCH_ROW_WITH_BUTTON;
}
return -1;
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java b/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
index 258d977..65ac3f9 100644
--- a/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
+++ b/quickstep/src/com/android/launcher3/search/SearchAdapterItem.java
@@ -32,12 +32,16 @@
import com.android.launcher3.allapps.AllAppsGridAdapter;
import com.android.systemui.plugins.shared.SearchTargetLegacy;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Extension of AdapterItem that contains an extra payload specific to item
*/
public class SearchAdapterItem extends AllAppsGridAdapter.AdapterItem {
private SearchTargetLegacy mSearchTargetLegacy;
private SearchTarget mSearchTarget;
+ private List<SearchTarget> mInlineItems = new ArrayList<>();
private static final int AVAILABLE_FOR_ACCESSIBILITY = VIEW_TYPE_SEARCH_ROW_WITH_BUTTON
@@ -65,6 +69,9 @@
return mSearchTarget;
}
+ public List<SearchTarget> getInlineItems() {
+ return mInlineItems;
+ }
@Override
protected boolean isCountedForAccessibility() {
return (AVAILABLE_FOR_ACCESSIBILITY & viewType) == viewType;
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
index e4d737c..d5fe0e8 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIcon.java
@@ -31,10 +31,12 @@
import android.view.View;
import android.view.ViewGroup;
+import com.android.app.search.ResultType;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.allapps.AllAppsStore;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.BitmapInfo;
import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.AppInfo;
@@ -46,6 +48,7 @@
import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
import com.android.systemui.plugins.shared.SearchTargetLegacy;
+import java.util.List;
import java.util.function.Consumer;
/**
@@ -128,10 +131,27 @@
}
}
+ /**
+ * Applies {@link SearchTarget} to view. registers a consumer after a corresponding
+ * {@link ItemInfoWithIcon} is created
+ */
+ public void applySearchTarget(SearchTarget searchTarget, List<SearchTarget> inlineItems,
+ Consumer<ItemInfoWithIcon> cb) {
+ mOnItemInfoChanged = cb;
+ applySearchTarget(searchTarget, inlineItems);
+ }
+
@Override
- public void applySearchTarget(SearchTarget searchTarget) {
- prepareUsingApp(new ComponentName(searchTarget.getPackageName(),
- searchTarget.getExtras().getString("class")), searchTarget.getUserHandle());
+ public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ switch (parentTarget.getResultType()) {
+ case ResultType.APPLICATION:
+ prepareUsingApp(new ComponentName(parentTarget.getPackageName(),
+ parentTarget.getExtras().getString("class")), parentTarget.getUserHandle());
+ break;
+ case ResultType.SHORTCUT:
+ prepareUsingShortcutInfo(parentTarget.getShortcutInfo());
+ break;
+ }
}
private void prepareUsingApp(ComponentName componentName, UserHandle userHandle) {
@@ -185,7 +205,9 @@
@Override
public void handleSelection(int eventType) {
mLauncher.getItemOnClickListener().onClick(this);
- reportEvent(eventType);
+ if (!FeatureFlags.USE_SEARCH_API.get()) {
+ reportEvent(eventType);
+ }
}
private void reportEvent(int eventType) {
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java b/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
index 8c491d2..80d543a 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultIconRow.java
@@ -18,6 +18,7 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import android.app.search.SearchTarget;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ShortcutInfo;
@@ -32,6 +33,7 @@
import androidx.annotation.Nullable;
+import com.android.app.search.ResultType;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
@@ -112,6 +114,16 @@
}
@Override
+ public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ mResultIcon.applySearchTarget(parentTarget, children, this);
+ if (parentTarget.getResultType() == ResultType.SHORTCUT) {
+ ShortcutInfo shortcutInfo = parentTarget.getShortcutInfo();
+ setProviderDetails(new ComponentName(shortcutInfo.getPackage(), ""),
+ shortcutInfo.getUserHandle());
+ }
+ }
+
+ @Override
public void applySearchTarget(SearchTargetLegacy searchTarget) {
mSearchTarget = searchTarget;
mResultIcon.applySearchTarget(searchTarget, this);
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultPlayItem.java b/quickstep/src/com/android/launcher3/search/SearchResultPlayItem.java
index 3bb821f..840bde9 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultPlayItem.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultPlayItem.java
@@ -17,6 +17,8 @@
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import android.app.search.SearchAction;
+import android.app.search.SearchTarget;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
@@ -27,8 +29,6 @@
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
-import android.net.Uri;
-import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
@@ -43,12 +43,11 @@
import com.android.launcher3.R;
import com.android.launcher3.icons.BitmapRenderer;
import com.android.launcher3.util.Themes;
-import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
-import com.android.systemui.plugins.shared.SearchTargetLegacy;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
+import java.util.List;
/**
* A View representing a PlayStore item.
@@ -67,9 +66,8 @@
private TextView[] mDetailViews = new TextView[3];
private Button mPreviewButton;
private String mPackageName;
- private boolean mIsInstantGame;
-
- private SearchTargetLegacy mSearchTarget;
+ private Intent mIntent;
+ private Intent mSecondaryIntent;
public SearchResultPlayItem(Context context) {
@@ -93,7 +91,7 @@
mIconView = findViewById(R.id.icon);
mTitleView = findViewById(R.id.title_view);
mPreviewButton = findViewById(R.id.try_button);
- mPreviewButton.setOnClickListener(view -> launchInstantGame());
+ mPreviewButton.setOnClickListener(view -> launchIntent(mSecondaryIntent));
mDetailViews[0] = findViewById(R.id.detail_0);
mDetailViews[1] = findViewById(R.id.detail_1);
mDetailViews[2] = findViewById(R.id.detail_2);
@@ -101,9 +99,59 @@
ViewGroup.LayoutParams iconParams = mIconView.getLayoutParams();
iconParams.height = mDeviceProfile.allAppsIconSizePx;
iconParams.width = mDeviceProfile.allAppsIconSizePx;
- setOnClickListener(view -> handleSelection(SearchTargetEventLegacy.SELECT));
+ setOnClickListener(view -> launchIntent(mIntent));
}
+ private void showIfNecessary(TextView textView, @Nullable String string) {
+ if (string == null || string.isEmpty()) {
+ textView.setVisibility(GONE);
+ } else {
+ textView.setText(string);
+ textView.setVisibility(VISIBLE);
+ }
+ }
+
+ private void launchIntent(Intent intent) {
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getContext().startActivity(intent);
+ }
+
+ @Override
+ public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ if (parentTarget.getPackageName().equals(mPackageName)) {
+ return;
+ }
+ mPackageName = parentTarget.getPackageName();
+ SearchAction action = parentTarget.getSearchAction();
+ mTitleView.setText(action.getTitle());
+ showIfNecessary(mDetailViews[0], action.getSubtitle().toString());
+ mIntent = action.getIntent();
+
+ mIconView.setBackgroundResource(R.drawable.ic_deepshortcut_placeholder);
+ loadIcon(action.getIcon().getUri().toString());
+
+ mSecondaryIntent = children.size() == 1 ? children.get(0).getSearchAction().getIntent()
+ : null;
+ mPreviewButton.setVisibility(mSecondaryIntent == null ? GONE : VISIBLE);
+ }
+
+ private void loadIcon(String iconUrl) {
+ UI_HELPER_EXECUTOR.execute(() -> {
+ try {
+ URL url = new URL(iconUrl);
+ URLConnection con = url.openConnection();
+ con.addRequestProperty("Cache-Control", "max-age: 0");
+ con.setUseCaches(true);
+ Bitmap bitmap = BitmapFactory.decodeStream(con.getInputStream());
+ BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), getRoundedBitmap(
+ Bitmap.createScaledBitmap(bitmap, mDeviceProfile.allAppsIconSizePx,
+ mDeviceProfile.allAppsIconSizePx, false)));
+ mIconView.post(() -> mIconView.setBackground(bitmapDrawable));
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ });
+ }
private Bitmap getRoundedBitmap(Bitmap bitmap) {
final int iconSize = bitmap.getWidth();
@@ -124,80 +172,4 @@
});
return output;
}
-
-
- @Override
- public void applySearchTarget(SearchTargetLegacy searchTarget) {
- mSearchTarget = searchTarget;
- Bundle bundle = searchTarget.getExtras();
- SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
- if (bundle.getString("package", "").equals(mPackageName)) {
- return;
- }
- mIsInstantGame = bundle.getBoolean("instant_game", false);
- mPackageName = bundle.getString("package");
- mPreviewButton.setVisibility(mIsInstantGame ? VISIBLE : GONE);
- mTitleView.setText(bundle.getString("title"));
-// TODO: Should use a generic type to get values b/165320033
- showIfNecessary(mDetailViews[0], bundle.getString("price"));
- showIfNecessary(mDetailViews[1], bundle.getString("rating"));
-
- mIconView.setBackgroundResource(R.drawable.ic_deepshortcut_placeholder);
- UI_HELPER_EXECUTOR.execute(() -> {
- try {
- URL url = new URL(bundle.getString("icon_url"));
- URLConnection con = url.openConnection();
-// TODO: monitor memory and investigate if it's better to use glide
- con.addRequestProperty("Cache-Control", "max-age: 0");
- con.setUseCaches(true);
- Bitmap bitmap = BitmapFactory.decodeStream(con.getInputStream());
- BitmapDrawable bitmapDrawable = new BitmapDrawable(getResources(), getRoundedBitmap(
- Bitmap.createScaledBitmap(bitmap, mDeviceProfile.allAppsIconSizePx,
- mDeviceProfile.allAppsIconSizePx, false)));
- mIconView.post(() -> mIconView.setBackground(bitmapDrawable));
- } catch (IOException e) {
- e.printStackTrace();
- }
- });
- }
-
- private void showIfNecessary(TextView textView, @Nullable String string) {
- if (string == null || string.isEmpty()) {
- textView.setVisibility(GONE);
- } else {
- textView.setText(string);
- textView.setVisibility(VISIBLE);
- }
- }
-
- @Override
- public void handleSelection(int eventType) {
- if (mPackageName == null) return;
- Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(
- "https://play.google.com/store/apps/details?id="
- + mPackageName));
- i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getContext().startActivity(i);
- logSearchEvent(eventType);
- }
-
- private void launchInstantGame() {
- if (!mIsInstantGame) return;
- Intent intent = new Intent(Intent.ACTION_VIEW);
- String referrer = "Pixel_Launcher";
- String id = mPackageName;
- String deepLinkUrl = "market://details?id=" + id + "&launch=true&referrer=" + referrer;
- intent.setPackage("com.android.vending");
- intent.setData(Uri.parse(deepLinkUrl));
- intent.putExtra("overlay", true);
- intent.putExtra("callerId", getContext().getPackageName());
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- getContext().startActivity(intent);
- logSearchEvent(SearchTargetEventLegacy.CHILD_SELECT);
- }
-
- private void logSearchEvent(int eventType) {
- SearchEventTracker.INSTANCE.get(getContext()).notifySearchTargetEvent(
- new SearchTargetEventLegacy.Builder(mSearchTarget, eventType).build());
- }
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchResultSettingsSlice.java b/quickstep/src/com/android/launcher3/search/SearchResultSettingsSlice.java
index 80ad305..bf50b67 100644
--- a/quickstep/src/com/android/launcher3/search/SearchResultSettingsSlice.java
+++ b/quickstep/src/com/android/launcher3/search/SearchResultSettingsSlice.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.search;
+import android.app.search.SearchTarget;
import android.content.Context;
import android.net.Uri;
import android.util.AttributeSet;
@@ -35,6 +36,8 @@
import com.android.systemui.plugins.shared.SearchTargetEventLegacy;
import com.android.systemui.plugins.shared.SearchTargetLegacy;
+import java.util.List;
+
/**
* A slice view wrapper with settings app icon at start
*/
@@ -89,6 +92,18 @@
}
@Override
+ public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ reset();
+ try {
+ mSliceLiveData = mLauncher.getLiveSearchManager().getSliceForUri(
+ parentTarget.getSliceUri());
+ mSliceLiveData.observe(mLauncher, mSliceView);
+ } catch (Exception ex) {
+ Log.e(TAG, "unable to bind slice", ex);
+ }
+ }
+
+ @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mSliceView.setOnSliceActionListener(this);
diff --git a/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java b/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
index eb40938..ccc38db 100644
--- a/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
+++ b/quickstep/src/com/android/launcher3/search/SearchSectionHeaderView.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.search;
+import android.app.search.SearchTarget;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.TextView;
@@ -23,6 +24,8 @@
import com.android.systemui.plugins.shared.SearchTargetLegacy;
+import java.util.List;
+
/**
* Header text view that shows a title for a given section in All apps search
*/
@@ -53,4 +56,10 @@
setVisibility(INVISIBLE);
}
}
+
+ @Override
+ public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ setText(parentTarget.getSearchAction().getTitle());
+ setVisibility(VISIBLE);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/search/SearchServicePipeline.java b/quickstep/src/com/android/launcher3/search/SearchServicePipeline.java
new file mode 100644
index 0000000..6585213
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/search/SearchServicePipeline.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2020 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.launcher3.search;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.app.search.Query;
+import android.app.search.SearchContext;
+import android.app.search.SearchSession;
+import android.app.search.SearchTarget;
+import android.app.search.SearchUiManager;
+import android.content.Context;
+import android.os.CancellationSignal;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.app.search.ResultType;
+import com.android.launcher3.allapps.AllAppsGridAdapter;
+import com.android.launcher3.allapps.AllAppsSectionDecorator;
+import com.android.launcher3.allapps.search.SearchPipeline;
+import com.android.launcher3.allapps.search.SearchSectionInfo;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Search pipeline utilizing {@link android.app.search.SearchUiManager}
+ */
+public class SearchServicePipeline implements SearchPipeline {
+ private static final int SUPPORTED_RESULT_TYPES =
+ ResultType.APPLICATION | ResultType.SHORTCUT | ResultType.PLAY | ResultType.PEOPLE
+ | ResultType.SETTING;
+ private static final int REQUEST_TIMEOUT = 200;
+ private static final String TAG = "SearchServicePipeline";
+
+
+ private final Context mContext;
+ private final SearchSession mSession;
+ private final DeviceSearchAdapterProvider mAdapterProvider;
+
+ private boolean mCanceled = false;
+
+
+ public SearchServicePipeline(Context context, DeviceSearchAdapterProvider adapterProvider) {
+ mContext = context;
+ mAdapterProvider = adapterProvider;
+ SearchUiManager manager = context.getSystemService(SearchUiManager.class);
+ mSession = manager.createSearchSession(
+ new SearchContext(SUPPORTED_RESULT_TYPES, REQUEST_TIMEOUT, null));
+ }
+
+ @Override
+ public void query(String input, Consumer<ArrayList<AllAppsGridAdapter.AdapterItem>> callback,
+ CancellationSignal cancellationSignal) {
+ mCanceled = false;
+ Query query = new Query(input, System.currentTimeMillis(), null);
+ mSession.query(query, UI_HELPER_EXECUTOR, items -> {
+ if (!mCanceled) {
+ callback.accept(this.onResult(items));
+ }
+ Log.w(TAG, "Ignoring results due to cancel signal");
+ });
+ }
+
+ /**
+ * Given A list of search Targets, pairs a group of search targets to a AdapterItem that can
+ * be inflated in AllAppsRecyclerView
+ */
+ private ArrayList<AllAppsGridAdapter.AdapterItem> onResult(List<SearchTarget> searchTargets) {
+ HashMap<String, SearchAdapterItem> adapterMap = new LinkedHashMap<>();
+ List<SearchTarget> unmappedChildren = new ArrayList<>();
+ SearchSectionInfo section = new SearchSectionInfo();
+ section.setDecorationHandler(
+ new AllAppsSectionDecorator.SectionDecorationHandler(mContext, true));
+ for (SearchTarget target : searchTargets) {
+ if (!TextUtils.isEmpty(target.getParentId())) {
+ if (!addChildToParent(target, adapterMap)) {
+ unmappedChildren.add(target);
+ }
+ continue;
+ }
+ int viewType = mAdapterProvider.getViewTypeForSearchTarget(target);
+ if (viewType != -1) {
+ SearchAdapterItem adapterItem = new SearchAdapterItem(target, viewType);
+ adapterItem.searchSectionInfo = section;
+ adapterMap.put(target.getId(), adapterItem);
+ }
+ }
+ for (SearchTarget s : unmappedChildren) {
+ if (!addChildToParent(s, adapterMap)) {
+ Log.w(TAG,
+ "Unable to pair child " + s.getId() + " to parent " + s.getParentId());
+ }
+ }
+ return new ArrayList<>(adapterMap.values());
+ }
+
+ /**
+ * Adds a child SearchTarget to a collection of searchTarget children with a shared parentId.
+ * Returns false if no parent searchTarget with id=$parentId does not exists.
+ */
+ private boolean addChildToParent(SearchTarget target, HashMap<String, SearchAdapterItem> map) {
+ if (!map.containsKey(target.getParentId())) return false;
+ map.get(target.getParentId()).getInlineItems().add(target);
+ return true;
+ }
+
+ /**
+ * Unregister callbacks and destroy search session
+ */
+ public void destroy() {
+ mSession.destroy();
+ }
+
+ /**
+ * Cancels current ongoing search request.
+ */
+ public void cancel() {
+ mCanceled = true;
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/search/SearchSettingsRowView.java b/quickstep/src/com/android/launcher3/search/SearchSettingsRowView.java
index 8306e3b..6fc0046 100644
--- a/quickstep/src/com/android/launcher3/search/SearchSettingsRowView.java
+++ b/quickstep/src/com/android/launcher3/search/SearchSettingsRowView.java
@@ -19,6 +19,8 @@
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
+import android.app.search.SearchAction;
+import android.app.search.SearchTarget;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -97,6 +99,14 @@
SearchEventTracker.INSTANCE.get(getContext()).registerWeakHandler(searchTarget, this);
}
+ @Override
+ public void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
+ SearchAction action = parentTarget.getSearchAction();
+ mIconView.setContentDescription(action.getTitle());
+ showIfAvailable(mTitleView, action.getTitle().toString());
+ showIfAvailable(mBreadcrumbsView, action.getSubtitle().toString());
+ }
+
private void showIfAvailable(TextView view, @Nullable String string) {
if (TextUtils.isEmpty(string)) {
view.setVisibility(GONE);
diff --git a/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java b/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
index 9ff057f..e72578d 100644
--- a/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
+++ b/quickstep/src/com/android/launcher3/search/SearchTargetHandler.java
@@ -20,6 +20,8 @@
import com.android.systemui.plugins.shared.SearchTargetLegacy;
+import java.util.List;
+
/**
* An interface for supporting dynamic search results
*/
@@ -28,13 +30,14 @@
/**
* Update view using values from {@link SearchTargetLegacy}
*/
- void applySearchTarget(SearchTargetLegacy searchTarget);
+ default void applySearchTarget(SearchTargetLegacy searchTarget) {
+ }
+
/**
* Update view using values from {@link SearchTargetLegacy}
*/
- default void applySearchTarget(SearchTarget searchTarget){
-
+ default void applySearchTarget(SearchTarget parentTarget, List<SearchTarget> children) {
}
/**
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 5c68465..a00ce56 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -220,6 +220,7 @@
@Override
public void onDestroy() {
super.onDestroy();
+ getAppsView().getSearchUiManager().destroy();
if (mHotseatPredictionController != null) {
mHotseatPredictionController.destroy();
mHotseatPredictionController = null;
diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
index 74b56e9..4301377 100644
--- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
+++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java
@@ -24,6 +24,7 @@
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ASSIST_GESTURE_CONSTRAINED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BUBBLES_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_GLOBAL_ACTIONS_SHOWING;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
@@ -383,6 +384,7 @@
*/
public boolean canStartSystemGesture() {
boolean canStartWithNavHidden = (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
+ || (mSystemUiStateFlags & SYSUI_STATE_ALLOW_GESTURE_IGNORING_BAR_VISIBILITY) != 0
|| mRotationTouchHelper.isTaskListFrozen();
return canStartWithNavHidden
&& (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index f281296..2f2b566 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -72,7 +72,6 @@
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.FloatProperty;
-import android.util.Property;
import android.util.SparseBooleanArray;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
@@ -1515,7 +1514,9 @@
}
int scrollDiff = newScroll[i] - oldScroll[i] + offset;
if (scrollDiff != 0) {
- Property translationProperty = mOrientationHandler.getPrimaryViewTranslate();
+ FloatProperty translationProperty = child instanceof TaskView
+ ? ((TaskView) child).getPrimaryFillDismissGapTranslationProperty()
+ : mOrientationHandler.getPrimaryViewTranslate();
ResourceProvider rp = DynamicResource.provider(mActivity);
SpringProperty sp = new SpringProperty(SpringProperty.FLAG_CAN_SPRING_ON_END)
@@ -1927,7 +1928,11 @@
? modalLeftOffsetSize
: modalRightOffsetSize;
float totalTranslation = translation + modalTranslation;
- mOrientationHandler.getPrimaryViewTranslate().set(getChildAt(i),
+ View child = getChildAt(i);
+ FloatProperty translationProperty = child instanceof TaskView
+ ? ((TaskView) child).getPrimaryTaskOffsetTranslationProperty()
+ : mOrientationHandler.getPrimaryViewTranslate();
+ translationProperty.set(child,
totalTranslation * mOrientationHandler.getPrimaryTranslationDirectionFactor());
}
updateCurveProperties();
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index d94e623..b791d29 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -152,6 +152,58 @@
}
};
+ private static final FloatProperty<TaskView> FILL_DISMISS_GAP_TRANSLATION_X =
+ new FloatProperty<TaskView>("fillDismissGapTranslationX") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setFillDismissGapTranslationX(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mFillDismissGapTranslationX;
+ }
+ };
+
+ private static final FloatProperty<TaskView> FILL_DISMISS_GAP_TRANSLATION_Y =
+ new FloatProperty<TaskView>("fillDismissGapTranslationY") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setFillDismissGapTranslationY(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mFillDismissGapTranslationY;
+ }
+ };
+
+ private static final FloatProperty<TaskView> TASK_OFFSET_TRANSLATION_X =
+ new FloatProperty<TaskView>("taskOffsetTranslationX") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setTaskOffsetTranslationX(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mTaskOffsetTranslationX;
+ }
+ };
+
+ private static final FloatProperty<TaskView> TASK_OFFSET_TRANSLATION_Y =
+ new FloatProperty<TaskView>("taskOffsetTranslationY") {
+ @Override
+ public void setValue(TaskView taskView, float v) {
+ taskView.setTaskOffsetTranslationY(v);
+ }
+
+ @Override
+ public Float get(TaskView taskView) {
+ return taskView.mTaskOffsetTranslationY;
+ }
+ };
+
private final OnAttachStateChangeListener mTaskMenuStateListener =
new OnAttachStateChangeListener() {
@Override
@@ -179,6 +231,13 @@
private final FullscreenDrawParams mCurrentFullscreenParams;
private final StatefulActivity mActivity;
+ // Various causes of changing primary translation, which we aggregate to setTranslationX/Y().
+ // TODO: We should do this for secondary translation properties as well.
+ private float mFillDismissGapTranslationX;
+ private float mFillDismissGapTranslationY;
+ private float mTaskOffsetTranslationX;
+ private float mTaskOffsetTranslationY;
+
private ObjectAnimator mIconAndDimAnimator;
private float mIconScaleAnimStartProgress = 0;
private float mFocusTransitionProgress = 1;
@@ -601,6 +660,8 @@
protected void resetViewTransforms() {
setCurveScale(1);
+ mFillDismissGapTranslationX = mTaskOffsetTranslationX = 0f;
+ mFillDismissGapTranslationY = mTaskOffsetTranslationY = 0f;
setTranslationX(0f);
setTranslationY(0f);
setTranslationZ(0);
@@ -745,6 +806,44 @@
return mCurveScale;
}
+ private void setFillDismissGapTranslationX(float x) {
+ mFillDismissGapTranslationX = x;
+ applyTranslationX();
+ }
+
+ private void setFillDismissGapTranslationY(float y) {
+ mFillDismissGapTranslationY = y;
+ applyTranslationY();
+ }
+
+ private void setTaskOffsetTranslationX(float x) {
+ mTaskOffsetTranslationX = x;
+ applyTranslationX();
+ }
+
+ private void setTaskOffsetTranslationY(float y) {
+ mTaskOffsetTranslationY = y;
+ applyTranslationY();
+ }
+
+ private void applyTranslationX() {
+ setTranslationX(mFillDismissGapTranslationX + mTaskOffsetTranslationX);
+ }
+
+ private void applyTranslationY() {
+ setTranslationY(mFillDismissGapTranslationY + mTaskOffsetTranslationY);
+ }
+
+ public FloatProperty<TaskView> getPrimaryFillDismissGapTranslationProperty() {
+ return getPagedOrientationHandler().getPrimaryValue(
+ FILL_DISMISS_GAP_TRANSLATION_X, FILL_DISMISS_GAP_TRANSLATION_Y);
+ }
+
+ public FloatProperty<TaskView> getPrimaryTaskOffsetTranslationProperty() {
+ return getPagedOrientationHandler().getPrimaryValue(
+ TASK_OFFSET_TRANSLATION_X, TASK_OFFSET_TRANSLATION_Y);
+ }
+
@Override
public boolean hasOverlappingRendering() {
// TODO: Clip-out the icon region from the thumbnail, since they are overlapping.
diff --git a/src/com/android/launcher3/allapps/SearchUiManager.java b/src/com/android/launcher3/allapps/SearchUiManager.java
index aa056a0..f926086 100644
--- a/src/com/android/launcher3/allapps/SearchUiManager.java
+++ b/src/com/android/launcher3/allapps/SearchUiManager.java
@@ -59,6 +59,11 @@
Interpolator interpolator);
/**
+ * Called when activity is destroyed. Used to close search system services
+ */
+ default void destroy(){}
+
+ /**
* Returns true if the QSB should be visible for the given set of visible elements
*/
default boolean isQsbVisible(int visibleElements) {
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 2455706..81174d8 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -98,9 +98,8 @@
public static final BooleanFlag ENABLE_DEVICE_SEARCH = getDebugFlag(
"ENABLE_DEVICE_SEARCH", false, "Allows on device search in all apps");
- public static final BooleanFlag SEARCH_TARGET_LEGACY = getDebugFlag(
- "SEARCH_TARGET_LEGACY", true,
- "Use SearchTarget provided by plugin lib (only during migration)");
+ public static final BooleanFlag USE_SEARCH_API = getDebugFlag(
+ "USE_SEARCH_API", true, "Use SearchUIManager api for device search");
public static final BooleanFlag DISABLE_INITIAL_IME_IN_ALLAPPS = getDebugFlag(
"DISABLE_INITIAL_IME_IN_ALLAPPS", false, "Disable default IME state in all apps");
diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java
index c57c3e4..d4fa278 100644
--- a/src/com/android/launcher3/model/AllAppsList.java
+++ b/src/com/android/launcher3/model/AllAppsList.java
@@ -26,7 +26,6 @@
import android.content.pm.LauncherActivityInfo;
import android.content.pm.LauncherApps;
import android.os.LocaleList;
-import android.os.Process;
import android.os.UserHandle;
import android.util.Log;
@@ -162,7 +161,7 @@
/** Updates the given PackageInstallInfo's associated AppInfo's installation info. */
public List<AppInfo> updatePromiseInstallInfo(PackageInstallInfo installInfo) {
List<AppInfo> updatedAppInfos = new ArrayList<>();
- UserHandle user = Process.myUserHandle();
+ UserHandle user = installInfo.user;
for (int i = data.size() - 1; i >= 0; i--) {
final AppInfo appInfo = data.get(i);
final ComponentName tgtComp = appInfo.getTargetComponent();
@@ -177,7 +176,8 @@
appInfo.setProgressLevel(installInfo);
updatedAppInfos.add(appInfo);
- } else if (installInfo.state == PackageInstallInfo.STATUS_FAILED) {
+ } else if (installInfo.state == PackageInstallInfo.STATUS_FAILED
+ && !appInfo.isAppStartable()) {
removeApp(i);
}
}
diff --git a/src/com/android/launcher3/states/RotationHelper.java b/src/com/android/launcher3/states/RotationHelper.java
index ecf4f36..ba28e82 100644
--- a/src/com/android/launcher3/states/RotationHelper.java
+++ b/src/com/android/launcher3/states/RotationHelper.java
@@ -51,7 +51,7 @@
public static final int REQUEST_ROTATE = 1;
public static final int REQUEST_LOCK = 2;
- private final Activity mActivity;
+ private Activity mActivity;
private final SharedPreferences mSharedPrefs;
private boolean mIgnoreAutoRotateSettings;
@@ -95,6 +95,7 @@
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
+ if (mDestroyed) return;
boolean wasRotationEnabled = mHomeRotationEnabled;
mHomeRotationEnabled = mSharedPrefs.getBoolean(ALLOW_ROTATION_PREFERENCE_KEY,
getAllowRotationDefaultValue());
@@ -141,6 +142,7 @@
public void destroy() {
if (!mDestroyed) {
mDestroyed = true;
+ mActivity = null;
if (mSharedPrefs != null) {
mSharedPrefs.unregisterOnSharedPreferenceChangeListener(this);
}