LauncherAppState.java revision 957c13f032fc4088b3273cec08603c67c069e2c6
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 // For handling managed profiles 116 filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED); 117 filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED); 118 119 sContext.registerReceiver(mModel, filter); 120 } 121 122 /** 123 * Call from Application.onTerminate(), which is not guaranteed to ever be called. 124 */ 125 public void onTerminate() { 126 sContext.unregisterReceiver(mModel); 127 final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext); 128 launcherApps.removeOnAppsChangedCallback(mModel); 129 PackageInstallerCompat.getInstance(sContext).onStop(); 130 } 131 132 /** 133 * Reloads the workspace items from the DB and re-binds the workspace. This should generally 134 * not be called as DB updates are automatically followed by UI update 135 */ 136 public void reloadWorkspace() { 137 mModel.resetLoadedState(false, true); 138 mModel.startLoaderFromBackground(); 139 } 140 141 LauncherModel setLauncher(Launcher launcher) { 142 mModel.initialize(launcher); 143 mAccessibilityDelegate = ((launcher != null) && Utilities.isLmpOrAbove()) ? 144 new LauncherAccessibilityDelegate(launcher) : null; 145 return mModel; 146 } 147 148 public LauncherAccessibilityDelegate getAccessibilityDelegate() { 149 return mAccessibilityDelegate; 150 } 151 152 public IconCache getIconCache() { 153 return mIconCache; 154 } 155 156 public LauncherModel getModel() { 157 return mModel; 158 } 159 160 boolean shouldShowAppOrWidgetProvider(ComponentName componentName) { 161 return mAppFilter == null || mAppFilter.shouldShowApp(componentName); 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 LauncherFiles.SHARED_PREFERENCES_KEY; 174 } 175 176 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 177 DeviceProfile initDynamicGrid(Context context) { 178 mDynamicGrid = createDynamicGrid(context, mDynamicGrid); 179 mDynamicGrid.getDeviceProfile().addCallback(this); 180 return mDynamicGrid.getDeviceProfile(); 181 } 182 183 @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 184 static DynamicGrid createDynamicGrid(Context context, DynamicGrid dynamicGrid) { 185 // Determine the dynamic grid properties 186 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 187 Display display = wm.getDefaultDisplay(); 188 189 Point realSize = new Point(); 190 display.getRealSize(realSize); 191 DisplayMetrics dm = new DisplayMetrics(); 192 display.getMetrics(dm); 193 194 if (dynamicGrid == null) { 195 Point smallestSize = new Point(); 196 Point largestSize = new Point(); 197 display.getCurrentSizeRange(smallestSize, largestSize); 198 199 dynamicGrid = new DynamicGrid(context, 200 context.getResources(), 201 Math.min(smallestSize.x, smallestSize.y), 202 Math.min(largestSize.x, largestSize.y), 203 realSize.x, realSize.y, 204 dm.widthPixels, dm.heightPixels); 205 } 206 207 // Update the icon size 208 DeviceProfile grid = dynamicGrid.getDeviceProfile(); 209 grid.updateFromConfiguration(context, context.getResources(), 210 realSize.x, realSize.y, 211 dm.widthPixels, dm.heightPixels); 212 return dynamicGrid; 213 } 214 215 public DynamicGrid getDynamicGrid() { 216 return mDynamicGrid; 217 } 218 219 public WidgetPreviewLoader getWidgetCache() { 220 return mWidgetCache; 221 } 222 223 public boolean isScreenLarge() { 224 return mIsScreenLarge; 225 } 226 227 // Need a version that doesn't require an instance of LauncherAppState for the wallpaper picker 228 public static boolean isScreenLarge(Resources res) { 229 return res.getBoolean(R.bool.is_large_tablet); 230 } 231 232 public static boolean isScreenLandscape(Context context) { 233 return context.getResources().getConfiguration().orientation == 234 Configuration.ORIENTATION_LANDSCAPE; 235 } 236 237 public float getScreenDensity() { 238 return mScreenDensity; 239 } 240 241 public int getLongPressTimeout() { 242 return mLongPressTimeout; 243 } 244 245 public void onWallpaperChanged() { 246 mWallpaperChangedSinceLastCheck = true; 247 } 248 249 public boolean hasWallpaperChangedSinceLastCheck() { 250 boolean result = mWallpaperChangedSinceLastCheck; 251 mWallpaperChangedSinceLastCheck = false; 252 return result; 253 } 254 255 @Override 256 public void onAvailableSizeChanged(DeviceProfile grid) { 257 Utilities.setIconSize(grid.iconSizePx); 258 } 259 260 public static boolean isDogfoodBuild() { 261 return getInstance().mBuildInfo.isDogfoodBuild(); 262 } 263} 264