Home | History | Annotate | Download | only in systemui
      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
     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      */
    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      */
    135     void startSecondaryUserServicesIfNeeded() {
    136         startServicesIfNeeded(SERVICES_PER_USER);
    137     }
    138 
    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
    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")
    193     public <T> T getComponent(Class<T> interfaceType) {
    194         return (T) mComponents.get(interfaceType);
    195     }
    196 
    197     public SystemUI[] getServices() {
    198         return mServices;
    199     }
    200 }
    201