blob: e44e58a84dc864371a685f2c03066bb34dffcdc0 [file] [log] [blame]
Jason Monkea54e8a2018-12-20 10:01:48 -05001/*
2 * Copyright (C) 2018 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
17package com.android.systemui.util;
18
19import android.content.Context;
20import android.util.ArrayMap;
21import android.util.AttributeSet;
22import android.view.InflateException;
23import android.view.LayoutInflater;
24import android.view.View;
25
Robert Snoebergerbe35b762019-03-15 14:33:02 -040026import com.android.keyguard.KeyguardClockSwitch;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070027import com.android.keyguard.KeyguardMessageArea;
Lucas Dupinad079442019-04-03 13:14:11 -070028import com.android.keyguard.KeyguardSliceView;
Dave Mankoff1a0e3822019-07-03 13:26:55 -040029import com.android.systemui.SystemUIRootComponent;
Fabian Kozynskia48d2d02019-02-27 11:36:02 -050030import com.android.systemui.qs.QSCarrierGroup;
Jason Monk7a56b832018-12-27 13:45:51 -050031import com.android.systemui.qs.QSFooterImpl;
Fabian Kozynski00d494d2019-04-04 09:53:50 -040032import com.android.systemui.qs.QSPanel;
33import com.android.systemui.qs.QuickQSPanel;
Jason Monkea54e8a2018-12-20 10:01:48 -050034import com.android.systemui.qs.QuickStatusBarHeader;
Fabian Kozynskif4b368e2019-08-13 10:34:06 -040035import com.android.systemui.qs.customize.QSCustomizer;
Selim Cineke3c6e462019-06-24 19:37:06 -070036import com.android.systemui.statusbar.NotificationShelf;
Gus Prevas59ec2ff2018-12-28 16:20:28 -050037import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
Lucas Dupin2e838ac2019-04-17 16:50:58 -070038import com.android.systemui.statusbar.phone.LockIcon;
Selim Cinekd5921a82019-01-29 19:04:08 -080039import com.android.systemui.statusbar.phone.NotificationPanelView;
Jason Monkea54e8a2018-12-20 10:01:48 -050040
41import java.lang.reflect.InvocationTargetException;
42import java.lang.reflect.Method;
43import java.lang.reflect.Modifier;
44
45import javax.inject.Inject;
46import javax.inject.Named;
47import javax.inject.Singleton;
48
49import dagger.Module;
50import dagger.Provides;
51import dagger.Subcomponent;
52
53/**
54 * Manages inflation that requires dagger injection.
55 * See docs/dagger.md for details.
56 */
57@Singleton
58public class InjectionInflationController {
59
60 public static final String VIEW_CONTEXT = "view_context";
61 private final ViewCreator mViewCreator;
62 private final ArrayMap<String, Method> mInjectionMap = new ArrayMap<>();
63 private final LayoutInflater.Factory2 mFactory = new InjectionFactory();
64
65 @Inject
Dave Mankoff1a0e3822019-07-03 13:26:55 -040066 public InjectionInflationController(SystemUIRootComponent rootComponent) {
Jason Monkea54e8a2018-12-20 10:01:48 -050067 mViewCreator = rootComponent.createViewCreator();
68 initInjectionMap();
69 }
70
71 ArrayMap<String, Method> getInjectionMap() {
72 return mInjectionMap;
73 }
74
75 ViewCreator getFragmentCreator() {
76 return mViewCreator;
77 }
78
79 /**
80 * Wraps a {@link LayoutInflater} to support creating dagger injected views.
81 * See docs/dagger.md for details.
82 */
83 public LayoutInflater injectable(LayoutInflater inflater) {
84 LayoutInflater ret = inflater.cloneInContext(inflater.getContext());
85 ret.setPrivateFactory(mFactory);
86 return ret;
87 }
88
89 private void initInjectionMap() {
90 for (Method method : ViewInstanceCreator.class.getDeclaredMethods()) {
91 if (View.class.isAssignableFrom(method.getReturnType())
92 && (method.getModifiers() & Modifier.PUBLIC) != 0) {
93 mInjectionMap.put(method.getReturnType().getName(), method);
94 }
95 }
96 }
97
98 /**
99 * The subcomponent of dagger that holds all views that need injection.
100 */
101 @Subcomponent
102 public interface ViewCreator {
103 /**
104 * Creates another subcomponent to actually generate the view.
105 */
106 ViewInstanceCreator createInstanceCreator(ViewAttributeProvider attributeProvider);
107 }
108
109 /**
110 * Secondary sub-component that actually creates the views.
111 *
112 * Having two subcomponents lets us hide the complexity of providing the named context
113 * and AttributeSet from the SystemUIRootComponent, instead we have one subcomponent that
114 * creates a new ViewInstanceCreator any time we need to inflate a view.
115 */
116 @Subcomponent(modules = ViewAttributeProvider.class)
117 public interface ViewInstanceCreator {
118 /**
119 * Creates the QuickStatusBarHeader.
120 */
121 QuickStatusBarHeader createQsHeader();
Jason Monk7a56b832018-12-27 13:45:51 -0500122 /**
123 * Creates the QSFooterImpl.
124 */
125 QSFooterImpl createQsFooter();
Gus Prevas59ec2ff2018-12-28 16:20:28 -0500126
127 /**
128 * Creates the NotificationStackScrollLayout.
129 */
130 NotificationStackScrollLayout createNotificationStackScrollLayout();
Selim Cinekd5921a82019-01-29 19:04:08 -0800131
132 /**
133 * Creates the NotificationPanelView.
134 */
135 NotificationPanelView createPanelView();
Fabian Kozynskia48d2d02019-02-27 11:36:02 -0500136
137 /**
138 * Creates the QSCarrierGroup
139 */
140 QSCarrierGroup createQSCarrierGroup();
Robert Snoebergerbe35b762019-03-15 14:33:02 -0400141
142 /**
Selim Cineke3c6e462019-06-24 19:37:06 -0700143 * Creates the Shelf.
144 */
145 NotificationShelf creatNotificationShelf();
146
147 /**
Robert Snoebergerbe35b762019-03-15 14:33:02 -0400148 * Creates the KeyguardClockSwitch.
149 */
150 KeyguardClockSwitch createKeyguardClockSwitch();
Lucas Dupinad079442019-04-03 13:14:11 -0700151
152 /**
153 * Creates the KeyguardSliceView.
154 */
155 KeyguardSliceView createKeyguardSliceView();
Lucas Dupin2e838ac2019-04-17 16:50:58 -0700156
157 /**
158 * Creates the KeyguardMessageArea.
159 */
160 KeyguardMessageArea createKeyguardMessageArea();
161
162 /**
163 * Creates the keyguard LockIcon.
164 */
165 LockIcon createLockIcon();
Fabian Kozynski00d494d2019-04-04 09:53:50 -0400166
167 /**
168 * Creates the QSPanel.
169 */
170 QSPanel createQSPanel();
171
172 /**
173 * Creates the QuickQSPanel.
174 */
175 QuickQSPanel createQuickQSPanel();
Fabian Kozynskif4b368e2019-08-13 10:34:06 -0400176
177 /**
178 * Creates the QSCustomizer.
179 */
180 QSCustomizer createQSCustomizer();
Jason Monkea54e8a2018-12-20 10:01:48 -0500181 }
182
183 /**
184 * Module for providing view-specific constructor objects.
185 */
186 @Module
187 public class ViewAttributeProvider {
188 private final Context mContext;
189 private final AttributeSet mAttrs;
190
191 private ViewAttributeProvider(Context context, AttributeSet attrs) {
192 mContext = context;
193 mAttrs = attrs;
194 }
195
196 /**
197 * Provides the view-themed context (as opposed to the global sysui application context).
198 */
199 @Provides
200 @Named(VIEW_CONTEXT)
201 public Context provideContext() {
202 return mContext;
203 }
204
205 /**
206 * Provides the AttributeSet for the current view being inflated.
207 */
208 @Provides
209 public AttributeSet provideAttributeSet() {
210 return mAttrs;
211 }
212 }
213
214 private class InjectionFactory implements LayoutInflater.Factory2 {
215
216 @Override
217 public View onCreateView(String name, Context context, AttributeSet attrs) {
218 Method creationMethod = mInjectionMap.get(name);
219 if (creationMethod != null) {
220 ViewAttributeProvider provider = new ViewAttributeProvider(context, attrs);
221 try {
222 return (View) creationMethod.invoke(
223 mViewCreator.createInstanceCreator(provider));
224 } catch (IllegalAccessException e) {
225 throw new InflateException("Could not inflate " + name, e);
226 } catch (InvocationTargetException e) {
227 throw new InflateException("Could not inflate " + name, e);
228 }
229 }
230 return null;
231 }
232
233 @Override
234 public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
235 return onCreateView(name, context, attrs);
236 }
237 }
238}