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.Context; 22import android.content.Intent; 23import android.content.IntentFilter; 24import android.util.Log; 25 26import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; 27import com.android.launcher3.compat.LauncherAppsCompat; 28import com.android.launcher3.compat.PackageInstallerCompat; 29import com.android.launcher3.util.Thunk; 30 31import java.lang.ref.WeakReference; 32 33public class LauncherAppState { 34 35 private final AppFilter mAppFilter; 36 private final BuildInfo mBuildInfo; 37 @Thunk final LauncherModel mModel; 38 private final IconCache mIconCache; 39 private final WidgetPreviewLoader mWidgetCache; 40 41 private boolean mWallpaperChangedSinceLastCheck; 42 43 private static WeakReference<LauncherProvider> sLauncherProvider; 44 private static Context sContext; 45 46 private static LauncherAppState INSTANCE; 47 48 private InvariantDeviceProfile mInvariantDeviceProfile; 49 50 private LauncherAccessibilityDelegate mAccessibilityDelegate; 51 52 public static LauncherAppState getInstance() { 53 if (INSTANCE == null) { 54 INSTANCE = new LauncherAppState(); 55 } 56 return INSTANCE; 57 } 58 59 public static LauncherAppState getInstanceNoCreate() { 60 return INSTANCE; 61 } 62 63 public Context getContext() { 64 return sContext; 65 } 66 67 public static void setApplicationContext(Context context) { 68 if (sContext != null) { 69 Log.w(Launcher.TAG, "setApplicationContext called twice! old=" + sContext + " new=" + context); 70 } 71 sContext = context.getApplicationContext(); 72 } 73 74 private LauncherAppState() { 75 if (sContext == null) { 76 throw new IllegalStateException("LauncherAppState inited before app context set"); 77 } 78 79 Log.v(Launcher.TAG, "LauncherAppState inited"); 80 81 if (sContext.getResources().getBoolean(R.bool.debug_memory_enabled)) { 82 MemoryTracker.startTrackingMe(sContext, "L"); 83 } 84 85 mInvariantDeviceProfile = new InvariantDeviceProfile(sContext); 86 mIconCache = new IconCache(sContext, mInvariantDeviceProfile); 87 mWidgetCache = new WidgetPreviewLoader(sContext, mIconCache); 88 89 mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class)); 90 mBuildInfo = BuildInfo.loadByName(sContext.getString(R.string.build_info_class)); 91 mModel = new LauncherModel(this, mIconCache, mAppFilter); 92 93 LauncherAppsCompat.getInstance(sContext).addOnAppsChangedCallback(mModel); 94 95 // Register intent receivers 96 IntentFilter filter = new IntentFilter(); 97 filter.addAction(Intent.ACTION_LOCALE_CHANGED); 98 filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED); 99 filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED); 100 // For handling managed profiles 101 filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_ADDED); 102 filter.addAction(LauncherAppsCompat.ACTION_MANAGED_PROFILE_REMOVED); 103 104 sContext.registerReceiver(mModel, filter); 105 } 106 107 /** 108 * Call from Application.onTerminate(), which is not guaranteed to ever be called. 109 */ 110 public void onTerminate() { 111 sContext.unregisterReceiver(mModel); 112 final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext); 113 launcherApps.removeOnAppsChangedCallback(mModel); 114 PackageInstallerCompat.getInstance(sContext).onStop(); 115 } 116 117 /** 118 * Reloads the workspace items from the DB and re-binds the workspace. This should generally 119 * not be called as DB updates are automatically followed by UI update 120 */ 121 public void reloadWorkspace() { 122 mModel.resetLoadedState(false, true); 123 mModel.startLoaderFromBackground(); 124 } 125 126 LauncherModel setLauncher(Launcher launcher) { 127 getLauncherProvider().setLauncherProviderChangeListener(launcher); 128 mModel.initialize(launcher); 129 mAccessibilityDelegate = ((launcher != null) && Utilities.isLmpOrAbove()) ? 130 new LauncherAccessibilityDelegate(launcher) : null; 131 return mModel; 132 } 133 134 public LauncherAccessibilityDelegate getAccessibilityDelegate() { 135 return mAccessibilityDelegate; 136 } 137 138 public IconCache getIconCache() { 139 return mIconCache; 140 } 141 142 public LauncherModel getModel() { 143 return mModel; 144 } 145 146 static void setLauncherProvider(LauncherProvider provider) { 147 sLauncherProvider = new WeakReference<LauncherProvider>(provider); 148 } 149 150 static LauncherProvider getLauncherProvider() { 151 return sLauncherProvider.get(); 152 } 153 154 public static String getSharedPreferencesKey() { 155 return LauncherFiles.SHARED_PREFERENCES_KEY; 156 } 157 158 public WidgetPreviewLoader getWidgetCache() { 159 return mWidgetCache; 160 } 161 162 public void onWallpaperChanged() { 163 mWallpaperChangedSinceLastCheck = true; 164 } 165 166 public boolean hasWallpaperChangedSinceLastCheck() { 167 boolean result = mWallpaperChangedSinceLastCheck; 168 mWallpaperChangedSinceLastCheck = false; 169 return result; 170 } 171 172 public InvariantDeviceProfile getInvariantDeviceProfile() { 173 return mInvariantDeviceProfile; 174 } 175 176 public static boolean isDogfoodBuild() { 177 return getInstance().mBuildInfo.isDogfoodBuild(); 178 } 179} 180