1 /* 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 17 package com.android.systemui; 18 19 import android.app.Application; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.content.res.Configuration; 25 import android.os.Process; 26 import android.os.SystemProperties; 27 import android.os.UserHandle; 28 import android.util.Log; 29 30 import com.android.systemui.stackdivider.Divider; 31 32 import java.util.HashMap; 33 import java.util.Map; 34 35 /** 36 * Application class for SystemUI. 37 */ 38 public 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[] { 47 com.android.systemui.tuner.TunerService.class, 48 com.android.systemui.keyguard.KeyguardViewMediator.class, 49 com.android.systemui.recents.Recents.class, 50 com.android.systemui.volume.VolumeUI.class, 51 Divider.class, 52 com.android.systemui.statusbar.SystemBars.class, 53 com.android.systemui.usb.StorageNotification.class, 54 com.android.systemui.power.PowerUI.class, 55 com.android.systemui.media.RingtonePlayer.class, 56 com.android.systemui.keyboard.KeyboardUI.class, 57 com.android.systemui.tv.pip.PipUI.class, 58 com.android.systemui.shortcut.ShortcutKeyDispatcher.class, 59 com.android.systemui.VendorServices.class 60 }; 61 62 /** 63 * The classes of the stuff to start for each user. This is a subset of the services listed 64 * above. 65 */ 66 private final Class<?>[] SERVICES_PER_USER = new Class[] { 67 com.android.systemui.recents.Recents.class, 68 com.android.systemui.tv.pip.PipUI.class 69 }; 70 71 /** 72 * Hold a reference on the stuff we start. 73 */ 74 private final SystemUI[] mServices = new SystemUI[SERVICES.length]; 75 private boolean mServicesStarted; 76 private boolean mBootCompleted; 77 private final Map<Class<?>, Object> mComponents = new HashMap<>(); 78 79 @Override onCreate()80 public void onCreate() { 81 super.onCreate(); 82 // Set the application theme that is inherited by all services. Note that setting the 83 // application theme in the manifest does only work for activities. Keep this in sync with 84 // the theme set there. 85 setTheme(R.style.systemui_theme); 86 87 SystemUIFactory.createFromConfig(this); 88 89 if (Process.myUserHandle().equals(UserHandle.SYSTEM)) { 90 IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); 91 filter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY); 92 registerReceiver(new BroadcastReceiver() { 93 @Override 94 public void onReceive(Context context, Intent intent) { 95 if (mBootCompleted) return; 96 97 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received"); 98 unregisterReceiver(this); 99 mBootCompleted = true; 100 if (mServicesStarted) { 101 final int N = mServices.length; 102 for (int i = 0; i < N; i++) { 103 mServices[i].onBootCompleted(); 104 } 105 } 106 } 107 }, filter); 108 } else { 109 // For a secondary user, boot-completed will never be called because it has already 110 // been broadcasted on startup for the primary SystemUI process. Instead, for 111 // components which require the SystemUI component to be initialized per-user, we 112 // start those components now for the current non-system user. 113 startServicesIfNeeded(SERVICES_PER_USER); 114 } 115 } 116 117 /** 118 * Makes sure that all the SystemUI services are running. If they are already running, this is a 119 * no-op. This is needed to conditinally start all the services, as we only need to have it in 120 * the main process. 121 * 122 * <p>This method must only be called from the main thread.</p> 123 */ startServicesIfNeeded()124 public void startServicesIfNeeded() { 125 startServicesIfNeeded(SERVICES); 126 } 127 128 /** 129 * Ensures that all the Secondary user SystemUI services are running. If they are already 130 * running, this is a no-op. This is needed to conditinally start all the services, as we only 131 * need to have it in the main process. 132 * 133 * <p>This method must only be called from the main thread.</p> 134 */ startSecondaryUserServicesIfNeeded()135 void startSecondaryUserServicesIfNeeded() { 136 startServicesIfNeeded(SERVICES_PER_USER); 137 } 138 startServicesIfNeeded(Class<?>[] services)139 private void startServicesIfNeeded(Class<?>[] services) { 140 if (mServicesStarted) { 141 return; 142 } 143 144 if (!mBootCompleted) { 145 // check to see if maybe it was already completed long before we began 146 // see ActivityManagerService.finishBooting() 147 if ("1".equals(SystemProperties.get("sys.boot_completed"))) { 148 mBootCompleted = true; 149 if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent"); 150 } 151 } 152 153 Log.v(TAG, "Starting SystemUI services for user " + 154 Process.myUserHandle().getIdentifier() + "."); 155 final int N = services.length; 156 for (int i=0; i<N; i++) { 157 Class<?> cl = services[i]; 158 if (DEBUG) Log.d(TAG, "loading: " + cl); 159 try { 160 Object newService = SystemUIFactory.getInstance().createInstance(cl); 161 mServices[i] = (SystemUI) ((newService == null) ? cl.newInstance() : newService); 162 } catch (IllegalAccessException ex) { 163 throw new RuntimeException(ex); 164 } catch (InstantiationException ex) { 165 throw new RuntimeException(ex); 166 } 167 168 mServices[i].mContext = this; 169 mServices[i].mComponents = mComponents; 170 if (DEBUG) Log.d(TAG, "running: " + mServices[i]); 171 mServices[i].start(); 172 173 if (mBootCompleted) { 174 mServices[i].onBootCompleted(); 175 } 176 } 177 mServicesStarted = true; 178 } 179 180 @Override onConfigurationChanged(Configuration newConfig)181 public void onConfigurationChanged(Configuration newConfig) { 182 if (mServicesStarted) { 183 int len = mServices.length; 184 for (int i = 0; i < len; i++) { 185 if (mServices[i] != null) { 186 mServices[i].onConfigurationChanged(newConfig); 187 } 188 } 189 } 190 } 191 192 @SuppressWarnings("unchecked") getComponent(Class<T> interfaceType)193 public <T> T getComponent(Class<T> interfaceType) { 194 return (T) mComponents.get(interfaceType); 195 } 196 getServices()197 public SystemUI[] getServices() { 198 return mServices; 199 } 200 } 201