mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-19 18:58:19 +00:00
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
This commit is contained in:
@@ -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);
|
||||
|
||||
mMessageHandler.sendEmptyMessage(MSG_INIT);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void onIdpChanged(int changeFlags, InvariantDeviceProfile profile) {
|
||||
// Reinitialize everything
|
||||
setEnabled(mEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
@UiThread
|
||||
public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
|
||||
if (KEY_APP_SUGGESTION.equals(key)) {
|
||||
setEnabled(prefs.getBoolean(KEY_APP_SUGGESTION, true));
|
||||
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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<BubbleTextView> 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<AppTarget> targets = new ArrayList<>(activities.length);
|
||||
|
||||
Reference in New Issue
Block a user