• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 
17 package com.android.launcher3;
18 
19 import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
20 import static com.android.launcher3.util.SecureSettingsObserver.newNotificationSettingsObserver;
21 
22 import android.app.KeyguardManager;
23 import android.content.ComponentName;
24 import android.content.ContentProviderClient;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.IntentFilter;
28 import android.os.Handler;
29 import android.os.Process;
30 import android.util.Log;
31 
32 import com.android.launcher3.compat.LauncherAppsCompat;
33 import com.android.launcher3.compat.PackageInstallerCompat;
34 import com.android.launcher3.compat.UserManagerCompat;
35 import com.android.launcher3.config.FeatureFlags;
36 import com.android.launcher3.icons.IconCache;
37 import com.android.launcher3.icons.LauncherIcons;
38 import com.android.launcher3.notification.NotificationListener;
39 import com.android.launcher3.util.MainThreadInitializedObject;
40 import com.android.launcher3.util.Preconditions;
41 import com.android.launcher3.util.SecureSettingsObserver;
42 
43 public class LauncherAppState {
44 
45     public static final String ACTION_FORCE_ROLOAD = "force-reload-launcher";
46 
47     // We do not need any synchronization for this variable as its only written on UI thread.
48     private static final MainThreadInitializedObject<LauncherAppState> INSTANCE =
49             new MainThreadInitializedObject<>((c) -> new LauncherAppState(c));
50 
51     private final Context mContext;
52     private final LauncherModel mModel;
53     private final IconCache mIconCache;
54     private final WidgetPreviewLoader mWidgetCache;
55     private final InvariantDeviceProfile mInvariantDeviceProfile;
56     private final SecureSettingsObserver mNotificationDotsObserver;
57 
getInstance(final Context context)58     public static LauncherAppState getInstance(final Context context) {
59         return INSTANCE.get(context);
60     }
61 
getInstanceNoCreate()62     public static LauncherAppState getInstanceNoCreate() {
63         return INSTANCE.getNoCreate();
64     }
65 
getContext()66     public Context getContext() {
67         return mContext;
68     }
69 
LauncherAppState(Context context)70     private LauncherAppState(Context context) {
71         if (getLocalProvider(context) == null) {
72             throw new RuntimeException(
73                     "Initializing LauncherAppState in the absence of LauncherProvider");
74         }
75         Log.v(Launcher.TAG, "LauncherAppState initiated");
76         Preconditions.assertUIThread();
77         mContext = context;
78 
79         mInvariantDeviceProfile = InvariantDeviceProfile.INSTANCE.get(mContext);
80         mIconCache = new IconCache(mContext, mInvariantDeviceProfile);
81         mWidgetCache = new WidgetPreviewLoader(mContext, mIconCache);
82         mModel = new LauncherModel(this, mIconCache, AppFilter.newInstance(mContext));
83 
84         LauncherAppsCompat.getInstance(mContext).addOnAppsChangedCallback(mModel);
85 
86         // Register intent receivers
87         IntentFilter filter = new IntentFilter();
88         filter.addAction(Intent.ACTION_LOCALE_CHANGED);
89         // For handling managed profiles
90         filter.addAction(Intent.ACTION_MANAGED_PROFILE_ADDED);
91         filter.addAction(Intent.ACTION_MANAGED_PROFILE_REMOVED);
92         filter.addAction(Intent.ACTION_MANAGED_PROFILE_AVAILABLE);
93         filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNAVAILABLE);
94         filter.addAction(Intent.ACTION_MANAGED_PROFILE_UNLOCKED);
95 
96         if (FeatureFlags.IS_DOGFOOD_BUILD) {
97             filter.addAction(ACTION_FORCE_ROLOAD);
98         }
99 
100         mContext.registerReceiver(mModel, filter);
101         UserManagerCompat.getInstance(mContext).enableAndResetCache();
102         mInvariantDeviceProfile.addOnChangeListener(this::onIdpChanged);
103         new Handler().post( () -> mInvariantDeviceProfile.verifyConfigChangedInBackground(context));
104 
105         if (!mContext.getResources().getBoolean(R.bool.notification_dots_enabled)) {
106             mNotificationDotsObserver = null;
107         } else {
108             // Register an observer to rebind the notification listener when dots are re-enabled.
109             mNotificationDotsObserver =
110                     newNotificationSettingsObserver(mContext, this::onNotificationSettingsChanged);
111             mNotificationDotsObserver.register();
112             mNotificationDotsObserver.dispatchOnChange();
113         }
114     }
115 
onNotificationSettingsChanged(boolean areNotificationDotsEnabled)116     protected void onNotificationSettingsChanged(boolean areNotificationDotsEnabled) {
117         if (areNotificationDotsEnabled) {
118             NotificationListener.requestRebind(new ComponentName(
119                     mContext, NotificationListener.class));
120         }
121     }
122 
onIdpChanged(int changeFlags, InvariantDeviceProfile idp)123     private void onIdpChanged(int changeFlags, InvariantDeviceProfile idp) {
124         if (changeFlags == 0) {
125             return;
126         }
127 
128         if ((changeFlags & CHANGE_FLAG_ICON_PARAMS) != 0) {
129             LauncherIcons.clearPool();
130             mIconCache.updateIconParams(idp.fillResIconDpi, idp.iconBitmapSize);
131             mWidgetCache.refresh();
132         }
133 
134         mModel.forceReload();
135     }
136 
137     /**
138      * Call from Application.onTerminate(), which is not guaranteed to ever be called.
139      */
onTerminate()140     public void onTerminate() {
141         mContext.unregisterReceiver(mModel);
142         final LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(mContext);
143         launcherApps.removeOnAppsChangedCallback(mModel);
144         PackageInstallerCompat.getInstance(mContext).onStop();
145         if (mNotificationDotsObserver != null) {
146             mNotificationDotsObserver.unregister();
147         }
148     }
149 
setLauncher(Launcher launcher)150     LauncherModel setLauncher(Launcher launcher) {
151         getLocalProvider(mContext).setLauncherProviderChangeListener(launcher);
152         mModel.initialize(launcher);
153         return mModel;
154     }
155 
getIconCache()156     public IconCache getIconCache() {
157         return mIconCache;
158     }
159 
getModel()160     public LauncherModel getModel() {
161         return mModel;
162     }
163 
getWidgetCache()164     public WidgetPreviewLoader getWidgetCache() {
165         return mWidgetCache;
166     }
167 
getInvariantDeviceProfile()168     public InvariantDeviceProfile getInvariantDeviceProfile() {
169         return mInvariantDeviceProfile;
170     }
171 
172     /**
173      * Shorthand for {@link #getInvariantDeviceProfile()}
174      */
getIDP(Context context)175     public static InvariantDeviceProfile getIDP(Context context) {
176         return InvariantDeviceProfile.INSTANCE.get(context);
177     }
178 
getLocalProvider(Context context)179     private static LauncherProvider getLocalProvider(Context context) {
180         try (ContentProviderClient cl = context.getContentResolver()
181                 .acquireContentProviderClient(LauncherProvider.AUTHORITY)) {
182             return (LauncherProvider) cl.getLocalContentProvider();
183         }
184     }
185 }
186