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