blob: 472648a2f7f6fbd580c48cbe90be6d4dd3830375 [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
19import android.app.Application;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -040020import android.content.BroadcastReceiver;
21import android.content.Context;
22import android.content.Intent;
23import android.content.IntentFilter;
Jorim Jaggicff0acb2014-03-31 16:35:15 +020024import android.content.res.Configuration;
Winsonfe67aba2015-09-22 14:04:46 -070025import android.os.Process;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -040026import android.os.SystemProperties;
Winsonfe67aba2015-09-22 14:04:46 -070027import android.os.UserHandle;
Jorim Jaggicff0acb2014-03-31 16:35:15 +020028import android.util.Log;
29
Jorim Jaggi1fcbab62015-11-04 16:39:50 +010030import com.android.systemui.stackdivider.Divider;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010031
Jorim Jaggicff0acb2014-03-31 16:35:15 +020032import java.util.HashMap;
33import java.util.Map;
34
35/**
36 * Application class for SystemUI.
37 */
38public class SystemUIApplication extends Application {
39
40 private static final String TAG = "SystemUIService";
41 private static final boolean DEBUG = false;
42
43 /**
44 * The classes of the stuff to start.
45 */
46 private final Class<?>[] SERVICES = new Class[] {
Jason Monk5e745172015-06-02 19:14:44 -040047 com.android.systemui.tuner.TunerService.class,
Jorim Jaggicff0acb2014-03-31 16:35:15 +020048 com.android.systemui.keyguard.KeyguardViewMediator.class,
Jorim Jaggid61f2272014-12-19 20:35:35 +010049 com.android.systemui.recents.Recents.class,
John Spurlock86005342014-05-23 11:58:00 -040050 com.android.systemui.volume.VolumeUI.class,
Jorim Jaggidd98d412015-11-18 15:57:38 -080051 Divider.class,
Jorim Jaggicff0acb2014-03-31 16:35:15 +020052 com.android.systemui.statusbar.SystemBars.class,
53 com.android.systemui.usb.StorageNotification.class,
54 com.android.systemui.power.PowerUI.class,
Jason Monk5e745172015-06-02 19:14:44 -040055 com.android.systemui.media.RingtonePlayer.class,
Michael Wright9209c9c2015-09-03 17:57:01 +010056 com.android.systemui.keyboard.KeyboardUI.class,
Youngsang Chof1647922015-12-17 13:39:39 -080057 com.android.systemui.tv.pip.PipUI.class
Jorim Jaggicff0acb2014-03-31 16:35:15 +020058 };
59
60 /**
Winsonfe67aba2015-09-22 14:04:46 -070061 * The classes of the stuff to start for each user. This is a subset of the services listed
62 * above.
63 */
64 private final Class<?>[] SERVICES_PER_USER = new Class[] {
65 com.android.systemui.recents.Recents.class
66 };
67
68 /**
Jorim Jaggicff0acb2014-03-31 16:35:15 +020069 * Hold a reference on the stuff we start.
70 */
71 private final SystemUI[] mServices = new SystemUI[SERVICES.length];
Jorim Jaggi3beffdf2014-04-03 17:37:37 +020072 private boolean mServicesStarted;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -040073 private boolean mBootCompleted;
Winsonfe67aba2015-09-22 14:04:46 -070074 private final Map<Class<?>, Object> mComponents = new HashMap<>();
Jorim Jaggicff0acb2014-03-31 16:35:15 +020075
Adrian Roos070a0b62014-04-10 23:25:03 +020076 @Override
77 public void onCreate() {
78 super.onCreate();
79 // Set the application theme that is inherited by all services. Note that setting the
80 // application theme in the manifest does only work for activities. Keep this in sync with
81 // the theme set there.
82 setTheme(R.style.systemui_theme);
Dan Sandlerdc5f16b2014-04-22 11:51:42 -040083
Xiyuan Xia1b30f792016-01-06 08:50:30 -080084 SystemUIFactory.createFromConfig(this);
85
Winsonfe67aba2015-09-22 14:04:46 -070086 if (Process.myUserHandle().equals(UserHandle.SYSTEM)) {
87 IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
88 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
89 registerReceiver(new BroadcastReceiver() {
90 @Override
91 public void onReceive(Context context, Intent intent) {
92 if (mBootCompleted) return;
Dan Sandlerdc5f16b2014-04-22 11:51:42 -040093
Winsonfe67aba2015-09-22 14:04:46 -070094 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
95 unregisterReceiver(this);
96 mBootCompleted = true;
97 if (mServicesStarted) {
98 final int N = mServices.length;
99 for (int i = 0; i < N; i++) {
100 mServices[i].onBootCompleted();
101 }
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400102 }
103 }
Winsonfe67aba2015-09-22 14:04:46 -0700104 }, filter);
105 } else {
106 // For a secondary user, boot-completed will never be called because it has already
107 // been broadcasted on startup for the primary SystemUI process. Instead, for
108 // components which require the SystemUI component to be initialized per-user, we
109 // start those components now for the current non-system user.
110 startServicesIfNeeded(SERVICES_PER_USER);
111 }
Adrian Roos070a0b62014-04-10 23:25:03 +0200112 }
113
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200114 /**
115 * Makes sure that all the SystemUI services are running. If they are already running, this is a
116 * no-op. This is needed to conditinally start all the services, as we only need to have it in
117 * the main process.
118 *
119 * <p>This method must only be called from the main thread.</p>
120 */
121 public void startServicesIfNeeded() {
Winsonfe67aba2015-09-22 14:04:46 -0700122 startServicesIfNeeded(SERVICES);
123 }
124
125 private void startServicesIfNeeded(Class<?>[] services) {
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200126 if (mServicesStarted) {
127 return;
128 }
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400129
130 if (!mBootCompleted) {
131 // check to see if maybe it was already completed long before we began
132 // see ActivityManagerService.finishBooting()
133 if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
134 mBootCompleted = true;
135 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
136 }
137 }
138
Winsonfe67aba2015-09-22 14:04:46 -0700139 Log.v(TAG, "Starting SystemUI services for user " +
140 Process.myUserHandle().getIdentifier() + ".");
141 final int N = services.length;
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200142 for (int i=0; i<N; i++) {
Winsonfe67aba2015-09-22 14:04:46 -0700143 Class<?> cl = services[i];
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200144 if (DEBUG) Log.d(TAG, "loading: " + cl);
145 try {
Winsonfe67aba2015-09-22 14:04:46 -0700146 mServices[i] = (SystemUI) cl.newInstance();
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200147 } catch (IllegalAccessException ex) {
148 throw new RuntimeException(ex);
149 } catch (InstantiationException ex) {
150 throw new RuntimeException(ex);
151 }
152 mServices[i].mContext = this;
153 mServices[i].mComponents = mComponents;
154 if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
155 mServices[i].start();
Dan Sandlerdc5f16b2014-04-22 11:51:42 -0400156
157 if (mBootCompleted) {
158 mServices[i].onBootCompleted();
159 }
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200160 }
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200161 mServicesStarted = true;
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200162 }
163
164 @Override
165 public void onConfigurationChanged(Configuration newConfig) {
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200166 if (mServicesStarted) {
167 int len = mServices.length;
168 for (int i = 0; i < len; i++) {
Winson94a14852015-09-23 12:44:33 -0700169 if (mServices[i] != null) {
170 mServices[i].onConfigurationChanged(newConfig);
171 }
Jorim Jaggi3beffdf2014-04-03 17:37:37 +0200172 }
Jorim Jaggicff0acb2014-03-31 16:35:15 +0200173 }
174 }
175
176 @SuppressWarnings("unchecked")
177 public <T> T getComponent(Class<T> interfaceType) {
178 return (T) mComponents.get(interfaceType);
179 }
180
181 public SystemUI[] getServices() {
182 return mServices;
183 }
184}