LauncherAppState.java revision 1d4a2df091e2b5928406ea503321563a0ec8a01e
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.Context; 23import android.content.Intent; 24import android.content.IntentFilter; 25import android.content.res.Configuration; 26import android.content.res.Resources; 27import android.graphics.Point; 28import android.os.Build; 29import android.util.DisplayMetrics; 30import android.util.Log; 31import android.view.Display; 32import android.view.WindowManager; 33 34import com.android.launcher3.compat.LauncherAppsCompat; 35import com.android.launcher3.compat.PackageInstallerCompat; 36import com.android.launcher3.compat.PackageInstallerCompat.PackageInstallInfo; 37import com.android.launcher3.util.Thunk; 38 39import java.lang.ref.WeakReference; 40import java.util.ArrayList; 41 42public class LauncherAppState implements DeviceProfile.DeviceProfileCallbacks { 43 44 private final AppFilter mAppFilter; 45 private final BuildInfo mBuildInfo; 46 @Thunk final LauncherModel mModel; 47 private final IconCache mIconCache; 48 private final WidgetPreviewLoader mWidgetCache; 49 50 private final boolean mIsScreenLarge; 51 private final float mScreenDensity; 52 private final int mLongPressTimeout = 300; 53 54 private boolean mWallpaperChangedSinceLastCheck; 55 56 private static WeakReference<LauncherProvider> sLauncherProvider; 57 private static Context sContext; 58 59 private static LauncherAppState INSTANCE; 60 61 private DynamicGrid mDynamicGrid; 62 private LauncherAccessibilityDelegate mAccessibilityDelegate; 63 64 public static LauncherAppState getInstance() { 65 if (INSTANCE == null) { 66 INSTANCE = new LauncherAppState(); 67 } 68 return INSTANCE; 69 } 70 71 public static LauncherAppState getInstanceNoCreate() { 72 return INSTANCE; 73 } 74 75 public Context getContext() { 76 return sContext; 77 } 78 79 public static void setApplicationContext(Context context) { 80 if (sContext != null) { 81 Log.w(Launcher.TAG, "setApplicationContext called twice! old=" + sContext + " new=" + context); 82 } 83 sContext = context.getApplicationContext(); 84 } 85 86 private LauncherAppState() { 87 if (sContext == null) { 88 throw new IllegalStateException("LauncherAppState inited before app context set"); 89 } 90 91 Log.v(Launcher.TAG, "LauncherAppState inited"); 92 93 if (sContext.getResources().getBoolean(R.bool.debug_memory_enabled)) { 94 MemoryTracker.startTrackingMe(sContext, "L"); 95 } 96 97 // set sIsScreenXLarge and mScreenDensity *before* creating icon cache 98 mIsScreenLarge = isScreenLarge(sContext.getResources()); 99 mScreenDensity = sContext.getResources().getDisplayMetrics().density; 100 mIconCache = new IconCache(sContext); 101 mWidgetCache = new WidgetPreviewLoader(sContext, mIconCache); 102 103 mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class)); 104 mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class)); 105 mModel = new LauncherModel(this, mIconCache, mAppFilter); 106 107 LauncherAppsCompat.getInstance(sContext).addOnAppsChangedCallback(mModel); 108 109 // Register intent receivers 110 IntentFilter filter = new IntentFilter(); 111 filter.addAction(Intent.ACTION_LOCALE_CHANGED); 112 filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); 113 filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED); 114 filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED); 115 sContext.registerReceiver(mModel, filter); 116 } 117 118 /** 119 * Call from Application.onTerminate(), which is not guaranteed to ever be called. 120 */ 121 public void onTerminate() { 122 sContext.unregisterReceiver(mModel); 123 final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext); 124 launcherApps.removeOnAppsChangedCallback(mModel); 125 PackageInstallerCompat.getInstance(sContext).onStop(); 126 } 127 128 /** 129 * Reloads the workspace items from the DB and re-binds the workspace. This should generally 130 * not be called as DB updates are automatically followed by UI update 131 */ 132 public void reloadWorkspace() { 133 mModel.resetLoadedState(false, true); 134 mModel.startLoaderFromBackground(); 135 } 136 137 LauncherModel setLauncher(Launcher launcher) { 138 mModel.initialize(launcher); 139 mAccessibilityDelegate = ((launcher != null) && Utilities.isLmpOrAbove()) ? 140 new LauncherAccessibilityDelegate(launcher) : null; 141 return mModel; 142 } 143 144 LauncherAccessibilityDelegate getAccessibilityDelegate() { 145 return mAccessibilityDelegate; 146 } 147 148 public 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 static void setLauncherProvider(LauncherProvider provider) { 161 sLauncherProvider = new WeakReference<LauncherProvider>(provider); 162 } 163 164 static LauncherProvider getLauncherProvider() { 165 return sLauncherProvider.get(); 166 } 167 168 public static String getSharedPreferencesKey() { 169 return LauncherFiles.SHARED_PREFERENCES_KEY; 170 } 171 172 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 173 DeviceProfile initDynamicGrid(Context context) { 174 mDynamicGrid = createDynamicGrid(context, mDynamicGrid); 175 mDynamicGrid.getDeviceProfile().addCallback(this); 176 return mDynamicGrid.getDeviceProfile(); 177 } 178 179 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 180 static DynamicGrid createDynamicGrid(Context context, DynamicGrid dynamicGrid) { 181 // Determine the dynamic grid properties 182 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 183 Display display = wm.getDefaultDisplay(); 184 185 Point realSize = new Point(); 186 display.getRealSize(realSize); 187 DisplayMetrics dm = new DisplayMetrics(); 188 display.getMetrics(dm); 189 190 if (dynamicGrid == null) { 191 Point smallestSize = new Point(); 192 Point largestSize = new Point(); 193 display.getCurrentSizeRange(smallestSize, largestSize); 194 195 dynamicGrid = new DynamicGrid(context, 196 context.getResources(), 197 Math.min(smallestSize.x, smallestSize.y), 198 Math.min(largestSize.x, largestSize.y), 199 realSize.x, realSize.y, 200 dm.widthPixels, dm.heightPixels); 201 } 202 203 // Update the icon size 204 DeviceProfile grid = dynamicGrid.getDeviceProfile(); 205 grid.updateFromConfiguration(context, context.getResources(), 206 realSize.x, realSize.y, 207 dm.widthPixels, dm.heightPixels); 208 return dynamicGrid; 209 } 210 211 public DynamicGrid getDynamicGrid() { 212 return mDynamicGrid; 213 } 214 215 public WidgetPreviewLoader getWidgetCache() { 216 return mWidgetCache; 217 } 218 219 public boolean isScreenLarge() { 220 return mIsScreenLarge; 221 } 222 223 // Need a version that doesn't require an instance of LauncherAppState for the wallpaper picker 224 public static boolean isScreenLarge(Resources res) { 225 return res.getBoolean(R.bool.is_large_tablet); 226 } 227 228 public static boolean isScreenLandscape(Context context) { 229 return context.getResources().getConfiguration().orientation == 230 Configuration.ORIENTATION_LANDSCAPE; 231 } 232 233 public float getScreenDensity() { 234 return mScreenDensity; 235 } 236 237 public int getLongPressTimeout() { 238 return mLongPressTimeout; 239 } 240 241 public void onWallpaperChanged() { 242 mWallpaperChangedSinceLastCheck = true; 243 } 244 245 public boolean hasWallpaperChangedSinceLastCheck() { 246 boolean result = mWallpaperChangedSinceLastCheck; 247 mWallpaperChangedSinceLastCheck = false; 248 return result; 249 } 250 251 @Override 252 public void onAvailableSizeChanged(DeviceProfile grid) { 253 Utilities.setIconSize(grid.iconSizePx); 254 } 255 256 public static boolean isDogfoodBuild() { 257 return getInstance().mBuildInfo.isDogfoodBuild(); 258 } 259 260 public void setPackageState(ArrayList<PackageInstallInfo> installInfo) { 261 mModel.setPackageState(installInfo); 262 } 263 264 /** 265 * Updates the icons and label of all icons for the provided package name. 266 */ 267 public void updatePackageBadge(String packageName) { 268 mModel.updatePackageBadge(packageName); 269 } 270} 271