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