• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 
17 package com.android.launcher3;
18 
19 import android.app.SearchManager;
20 import android.content.ComponentName;
21 import android.content.ContentResolver;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.IntentFilter;
25 import android.content.res.Configuration;
26 import android.content.res.Resources;
27 import android.database.ContentObserver;
28 import android.os.Handler;
29 import android.util.Log;
30 
31 import com.android.launcher3.compat.LauncherAppsCompat;
32 import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo;
33 
34 import java.lang.ref.WeakReference;
35 import java.util.ArrayList;
36 
37 public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks {
38     private static final String TAG = "LauncherAppState";
39     private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
40 
41     private static final boolean DEBUG = false;
42 
43     private final AppFilter mAppFilter;
44     private final BuildInfo mBuildInfo;
45     private LauncherModel mModel;
46     private IconCache mIconCache;
47     private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb;
48     private boolean mIsScreenLarge;
49     private float mScreenDensity;
50     private int mLongPressTimeout = 300;
51     private boolean mWallpaperChangedSinceLastCheck;
52 
53     private static WeakReference<LauncherProvider> sLauncherProvider;
54     private static Context sContext;
55 
56     private static LauncherAppState INSTANCE;
57 
58     private DynamicGrid mDynamicGrid;
59 
getInstance()60     public static LauncherAppState getInstance() {
61         if (INSTANCE == null) {
62             INSTANCE = new LauncherAppState();
63         }
64         return INSTANCE;
65     }
66 
getInstanceNoCreate()67     public static LauncherAppState getInstanceNoCreate() {
68         return INSTANCE;
69     }
70 
getContext()71     public Context getContext() {
72         return sContext;
73     }
74 
setApplicationContext(Context context)75     public static void setApplicationContext(Context context) {
76         if (sContext != null) {
77             Log.w(Launcher.TAG, "setApplicationContext called twice! old=" + sContext + " new=" + context);
78         }
79         sContext = context.getApplicationContext();
80     }
81 
LauncherAppState()82     private LauncherAppState() {
83         if (sContext == null) {
84             throw new IllegalStateException("LauncherAppState inited before app context set");
85         }
86 
87         Log.v(Launcher.TAG, "LauncherAppState inited");
88 
89         if (sContext.getResources().getBoolean(R.bool.debug_memory_enabled)) {
90             MemoryTracker.startTrackingMe(sContext, "L");
91         }
92 
93         // set sIsScreenXLarge and mScreenDensity *before* creating icon cache
94         mIsScreenLarge = isScreenLarge(sContext.getResources());
95         mScreenDensity = sContext.getResources().getDisplayMetrics().density;
96 
97         recreateWidgetPreviewDb();
98         mIconCache = new IconCache(sContext);
99 
100         mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class));
101         mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class));
102         mModel = new LauncherModel(this, mIconCache, mAppFilter);
103         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
104         launcherApps.addOnAppsChangedCallback(mModel);
105 
106         // Register intent receivers
107         IntentFilter filter = new IntentFilter();
108         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
109         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
110         sContext.registerReceiver(mModel, filter);
111         filter = new IntentFilter();
112         filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
113         sContext.registerReceiver(mModel, filter);
114         filter = new IntentFilter();
115         filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
116         sContext.registerReceiver(mModel, filter);
117 
118         // Register for changes to the favorites
119         ContentResolver resolver = sContext.getContentResolver();
120         resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,
121                 mFavoritesObserver);
122     }
123 
recreateWidgetPreviewDb()124     public void recreateWidgetPreviewDb() {
125         if (mWidgetPreviewCacheDb != null) {
126             mWidgetPreviewCacheDb.close();
127         }
128         mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
129     }
130 
131     /**
132      * Call from Application.onTerminate(), which is not guaranteed to ever be called.
133      */
onTerminate()134     public void onTerminate() {
135         sContext.unregisterReceiver(mModel);
136         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
137         launcherApps.removeOnAppsChangedCallback(mModel);
138 
139         ContentResolver resolver = sContext.getContentResolver();
140         resolver.unregisterContentObserver(mFavoritesObserver);
141     }
142 
143     /**
144      * Receives notifications whenever the user favorites have changed.
145      */
146     private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
147         @Override
148         public void onChange(boolean selfChange) {
149             // If the database has ever changed, then we really need to force a reload of the
150             // workspace on the next load
151             mModel.resetLoadedState(false, true);
152             mModel.startLoaderFromBackground();
153         }
154     };
155 
setLauncher(Launcher launcher)156     LauncherModel setLauncher(Launcher launcher) {
157         if (mModel == null) {
158             throw new IllegalStateException("setLauncher() called before init()");
159         }
160         mModel.initialize(launcher);
161         return mModel;
162     }
163 
getIconCache()164     public IconCache getIconCache() {
165         return mIconCache;
166     }
167 
getModel()168     LauncherModel getModel() {
169         return mModel;
170     }
171 
shouldShowAppOrWidgetProvider(ComponentName componentName)172     boolean shouldShowAppOrWidgetProvider(ComponentName componentName) {
173         return mAppFilter == null || mAppFilter.shouldShowApp(componentName);
174     }
175 
getWidgetPreviewCacheDb()176     WidgetPreviewLoader.CacheDb getWidgetPreviewCacheDb() {
177         return mWidgetPreviewCacheDb;
178     }
179 
setLauncherProvider(LauncherProvider provider)180     static void setLauncherProvider(LauncherProvider provider) {
181         sLauncherProvider = new WeakReference<LauncherProvider>(provider);
182     }
183 
getLauncherProvider()184     static LauncherProvider getLauncherProvider() {
185         return sLauncherProvider.get();
186     }
187 
getSharedPreferencesKey()188     public static String getSharedPreferencesKey() {
189         return SHARED_PREFERENCES_KEY;
190     }
191 
initDynamicGrid(Context context, int minWidth, int minHeight, int width, int height, int availableWidth, int availableHeight)192     DeviceProfile initDynamicGrid(Context context, int minWidth, int minHeight,
193                                   int width, int height,
194                                   int availableWidth, int availableHeight) {
195         if (mDynamicGrid == null) {
196             mDynamicGrid = new DynamicGrid(context,
197                     context.getResources(),
198                     minWidth, minHeight, width, height,
199                     availableWidth, availableHeight);
200             mDynamicGrid.getDeviceProfile().addCallback(this);
201         }
202 
203         // Update the icon size
204         DeviceProfile grid = mDynamicGrid.getDeviceProfile();
205         grid.updateFromConfiguration(context, context.getResources(), width, height,
206                 availableWidth, availableHeight);
207         return grid;
208     }
getDynamicGrid()209     public DynamicGrid getDynamicGrid() {
210         return mDynamicGrid;
211     }
212 
isScreenLarge()213     public boolean isScreenLarge() {
214         return mIsScreenLarge;
215     }
216 
217     // Need a version that doesn't require an instance of LauncherAppState for the wallpaper picker
isScreenLarge(Resources res)218     public static boolean isScreenLarge(Resources res) {
219         return res.getBoolean(R.bool.is_large_tablet);
220     }
221 
isScreenLandscape(Context context)222     public static boolean isScreenLandscape(Context context) {
223         return context.getResources().getConfiguration().orientation ==
224             Configuration.ORIENTATION_LANDSCAPE;
225     }
226 
getScreenDensity()227     public float getScreenDensity() {
228         return mScreenDensity;
229     }
230 
getLongPressTimeout()231     public int getLongPressTimeout() {
232         return mLongPressTimeout;
233     }
234 
onWallpaperChanged()235     public void onWallpaperChanged() {
236         mWallpaperChangedSinceLastCheck = true;
237     }
238 
hasWallpaperChangedSinceLastCheck()239     public boolean hasWallpaperChangedSinceLastCheck() {
240         boolean result = mWallpaperChangedSinceLastCheck;
241         mWallpaperChangedSinceLastCheck = false;
242         return result;
243     }
244 
245     @Override
onAvailableSizeChanged(DeviceProfile grid)246     public void onAvailableSizeChanged(DeviceProfile grid) {
247         Utilities.setIconSize(grid.iconSizePx);
248     }
249 
isDisableAllApps()250     public static boolean isDisableAllApps() {
251         // Returns false on non-dogfood builds.
252         return getInstance().mBuildInfo.isDogfoodBuild() &&
253                 Launcher.isPropertyEnabled(Launcher.DISABLE_ALL_APPS_PROPERTY);
254     }
255 
isDogfoodBuild()256     public static boolean isDogfoodBuild() {
257         return getInstance().mBuildInfo.isDogfoodBuild();
258     }
259 
setPackageState(ArrayList<PackageInstallInfo> installInfo)260     public void setPackageState(ArrayList<PackageInstallInfo> installInfo) {
261         mModel.setPackageState(installInfo);
262     }
263 
264     /**
265      * Updates the icons and label of all icons for the provided package name.
266      */
updatePackageBadge(String packageName)267     public void updatePackageBadge(String packageName) {
268         mModel.updatePackageBadge(packageName);
269     }
270 }
271