1 /* 2 * Copyright (C) 2018 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.allapps; 17 18 import android.view.View; 19 import android.view.ViewGroup; 20 21 import com.android.launcher3.AppInfo; 22 import com.android.launcher3.BubbleTextView; 23 import com.android.launcher3.ItemInfo; 24 import com.android.launcher3.PromiseAppInfo; 25 import com.android.launcher3.util.ComponentKey; 26 import com.android.launcher3.util.PackageUserKey; 27 28 import java.util.ArrayList; 29 import java.util.Collection; 30 import java.util.HashMap; 31 import java.util.List; 32 import java.util.function.Consumer; 33 import java.util.function.Predicate; 34 35 /** 36 * A utility class to maintain the collection of all apps. 37 */ 38 public class AllAppsStore { 39 40 // Defer updates flag used to defer all apps updates to the next draw. 41 public static final int DEFER_UPDATES_NEXT_DRAW = 1 << 0; 42 // Defer updates flag used to defer all apps updates while the user interacts with all apps. 43 public static final int DEFER_UPDATES_USER_INTERACTION = 1 << 1; 44 // Defer updates flag used to defer all apps updates by a test's request. 45 public static final int DEFER_UPDATES_TEST = 1 << 2; 46 47 private PackageUserKey mTempKey = new PackageUserKey(null, null); 48 private final HashMap<ComponentKey, AppInfo> mComponentToAppMap = new HashMap<>(); 49 private final List<OnUpdateListener> mUpdateListeners = new ArrayList<>(); 50 private final ArrayList<ViewGroup> mIconContainers = new ArrayList<>(); 51 52 private int mDeferUpdatesFlags = 0; 53 private boolean mUpdatePending = false; 54 getApps()55 public Collection<AppInfo> getApps() { 56 return mComponentToAppMap.values(); 57 } 58 59 /** 60 * Sets the current set of apps. 61 */ setApps(List<AppInfo> apps)62 public void setApps(List<AppInfo> apps) { 63 mComponentToAppMap.clear(); 64 addOrUpdateApps(apps); 65 } 66 getApp(ComponentKey key)67 public AppInfo getApp(ComponentKey key) { 68 return mComponentToAppMap.get(key); 69 } 70 enableDeferUpdates(int flag)71 public void enableDeferUpdates(int flag) { 72 mDeferUpdatesFlags |= flag; 73 } 74 disableDeferUpdates(int flag)75 public void disableDeferUpdates(int flag) { 76 mDeferUpdatesFlags &= ~flag; 77 if (mDeferUpdatesFlags == 0 && mUpdatePending) { 78 notifyUpdate(); 79 mUpdatePending = false; 80 } 81 } 82 getDeferUpdatesFlags()83 public int getDeferUpdatesFlags() { 84 return mDeferUpdatesFlags; 85 } 86 87 /** 88 * Adds or updates existing apps in the list 89 */ addOrUpdateApps(List<AppInfo> apps)90 public void addOrUpdateApps(List<AppInfo> apps) { 91 for (AppInfo app : apps) { 92 mComponentToAppMap.put(app.toComponentKey(), app); 93 } 94 notifyUpdate(); 95 } 96 97 /** 98 * Removes some apps from the list. 99 */ removeApps(List<AppInfo> apps)100 public void removeApps(List<AppInfo> apps) { 101 for (AppInfo app : apps) { 102 mComponentToAppMap.remove(app.toComponentKey()); 103 } 104 notifyUpdate(); 105 } 106 107 notifyUpdate()108 private void notifyUpdate() { 109 if (mDeferUpdatesFlags != 0) { 110 mUpdatePending = true; 111 return; 112 } 113 int count = mUpdateListeners.size(); 114 for (int i = 0; i < count; i++) { 115 mUpdateListeners.get(i).onAppsUpdated(); 116 } 117 } 118 addUpdateListener(OnUpdateListener listener)119 public void addUpdateListener(OnUpdateListener listener) { 120 mUpdateListeners.add(listener); 121 } 122 removeUpdateListener(OnUpdateListener listener)123 public void removeUpdateListener(OnUpdateListener listener) { 124 mUpdateListeners.remove(listener); 125 } 126 registerIconContainer(ViewGroup container)127 public void registerIconContainer(ViewGroup container) { 128 if (container != null) { 129 mIconContainers.add(container); 130 } 131 } 132 unregisterIconContainer(ViewGroup container)133 public void unregisterIconContainer(ViewGroup container) { 134 mIconContainers.remove(container); 135 } 136 updateNotificationDots(Predicate<PackageUserKey> updatedDots)137 public void updateNotificationDots(Predicate<PackageUserKey> updatedDots) { 138 updateAllIcons((child) -> { 139 if (child.getTag() instanceof ItemInfo) { 140 ItemInfo info = (ItemInfo) child.getTag(); 141 if (mTempKey.updateFromItemInfo(info) && updatedDots.test(mTempKey)) { 142 child.applyDotState(info, true /* animate */); 143 } 144 } 145 }); 146 } 147 updatePromiseAppProgress(PromiseAppInfo app)148 public void updatePromiseAppProgress(PromiseAppInfo app) { 149 updateAllIcons((child) -> { 150 if (child.getTag() == app) { 151 child.applyProgressLevel(app.level); 152 } 153 }); 154 } 155 updateAllIcons(Consumer<BubbleTextView> action)156 private void updateAllIcons(Consumer<BubbleTextView> action) { 157 for (int i = mIconContainers.size() - 1; i >= 0; i--) { 158 ViewGroup parent = mIconContainers.get(i); 159 int childCount = parent.getChildCount(); 160 161 for (int j = 0; j < childCount; j++) { 162 View child = parent.getChildAt(j); 163 if (child instanceof BubbleTextView) { 164 action.accept((BubbleTextView) child); 165 } 166 } 167 } 168 } 169 170 public interface OnUpdateListener { onAppsUpdated()171 void onAppsUpdated(); 172 } 173 } 174