LauncherAppState.java revision e060b0b3c72b93b47031f0f33bf18b121fb99333
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
19cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandlerimport android.app.SearchManager;
20b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandlerimport android.content.*;
21cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandlerimport android.content.res.Configuration;
22cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandlerimport android.database.ContentObserver;
23cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandlerimport android.os.Handler;
24b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandlerimport android.util.Log;
25cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
26cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandlerimport java.lang.ref.WeakReference;
27cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
28cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandlerpublic class LauncherAppState {
29e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private static final String SHARED_PREFERENCES_KEY = "com.android.launcher3.prefs";
30e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler
31cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    private LauncherModel mModel;
32cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    private IconCache mIconCache;
33cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    private WidgetPreviewLoader.CacheDb mWidgetPreviewCacheDb;
34e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private boolean mIsScreenLarge;
35e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private float mScreenDensity;
36e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private int mLongPressTimeout = 300;
37cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
38e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private static WeakReference<LauncherProvider> sLauncherProvider;
39e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private static Context sContext;
40cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
41e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private static Object mLock = new Object();
42e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private static LauncherAppState INSTANCE;
43cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
44cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    public static LauncherAppState getInstance() {
45e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        if (INSTANCE == null) {
46e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler            INSTANCE = new LauncherAppState();
47e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        }
48cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return INSTANCE;
49cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
50cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
51cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    public Context getContext() {
52e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        return sContext;
53cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
54cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
55e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    public static void setApplicationContext(Context context) {
56e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        if (sContext != null) {
57e060b0b3c72b93b47031f0f33bf18b121fb99333Daniel Sandler            Log.w(Launcher.TAG, "setApplicationContext called twice! old=" + sContext + " new=" + context);
58e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        }
59e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sContext = context.getApplicationContext();
60e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    }
61b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler
62e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    private LauncherAppState() {
63e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        if (sContext == null) {
64e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler            throw new IllegalStateException("LauncherAppState inited before app context set");
65e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        }
66cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
67e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        Log.v(Launcher.TAG, "LauncherAppState inited");
68924b993c750e6de8537afb750c2d2b9932efbdacDaniel Sandler
69e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        if (sContext.getResources().getBoolean(R.bool.debug_memory_enabled)) {
70e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler            MemoryTracker.startTrackingMe(sContext, "L");
71b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler        }
72b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler
73e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        // set sIsScreenXLarge and mScreenDensity *before* creating icon cache
74e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        mIsScreenLarge = sContext.getResources().getBoolean(R.bool.is_large_screen);
75e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        mScreenDensity = sContext.getResources().getDisplayMetrics().density;
76b9eb2865af05d9ade572e71934a9e6a50421aa7dDaniel Sandler
77e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        mWidgetPreviewCacheDb = new WidgetPreviewLoader.CacheDb(sContext);
78e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        mIconCache = new IconCache(sContext);
79e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        mModel = new LauncherModel(this, mIconCache);
80cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
81cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        // Register intent receivers
82cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
83cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
84cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
85cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addDataScheme("package");
86e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sContext.registerReceiver(mModel, filter);
87cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter = new IntentFilter();
88cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
89cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
90cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
91cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
92e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sContext.registerReceiver(mModel, filter);
93cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter = new IntentFilter();
94cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
95e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sContext.registerReceiver(mModel, filter);
96cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter = new IntentFilter();
97cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        filter.addAction(SearchManager.INTENT_ACTION_SEARCHABLES_CHANGED);
98e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sContext.registerReceiver(mModel, filter);
99cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
100cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        // Register for changes to the favorites
101e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        ContentResolver resolver = sContext.getContentResolver();
102cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        resolver.registerContentObserver(LauncherSettings.Favorites.CONTENT_URI, true,
103cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler                mFavoritesObserver);
104cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
105cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
106cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    /**
107cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler     * Call from Application.onTerminate(), which is not guaranteed to ever be called.
108cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler     */
109cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    public void onTerminate() {
110e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sContext.unregisterReceiver(mModel);
111cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
112e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        ContentResolver resolver = sContext.getContentResolver();
113cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        resolver.unregisterContentObserver(mFavoritesObserver);
114cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
115cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
116cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    /**
117cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler     * Receives notifications whenever the user favorites have changed.
118cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler     */
119cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
120cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        @Override
121cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        public void onChange(boolean selfChange) {
122cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            // If the database has ever changed, then we really need to force a reload of the
123cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            // workspace on the next load
124cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            mModel.resetLoadedState(false, true);
125cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            mModel.startLoaderFromBackground();
126cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        }
127cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    };
128cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
129cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    LauncherModel setLauncher(Launcher launcher) {
130e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        if (mModel == null) {
131e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler            throw new IllegalStateException("setLauncher() called before init()");
132e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        }
133cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        mModel.initialize(launcher);
134cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return mModel;
135cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
136cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
137cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    IconCache getIconCache() {
138cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return mIconCache;
139cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
140cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
141cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    LauncherModel getModel() {
142cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return mModel;
143cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
144cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
145cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    WidgetPreviewLoader.CacheDb getWidgetPreviewCacheDb() {
146cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return mWidgetPreviewCacheDb;
147cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
148cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
149e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    static void setLauncherProvider(LauncherProvider provider) {
150e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        sLauncherProvider = new WeakReference<LauncherProvider>(provider);
151cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
152cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
153e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    static LauncherProvider getLauncherProvider() {
154e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        return sLauncherProvider.get();
155924b993c750e6de8537afb750c2d2b9932efbdacDaniel Sandler    }
156924b993c750e6de8537afb750c2d2b9932efbdacDaniel Sandler
157cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    public static String getSharedPreferencesKey() {
158e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        return SHARED_PREFERENCES_KEY;
159cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
160cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
161e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    public boolean isScreenLarge() {
162e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        return mIsScreenLarge;
163cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
164cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
165cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    public static boolean isScreenLandscape(Context context) {
166cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler        return context.getResources().getConfiguration().orientation ==
167cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler            Configuration.ORIENTATION_LANDSCAPE;
168cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
169cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
170e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    public float getScreenDensity() {
171e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        return mScreenDensity;
172cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
173cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler
174e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler    public int getLongPressTimeout() {
175e4f9891f01bdc10d8f96e4e2429e2f4d0558238bDaniel Sandler        return mLongPressTimeout;
176cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler    }
177cc8befac3550c81d04ea206c170adae36c9a6c93Daniel Sandler}
178