diff --git a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java index 330ec6806b..e268f567ae 100644 --- a/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java +++ b/src/com/android/launcher3/allapps/search/DefaultSearchAdapterProvider.java @@ -15,6 +15,7 @@ */ package com.android.launcher3.allapps.search; +import android.net.Uri; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -36,6 +37,11 @@ public class DefaultSearchAdapterProvider extends SearchAdapterProvider { } + @Override + public void onSliceStatusUpdate(Uri sliceUri) { + + } + @Override public boolean isSearchView(int viewType) { return false; diff --git a/src/com/android/launcher3/allapps/search/LiveSearchManager.java b/src/com/android/launcher3/allapps/search/LiveSearchManager.java index 76099a6478..adb882a90a 100644 --- a/src/com/android/launcher3/allapps/search/LiveSearchManager.java +++ b/src/com/android/launcher3/allapps/search/LiveSearchManager.java @@ -42,6 +42,7 @@ import androidx.slice.Slice; import androidx.slice.SliceViewManager; import androidx.slice.SliceViewManager.SliceCallback; +import com.android.launcher3.Alarm; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.statemanager.StateManager.StateListener; @@ -52,6 +53,7 @@ import com.android.launcher3.widget.PendingAddWidgetInfo; import java.util.ArrayList; import java.util.HashMap; +import java.util.function.Consumer; /** * Manages Lifecycle for Live search results @@ -60,6 +62,7 @@ public class LiveSearchManager implements StateListener { private static final String TAG = "LiveSearchManager"; + private static final long SLICE_TIMEOUT_MS = 50; public static final int SEARCH_APPWIDGET_HOST_ID = 2048; private final Launcher mLauncher; @@ -144,16 +147,50 @@ public class LiveSearchManager implements StateListener { /** * Adds a new observer for the provided uri and returns a callback to cancel this observer */ - public SafeCloseable addObserver(Uri uri, Observer listener) { + public SafeCloseable addObserver(Uri uri, Observer listener, + Consumer timeoutConsumer) { SliceLifeCycle slc = mUriSliceMap.get(uri); if (slc == null) { slc = new SliceLifeCycle(uri, mLauncher); mUriSliceMap.put(uri, slc); } - slc.addListener(listener); + if (slc.mLastValue != null) { + listener.onChanged(slc.mLastValue); + } + + // Use a listener wrapper to handle error timeout. + Observer listenerWrapper = new Observer() { + final Alarm mErrorTimeout = new Alarm(); + { + mErrorTimeout.setOnAlarmListener(alarm -> { + alarm.cancelAlarm(); + timeoutConsumer.accept(uri); + }); + mErrorTimeout.setAlarm(SLICE_TIMEOUT_MS); + } + + @Override + public void onChanged(Slice slice) { + if (slice == null) { + return; + } + + if (mErrorTimeout.alarmPending()) { + mErrorTimeout.cancelAlarm(); + } + + if (mUriSliceMap.get(uri) != null) { + mUriSliceMap.get(uri).mLastValue = slice; + } + + listener.onChanged(slice); + } + }; + + slc.addListener(listenerWrapper); final SliceLifeCycle sliceLifeCycle = slc; - return () -> sliceLifeCycle.removeListener(listener); + return () -> sliceLifeCycle.removeListener(listenerWrapper); } static class SearchWidgetHost extends AppWidgetHost { @@ -184,6 +221,8 @@ public class LiveSearchManager implements StateListener { private boolean mDestroyed = false; private boolean mWasListening = false; + Slice mLastValue; + SliceLifeCycle(Uri uri, Launcher launcher) { mUri = uri; mLauncher = launcher; diff --git a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java index fdacd3d2d9..0864090ade 100644 --- a/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java +++ b/src/com/android/launcher3/allapps/search/SearchAdapterProvider.java @@ -16,6 +16,7 @@ package com.android.launcher3.allapps.search; +import android.net.Uri; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -39,6 +40,11 @@ public abstract class SearchAdapterProvider { */ public abstract void onBindView(AllAppsGridAdapter.ViewHolder holder, int position); + /** + * Called from LiveSearchManager to notify slice status updates. + */ + public abstract void onSliceStatusUpdate(Uri sliceUri); + /** * Returns whether or not viewType can be handled by searchProvider */