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
194b17147c28488c20b01aea18297fd6a327bad213Sunny Goyalimport android.content.BroadcastReceiver;
20e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.Context;
21e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.Intent;
22e755d469d40b95e763a9dcb67d0e4f511d1948ddSunny Goyalimport android.content.IntentFilter;
23b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandlerimport android.util.Log;
2471b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
25ed13187a745866483139e2878037e1f8427ce567Kenny Guyimport com.android.launcher3.compat.LauncherAppsCompat;
264390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyalimport com.android.launcher3.compat.PackageInstallerCompat;
27823fd5090209017a029460e7dbd8ab9d51d013ddSunny Goyalimport com.android.launcher3.compat.UserManagerCompat;
28e26d1008eb587303db25797ca02cc32464e45656Sunny Goyalimport com.android.launcher3.config.ProviderConfig;
29827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickhamimport com.android.launcher3.dynamicui.ExtractionUtils;
30713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyalimport com.android.launcher3.logging.FileLog;
31bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickhamimport com.android.launcher3.shortcuts.DeepShortcutManager;
32bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickhamimport com.android.launcher3.shortcuts.ShortcutCache;
33ae50284e0a838139c67caf0064a0977c871497faSunny Goyalimport com.android.launcher3.util.ConfigMonitor;
34322d55622031985c75f7e5db07964b7730a97dacSunny Goyalimport com.android.launcher3.util.TestingUtils;
35091440a9cb9d4f42406631004aa484cbb79214caAdam Cohenimport com.android.launcher3.util.Thunk;
3671b5c0b988a64b3a0613ded5403749bc537ee8a5Sunny Goyal
37cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandlerimport java.lang.ref.WeakReference;
38cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
39c6205603efe1f2987caf96504c87d720a25b5a94Sunny Goyalpublic class LauncherAppState {
40aeff7ea43409d817490fbb8c22b8d4b9725bb54fChris Wren
41e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal    public static final boolean PROFILE_STARTUP = ProviderConfig.IS_DOGFOOD_BUILD;
42e26d1008eb587303db25797ca02cc32464e45656Sunny Goyal
4316f3ea870aac47292cd6cbe1a4b4343173097aa9Nilesh Agrawal    private final AppFilter mAppFilter;
44091440a9cb9d4f42406631004aa484cbb79214caAdam Cohen    @Thunk final LauncherModel mModel;
45e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal    private final IconCache mIconCache;
465b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    private final WidgetPreviewLoader mWidgetCache;
47bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    private final DeepShortcutManager mDeepShortcutManager;
48e0f58d73646871497596fb8f7321d407e7565c28Sunny Goyal
494b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal    @Thunk boolean mWallpaperChangedSinceLastCheck;
50cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
51e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private static WeakReference<LauncherProvider> sLauncherProvider;
52e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private static Context sContext;
53cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
54e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private static LauncherAppState INSTANCE;
55cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
562e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen    private InvariantDeviceProfile mInvariantDeviceProfile;
577779d62308b87ca26e3be47df836893f6f7693ecSunny Goyal
58cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    public static LauncherAppState getInstance() {
59e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        if (INSTANCE == null) {
60e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler            INSTANCE = new LauncherAppState();
61e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        }
62cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return INSTANCE;
63cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
64cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
65d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren    public static LauncherAppState getInstanceNoCreate() {
66d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren        return INSTANCE;
67d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren    }
68d8fe6de10d5ffc293f771b070bd1361a027757bbChris Wren
69cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    public Context getContext() {
70e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        return sContext;
71cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
72cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
73d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal    static void setLauncherProvider(LauncherProvider provider) {
74d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal        if (sLauncherProvider != null) {
75d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal            Log.w(Launcher.TAG, "setLauncherProvider called twice! old=" +
76d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal                    sLauncherProvider.get() + " new=" + provider);
77e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        }
78d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal        sLauncherProvider = new WeakReference<>(provider);
79d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal
80d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal        // The content provider exists for the entire duration of the launcher main process and
81d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal        // is the first component to get created. Initializing application context here ensures
82d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal        // that LauncherAppState always exists in the main process.
83d3849d191bc0bd2d561cf03018ad90b896b13c56Sunny Goyal        sContext = provider.getContext().getApplicationContext();
84713edfce264db7edc409216d5c083f8dd6a7083fSunny Goyal        FileLog.setDir(sContext.getFilesDir());
85e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    }
86b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler
87e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private LauncherAppState() {
88e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        if (sContext == null) {
89e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler            throw new IllegalStateException("LauncherAppState inited before app context set");
90e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        }
91cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
92e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        Log.v(Launcher.TAG, "LauncherAppState inited");
93924b993c750e6de8537afb750c2d2b9932efbdacDaniel Sandler
94322d55622031985c75f7e5db07964b7730a97dacSunny Goyal        if (TestingUtils.MEMORY_DUMP_ENABLED) {
95322d55622031985c75f7e5db07964b7730a97dacSunny Goyal            TestingUtils.startTrackingMemory(sContext);
96b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler        }
97b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler
982e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        mInvariantDeviceProfile = new InvariantDeviceProfile(sContext);
992e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        mIconCache = new IconCache(sContext, mInvariantDeviceProfile);
100383c507c47a5abf3258fc04220f37c366f983a97Sunny Goyal        mWidgetCache = new WidgetPreviewLoader(sContext, mIconCache);
101bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        mDeepShortcutManager = new DeepShortcutManager(sContext, new ShortcutCache());
1021307f63f8a93541bf6e2d29c11fab69778a25e42Bjorn Bringert
1031307f63f8a93541bf6e2d29c11fab69778a25e42Bjorn Bringert        mAppFilter = AppFilter.loadByName(sContext.getString(R.string.app_filter_class));
104bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        mModel = new LauncherModel(this, mIconCache, mAppFilter, mDeepShortcutManager);
10527595796b3c0373d1a1d56af9a30392bc7016624Sunny Goyal
10627595796b3c0373d1a1d56af9a30392bc7016624Sunny Goyal        LauncherAppsCompat.getInstance(sContext).addOnAppsChangedCallback(mModel);
107cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
108cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        // Register intent receivers
109ed13187a745866483139e2878037e1f8427ce567Kenny Guy        IntentFilter filter = new IntentFilter();
110cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
111957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal        // For handling managed profiles
112d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
113d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
114d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
115d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
116d3b87ef1963fb96177ca85bcd6a25879e27e419cSunny Goyal        filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
117827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham        // For extracting colors from the wallpaper
118827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham        if (Utilities.isNycOrAbove()) {
119827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham            // TODO: add a broadcast entry to the manifest for pre-N.
120827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham            filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
121827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham        }
122957c13f032fc4088b3273cec08603c67c069e2c6Sunny Goyal
123e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sContext.registerReceiver(mModel, filter);
124823fd5090209017a029460e7dbd8ab9d51d013ddSunny Goyal        UserManagerCompat.getInstance(sContext).enableAndResetCache();
1254b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal        if (!Utilities.ATLEAST_KITKAT) {
1264b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal            sContext.registerReceiver(new BroadcastReceiver() {
1274b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal
1284b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal                @Override
1294b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal                public void onReceive(Context context, Intent intent) {
1304b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal                    mWallpaperChangedSinceLastCheck = true;
1314b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal                }
1324b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal            }, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
1334b17147c28488c20b01aea18297fd6a327bad213Sunny Goyal        }
134a50a419b824c10f11d12097215982c978f740e00Sunny Goyal        new ConfigMonitor(sContext).register();
135827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham
136827cef203f386cb548b98a7fa9888b75478c8e20Tony Wickham        ExtractionUtils.startColorExtractionServiceIfNecessary(sContext);
137cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
1381317e2dd4a2fb097d1e54759536d515fdeca2c3eKenny Guy
139cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    /**
140cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler     * Call from Application.onTerminate(), which is not guaranteed to ever be called.
141cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler     */
142cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    public void onTerminate() {
143e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sContext.unregisterReceiver(mModel);
1441317e2dd4a2fb097d1e54759536d515fdeca2c3eKenny Guy        final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(sContext);
145c2bd8101b8e26b9ebb2c079ae6867229dad3f196Kenny Guy        launcherApps.removeOnAppsChangedCallback(mModel);
1464390acea35aefae52bd3fe38f5fdbb7ea322afb0Sunny Goyal        PackageInstallerCompat.getInstance(sContext).onStop();
147cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
148cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
149cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    /**
1501d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal     * Reloads the workspace items from the DB and re-binds the workspace. This should generally
1511d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal     * not be called as DB updates are automatically followed by UI update
152cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler     */
1531d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal    public void reloadWorkspace() {
1541d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal        mModel.resetLoadedState(false, true);
1551d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal        mModel.startLoaderFromBackground();
1561d4a2df091e2b5928406ea503321563a0ec8a01eSunny Goyal    }
157cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
158cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    LauncherModel setLauncher(Launcher launcher) {
159d249748abf357925b326d57ab68eb6c2b23c4ef6Sunny Goyal        sLauncherProvider.get().setLauncherProviderChangeListener(launcher);
160cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        mModel.initialize(launcher);
161cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return mModel;
162cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
163cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
164349426234e8c5a0e5bcf2c8d94dbb9844b5f724aSunny Goyal    public IconCache getIconCache() {
165cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return mIconCache;
166cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
167cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
16818bf8e2ffde3444d53aaa9654da02cdedd0b7cd1Sunny Goyal    public LauncherModel getModel() {
169cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return mModel;
170cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
171cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
1725b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    public WidgetPreviewLoader getWidgetCache() {
1735b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal        return mWidgetCache;
1745b0e669169ea2c951bf2f6f71faf793b24db3c23Sunny Goyal    }
175a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka
176bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    public DeepShortcutManager getShortcutManager() {
177bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham        return mDeepShortcutManager;
178bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham    }
179bfbf7f9f4a0b300613f0ff27a4eb592d88c08325Tony Wickham
180a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka    public boolean hasWallpaperChangedSinceLastCheck() {
181a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka        boolean result = mWallpaperChangedSinceLastCheck;
182a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka        mWallpaperChangedSinceLastCheck = false;
183a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka        return result;
184a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka    }
185a6a0547fa6df0769fcd107a2e5f7c7d527fa0700Michael Jurka
1862e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen    public InvariantDeviceProfile getInvariantDeviceProfile() {
1872e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen        return mInvariantDeviceProfile;
1882e6da1539bc7286336b3c24d96ab76434939ce4dAdam Cohen    }
189cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler}
190