summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/allapps/PredictiveAppsProvider.java
blob: ba39094c1a591eb1febe0139d38568f459eadbab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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;
        }
    }

}