From 27283f7ea8b4eea6b9420ee652c841db1a96a008 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Fri, 26 Apr 2019 10:56:52 -0700 Subject: Setting predition enabled/disabled state based on callbacks from the service > If no callback is received within a timeout, it is set to disabled Bug: 131188880 Change-Id: Ie6022b190a2504739f1569a500d6f5cc1566d373 --- .../appprediction/PredictionAppTracker.java | 47 +++++----------------- .../appprediction/PredictionUiStateManager.java | 47 ++++++++++++++-------- .../android/quickstep/AppPredictionsUITests.java | 41 ++++++++----------- 3 files changed, 57 insertions(+), 78 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java index bd7857330..0b8c1c57f 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionAppTracker.java @@ -15,7 +15,7 @@ */ package com.android.launcher3.appprediction; -import static com.android.launcher3.appprediction.PredictionUiStateManager.KEY_APP_SUGGESTION; +import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_GRID; import android.annotation.TargetApi; import android.app.prediction.AppPredictionContext; @@ -26,8 +26,6 @@ import android.app.prediction.AppTargetEvent; import android.app.prediction.AppTargetId; import android.content.ComponentName; import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Build; import android.os.Handler; import android.os.Message; @@ -35,12 +33,10 @@ import android.os.UserHandle; import android.util.Log; import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.Utilities; +import com.android.launcher3.appprediction.PredictionUiStateManager.Client; import com.android.launcher3.model.AppLaunchTracker; import com.android.launcher3.util.UiThreadHelper; -import com.android.launcher3.appprediction.PredictionUiStateManager.Client; - import androidx.annotation.UiThread; import androidx.annotation.WorkerThread; @@ -48,8 +44,7 @@ import androidx.annotation.WorkerThread; * Subclass of app tracker which publishes the data to the prediction engine and gets back results. */ @TargetApi(Build.VERSION_CODES.Q) -public class PredictionAppTracker extends AppLaunchTracker - implements OnSharedPreferenceChangeListener { +public class PredictionAppTracker extends AppLaunchTracker { private static final String TAG = "PredictionAppTracker"; private static final boolean DBG = false; @@ -62,8 +57,6 @@ public class PredictionAppTracker extends AppLaunchTracker private final Context mContext; private final Handler mMessageHandler; - private boolean mEnabled; - // Accessed only on worker thread private AppPredictor mHomeAppPredictor; private AppPredictor mRecentsOverviewPredictor; @@ -71,24 +64,16 @@ public class PredictionAppTracker extends AppLaunchTracker public PredictionAppTracker(Context context) { mContext = context; mMessageHandler = new Handler(UiThreadHelper.getBackgroundLooper(), this::handleMessage); - - SharedPreferences prefs = Utilities.getPrefs(context); - setEnabled(prefs.getBoolean(KEY_APP_SUGGESTION, true)); - prefs.registerOnSharedPreferenceChangeListener(this); InvariantDeviceProfile.INSTANCE.get(mContext).addOnChangeListener(this::onIdpChanged); - } - @UiThread - private void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) { - // Reinitialize everything - setEnabled(mEnabled); + mMessageHandler.sendEmptyMessage(MSG_INIT); } - @Override @UiThread - public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - if (KEY_APP_SUGGESTION.equals(key)) { - setEnabled(prefs.getBoolean(KEY_APP_SUGGESTION, true)); + private void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) { + if ((changeFlags & CHANGE_FLAG_GRID) != 0) { + // Reinitialize everything + mMessageHandler.sendEmptyMessage(MSG_INIT); } } @@ -137,13 +122,13 @@ public class PredictionAppTracker extends AppLaunchTracker return true; } case MSG_LAUNCH: { - if (mEnabled && mHomeAppPredictor != null) { + if (mHomeAppPredictor != null) { mHomeAppPredictor.notifyAppTargetEvent((AppTargetEvent) msg.obj); } return true; } case MSG_PREDICT: { - if (mEnabled && mHomeAppPredictor != null) { + if (mHomeAppPredictor != null) { String client = (String) msg.obj; if (Client.HOME.id.equals(client)) { mHomeAppPredictor.requestPredictionUpdate(); @@ -168,18 +153,6 @@ public class PredictionAppTracker extends AppLaunchTracker } } - @UiThread - public void setEnabled(boolean isEnabled) { - mEnabled = isEnabled; - if (isEnabled) { - mMessageHandler.removeMessages(MSG_DESTROY); - mMessageHandler.sendEmptyMessage(MSG_INIT); - } else { - mMessageHandler.removeMessages(MSG_INIT); - mMessageHandler.sendEmptyMessage(MSG_DESTROY); - } - } - @Override @UiThread public void onStartShortcut(String packageName, String shortcutId, UserHandle user, diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java index 54fd84522..48a163d87 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/appprediction/PredictionUiStateManager.java @@ -24,8 +24,7 @@ import android.app.prediction.AppPredictor; import android.app.prediction.AppTarget; import android.content.ComponentName; import android.content.Context; -import android.content.SharedPreferences; -import android.content.SharedPreferences.OnSharedPreferenceChangeListener; +import android.os.Handler; import android.view.ViewTreeObserver.OnGlobalLayoutListener; import com.android.launcher3.AppInfo; @@ -61,9 +60,10 @@ import java.util.List; * that client id. */ public class PredictionUiStateManager implements OnGlobalLayoutListener, ItemInfoUpdateReceiver, - OnSharedPreferenceChangeListener, OnIDPChangeListener, OnUpdateListener { + OnIDPChangeListener, OnUpdateListener { - public static final String KEY_APP_SUGGESTION = "pref_show_predictions"; + public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state"; + private static final long INITIAL_CALLBACK_WAIT_TIMEOUT_MS = 5000; // TODO (b/129421797): Update the client constants public enum Client { @@ -81,7 +81,6 @@ public class PredictionUiStateManager implements OnGlobalLayoutListener, ItemInf new MainThreadInitializedObject<>(PredictionUiStateManager::new); private final Context mContext; - private final SharedPreferences mMainPrefs; private final DynamicItemCache mDynamicItemCache; private final List[] mPredictionServicePredictions; @@ -94,9 +93,10 @@ public class PredictionUiStateManager implements OnGlobalLayoutListener, ItemInf private PredictionState mPendingState; private PredictionState mCurrentState; + private boolean mGettingValidPredictionResults; + private PredictionUiStateManager(Context context) { mContext = context; - mMainPrefs = Utilities.getPrefs(context); mDynamicItemCache = new DynamicItemCache(context, this::onAppsUpdated); @@ -110,8 +110,14 @@ public class PredictionUiStateManager implements OnGlobalLayoutListener, ItemInf for (int i = 0; i < mPredictionServicePredictions.length; i++) { mPredictionServicePredictions[i] = Collections.emptyList(); } - // Listens for enable/disable signal, and predictions if using AiAi is disabled. - mMainPrefs.registerOnSharedPreferenceChangeListener(this); + + mGettingValidPredictionResults = Utilities.getDevicePrefs(context) + .getBoolean(LAST_PREDICTION_ENABLED_STATE, true); + if (mGettingValidPredictionResults) { + new Handler().postDelayed( + this::updatePredictionStateAfterCallback, INITIAL_CALLBACK_WAIT_TIMEOUT_MS); + } + // Call this last mCurrentState = parseLastState(); } @@ -177,13 +183,6 @@ public class PredictionUiStateManager implements OnGlobalLayoutListener, ItemInf } } - @Override - public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { - if (KEY_APP_SUGGESTION.equals(key)) { - dispatchOnChange(true); - } - } - private void applyState(PredictionState state) { boolean wasEnabled = mCurrentState.isEnabled; mCurrentState = state; @@ -198,10 +197,24 @@ public class PredictionUiStateManager implements OnGlobalLayoutListener, ItemInf } } + private void updatePredictionStateAfterCallback() { + boolean validResults = false; + for (List l : mPredictionServicePredictions) { + validResults |= l != null && !l.isEmpty(); + } + if (validResults != mGettingValidPredictionResults) { + mGettingValidPredictionResults = validResults; + Utilities.getDevicePrefs(mContext).edit() + .putBoolean(LAST_PREDICTION_ENABLED_STATE, true) + .apply(); + } + dispatchOnChange(true); + } + public AppPredictor.Callback appPredictorCallback(Client client) { return targets -> { mPredictionServicePredictions[client.ordinal()] = targets; - dispatchOnChange(true); + updatePredictionStateAfterCallback(); }; } @@ -217,7 +230,7 @@ public class PredictionUiStateManager implements OnGlobalLayoutListener, ItemInf private PredictionState parseLastState() { PredictionState state = new PredictionState(); - state.isEnabled = mMainPrefs.getBoolean(KEY_APP_SUGGESTION, true); + state.isEnabled = mGettingValidPredictionResults; if (!state.isEnabled) { state.apps = Collections.EMPTY_LIST; return state; diff --git a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java index 72de80bfa..e6dbf875c 100644 --- a/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java +++ b/quickstep/tests/src/com/android/quickstep/AppPredictionsUITests.java @@ -17,6 +17,7 @@ package com.android.quickstep; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import android.app.prediction.AppPredictor; import android.app.prediction.AppTarget; @@ -25,7 +26,6 @@ import android.content.ComponentName; import android.content.pm.LauncherActivityInfo; import android.os.Process; import android.view.View; -import android.widget.ProgressBar; import com.android.launcher3.BubbleTextView; import com.android.launcher3.Launcher; @@ -49,8 +49,7 @@ import androidx.test.runner.AndroidJUnit4; @LargeTest @RunWith(AndroidJUnit4.class) -public class AppPredictionsUITests extends AbstractQuickStepTest { - private static final String TAG = "AppPredictionsUITests"; +public class AppPredictionsUITests extends AbstractQuickStepTest { private LauncherActivityInfo mSampleApp1; private LauncherActivityInfo mSampleApp2; @@ -91,20 +90,15 @@ public class AppPredictionsUITests extends AbstractQuickStepTest { mActivityMonitor.startLauncher(); mLauncher.pressHome().switchToAllApps(); - // There has not been any update, verify that progress bar is showing - waitForLauncherCondition("Prediction is not in loading state", launcher -> { - ProgressBar p = findLoadingBar(launcher); - return p != null && p.isShown(); - }); - // Dispatch an update sendPredictionUpdate(mSampleApp1, mSampleApp2); + // The first update should apply immediately. waitForLauncherCondition("Predictions were not updated in loading state", launcher -> getPredictedApp(launcher).size() == 2); } /** - * Test tat prediction update is deferred if it is already visible + * Test that prediction update is deferred if it is already visible */ @Test @Ignore // b/131188880 @@ -124,6 +118,19 @@ public class AppPredictionsUITests extends AbstractQuickStepTest { assertEquals(3, getFromLauncher(this::getPredictedApp).size()); } + @Test + public void testPredictionsDisabled() { + mActivityMonitor.startLauncher(); + sendPredictionUpdate(); + mLauncher.pressHome().switchToAllApps(); + + waitForLauncherCondition("Predictions were not updated in loading state", + launcher -> launcher.getAppsView().getFloatingHeaderView() + .findFixedRowByType(PredictionRowView.class).getVisibility() == View.GONE); + assertFalse(PredictionUiStateManager.INSTANCE.get(mTargetContext) + .getCurrentState().isEnabled); + } + public ArrayList getPredictedApp(Launcher launcher) { PredictionRowView container = launcher.getAppsView().getFloatingHeaderView() .findFixedRowByType(PredictionRowView.class); @@ -138,20 +145,6 @@ public class AppPredictionsUITests extends AbstractQuickStepTest { return predictedAppViews; } - private ProgressBar findLoadingBar(Launcher launcher) { - PredictionRowView container = launcher.getAppsView().getFloatingHeaderView() - .findFixedRowByType(PredictionRowView.class); - - for (int i = 0; i < container.getChildCount(); i++) { - View view = container.getChildAt(i); - if (view instanceof ProgressBar) { - return (ProgressBar) view; - } - } - return null; - } - - private void sendPredictionUpdate(LauncherActivityInfo... activities) { getOnUiThread(() -> { List targets = new ArrayList<>(activities.length); -- cgit v1.2.3