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