15c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock/* 25c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * Copyright (C) 2013 The Android Open Source Project 35c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * 45c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * Licensed under the Apache License, Version 2.0 (the "License"); 55c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * you may not use this file except in compliance with the License. 65c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * You may obtain a copy of the License at 75c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * 85c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * http://www.apache.org/licenses/LICENSE-2.0 95c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * 105c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * Unless required by applicable law or agreed to in writing, software 115c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * distributed under the License is distributed on an "AS IS" BASIS, 125c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * See the License for the specific language governing permissions and 145c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * limitations under the License. 155c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock */ 165c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 175c4541246c6a70f53552423dc35940386788bd5fJohn Spurlockpackage com.android.systemui.statusbar; 185c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 19777dcdeeb67c570168e04d5096d2a7a9eb408ceaDaniel Sandlerimport android.content.res.Configuration; 205c4541246c6a70f53552423dc35940386788bd5fJohn Spurlockimport android.provider.Settings; 215c4541246c6a70f53552423dc35940386788bd5fJohn Spurlockimport android.util.Log; 225c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 235c4541246c6a70f53552423dc35940386788bd5fJohn Spurlockimport com.android.systemui.R; 245c4541246c6a70f53552423dc35940386788bd5fJohn Spurlockimport com.android.systemui.SystemUI; 255c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 260ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlockimport java.io.FileDescriptor; 270ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlockimport java.io.PrintWriter; 280ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlock 295c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock/** 305c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * Ensure a single status bar service implementation is running at all times. 315c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * 325c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * <p>The implementation either comes from a service component running in a remote process (defined 335c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * using a secure setting), else falls back to using the in-process implementation according 345c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock * to the product config. 355c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock */ 365c4541246c6a70f53552423dc35940386788bd5fJohn Spurlockpublic class SystemBars extends SystemUI implements ServiceMonitor.Callbacks { 375c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock private static final String TAG = "SystemBars"; 38342cad772be1973875dea6a31ceb04bc72e7a6b5John Spurlock private static final boolean DEBUG = false; 395c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock private static final int WAIT_FOR_BARS_TO_DIE = 500; 405c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 415c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock // manages the implementation coming from the remote process 425c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock private ServiceMonitor mServiceMonitor; 435c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 445c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock // in-process fallback implementation, per the product config 455c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock private BaseStatusBar mStatusBar; 465c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 475c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock @Override 485c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock public void start() { 495c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock if (DEBUG) Log.d(TAG, "start"); 505c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock mServiceMonitor = new ServiceMonitor(TAG, DEBUG, 515c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this); 525c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock mServiceMonitor.start(); // will call onNoService if no remote service is found 535c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 545c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 555c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock @Override 565c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock public void onNoService() { 575c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock if (DEBUG) Log.d(TAG, "onNoService"); 585c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock createStatusBarFromConfig(); // fallback to using an in-process implementation 595c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 605c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 615c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock @Override 625c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock public long onServiceStartAttempt() { 635c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock if (DEBUG) Log.d(TAG, "onServiceStartAttempt mStatusBar="+mStatusBar); 645c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock if (mStatusBar != null) { 655c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock // tear down the in-process version, we'll recreate it again if needed 665c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock mStatusBar.destroy(); 675c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock mStatusBar = null; 685c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock return WAIT_FOR_BARS_TO_DIE; 695c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 705c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock return 0; 715c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 725c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 730ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlock @Override 74777dcdeeb67c570168e04d5096d2a7a9eb408ceaDaniel Sandler protected void onConfigurationChanged(Configuration newConfig) { 75777dcdeeb67c570168e04d5096d2a7a9eb408ceaDaniel Sandler if (mStatusBar != null) { 76777dcdeeb67c570168e04d5096d2a7a9eb408ceaDaniel Sandler mStatusBar.onConfigurationChanged(newConfig); 77777dcdeeb67c570168e04d5096d2a7a9eb408ceaDaniel Sandler } 78777dcdeeb67c570168e04d5096d2a7a9eb408ceaDaniel Sandler } 79777dcdeeb67c570168e04d5096d2a7a9eb408ceaDaniel Sandler 80777dcdeeb67c570168e04d5096d2a7a9eb408ceaDaniel Sandler @Override 810ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlock public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 820ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlock if (mStatusBar != null) { 830ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlock mStatusBar.dump(fd, pw, args); 840ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlock } 850ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlock } 860ec64c65fb7fbfd89556bc33f5caab4ef0937fd4John Spurlock 875c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock private void createStatusBarFromConfig() { 885c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock if (DEBUG) Log.d(TAG, "createStatusBarFromConfig"); 895c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock final String clsName = mContext.getString(R.string.config_statusBarComponent); 905c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock if (clsName == null || clsName.length() == 0) { 915c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock throw andLog("No status bar component configured", null); 925c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 935c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock Class<?> cls = null; 945c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock try { 955c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock cls = mContext.getClassLoader().loadClass(clsName); 965c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } catch (Throwable t) { 975c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock throw andLog("Error loading status bar component: " + clsName, t); 985c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 995c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock try { 1005c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock mStatusBar = (BaseStatusBar) cls.newInstance(); 1015c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } catch (Throwable t) { 1025c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock throw andLog("Error creating status bar component: " + clsName, t); 1035c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 1045c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock mStatusBar.mContext = mContext; 105d08de37a2223d5183620098737eb93907a4ba92cJohn Spurlock mStatusBar.mComponents = mComponents; 1065c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock mStatusBar.start(); 1075c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName()); 1085c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 1095c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock 1105c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock private RuntimeException andLog(String msg, Throwable t) { 1115c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock Log.w(TAG, msg, t); 1125c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock throw new RuntimeException(msg, t); 1135c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock } 1145c4541246c6a70f53552423dc35940386788bd5fJohn Spurlock} 115