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 19fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport android.content.ContentProviderClient; 20e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.Context; 21e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.Intent; 22e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.IntentFilter; 23fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport android.os.Looper; 24b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandlerimport android.util.Log; 2571b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal 26ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherAppsCompat; 274390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport com.android.launcher3.compat.PackageInstallerCompat; 28823fd5090209017a029460e7dbd8ab9d51d013ddSunny Goyalimport com.android.launcher3.compat.UserManagerCompat; 29e26d1008eb587303db25797ca02cc32464e45656Sunny Goyalimport com.android.launcher3.config.ProviderConfig; 30827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickhamimport com.android.launcher3.dynamicui.ExtractionUtils; 31ae50284e0a838139c67caf0064a0977c871497faSunny Goyalimport com.android.launcher3.util.ConfigMonitor; 32fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport com.android.launcher3.util.Preconditions; 33322d55622031985c75f7e5db07964b7730a97dacSunny Goyalimport com.android.launcher3.util.TestingUtils; 3471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal 35fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport java.util.concurrent.Callable; 36fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyalimport java.util.concurrent.ExecutionException; 37cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 38c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyalpublic class LauncherAppState { 39aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren 40e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal public static final boolean PROFILE_STARTUP = ProviderConfig.IS_DOGFOOD_BUILD; 41e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal 42fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal // We do not need any synchronization for this variable as its only written on UI thread. 43fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private static LauncherAppState INSTANCE; 44fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal 45fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private final Context mContext; 46fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private final LauncherModel mModel; 47e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal private final IconCache mIconCache; 485b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal private final WidgetPreviewLoader mWidgetCache; 49fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private final InvariantDeviceProfile mInvariantDeviceProfile; 50e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal 51cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 52fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal public static LauncherAppState getInstance(final Context context) { 53e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler if (INSTANCE == null) { 54fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal if (Looper.myLooper() == Looper.getMainLooper()) { 55fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal INSTANCE = new LauncherAppState(context.getApplicationContext()); 56fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } else { 57fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal try { 58fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal return new MainThreadExecutor().submit(new Callable<LauncherAppState>() { 59fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal @Override 60fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal public LauncherAppState call() throws Exception { 61fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal return LauncherAppState.getInstance(context); 62fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 63fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal }).get(); 64fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } catch (InterruptedException|ExecutionException e) { 65fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal throw new RuntimeException(e); 66fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 67fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 68e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler } 69cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler return INSTANCE; 70cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 71cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 72d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren public static LauncherAppState getInstanceNoCreate() { 73d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren return INSTANCE; 74d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren } 75d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren 76cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler public Context getContext() { 77fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal return mContext; 78cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 79cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 80fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private LauncherAppState(Context context) { 81fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal if (getLocalProvider(context) == null) { 82fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal throw new RuntimeException( 83fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal "Initializing LauncherAppState in the absence of LauncherProvider"); 84e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler } 850de011705b132eacdd10f7bfb5cdc4bd79a147e8Hyunyoung Song Log.v(Launcher.TAG, "LauncherAppState initiated"); 86fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal Preconditions.assertUIThread(); 87fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mContext = context; 88924b993c750e6de8537afb750c2d2b9932efbdacDaniel Sandler 89322d55622031985c75f7e5db07964b7730a97dacSunny Goyal if (TestingUtils.MEMORY_DUMP_ENABLED) { 90fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal TestingUtils.startTrackingMemory(mContext); 91b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler } 92b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler 93fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mInvariantDeviceProfile = new InvariantDeviceProfile(mContext); 94fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mIconCache = new IconCache(mContext, mInvariantDeviceProfile); 95fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache); 961307f63f8a93541bf6e2d29c11fab69778a25e42Bjorn Bringert 97ab121c17159a7f655b772fa78c04a6d2479e2a8eSunny Goyal mModel = new LauncherModel(this, mIconCache, 98fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal Utilities.getOverrideObject(AppFilter.class, mContext, R.string.app_filter_class)); 9927595796b3c0373d1a1d56af9a30392bc7016624Sunny Goyal 100fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel); 101cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 102cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler // Register intent receivers 103ed13187a745866483139e2878037e1f8427ce567Kenny Guy IntentFilter filter = new IntentFilter(); 104cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler filter.addAction(Intent.ACTION_LOCALE_CHANGED); 105957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal // For handling managed profiles 106d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED); 107d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED); 108d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE); 109d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE); 110d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED); 111827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham // For extracting colors from the wallpaper 112f5e3744637db1598c389e62450627b2548f8f517Sunny Goyal if (Utilities.ATLEAST_NOUGAT) { 113827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham // TODO: add a broadcast entry to the manifest for pre-N. 114827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham filter.addAction(Intent.ACTION_WALLPAPER_CHANGED); 115827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham } 116957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal 117fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mContext.registerReceiver(mModel, filter); 118fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal UserManagerCompat.getInstance(mContext).enableAndResetCache(); 119fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal new ConfigMonitor(mContext).register(); 120827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham 121fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal ExtractionUtils.startColorExtractionServiceIfNecessary(mContext); 122cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 1231317e2dd4a2fb097d1e54759536d515fdeca2c3eKenny Guy 124cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler /** 125cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler * Call from Application.onTerminate(), which is not guaranteed to ever be called. 126cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler */ 127cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler public void onTerminate() { 128fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal mContext.unregisterReceiver(mModel); 129fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext); 130c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy launcherApps.removeOnAppsChangedCallback(mModel); 131fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal PackageInstallerCompat.getInstance(mContext).onStop(); 132cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 133cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 134cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler LauncherModel setLauncher(Launcher launcher) { 135fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal getLocalProvider(mContext).setLauncherProviderChangeListener(launcher); 136cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler mModel.initialize(launcher); 137cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler return mModel; 138cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 139cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 140349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal public IconCache getIconCache() { 141cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler return mIconCache; 142cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 143cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 14418bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal public LauncherModel getModel() { 145cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler return mModel; 146cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler } 147cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler 1485b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal public WidgetPreviewLoader getWidgetCache() { 1495b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal return mWidgetCache; 1505b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal } 151a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka 1522e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen public InvariantDeviceProfile getInvariantDeviceProfile() { 1532e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen return mInvariantDeviceProfile; 1542e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen } 15587f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal 15687f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal /** 15787f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal * Shorthand for {@link #getInvariantDeviceProfile()} 15887f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal */ 15987f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal public static InvariantDeviceProfile getIDP(Context context) { 16087f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal return LauncherAppState.getInstance(context).getInvariantDeviceProfile(); 16187f784c285fdeed9091a4de8b9b44db3eca677d8Sunny Goyal } 162fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal 163fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal private static LauncherProvider getLocalProvider(Context context) { 164fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal try (ContentProviderClient cl = context.getContentResolver() 165fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal .acquireContentProviderClient(LauncherProvider.AUTHORITY)) { 166fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal return (LauncherProvider) cl.getLocalContentProvider(); 167fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 168fdbef27759bdd5ccaca6a0e70fbdf008c0053981Sunny Goyal } 169cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler} 170