1cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler/* 2cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * Copyright (C) 2013 The Android Open Source Project 3cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * 4cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * Licensed under the Apache License, Version 2.0 (the "License"); 5cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * you may not use this file except in compliance with the License. 6cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * You may obtain a copy of the License at 7cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * 8cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * http://www.apache.org/licenses/LICENSE-2.0 9cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * 10cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * Unless required by applicable law or agreed to in writing, software 11cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * distributed under the License is distributed on an "AS IS" BASIS, 12cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * See the License for the specific language governing permissions and 14cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * limitations under the License. 15cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler */ 16cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 17cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandlerpackage com.android.launcher3; 18cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 19d48710c2835d891b216914ef1fdd3740e6cfc101Tonyimport android.content.ComponentName; 20fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport android.content.ContentProviderClient; 21e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.Context; 22e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.Intent; 23e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.IntentFilter; 24fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport android.os.Looper; 25b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandlerimport android.util.Log; 2671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal 27ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherAppsCompat; 284390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport com.android.launcher3.compat.PackageInstallerCompat; 29823fd5090209017a029460e7dbd8ab9d51d013ddSunny Goyalimport com.android.launcher3.compat.UserManagerCompat; 303d706ad70365052e3224fc4f4b0e7d1f5e8abf22Sunny Goyalimport com.android.launcher3.config.FeatureFlags; 31827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickhamimport com.android.launcher3.dynamicui.ExtractionUtils; 32d48710c2835d891b216914ef1fdd3740e6cfc101Tonyimport com.android.launcher3.notification.NotificationListener; 33ae50284e0a838139c67caf0064a0977c871497faSunny Goyalimport com.android.launcher3.util.ConfigMonitor; 34fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport com.android.launcher3.util.Preconditions; 35d48710c2835d891b216914ef1fdd3740e6cfc101Tonyimport com.android.launcher3.util.SettingsObserver; 36322d55622031985c75f7e5db07964b7730a97dacSunny Goyalimport com.android.launcher3.util.TestingUtils; 3771b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal 38fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport java.util.concurrent.Callable; 39fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport java.util.concurrent.ExecutionException; 40cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 41d48710c2835d891b216914ef1fdd3740e6cfc101Tonyimport static com.android.launcher3.SettingsActivity.NOTIFICATION_BADGING; 42d48710c2835d891b216914ef1fdd3740e6cfc101Tony 43c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyalpublic class LauncherAppState { 44aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren 453d706ad70365052e3224fc4f4b0e7d1f5e8abf22Sunny Goyal public static final boolean PROFILE_STARTUP = FeatureFlags.IS_DOGFOOD_BUILD; 46e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal 47fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal // We do not need any synchronization for this variable as its only written on UI thread. 48fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private static LauncherAppState INSTANCE; 49fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal 50fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private final Context mContext; 51fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private final LauncherModel mModel; 52e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal private final IconCache mIconCache; 535b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal private final WidgetPreviewLoader mWidgetCache; 54fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private final InvariantDeviceProfile mInvariantDeviceProfile; 55d48710c2835d891b216914ef1fdd3740e6cfc101Tony private final SettingsObserver mNotificationBadgingObserver; 56cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 57fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal public static LauncherAppState getInstance(final Context context) { 58e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler if (INSTANCE == null) { 59fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal if (Looper.myLooper() == Looper.getMainLooper()) { 60fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal INSTANCE = new LauncherAppState(context.getApplicationContext()); 61fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } else { 62fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal try { 63fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal return new MainThreadExecutor().submit(new Callable<LauncherAppState>() { 64fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal @Override 65fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal public LauncherAppState call() throws Exception { 66fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal return LauncherAppState.getInstance(context); 67fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 68fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal }).get(); 69fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } catch (InterruptedException|ExecutionException e) { 70fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal throw new RuntimeException(e); 71fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 72fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 73e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler } 74cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler return INSTANCE; 75cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 76cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 77d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren public static LauncherAppState getInstanceNoCreate() { 78d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren return INSTANCE; 79d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren } 80d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren 81cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler public Context getContext() { 82fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal return mContext; 83cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 84cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 85fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private LauncherAppState(Context context) { 86fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal if (getLocalProvider(context) == null) { 87fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal throw new RuntimeException( 88fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal "Initializing LauncherAppState in the absence of LauncherProvider"); 89e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler } 900de011705b132eacdd10f7bfb5cdc4bd79a147e8Hyunyoung Song Log.v(Launcher.TAG, "LauncherAppState initiated"); 91fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal Preconditions.assertUIThread(); 92fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mContext = context; 93924b993c750e6de8537afb750c2d2b9932efbdacDaniel Sandler 94322d55622031985c75f7e5db07964b7730a97dacSunny Goyal if (TestingUtils.MEMORY_DUMP_ENABLED) { 95fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal TestingUtils.startTrackingMemory(mContext); 96b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler } 97b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler 98fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mInvariantDeviceProfile = new InvariantDeviceProfile(mContext); 99fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mIconCache = new IconCache(mContext, mInvariantDeviceProfile); 100fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache); 101c6e97692e4144a6fc33eb74fabb73b1aae9ff908Sunny Goyal mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext)); 10227595796b3c0373d1a1d56af9a30392bc7016624Sunny Goyal 103fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel); 104cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 105cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler // Register intent receivers 106ed13187a745866483139e2878037e1f8427ce567Kenny Guy IntentFilter filter = new IntentFilter(); 107cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler filter.addAction(Intent.ACTION_LOCALE_CHANGED); 108957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal // For handling managed profiles 109d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); 110d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); 111d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); 112d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); 113d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED); 114827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham // For extracting colors from the wallpaper 115f5e3744637db1598c389e62450627b2548f8f517Sunny Goyal if (Utilities.ATLEAST_NOUGAT) { 116827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham // TODO: add a broadcast entry to the manifest for pre-N. 117827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham filter.addAction(Intent.ACTION_WALLPAPER_CHANGED); 118827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham } 119957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal 120fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mContext.registerReceiver(mModel, filter); 121fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal UserManagerCompat.getInstance(mContext).enableAndResetCache(); 122fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal new ConfigMonitor(mContext).register(); 123827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham 124fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal ExtractionUtils.startColorExtractionServiceIfNecessary(mContext); 125d48710c2835d891b216914ef1fdd3740e6cfc101Tony 126d48710c2835d891b216914ef1fdd3740e6cfc101Tony if (!mContext.getResources().getBoolean(R.bool.notification_badging_enabled)) { 127d48710c2835d891b216914ef1fdd3740e6cfc101Tony mNotificationBadgingObserver = null; 128d48710c2835d891b216914ef1fdd3740e6cfc101Tony } else { 129d48710c2835d891b216914ef1fdd3740e6cfc101Tony // Register an observer to rebind the notification listener when badging is re-enabled. 130d48710c2835d891b216914ef1fdd3740e6cfc101Tony mNotificationBadgingObserver = new SettingsObserver.Secure( 131d48710c2835d891b216914ef1fdd3740e6cfc101Tony mContext.getContentResolver()) { 132d48710c2835d891b216914ef1fdd3740e6cfc101Tony @Override 133d48710c2835d891b216914ef1fdd3740e6cfc101Tony public void onSettingChanged(boolean isNotificationBadgingEnabled) { 134d48710c2835d891b216914ef1fdd3740e6cfc101Tony if (isNotificationBadgingEnabled) { 135d48710c2835d891b216914ef1fdd3740e6cfc101Tony NotificationListener.requestRebind(new ComponentName( 136d48710c2835d891b216914ef1fdd3740e6cfc101Tony mContext, NotificationListener.class)); 137d48710c2835d891b216914ef1fdd3740e6cfc101Tony } 138d48710c2835d891b216914ef1fdd3740e6cfc101Tony } 139d48710c2835d891b216914ef1fdd3740e6cfc101Tony }; 140d48710c2835d891b216914ef1fdd3740e6cfc101Tony mNotificationBadgingObserver.register(NOTIFICATION_BADGING); 141d48710c2835d891b216914ef1fdd3740e6cfc101Tony } 142cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 1431317e2dd4a2fb097d1e54759536d515fdeca2c3eKenny Guy 144cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler /** 145cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * Call from Application.onTerminate(), which is not guaranteed to ever be called. 146cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler */ 147cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler public void onTerminate() { 148fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mContext.unregisterReceiver(mModel); 149fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext); 150c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy launcherApps.removeOnAppsChangedCallback(mModel); 151fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal PackageInstallerCompat.getInstance(mContext).onStop(); 152d48710c2835d891b216914ef1fdd3740e6cfc101Tony if (mNotificationBadgingObserver != null) { 153d48710c2835d891b216914ef1fdd3740e6cfc101Tony mNotificationBadgingObserver.unregister(); 154d48710c2835d891b216914ef1fdd3740e6cfc101Tony } 155cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 156cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 157cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler LauncherModel setLauncher(Launcher launcher) { 158fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal getLocalProvider(mContext).setLauncherProviderChangeListener(launcher); 159cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler mModel.initialize(launcher); 160cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler return mModel; 161cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 162cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 163349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal public IconCache getIconCache() { 164cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler return mIconCache; 165cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 166cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 16718bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal public LauncherModel getModel() { 168cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler return mModel; 169cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 170cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 1715b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal public WidgetPreviewLoader getWidgetCache() { 1725b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal return mWidgetCache; 1735b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal } 174a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka 1752e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen public InvariantDeviceProfile getInvariantDeviceProfile() { 1762e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen return mInvariantDeviceProfile; 1772e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen } 17887f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal 17987f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal /** 18087f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal * Shorthand for {@link #getInvariantDeviceProfile()} 18187f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal */ 18287f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal public static InvariantDeviceProfile getIDP(Context context) { 18387f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal return LauncherAppState.getInstance(context).getInvariantDeviceProfile(); 18487f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal } 185fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal 186fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private static LauncherProvider getLocalProvider(Context context) { 187fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal try (ContentProviderClient cl = context.getContentResolver() 188fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal .acquireContentProviderClient(LauncherProvider.AUTHORITY)) { 189fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal return (LauncherProvider) cl.getLocalContentProvider(); 190fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 191fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 192cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler} 193