1 /* 2 * Copyright (C) 2013 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.statusbar; 18 19 import android.content.res.Configuration; 20 import android.provider.Settings; 21 import android.util.Log; 22 23 import com.android.systemui.R; 24 import com.android.systemui.SystemUI; 25 26 import java.io.FileDescriptor; 27 import java.io.PrintWriter; 28 29 /** 30 * Ensure a single status bar service implementation is running at all times. 31 * 32 * <p>The implementation either comes from a service component running in a remote process (defined 33 * using a secure setting), else falls back to using the in-process implementation according 34 * to the product config. 35 */ 36 public class SystemBars extends SystemUI implements ServiceMonitor.Callbacks { 37 private static final String TAG = "SystemBars"; 38 private static final boolean DEBUG = false; 39 private static final int WAIT_FOR_BARS_TO_DIE = 500; 40 41 // manages the implementation coming from the remote process 42 private ServiceMonitor mServiceMonitor; 43 44 // in-process fallback implementation, per the product config 45 private BaseStatusBar mStatusBar; 46 47 @Override 48 public void start() { 49 if (DEBUG) Log.d(TAG, "start"); 50 mServiceMonitor = new ServiceMonitor(TAG, DEBUG, 51 mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this); 52 mServiceMonitor.start(); // will call onNoService if no remote service is found 53 } 54 55 @Override 56 public void onNoService() { 57 if (DEBUG) Log.d(TAG, "onNoService"); 58 createStatusBarFromConfig(); // fallback to using an in-process implementation 59 } 60 61 @Override 62 public long onServiceStartAttempt() { 63 if (DEBUG) Log.d(TAG, "onServiceStartAttempt mStatusBar="+mStatusBar); 64 if (mStatusBar != null) { 65 // tear down the in-process version, we'll recreate it again if needed 66 mStatusBar.destroy(); 67 mStatusBar = null; 68 return WAIT_FOR_BARS_TO_DIE; 69 } 70 return 0; 71 } 72 73 @Override 74 protected void onConfigurationChanged(Configuration newConfig) { 75 if (mStatusBar != null) { 76 mStatusBar.onConfigurationChanged(newConfig); 77 } 78 } 79 80 @Override 81 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 82 if (mStatusBar != null) { 83 mStatusBar.dump(fd, pw, args); 84 } 85 } 86 87 private void createStatusBarFromConfig() { 88 if (DEBUG) Log.d(TAG, "createStatusBarFromConfig"); 89 final String clsName = mContext.getString(R.string.config_statusBarComponent); 90 if (clsName == null || clsName.length() == 0) { 91 throw andLog("No status bar component configured", null); 92 } 93 Class<?> cls = null; 94 try { 95 cls = mContext.getClassLoader().loadClass(clsName); 96 } catch (Throwable t) { 97 throw andLog("Error loading status bar component: " + clsName, t); 98 } 99 try { 100 mStatusBar = (BaseStatusBar) cls.newInstance(); 101 } catch (Throwable t) { 102 throw andLog("Error creating status bar component: " + clsName, t); 103 } 104 mStatusBar.mContext = mContext; 105 mStatusBar.mComponents = mComponents; 106 mStatusBar.start(); 107 if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName()); 108 } 109 110 private RuntimeException andLog(String msg, Throwable t) { 111 Log.w(TAG, msg, t); 112 throw new RuntimeException(msg, t); 113 } 114 } 115