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