summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYajat <yajatapps3@gmail.com>2017-11-10 21:08:21 +0100
committerArne Coucheron <arco68@gmail.com>2018-01-19 00:27:13 +0100
commitaca5a8bc95c1461419039a2041a8a54a84f49790 (patch)
tree1768ec3d10ef4bf859934f18030b768f513c9c32
parent7966f340e5ce151e19a6121a3b9c1ce8a9d8c87b (diff)
downloadandroid_packages_apps_Trebuchet-aca5a8bc95c1461419039a2041a8a54a84f49790.tar.gz
android_packages_apps_Trebuchet-aca5a8bc95c1461419039a2041a8a54a84f49790.tar.bz2
android_packages_apps_Trebuchet-aca5a8bc95c1461419039a2041a8a54a84f49790.zip
Trebuchet: predictive apps
jrizzoli: expose for runtime toggle Signed-off-by: Joey <joey@lineageos.org>
-rw-r--r--res/values/lineage_strings.xml5
-rw-r--r--res/xml/launcher_preferences.xml7
-rw-r--r--src/com/android/launcher3/Launcher.java31
-rw-r--r--src/com/android/launcher3/allapps/PredictiveAppsProvider.java125
-rw-r--r--src/com/android/launcher3/config/BaseFlags.java2
5 files changed, 164 insertions, 6 deletions
diff --git a/res/values/lineage_strings.xml b/res/values/lineage_strings.xml
index 5a453ef1f..fe574ebba 100644
--- a/res/values/lineage_strings.xml
+++ b/res/values/lineage_strings.xml
@@ -24,4 +24,9 @@
<!-- Expand statusbar -->
<string name="statusbar_expand">Swipe down to show notifications</string>
+
+ <!-- Predictive apps -->
+ <string name="predictive_apps_title">Predictive apps</string>
+ <string name="predictive_apps_summary_on">Your favorite apps will appear at the top of the drawer</string>
+ <string name="predictive_apps_summary_off">Your favorite apps won\'t appear at the top of the drawer</string>
</resources>
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 3be5d4792..7077758b2 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -59,4 +59,11 @@
android:defaultValue="true"
android:persistent="true" />
+ <SwitchPreference
+ android:key="pref_predictive_apps"
+ android:title="@string/predictive_apps_title"
+ android:summaryOn="@string/predictive_apps_summary_on"
+ android:summaryOff="@string/predictive_apps_summary_off"
+ android:defaultValue="true"
+ android:persistent="true" />
</PreferenceScreen>
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 7b4313314..ea5881608 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -87,6 +87,7 @@ import com.android.launcher3.Workspace.ItemOperator;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.allapps.AllAppsContainerView;
import com.android.launcher3.allapps.AllAppsTransitionController;
+import com.android.launcher3.allapps.PredictiveAppsProvider;
import com.android.launcher3.anim.AnimationLayerSet;
import com.android.launcher3.compat.AppWidgetManagerCompat;
import com.android.launcher3.compat.LauncherAppsCompat;
@@ -348,6 +349,8 @@ public class Launcher extends BaseActivity
private RotationPrefChangeHandler mRotationPrefChangeHandler;
+ private PredictiveAppsProvider mPredictiveAppsProvider;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
if (DEBUG_STRICT_MODE) {
@@ -368,6 +371,8 @@ public class Launcher extends BaseActivity
Trace.beginSection("Launcher-onCreate");
}
+ mPredictiveAppsProvider = new PredictiveAppsProvider(this);
+
if (mLauncherCallbacks != null) {
mLauncherCallbacks.preOnCreate();
}
@@ -487,6 +492,8 @@ public class Launcher extends BaseActivity
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onCreate(savedInstanceState);
}
+
+ tryAndUpdatePredictedApps();
}
@Override
@@ -2607,6 +2614,9 @@ public class Launcher extends BaseActivity
} else {
// Could be launching some bookkeeping activity
startActivity(intent, optsBundle);
+ if (isAllAppsVisible()) {
+ mPredictiveAppsProvider.updateComponentCount(intent.getComponent());
+ }
}
} finally {
StrictMode.setVmPolicy(oldPolicy);
@@ -2693,6 +2703,9 @@ public class Launcher extends BaseActivity
} else if (user == null || user.equals(Process.myUserHandle())) {
// Could be launching some bookkeeping activity
startActivity(intent, optsBundle);
+ if (isAllAppsVisible()) {
+ mPredictiveAppsProvider.updateComponentCount(intent.getComponent());
+ }
} else {
LauncherAppsCompat.getInstance(this).startActivityForProfile(
intent.getComponent(), user, intent.getSourceBounds(), optsBundle);
@@ -3053,12 +3066,20 @@ public class Launcher extends BaseActivity
* resumed.
*/
public void tryAndUpdatePredictedApps() {
- if (mLauncherCallbacks != null) {
- List<ComponentKeyMapper<AppInfo>> apps = mLauncherCallbacks.getPredictedApps();
- if (apps != null) {
- mAppsView.setPredictedApps(apps);
- }
+ if (!mSharedPrefs.getBoolean("pref_predictive_apps", true)) {
+ mAppsView.setPredictedApps(new ArrayList<>());
+ return;
+ }
+
+ List<ComponentKeyMapper<AppInfo>> apps;
+ if (mLauncherCallbacks == null) {
+ apps = mPredictiveAppsProvider.getPredictions();
+ mPredictiveAppsProvider.updateTopPredictedApps();
+ } else {
+ apps = mLauncherCallbacks.getPredictedApps();
}
+
+ mAppsView.setPredictedApps(apps);
}
void lockAllApps() {
diff --git a/src/com/android/launcher3/allapps/PredictiveAppsProvider.java b/src/com/android/launcher3/allapps/PredictiveAppsProvider.java
new file mode 100644
index 000000000..ba39094c1
--- /dev/null
+++ b/src/com/android/launcher3/allapps/PredictiveAppsProvider.java
@@ -0,0 +1,125 @@
+package com.android.launcher3.allapps;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Process;
+
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.util.ComponentKey;
+import com.android.launcher3.util.ComponentKeyMapper;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class PredictiveAppsProvider {
+ private static final int NUM_PREDICTIVE_APPS_TO_HOLD = 9; // since we can't have more than 9 columns
+
+ private static final String PREDICTIVE_APPS_KEY = "predictive_apps";
+ private static final String TOP_PREDICTIVE_APPS_KEY = "top_predictive_apps";
+
+ private SharedPreferences mPrefs;
+
+ public PredictiveAppsProvider(Context context) {
+ this.mPrefs = Utilities.getPrefs(context.getApplicationContext());
+ }
+
+ public void updateComponentCount(ComponentName component) {
+ String key = buildComponentString(component);
+ long current = mPrefs.getLong(key, 0);
+
+ mPrefs.edit().putLong(key, current + 1).apply();
+
+ // ensure that the set of predictive apps contains this one
+ Set<String> predictiveApps =
+ mPrefs.getStringSet(PREDICTIVE_APPS_KEY, new HashSet<>());
+ if (!predictiveApps.contains(key)) {
+ predictiveApps.add(key);
+ mPrefs.edit().putStringSet(PREDICTIVE_APPS_KEY, predictiveApps).apply();
+ }
+ }
+
+ public void updateTopPredictedApps() {
+ new Thread(() -> {
+ List< PredictedApp > allPredictions = new ArrayList<>();
+ Set<String> predictiveAppsSet =
+ mPrefs.getStringSet(PREDICTIVE_APPS_KEY, new HashSet<>());
+
+ for (String s : predictiveAppsSet) {
+ allPredictions.add(new PredictedApp(buildComponentFromString(s),
+ mPrefs.getLong(s, 0)));
+ }
+
+ Collections.sort(allPredictions, (result1, result2) ->
+ Long.valueOf(result2.count).compareTo(result1.count));
+
+ if (allPredictions.size() > NUM_PREDICTIVE_APPS_TO_HOLD) {
+ allPredictions = allPredictions.subList(0, NUM_PREDICTIVE_APPS_TO_HOLD);
+ }
+
+ mPrefs.edit().putString(TOP_PREDICTIVE_APPS_KEY,
+ buildStringFromAppList(allPredictions)).apply();
+ }).start();
+ }
+
+ public List<ComponentKeyMapper<AppInfo>> getPredictions() {
+ String predictions = mPrefs.getString(TOP_PREDICTIVE_APPS_KEY, "");
+ if (predictions.isEmpty()) {
+ return new ArrayList<>();
+ }
+
+ String[] topPredictions = predictions.split(" ");
+ List<ComponentKeyMapper<AppInfo>> keys = new ArrayList<>();
+
+ for (int i = 0; i < topPredictions.length - 1; i++) {
+ keys.add(buildComponentKey(topPredictions[i] + " " + topPredictions[i + 1]));
+ }
+
+ return keys;
+ }
+
+ private String buildStringFromAppList(List<PredictedApp> apps) {
+ StringBuilder string = new StringBuilder();
+ for (PredictedApp app : apps) {
+ string.append(buildComponentString(app.component)).append(" ");
+ }
+
+ try {
+ return string.substring(0, string.length() - 1);
+ } catch (StringIndexOutOfBoundsException e) {
+ return "";
+ }
+ }
+
+ private String buildComponentString(ComponentName component) {
+ return component.getPackageName() + " " + component.getClassName();
+ }
+
+ private ComponentName buildComponentFromString(String key) {
+ String[] arr = key.split(" ");
+ return new ComponentName(arr[0], arr[1]);
+ }
+
+ private ComponentKeyMapper<AppInfo> buildComponentKey(String key) {
+ return buildComponentKey(buildComponentFromString(key));
+ }
+
+ private ComponentKeyMapper<AppInfo> buildComponentKey(ComponentName component) {
+ return new ComponentKeyMapper<>(new ComponentKey(component, Process.myUserHandle()));
+ }
+
+ private class PredictedApp {
+ public ComponentName component;
+ public long count;
+
+ public PredictedApp(ComponentName component, long count) {
+ this.component = component;
+ this.count = count;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/src/com/android/launcher3/config/BaseFlags.java b/src/com/android/launcher3/config/BaseFlags.java
index 15fa553bf..a9ad301af 100644
--- a/src/com/android/launcher3/config/BaseFlags.java
+++ b/src/com/android/launcher3/config/BaseFlags.java
@@ -61,7 +61,7 @@ abstract class BaseFlags {
// When enabled, adaptive icons would have shadows baked when being stored to icon cache.
public static final boolean ADAPTIVE_ICON_SHADOW = true;
// When enabled, app discovery will be enabled if service is implemented
- public static final boolean DISCOVERY_ENABLED = false;
+ public static final boolean DISCOVERY_ENABLED = true;
// When enabled, the qsb will be moved to the hotseat.
public static final boolean QSB_IN_HOTSEAT = true;