1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.launcher3.util;
17 
18 import android.content.SharedPreferences;
19 import android.util.ArrayMap;
20 
21 import androidx.annotation.StringDef;
22 
23 import com.android.launcher3.Launcher;
24 
25 import java.lang.annotation.Retention;
26 import java.lang.annotation.RetentionPolicy;
27 import java.util.Collections;
28 import java.util.Map;
29 
30 /**
31  * Stores and retrieves onboarding-related data via SharedPreferences.
32  */
33 public class OnboardingPrefs<T extends Launcher> {
34 
35     public static final String HOME_BOUNCE_SEEN = "launcher.apps_view_shown";
36     public static final String SHELF_BOUNCE_SEEN = "launcher.shelf_bounce_seen";
37     public static final String HOME_BOUNCE_COUNT = "launcher.home_bounce_count";
38     public static final String SHELF_BOUNCE_COUNT = "launcher.shelf_bounce_count";
39     public static final String ALL_APPS_COUNT = "launcher.all_apps_count";
40     public static final String HOTSEAT_DISCOVERY_TIP_COUNT = "launcher.hotseat_discovery_tip_count";
41     public static final String HOTSEAT_LONGPRESS_TIP_SEEN = "launcher.hotseat_longpress_tip_seen";
42 
43     /**
44      * Events that either have happened or have not (booleans).
45      */
46     @StringDef(value = {
47             HOME_BOUNCE_SEEN,
48             SHELF_BOUNCE_SEEN
49     })
50     @Retention(RetentionPolicy.SOURCE)
51     public @interface EventBoolKey {}
52 
53     /**
54      * Events that occur multiple times, which we count up to a max defined in {@link #MAX_COUNTS}.
55      */
56     @StringDef(value = {
57             HOME_BOUNCE_COUNT,
58             SHELF_BOUNCE_COUNT,
59             ALL_APPS_COUNT,
60             HOTSEAT_DISCOVERY_TIP_COUNT
61     })
62     @Retention(RetentionPolicy.SOURCE)
63     public @interface EventCountKey {}
64 
65     private static final Map<String, Integer> MAX_COUNTS;
66     static {
67         Map<String, Integer> maxCounts = new ArrayMap<>(3);
maxCounts.put(HOME_BOUNCE_COUNT, 3)68         maxCounts.put(HOME_BOUNCE_COUNT, 3);
maxCounts.put(SHELF_BOUNCE_COUNT, 3)69         maxCounts.put(SHELF_BOUNCE_COUNT, 3);
maxCounts.put(ALL_APPS_COUNT, 5)70         maxCounts.put(ALL_APPS_COUNT, 5);
maxCounts.put(HOTSEAT_DISCOVERY_TIP_COUNT, 5)71         maxCounts.put(HOTSEAT_DISCOVERY_TIP_COUNT, 5);
72         MAX_COUNTS = Collections.unmodifiableMap(maxCounts);
73     }
74 
75     protected final T mLauncher;
76     protected final SharedPreferences mSharedPrefs;
77 
OnboardingPrefs(T launcher, SharedPreferences sharedPrefs)78     public OnboardingPrefs(T launcher, SharedPreferences sharedPrefs) {
79         mLauncher = launcher;
80         mSharedPrefs = sharedPrefs;
81     }
82 
83     /** @return The number of times we have seen the given event. */
getCount(@ventCountKey String key)84     public int getCount(@EventCountKey String key) {
85         return mSharedPrefs.getInt(key, 0);
86     }
87 
88     /** @return Whether we have seen this event enough times, as defined by {@link #MAX_COUNTS}. */
hasReachedMaxCount(@ventCountKey String eventKey)89     public boolean hasReachedMaxCount(@EventCountKey String eventKey) {
90         return hasReachedMaxCount(getCount(eventKey), eventKey);
91     }
92 
hasReachedMaxCount(int count, @EventCountKey String eventKey)93     private boolean hasReachedMaxCount(int count, @EventCountKey String eventKey) {
94         return count >= MAX_COUNTS.get(eventKey);
95     }
96 
97     /** @return Whether we have seen the given event. */
getBoolean(@ventBoolKey String key)98     public boolean getBoolean(@EventBoolKey String key) {
99         return mSharedPrefs.getBoolean(key, false);
100     }
101 
102     /**
103      * Marks on-boarding preference boolean at true
104      */
markChecked(String flag)105     public void markChecked(String flag) {
106         mSharedPrefs.edit().putBoolean(flag, true).apply();
107     }
108 
109     /**
110      * Add 1 to the given event count, if we haven't already reached the max count.
111      * @return Whether we have now reached the max count.
112      */
incrementEventCount(@ventCountKey String eventKey)113     public boolean incrementEventCount(@EventCountKey String eventKey) {
114         int count = getCount(eventKey);
115         if (hasReachedMaxCount(count, eventKey)) {
116             return true;
117         }
118         count++;
119         mSharedPrefs.edit().putInt(eventKey, count).apply();
120         return hasReachedMaxCount(count, eventKey);
121     }
122 }
123