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