2 * Copyright (C) 2013 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.launcher3;
19 import android.content.ContentProviderClient;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.os.Looper;
24 import android.util.Log;
26 import com.android.launcher3.compat.LauncherAppsCompat;
27 import com.android.launcher3.compat.PackageInstallerCompat;
28 import com.android.launcher3.compat.UserManagerCompat;
29 import com.android.launcher3.config.ProviderConfig;
30 import com.android.launcher3.dynamicui.ExtractionUtils;
31 import com.android.launcher3.model.GridSizeMigrationTask;
32 import com.android.launcher3.util.ConfigMonitor;
33 import com.android.launcher3.util.Preconditions;
34 import com.android.launcher3.util.TestingUtils;
36 import java.util.concurrent.Callable;
37 import java.util.concurrent.ExecutionException;
39 public class LauncherAppState {
41 public static final boolean PROFILE_STARTUP = ProviderConfig.IS_DOGFOOD_BUILD;
43 // We do not need any synchronization for this variable as its only written on UI thread.
44 private static LauncherAppState INSTANCE;
46 private final Context mContext;
47 private final LauncherModel mModel;
48 private final IconCache mIconCache;
49 private final WidgetPreviewLoader mWidgetCache;
50 private final InvariantDeviceProfile mInvariantDeviceProfile;
53 public static LauncherAppState getInstance(final Context context) {
54 if (INSTANCE == null) {
55 if (Looper.myLooper() == Looper.getMainLooper()) {
56 INSTANCE = new LauncherAppState(context.getApplicationContext());
57 GridSizeMigrationTask.logDeviceProfileIfChanged(
58 INSTANCE.getInvariantDeviceProfile(), context);
61 return new MainThreadExecutor().submit(new Callable<LauncherAppState>() {
63 public LauncherAppState call() throws Exception {
64 return LauncherAppState.getInstance(context);
67 } catch (InterruptedException|ExecutionException e) {
68 throw new RuntimeException(e);
75 public static LauncherAppState getInstanceNoCreate() {
79 public Context getContext() {
83 private LauncherAppState(Context context) {
84 if (getLocalProvider(context) == null) {
85 throw new RuntimeException(
86 "Initializing LauncherAppState in the absence of LauncherProvider");
88 Log.v(Launcher.TAG, "LauncherAppState initiated");
89 Preconditions.assertUIThread();
92 if (TestingUtils.MEMORY_DUMP_ENABLED) {
93 TestingUtils.startTrackingMemory(mContext);
96 mInvariantDeviceProfile = new InvariantDeviceProfile(mContext);
97 mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
98 mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
100 mModel = new LauncherModel(this, mIconCache,
101 Utilities.getOverrideObject(AppFilter.class, mContext, R.string.app_filter_class));
103 LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel);
105 // Register intent receivers
106 IntentFilter filter = new IntentFilter();
107 filter.addAction(Intent.ACTION_LOCALE_CHANGED);
108 // For handling managed profiles
109 filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
110 filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
111 filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
112 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
113 filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
114 // For extracting colors from the wallpaper
115 if (Utilities.ATLEAST_NOUGAT) {
116 // TODO: add a broadcast entry to the manifest for pre-N.
117 filter.addAction(Intent.ACTION_WALLPAPER_CHANGED);
120 mContext.registerReceiver(mModel, filter);
121 UserManagerCompat.getInstance(mContext).enableAndResetCache();
122 new ConfigMonitor(mContext).register();
124 ExtractionUtils.startColorExtractionServiceIfNecessary(mContext);
128 * Call from Application.onTerminate(), which is not guaranteed to ever be called.
130 public void onTerminate() {
131 mContext.unregisterReceiver(mModel);
132 final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
133 launcherApps.removeOnAppsChangedCallback(mModel);
134 PackageInstallerCompat.getInstance(mContext).onStop();
137 LauncherModel setLauncher(Launcher launcher) {
138 getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
139 mModel.initialize(launcher);
143 public IconCache getIconCache() {
147 public LauncherModel getModel() {
151 public WidgetPreviewLoader getWidgetCache() {
155 public InvariantDeviceProfile getInvariantDeviceProfile() {
156 return mInvariantDeviceProfile;
160 * Shorthand for {@link #getInvariantDeviceProfile()}
162 public static InvariantDeviceProfile getIDP(Context context) {
163 return LauncherAppState.getInstance(context).getInvariantDeviceProfile();
166 private static LauncherProvider getLocalProvider(Context context) {
167 try (ContentProviderClient cl = context.getContentResolver()
168 .acquireContentProviderClient(LauncherProvider.AUTHORITY)) {
169 return (LauncherProvider) cl.getLocalContentProvider();