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