blob: 9adafda7adf5da492a786aee556b921d76340899 [file] [log] [blame]
Jorim Jaggicff0acb2014-03-31 16:35:15 +02001/*
2 * Copyright (C) 2014 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
17package com.android.systemui;
18
dooyoung.hwangb6479842016-08-31 14:15:22 +090019import android.app.ActivityThread;
Jorim Jaggicff0acb2014-03-31 16:35:15 +020020import android.app.Application;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -040021import android.content.BroadcastReceiver;
22import android.content.Context;
23import android.content.Intent;
24import android.content.IntentFilter;
dooyoung.hwangb6479842016-08-31 14:15:22 +090025import android.content.pm.ApplicationInfo;
Jorim Jaggicff0acb2014-03-31 16:35:15 +020026import android.content.res.Configuration;
Winsonfe67aba2015-09-22 14:04:46 -070027import android.os.Process;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -040028import android.os.SystemProperties;
Fyodor Kupolovf3591352017-06-23 18:20:40 -070029import android.os.Trace;
Winsonfe67aba2015-09-22 14:04:46 -070030import android.os.UserHandle;
Jason Monk421a9412017-02-06 09:15:21 -080031import android.util.ArraySet;
Fyodor Kupolov6e3461b2017-08-10 17:00:43 -070032import android.util.TimingsTraceLog;
Jorim Jaggicff0acb2014-03-31 16:35:15 +020033import android.util.Log;
34
Jason Monk361915c2017-03-21 20:33:59 -040035import com.android.systemui.globalactions.GlobalActionsComponent;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020036import com.android.systemui.keyboard.KeyboardUI;
37import com.android.systemui.keyguard.KeyguardViewMediator;
38import com.android.systemui.media.RingtonePlayer;
Jason Monk97a06a12016-11-09 15:53:30 -050039import com.android.systemui.pip.PipUI;
Jason Monk361915c2017-03-21 20:33:59 -040040import com.android.systemui.plugins.GlobalActions;
Jason Monk86bc3312016-08-16 13:17:56 -040041import com.android.systemui.plugins.OverlayPlugin;
Jason Monk5bec68f2017-02-08 20:45:10 -080042import com.android.systemui.plugins.Plugin;
Jason Monk86bc3312016-08-16 13:17:56 -040043import com.android.systemui.plugins.PluginListener;
44import com.android.systemui.plugins.PluginManager;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020045import com.android.systemui.power.PowerUI;
46import com.android.systemui.recents.Recents;
47import com.android.systemui.shortcut.ShortcutKeyDispatcher;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010048import com.android.systemui.stackdivider.Divider;
Jason Monkb5b092012017-01-05 11:35:34 -050049import com.android.systemui.statusbar.CommandQueue;
Jason Monk2a6ea9c2017-01-26 11:14:51 -050050import com.android.systemui.statusbar.phone.StatusBar;
Jason Monk421a9412017-02-06 09:15:21 -080051import com.android.systemui.statusbar.phone.StatusBarWindowManager;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020052import com.android.systemui.usb.StorageNotification;
Dan Sandler8e032e12017-01-25 13:41:38 -050053import com.android.systemui.util.NotificationChannels;
Adrian Roos91250682017-02-06 14:48:15 -080054import com.android.systemui.util.leak.GarbageMonitor;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020055import com.android.systemui.volume.VolumeUI;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010056
Jorim Jaggicff0acb2014-03-31 16:35:15 +020057import java.util.HashMap;
58import java.util.Map;
59
60/**
61 * Application class for SystemUI.
62 */
Jason Monk49fa0162017-01-11 09:21:56 -050063public class SystemUIApplication extends Application implements SysUiServiceProvider {
Jorim Jaggicff0acb2014-03-31 16:35:15 +020064
65 private static final String TAG = "SystemUIService";
66 private static final boolean DEBUG = false;
67
68 /**
69 * The classes of the stuff to start.
70 */
71 private final Class<?>[] SERVICES = new Class[] {
Jason Monk9c7844c2017-01-18 15:21:53 -050072 Dependency.class,
Dan Sandler8e032e12017-01-25 13:41:38 -050073 NotificationChannels.class,
Jason Monkb5b092012017-01-05 11:35:34 -050074 CommandQueue.CommandQueueStart.class,
Jorim Jaggic3fe2042016-10-07 18:52:48 +020075 KeyguardViewMediator.class,
76 Recents.class,
77 VolumeUI.class,
Jorim Jaggidd98d412015-11-18 15:57:38 -080078 Divider.class,
Jorim Jaggic3fe2042016-10-07 18:52:48 +020079 SystemBars.class,
80 StorageNotification.class,
81 PowerUI.class,
82 RingtonePlayer.class,
83 KeyboardUI.class,
84 PipUI.class,
85 ShortcutKeyDispatcher.class,
86 VendorServices.class,
Adrian Roos91250682017-02-06 14:48:15 -080087 GarbageMonitor.Service.class,
Adrian Roosf9d13f62016-11-08 15:42:20 -080088 LatencyTester.class,
Jason Monk361915c2017-03-21 20:33:59 -040089 GlobalActionsComponent.class,
Jason Monkd4afe152017-05-01 15:37:43 -040090 RoundedCorners.class,
Jorim Jaggicff0acb2014-03-31 16:35:15 +020091 };
92
93 /**
Winsonfe67aba2015-09-22 14:04:46 -070094 * The classes of the stuff to start for each user. This is a subset of the services listed
95 * above.
96 */
97 private final Class<?>[] SERVICES_PER_USER = new Class[] {
Winson Chung0c7592f2017-02-06 09:04:07 -080098 Dependency.class,
Geoffrey Pitsch790e0912017-03-24 13:37:13 -040099 NotificationChannels.class,
Winson Chung853c99a2017-03-21 22:16:42 -0700100 Recents.class
Winsonfe67aba2015-09-22 14:04:46 -0700101 };
102
103 /**
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200104 * Hold a reference on the stuff we start.
105 */
106 private final SystemUI[] mServices = new SystemUI[SERVICES.length];
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200107 private boolean mServicesStarted;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400108 private boolean mBootCompleted;
Winsonfe67aba2015-09-22 14:04:46 -0700109 private final Map<Class<?>, Object> mComponents = new HashMap<>();
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200110
Adrian Roos070a0b62014-04-10 23:25:03 +0200111 @Override
112 public void onCreate() {
113 super.onCreate();
114 // Set the application theme that is inherited by all services. Note that setting the
115 // application theme in the manifest does only work for activities. Keep this in sync with
116 // the theme set there.
Lucas Dupine17ce522017-07-17 15:45:06 -0700117 setTheme(R.style.Theme_SystemUI);
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400118
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800119 SystemUIFactory.createFromConfig(this);
120
Winsonfe67aba2015-09-22 14:04:46 -0700121 if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
122 IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
123 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
124 registerReceiver(new BroadcastReceiver() {
125 @Override
126 public void onReceive(Context context, Intent intent) {
127 if (mBootCompleted) return;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400128
Winsonfe67aba2015-09-22 14:04:46 -0700129 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
130 unregisterReceiver(this);
131 mBootCompleted = true;
132 if (mServicesStarted) {
133 final int N = mServices.length;
134 for (int i = 0; i < N; i++) {
135 mServices[i].onBootCompleted();
136 }
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400137 }
138 }
Winsonfe67aba2015-09-22 14:04:46 -0700139 }, filter);
140 } else {
dooyoung.hwangb6479842016-08-31 14:15:22 +0900141 // We don't need to startServices for sub-process that is doing some tasks.
142 // (screenshots, sweetsweetdesserts or tuner ..)
143 String processName = ActivityThread.currentProcessName();
144 ApplicationInfo info = getApplicationInfo();
145 if (processName != null && processName.startsWith(info.processName + ":")) {
146 return;
147 }
Winsonfe67aba2015-09-22 14:04:46 -0700148 // For a secondary user, boot-completed will never be called because it has already
149 // been broadcasted on startup for the primary SystemUI process. Instead, for
150 // components which require the SystemUI component to be initialized per-user, we
151 // start those components now for the current non-system user.
152 startServicesIfNeeded(SERVICES_PER_USER);
153 }
Adrian Roos070a0b62014-04-10 23:25:03 +0200154 }
155
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200156 /**
157 * Makes sure that all the SystemUI services are running. If they are already running, this is a
158 * no-op. This is needed to conditinally start all the services, as we only need to have it in
159 * the main process.
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200160 * <p>This method must only be called from the main thread.</p>
161 */
Jason Monkbe3235a2017-04-05 09:29:53 -0400162
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200163 public void startServicesIfNeeded() {
Winsonfe67aba2015-09-22 14:04:46 -0700164 startServicesIfNeeded(SERVICES);
165 }
166
Winson3c2c34b2016-04-04 17:47:41 -0700167 /**
168 * Ensures that all the Secondary user SystemUI services are running. If they are already
169 * running, this is a no-op. This is needed to conditinally start all the services, as we only
170 * need to have it in the main process.
Winson3c2c34b2016-04-04 17:47:41 -0700171 * <p>This method must only be called from the main thread.</p>
172 */
173 void startSecondaryUserServicesIfNeeded() {
174 startServicesIfNeeded(SERVICES_PER_USER);
175 }
176
Winsonfe67aba2015-09-22 14:04:46 -0700177 private void startServicesIfNeeded(Class<?>[] services) {
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200178 if (mServicesStarted) {
179 return;
180 }
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400181
182 if (!mBootCompleted) {
183 // check to see if maybe it was already completed long before we began
184 // see ActivityManagerService.finishBooting()
185 if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
186 mBootCompleted = true;
187 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
188 }
189 }
190
Winsonfe67aba2015-09-22 14:04:46 -0700191 Log.v(TAG, "Starting SystemUI services for user " +
192 Process.myUserHandle().getIdentifier() + ".");
Fyodor Kupolov6e3461b2017-08-10 17:00:43 -0700193 TimingsTraceLog log = new TimingsTraceLog("SystemUIBootTiming",
Fyodor Kupolovf3591352017-06-23 18:20:40 -0700194 Trace.TRACE_TAG_APP);
195 log.traceBegin("StartServices");
Winsonfe67aba2015-09-22 14:04:46 -0700196 final int N = services.length;
Jason Monk421a9412017-02-06 09:15:21 -0800197 for (int i = 0; i < N; i++) {
Winsonfe67aba2015-09-22 14:04:46 -0700198 Class<?> cl = services[i];
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200199 if (DEBUG) Log.d(TAG, "loading: " + cl);
Fyodor Kupolovf3591352017-06-23 18:20:40 -0700200 log.traceBegin("StartServices" + cl.getSimpleName());
201 long ti = System.currentTimeMillis();
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200202 try {
Fyodor Kupolovf3591352017-06-23 18:20:40 -0700203
Muyuan Li94ce94e2016-02-24 16:20:54 -0800204 Object newService = SystemUIFactory.getInstance().createInstance(cl);
205 mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200206 } catch (IllegalAccessException ex) {
207 throw new RuntimeException(ex);
208 } catch (InstantiationException ex) {
209 throw new RuntimeException(ex);
210 }
Muyuan Li94ce94e2016-02-24 16:20:54 -0800211
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200212 mServices[i].mContext = this;
213 mServices[i].mComponents = mComponents;
214 if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
215 mServices[i].start();
Fyodor Kupolovf3591352017-06-23 18:20:40 -0700216 log.traceEnd();
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400217
Fyodor Kupolovf3591352017-06-23 18:20:40 -0700218 // Warn if initialization of component takes too long
219 ti = System.currentTimeMillis() - ti;
220 if (ti > 1000) {
221 Log.w(TAG, "Initialization of " + cl.getName() + " took " + ti + " ms");
222 }
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400223 if (mBootCompleted) {
224 mServices[i].onBootCompleted();
225 }
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200226 }
Fyodor Kupolovf3591352017-06-23 18:20:40 -0700227 log.traceEnd();
Jason Monk5bec68f2017-02-08 20:45:10 -0800228 Dependency.get(PluginManager.class).addPluginListener(
Jason Monk86bc3312016-08-16 13:17:56 -0400229 new PluginListener<OverlayPlugin>() {
Jason Monk421a9412017-02-06 09:15:21 -0800230 private ArraySet<OverlayPlugin> mOverlays;
231
232 @Override
233 public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
234 StatusBar statusBar = getComponent(StatusBar.class);
235 if (statusBar != null) {
236 plugin.setup(statusBar.getStatusBarWindow(),
237 statusBar.getNavigationBarView());
238 }
239 // Lazy init.
240 if (mOverlays == null) mOverlays = new ArraySet<>();
241 if (plugin.holdStatusBarOpen()) {
242 mOverlays.add(plugin);
243 Dependency.get(StatusBarWindowManager.class).setStateListener(b ->
244 mOverlays.forEach(o -> o.setCollapseDesired(b)));
245 Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
246 mOverlays.size() != 0);
247
248 }
249 }
250
251 @Override
252 public void onPluginDisconnected(OverlayPlugin plugin) {
253 mOverlays.remove(plugin);
254 Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
255 mOverlays.size() != 0);
256 }
Jason Monk5bec68f2017-02-08 20:45:10 -0800257 }, OverlayPlugin.class, true /* Allow multiple plugins */);
Jason Monk86bc3312016-08-16 13:17:56 -0400258
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200259 mServicesStarted = true;
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200260 }
261
262 @Override
263 public void onConfigurationChanged(Configuration newConfig) {
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200264 if (mServicesStarted) {
265 int len = mServices.length;
266 for (int i = 0; i < len; i++) {
Winson94a14852015-09-23 12:44:33 -0700267 if (mServices[i] != null) {
268 mServices[i].onConfigurationChanged(newConfig);
269 }
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200270 }
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200271 }
272 }
273
274 @SuppressWarnings("unchecked")
275 public <T> T getComponent(Class<T> interfaceType) {
276 return (T) mComponents.get(interfaceType);
277 }
278
279 public SystemUI[] getServices() {
280 return mServices;
281 }
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200282}