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.content.BroadcastReceiver; 20import android.content.Context; 21import android.content.Intent; 22import android.content.IntentFilter; 23import android.util.Log; 24 25import com.android.launcher3.compat.LauncherAppsCompat; 26import com.android.launcher3.compat.PackageInstallerCompat; 27import com.android.launcher3.compat.UserManagerCompat; 28import com.android.launcher3.config.ProviderConfig; 29import com.android.launcher3.dynamicui.ExtractionUtils; 30import com.android.launcher3.logging.FileLog; 31import com.android.launcher3.shortcuts.DeepShortcutManager; 32import com.android.launcher3.shortcuts.ShortcutCache; 33import com.android.launcher3.util.ConfigMonitor; 34import com.android.launcher3.util.TestingUtils; 35import com.android.launcher3.util.Thunk; 36 37import java.lang.ref.WeakReference; 38 39public class LauncherAppState { 40 41 public static final boolean PROFILE_STARTUP = ProviderConfig.IS_DOGFOOD_BUILD; 42 43 private final AppFilter mAppFilter; 44 @Thunk final LauncherModel mModel; 45 private final IconCache mIconCache; 46 private final WidgetPreviewLoader mWidgetCache; 47 private final DeepShortcutManager mDeepShortcutManager; 48 49 @Thunk boolean mWallpaperChangedSinceLastCheck; 50 51 private static WeakReference<LauncherProvider> sLauncherProvider; 52 private static Context sContext; 53 54 private static LauncherAppState INSTANCE; 55 56 private InvariantDeviceProfile mInvariantDeviceProfile; 57 58 public static LauncherAppState getInstance() { 59 if (INSTANCE == null) { 60 INSTANCE = new LauncherAppState(); 61 } 62 return INSTANCE; 63 } 64 65 public static LauncherAppState getInstanceNoCreate() { 66 return INSTANCE; 67 } 68 69 public Context getContext() { 70 return sContext; 71 } 72 73 static void setLauncherProvider(LauncherProvider provider) { 74 if (sLauncherProvider != null) { 75 Log.w(Launcher.TAG, "setLauncherProvider called twice! old=" + 76 sLauncherProvider.get() + " new=" + provider); 77 } 78 sLauncherProvider = new WeakReference<>(provider); 79 80 // The content provider exists for the entire duration of the launcher main process and 81 // is the first component to get created. Initializing application context here ensures 82 // that LauncherAppState always exists in the main process. 83 sContext = provider.getContext().getApplicationContext(); 84 FileLog.setDir(sContext.getFilesDir()); 85 } 86 87 private LauncherAppState() { 88 if (sContext == null) { 89 throw new IllegalStateException("LauncherAppState inited before app context set"); 90 } 91 92 Log.v(Launcher.TAG, "LauncherAppState inited"); 93 94 if (TestingUtils.MEMORY_DUMP_ENABLED) { 95 TestingUtils.startTrackingMemory(sContext); 96 } 97 98 mInvariantDeviceProfile = new InvariantDeviceProfile(sContext); 99 mIconCache = new IconCache(sContext, mInvariantDeviceProfile); 100 mWidgetCache = new WidgetPreviewLoader(sContext, mIconCache); 101 mDeepShortcutManager = new DeepShortcutManager(sContext, new ShortcutCache()); 102 103 mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class)); 104 mModel = new LauncherModel(this, mIconCache, mAppFilter, mDeepShortcutManager); 105 106 LauncherAppsCompat.getInstance(sContext).addOnAppsChangedCallback(mModel); 107 108 // Register intent receivers 109 IntentFilter filter = new IntentFilter(); 110 filter.addAction(Intent.ACTION_LOCALE_CHANGED); 111 // For handling managed profiles 112 filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); 113 filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); 114 filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); 115 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); 116 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED); 117 // For extracting colors from the wallpaper 118 if (Utilities.isNycOrAbove()) { 119 // TODO: add a broadcast entry to the manifest for pre-N. 120 filter.addAction(Intent.ACTION_WALLPAPER_CHANGED); 121 } 122 123 sContext.registerReceiver(mModel, filter); 124 UserManagerCompat.getInstance(sContext).enableAndResetCache(); 125 if (!Utilities.ATLEAST_KITKAT) { 126 sContext.registerReceiver(new BroadcastReceiver() { 127 128 @Override 129 public void onReceive(Context context, Intent intent) { 130 mWallpaperChangedSinceLastCheck = true; 131 } 132 }, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED)); 133 } 134 new ConfigMonitor(sContext).register(); 135 136 ExtractionUtils.startColorExtractionServiceIfNecessary(sContext); 137 } 138 139 /** 140 * Call from Application.onTerminate(), which is not guaranteed to ever be called. 141 */ 142 public void onTerminate() { 143 sContext.unregisterReceiver(mModel); 144 final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext); 145 launcherApps.removeOnAppsChangedCallback(mModel); 146 PackageInstallerCompat.getInstance(sContext).onStop(); 147 } 148 149 /** 150 * Reloads the workspace items from the DB and re-binds the workspace. This should generally 151 * not be called as DB updates are automatically followed by UI update 152 */ 153 public void reloadWorkspace() { 154 mModel.resetLoadedState(false, true); 155 mModel.startLoaderFromBackground(); 156 } 157 158 LauncherModel setLauncher(Launcher launcher) { 159 sLauncherProvider.get().setLauncherProviderChangeListener(launcher); 160 mModel.initialize(launcher); 161 return mModel; 162 } 163 164 public IconCache getIconCache() { 165 return mIconCache; 166 } 167 168 public LauncherModel getModel() { 169 return mModel; 170 } 171 172 public WidgetPreviewLoader getWidgetCache() { 173 return mWidgetCache; 174 } 175 176 public DeepShortcutManager getShortcutManager() { 177 return mDeepShortcutManager; 178 } 179 180 public boolean hasWallpaperChangedSinceLastCheck() { 181 boolean result = mWallpaperChangedSinceLastCheck; 182 mWallpaperChangedSinceLastCheck = false; 183 return result; 184 } 185 186 public InvariantDeviceProfile getInvariantDeviceProfile() { 187 return mInvariantDeviceProfile; 188 } 189} 190