OSDN Git Service

156befbe0ef58eae2aba239600e313cca8eca2e8
[android-x86/packages-apps-Launcher3.git] / src / com / android / launcher3 / LauncherAppState.java
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
50     public static LauncherAppState getInstance() {
51         if (INSTANCE == null) {
52             INSTANCE = new LauncherAppState();
53         }
54         return INSTANCE;
55     }
56
57     public static LauncherAppState getInstanceNoCreate() {
58         return INSTANCE;
59     }
60
61     public Context getContext() {
62         return sContext;
63     }
64
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
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     
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      */
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
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
157     IconCache getIconCache() {
158         return mIconCache;
159     }
160
161     LauncherModel getModel() {
162         return mModel;
163     }
164
165     boolean shouldShowAppOrWidgetProvider(ComponentName componentName) {
166         return mAppFilter == null || mAppFilter.shouldShowApp(componentName);
167     }
168
169     WidgetPreviewLoader.CacheDb getWidgetPreviewCacheDb() {
170         return mWidgetPreviewCacheDb;
171     }
172
173     static void setLauncherProvider(LauncherProvider provider) {
174         sLauncherProvider = new WeakReference<LauncherProvider>(provider);
175     }
176
177     static LauncherProvider getLauncherProvider() {
178         return sLauncherProvider.get();
179     }
180
181     public static String getSharedPreferencesKey() {
182         return SHARED_PREFERENCES_KEY;
183     }
184
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     }
202     public DynamicGrid getDynamicGrid() {
203         return mDynamicGrid;
204     }
205
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
211     public static boolean isScreenLarge(Resources res) {
212         return res.getBoolean(R.bool.is_large_tablet);
213     }
214
215     public static boolean isScreenLandscape(Context context) {
216         return context.getResources().getConfiguration().orientation ==
217             Configuration.ORIENTATION_LANDSCAPE;
218     }
219
220     public float getScreenDensity() {
221         return mScreenDensity;
222     }
223
224     public int getLongPressTimeout() {
225         return mLongPressTimeout;
226     }
227
228     public void onWallpaperChanged() {
229         mWallpaperChangedSinceLastCheck = true;
230     }
231
232     public boolean hasWallpaperChangedSinceLastCheck() {
233         boolean result = mWallpaperChangedSinceLastCheck;
234         mWallpaperChangedSinceLastCheck = false;
235         return result;
236     }
237
238     @Override
239     public void onAvailableSizeChanged(DeviceProfile grid) {
240         Utilities.setIconSize(grid.iconSizePx);
241     }
242
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 }