1 /* 2 * Copyright (C) 2016 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.annotation.NonNull; 20 import android.content.Context; 21 import android.content.res.Resources; 22 import android.os.Handler; 23 import android.os.Looper; 24 import android.util.Log; 25 import android.view.ViewGroup; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 import com.android.internal.widget.LockPatternUtils; 29 import com.android.keyguard.KeyguardUpdateMonitor; 30 import com.android.keyguard.ViewMediatorCallback; 31 import com.android.systemui.bubbles.BubbleController; 32 import com.android.systemui.dagger.DaggerSystemUIRootComponent; 33 import com.android.systemui.dagger.DependencyProvider; 34 import com.android.systemui.dagger.SystemUIRootComponent; 35 import com.android.systemui.keyguard.DismissCallbackRegistry; 36 import com.android.systemui.plugins.FalsingManager; 37 import com.android.systemui.plugins.statusbar.StatusBarStateController; 38 import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider; 39 import com.android.systemui.statusbar.NotificationListener; 40 import com.android.systemui.statusbar.NotificationMediaManager; 41 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator; 42 import com.android.systemui.statusbar.phone.DozeParameters; 43 import com.android.systemui.statusbar.phone.KeyguardBouncer; 44 import com.android.systemui.statusbar.phone.KeyguardBypassController; 45 import com.android.systemui.statusbar.phone.NotificationIconAreaController; 46 import com.android.systemui.statusbar.phone.StatusBar; 47 import com.android.systemui.statusbar.policy.KeyguardStateController; 48 49 import java.util.concurrent.Executor; 50 51 import dagger.Module; 52 import dagger.Provides; 53 54 /** 55 * Class factory to provide customizable SystemUI components. 56 */ 57 public class SystemUIFactory { 58 private static final String TAG = "SystemUIFactory"; 59 60 static SystemUIFactory mFactory; 61 private SystemUIRootComponent mRootComponent; 62 getInstance()63 public static <T extends SystemUIFactory> T getInstance() { 64 return (T) mFactory; 65 } 66 createFromConfig(Context context)67 public static void createFromConfig(Context context) { 68 if (mFactory != null) { 69 return; 70 } 71 72 final String clsName = context.getString(R.string.config_systemUIFactoryComponent); 73 if (clsName == null || clsName.length() == 0) { 74 throw new RuntimeException("No SystemUIFactory component configured"); 75 } 76 77 try { 78 Class<?> cls = null; 79 cls = context.getClassLoader().loadClass(clsName); 80 mFactory = (SystemUIFactory) cls.newInstance(); 81 mFactory.init(context); 82 } catch (Throwable t) { 83 Log.w(TAG, "Error creating SystemUIFactory component: " + clsName, t); 84 throw new RuntimeException(t); 85 } 86 } 87 88 @VisibleForTesting cleanup()89 static void cleanup() { 90 mFactory = null; 91 } 92 SystemUIFactory()93 public SystemUIFactory() {} 94 init(Context context)95 private void init(Context context) { 96 mRootComponent = buildSystemUIRootComponent(context); 97 98 // Every other part of our codebase currently relies on Dependency, so we 99 // really need to ensure the Dependency gets initialized early on. 100 101 Dependency dependency = new Dependency(); 102 mRootComponent.createDependency().createSystemUI(dependency); 103 dependency.start(); 104 } 105 initWithRootComponent(@onNull SystemUIRootComponent rootComponent)106 protected void initWithRootComponent(@NonNull SystemUIRootComponent rootComponent) { 107 if (mRootComponent != null) { 108 throw new RuntimeException("Root component can be set only once."); 109 } 110 111 mRootComponent = rootComponent; 112 } 113 buildSystemUIRootComponent(Context context)114 protected SystemUIRootComponent buildSystemUIRootComponent(Context context) { 115 return DaggerSystemUIRootComponent.builder() 116 .dependencyProvider(new DependencyProvider()) 117 .contextHolder(new ContextHolder(context)) 118 .build(); 119 } 120 getRootComponent()121 public SystemUIRootComponent getRootComponent() { 122 return mRootComponent; 123 } 124 125 /** Returns the list of system UI components that should be started. */ getSystemUIServiceComponents(Resources resources)126 public String[] getSystemUIServiceComponents(Resources resources) { 127 return resources.getStringArray(R.array.config_systemUIServiceComponents); 128 } 129 130 /** Returns the list of system UI components that should be started per user. */ getSystemUIServiceComponentsPerUser(Resources resources)131 public String[] getSystemUIServiceComponentsPerUser(Resources resources) { 132 return resources.getStringArray(R.array.config_systemUIServiceComponentsPerUser); 133 } 134 135 /** 136 * Creates an instance of ScreenshotNotificationSmartActionsProvider. 137 * This method is overridden in vendor specific implementation of Sys UI. 138 */ 139 public ScreenshotNotificationSmartActionsProvider createScreenshotNotificationSmartActionsProvider(Context context, Executor executor, Handler uiHandler)140 createScreenshotNotificationSmartActionsProvider(Context context, 141 Executor executor, 142 Handler uiHandler) { 143 return new ScreenshotNotificationSmartActionsProvider(); 144 } 145 createKeyguardBouncer(Context context, ViewMediatorCallback callback, LockPatternUtils lockPatternUtils, ViewGroup container, DismissCallbackRegistry dismissCallbackRegistry, KeyguardBouncer.BouncerExpansionCallback expansionCallback, KeyguardStateController keyguardStateController, FalsingManager falsingManager, KeyguardBypassController bypassController)146 public KeyguardBouncer createKeyguardBouncer(Context context, ViewMediatorCallback callback, 147 LockPatternUtils lockPatternUtils, ViewGroup container, 148 DismissCallbackRegistry dismissCallbackRegistry, 149 KeyguardBouncer.BouncerExpansionCallback expansionCallback, 150 KeyguardStateController keyguardStateController, FalsingManager falsingManager, 151 KeyguardBypassController bypassController) { 152 return new KeyguardBouncer(context, callback, lockPatternUtils, container, 153 dismissCallbackRegistry, falsingManager, 154 expansionCallback, keyguardStateController, 155 Dependency.get(KeyguardUpdateMonitor.class), bypassController, 156 new Handler(Looper.getMainLooper())); 157 } 158 createNotificationIconAreaController(Context context, StatusBar statusBar, NotificationWakeUpCoordinator wakeUpCoordinator, KeyguardBypassController keyguardBypassController, StatusBarStateController statusBarStateController)159 public NotificationIconAreaController createNotificationIconAreaController(Context context, 160 StatusBar statusBar, 161 NotificationWakeUpCoordinator wakeUpCoordinator, 162 KeyguardBypassController keyguardBypassController, 163 StatusBarStateController statusBarStateController) { 164 return new NotificationIconAreaController(context, statusBar, statusBarStateController, 165 wakeUpCoordinator, keyguardBypassController, 166 Dependency.get(NotificationMediaManager.class), 167 Dependency.get(NotificationListener.class), 168 Dependency.get(DozeParameters.class), 169 Dependency.get(BubbleController.class)); 170 } 171 172 @Module 173 public static class ContextHolder { 174 private Context mContext; 175 ContextHolder(Context context)176 public ContextHolder(Context context) { 177 mContext = context; 178 } 179 180 @Provides provideContext()181 public Context provideContext() { 182 return mContext; 183 } 184 } 185 } 186