blob: 359c3301960019a3293e4ada3fb2fca94e6f415c [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;
Winsonfe67aba2015-09-22 14:04:46 -070029import android.os.UserHandle;
Jorim Jaggicff0acb2014-03-31 16:35:15 +020030import android.util.Log;
31
Jason Monkbbac1212016-10-31 10:18:20 -040032import com.android.systemui.fragments.FragmentService;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020033import com.android.systemui.keyboard.KeyboardUI;
34import com.android.systemui.keyguard.KeyguardViewMediator;
35import com.android.systemui.media.RingtonePlayer;
Jason Monk86bc3312016-08-16 13:17:56 -040036import com.android.systemui.plugins.OverlayPlugin;
37import com.android.systemui.plugins.PluginListener;
38import com.android.systemui.plugins.PluginManager;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020039import com.android.systemui.power.PowerUI;
40import com.android.systemui.recents.Recents;
41import com.android.systemui.shortcut.ShortcutKeyDispatcher;
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010042import com.android.systemui.stackdivider.Divider;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020043import com.android.systemui.statusbar.SystemBars;
Jason Monk86bc3312016-08-16 13:17:56 -040044import com.android.systemui.statusbar.phone.PhoneStatusBar;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020045import com.android.systemui.tuner.TunerService;
Winson73bc1592016-10-18 18:47:43 -070046import com.android.systemui.pip.PipUI;
Jorim Jaggic3fe2042016-10-07 18:52:48 +020047import com.android.systemui.usb.StorageNotification;
48import com.android.systemui.volume.VolumeUI;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010049
Jorim Jaggicff0acb2014-03-31 16:35:15 +020050import java.util.HashMap;
51import java.util.Map;
52
53/**
54 * Application class for SystemUI.
55 */
56public class SystemUIApplication extends Application {
57
58 private static final String TAG = "SystemUIService";
59 private static final boolean DEBUG = false;
60
61 /**
62 * The classes of the stuff to start.
63 */
64 private final Class<?>[] SERVICES = new Class[] {
Jason Monkbbac1212016-10-31 10:18:20 -040065 FragmentService.class,
Jorim Jaggic3fe2042016-10-07 18:52:48 +020066 TunerService.class,
67 KeyguardViewMediator.class,
68 Recents.class,
69 VolumeUI.class,
Jorim Jaggidd98d412015-11-18 15:57:38 -080070 Divider.class,
Jorim Jaggic3fe2042016-10-07 18:52:48 +020071 SystemBars.class,
72 StorageNotification.class,
73 PowerUI.class,
74 RingtonePlayer.class,
75 KeyboardUI.class,
76 PipUI.class,
77 ShortcutKeyDispatcher.class,
78 VendorServices.class,
79 LatencyTester.class
Jorim Jaggicff0acb2014-03-31 16:35:15 +020080 };
81
82 /**
Winsonfe67aba2015-09-22 14:04:46 -070083 * The classes of the stuff to start for each user. This is a subset of the services listed
84 * above.
85 */
86 private final Class<?>[] SERVICES_PER_USER = new Class[] {
Jorim Jaggic3fe2042016-10-07 18:52:48 +020087 Recents.class,
88 PipUI.class
Winsonfe67aba2015-09-22 14:04:46 -070089 };
90
91 /**
Jorim Jaggicff0acb2014-03-31 16:35:15 +020092 * Hold a reference on the stuff we start.
93 */
94 private final SystemUI[] mServices = new SystemUI[SERVICES.length];
Jorim Jaggi3beffdf2014-04-03 17:37:37 +020095 private boolean mServicesStarted;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -040096 private boolean mBootCompleted;
Winsonfe67aba2015-09-22 14:04:46 -070097 private final Map<Class<?>, Object> mComponents = new HashMap<>();
Jorim Jaggicff0acb2014-03-31 16:35:15 +020098
Adrian Roos070a0b62014-04-10 23:25:03 +020099 @Override
100 public void onCreate() {
101 super.onCreate();
102 // Set the application theme that is inherited by all services. Note that setting the
103 // application theme in the manifest does only work for activities. Keep this in sync with
104 // the theme set there.
105 setTheme(R.style.systemui_theme);
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400106
Xiyuan Xia1b30f792016-01-06 08:50:30 -0800107 SystemUIFactory.createFromConfig(this);
108
Winsonfe67aba2015-09-22 14:04:46 -0700109 if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
110 IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
111 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
112 registerReceiver(new BroadcastReceiver() {
113 @Override
114 public void onReceive(Context context, Intent intent) {
115 if (mBootCompleted) return;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400116
Winsonfe67aba2015-09-22 14:04:46 -0700117 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
118 unregisterReceiver(this);
119 mBootCompleted = true;
120 if (mServicesStarted) {
121 final int N = mServices.length;
122 for (int i = 0; i < N; i++) {
123 mServices[i].onBootCompleted();
124 }
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400125 }
126 }
Winsonfe67aba2015-09-22 14:04:46 -0700127 }, filter);
128 } else {
dooyoung.hwangb6479842016-08-31 14:15:22 +0900129 // We don't need to startServices for sub-process that is doing some tasks.
130 // (screenshots, sweetsweetdesserts or tuner ..)
131 String processName = ActivityThread.currentProcessName();
132 ApplicationInfo info = getApplicationInfo();
133 if (processName != null && processName.startsWith(info.processName + ":")) {
134 return;
135 }
Winsonfe67aba2015-09-22 14:04:46 -0700136 // For a secondary user, boot-completed will never be called because it has already
137 // been broadcasted on startup for the primary SystemUI process. Instead, for
138 // components which require the SystemUI component to be initialized per-user, we
139 // start those components now for the current non-system user.
140 startServicesIfNeeded(SERVICES_PER_USER);
141 }
Adrian Roos070a0b62014-04-10 23:25:03 +0200142 }
143
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200144 /**
145 * Makes sure that all the SystemUI services are running. If they are already running, this is a
146 * no-op. This is needed to conditinally start all the services, as we only need to have it in
147 * the main process.
148 *
149 * <p>This method must only be called from the main thread.</p>
150 */
151 public void startServicesIfNeeded() {
Winsonfe67aba2015-09-22 14:04:46 -0700152 startServicesIfNeeded(SERVICES);
153 }
154
Winson3c2c34b2016-04-04 17:47:41 -0700155 /**
156 * Ensures that all the Secondary user SystemUI services are running. If they are already
157 * running, this is a no-op. This is needed to conditinally start all the services, as we only
158 * need to have it in the main process.
159 *
160 * <p>This method must only be called from the main thread.</p>
161 */
162 void startSecondaryUserServicesIfNeeded() {
163 startServicesIfNeeded(SERVICES_PER_USER);
164 }
165
Winsonfe67aba2015-09-22 14:04:46 -0700166 private void startServicesIfNeeded(Class<?>[] services) {
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200167 if (mServicesStarted) {
168 return;
169 }
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400170
171 if (!mBootCompleted) {
172 // check to see if maybe it was already completed long before we began
173 // see ActivityManagerService.finishBooting()
174 if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
175 mBootCompleted = true;
176 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
177 }
178 }
179
Winsonfe67aba2015-09-22 14:04:46 -0700180 Log.v(TAG, "Starting SystemUI services for user " +
181 Process.myUserHandle().getIdentifier() + ".");
182 final int N = services.length;
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200183 for (int i=0; i<N; i++) {
Winsonfe67aba2015-09-22 14:04:46 -0700184 Class<?> cl = services[i];
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200185 if (DEBUG) Log.d(TAG, "loading: " + cl);
186 try {
Muyuan Li94ce94e2016-02-24 16:20:54 -0800187 Object newService = SystemUIFactory.getInstance().createInstance(cl);
188 mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService);
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200189 } catch (IllegalAccessException ex) {
190 throw new RuntimeException(ex);
191 } catch (InstantiationException ex) {
192 throw new RuntimeException(ex);
193 }
Muyuan Li94ce94e2016-02-24 16:20:54 -0800194
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200195 mServices[i].mContext = this;
196 mServices[i].mComponents = mComponents;
197 if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
198 mServices[i].start();
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400199
200 if (mBootCompleted) {
201 mServices[i].onBootCompleted();
202 }
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200203 }
Jason Monk86bc3312016-08-16 13:17:56 -0400204 PluginManager.getInstance(this).addPluginListener(OverlayPlugin.ACTION,
205 new PluginListener<OverlayPlugin>() {
206 @Override
207 public void onPluginConnected(OverlayPlugin plugin) {
208 PhoneStatusBar phoneStatusBar = getComponent(PhoneStatusBar.class);
209 if (phoneStatusBar != null) {
210 plugin.setup(phoneStatusBar.getStatusBarWindow(),
211 phoneStatusBar.getNavigationBarView());
212 }
213 }
214 }, OverlayPlugin.VERSION, true /* Allow multiple plugins */);
215
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200216 mServicesStarted = true;
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200217 }
218
219 @Override
220 public void onConfigurationChanged(Configuration newConfig) {
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200221 if (mServicesStarted) {
222 int len = mServices.length;
223 for (int i = 0; i < len; i++) {
Winson94a14852015-09-23 12:44:33 -0700224 if (mServices[i] != null) {
225 mServices[i].onConfigurationChanged(newConfig);
226 }
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200227 }
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200228 }
229 }
230
231 @SuppressWarnings("unchecked")
232 public <T> T getComponent(Class<T> interfaceType) {
233 return (T) mComponents.get(interfaceType);
234 }
235
236 public SystemUI[] getServices() {
237 return mServices;
238 }
239}