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