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.views.ActivityContext; 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 * @param <T> Context which owns these preferences. 34 */ 35 public class OnboardingPrefs<T extends ActivityContext> { 36 37 public static final String HOME_BOUNCE_SEEN = "launcher.apps_view_shown"; 38 public static final String HOME_BOUNCE_COUNT = "launcher.home_bounce_count"; 39 public static final String HOTSEAT_DISCOVERY_TIP_COUNT = "launcher.hotseat_discovery_tip_count"; 40 public static final String HOTSEAT_LONGPRESS_TIP_SEEN = "launcher.hotseat_longpress_tip_seen"; 41 public static final String ALL_APPS_VISITED_COUNT = "launcher.all_apps_visited_count"; 42 public static final String TASKBAR_EDU_TOOLTIP_STEP = "launcher.taskbar_edu_tooltip_step"; 43 // When adding a new key, add it here as well, to be able to reset it from Developer Options. 44 public static final Map<String, String[]> ALL_PREF_KEYS = Map.of( 45 "All Apps Bounce", new String[] { HOME_BOUNCE_SEEN, HOME_BOUNCE_COUNT }, 46 "Hybrid Hotseat Education", new String[] { HOTSEAT_DISCOVERY_TIP_COUNT, 47 HOTSEAT_LONGPRESS_TIP_SEEN }, 48 "Taskbar Education", new String[] { TASKBAR_EDU_TOOLTIP_STEP }, 49 "All Apps Visited Count", new String[] {ALL_APPS_VISITED_COUNT} 50 ); 51 52 /** 53 * Events that either have happened or have not (booleans). 54 */ 55 @StringDef(value = { 56 HOME_BOUNCE_SEEN, 57 HOTSEAT_LONGPRESS_TIP_SEEN, 58 }) 59 @Retention(RetentionPolicy.SOURCE) 60 public @interface EventBoolKey {} 61 62 /** 63 * Events that occur multiple times, which we count up to a max defined in {@link #MAX_COUNTS}. 64 */ 65 @StringDef(value = { 66 HOME_BOUNCE_COUNT, 67 HOTSEAT_DISCOVERY_TIP_COUNT, 68 ALL_APPS_VISITED_COUNT, 69 TASKBAR_EDU_TOOLTIP_STEP, 70 }) 71 @Retention(RetentionPolicy.SOURCE) 72 public @interface EventCountKey {} 73 74 private static final Map<String, Integer> MAX_COUNTS; 75 76 static { 77 Map<String, Integer> maxCounts = new ArrayMap<>(5); maxCounts.put(HOME_BOUNCE_COUNT, 3)78 maxCounts.put(HOME_BOUNCE_COUNT, 3); maxCounts.put(HOTSEAT_DISCOVERY_TIP_COUNT, 5)79 maxCounts.put(HOTSEAT_DISCOVERY_TIP_COUNT, 5); maxCounts.put(ALL_APPS_VISITED_COUNT, 20)80 maxCounts.put(ALL_APPS_VISITED_COUNT, 20); maxCounts.put(TASKBAR_EDU_TOOLTIP_STEP, 2)81 maxCounts.put(TASKBAR_EDU_TOOLTIP_STEP, 2); 82 MAX_COUNTS = Collections.unmodifiableMap(maxCounts); 83 } 84 85 protected final T mLauncher; 86 protected final SharedPreferences mSharedPrefs; 87 OnboardingPrefs(T launcher, SharedPreferences sharedPrefs)88 public OnboardingPrefs(T launcher, SharedPreferences sharedPrefs) { 89 mLauncher = launcher; 90 mSharedPrefs = sharedPrefs; 91 } 92 93 /** @return The number of times we have seen the given event. */ getCount(@ventCountKey String key)94 public int getCount(@EventCountKey String key) { 95 return mSharedPrefs.getInt(key, 0); 96 } 97 98 /** @return Whether we have seen this event enough times, as defined by {@link #MAX_COUNTS}. */ hasReachedMaxCount(@ventCountKey String eventKey)99 public boolean hasReachedMaxCount(@EventCountKey String eventKey) { 100 return hasReachedMaxCount(getCount(eventKey), eventKey); 101 } 102 hasReachedMaxCount(int count, @EventCountKey String eventKey)103 private boolean hasReachedMaxCount(int count, @EventCountKey String eventKey) { 104 return count >= MAX_COUNTS.get(eventKey); 105 } 106 107 /** @return Whether we have seen the given event. */ getBoolean(@ventBoolKey String key)108 public boolean getBoolean(@EventBoolKey String key) { 109 return mSharedPrefs.getBoolean(key, false); 110 } 111 112 /** 113 * Marks on-boarding preference boolean at true 114 */ markChecked(String flag)115 public void markChecked(String flag) { 116 mSharedPrefs.edit().putBoolean(flag, true).apply(); 117 } 118 119 /** 120 * Add 1 to the given event count, if we haven't already reached the max count. 121 * 122 * @return Whether we have now reached the max count. 123 */ incrementEventCount(@ventCountKey String eventKey)124 public boolean incrementEventCount(@EventCountKey String eventKey) { 125 int count = getCount(eventKey); 126 if (hasReachedMaxCount(count, eventKey)) { 127 return true; 128 } 129 count++; 130 mSharedPrefs.edit().putInt(eventKey, count).apply(); 131 return hasReachedMaxCount(count, eventKey); 132 } 133 134 /** 135 * Sets the event count to the given value. 136 * 137 * @return Whether we have now reached the max count. 138 */ setEventCount(int count, @EventCountKey String eventKey)139 public boolean setEventCount(int count, @EventCountKey String eventKey) { 140 mSharedPrefs.edit().putInt(eventKey, count).apply(); 141 return hasReachedMaxCount(count, eventKey); 142 } 143 } 144