• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.systemui.util;
18 
19 import android.content.Context;
20 import android.util.ArrayMap;
21 import android.util.AttributeSet;
22 import android.view.InflateException;
23 import android.view.LayoutInflater;
24 import android.view.View;
25 
26 import com.android.systemui.dagger.SysUISingleton;
27 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
28 
29 import java.lang.reflect.InvocationTargetException;
30 import java.lang.reflect.Method;
31 import java.lang.reflect.Modifier;
32 
33 import javax.inject.Inject;
34 import javax.inject.Named;
35 
36 import dagger.BindsInstance;
37 import dagger.Subcomponent;
38 
39 /**
40  * Manages inflation that requires dagger injection.
41  * See docs/dagger.md for details.
42  */
43 @SysUISingleton
44 public class InjectionInflationController {
45 
46     public static final String VIEW_CONTEXT = "view_context";
47     private final ArrayMap<String, Method> mInjectionMap = new ArrayMap<>();
48     private final LayoutInflater.Factory2 mFactory = new InjectionFactory();
49     private final ViewInstanceCreator.Factory mViewInstanceCreatorFactory;
50 
51     @Inject
InjectionInflationController(ViewInstanceCreator.Factory viewInstanceCreatorFactory)52     public InjectionInflationController(ViewInstanceCreator.Factory viewInstanceCreatorFactory) {
53         mViewInstanceCreatorFactory = viewInstanceCreatorFactory;
54         initInjectionMap();
55     }
56 
57     /**
58      * Wraps a {@link LayoutInflater} to support creating dagger injected views.
59      * See docs/dagger.md for details.
60      */
injectable(LayoutInflater inflater)61     public LayoutInflater injectable(LayoutInflater inflater) {
62         LayoutInflater ret = inflater.cloneInContext(inflater.getContext());
63         ret.setPrivateFactory(mFactory);
64         return ret;
65     }
66 
initInjectionMap()67     private void initInjectionMap() {
68         for (Method method : ViewInstanceCreator.class.getDeclaredMethods()) {
69             if (View.class.isAssignableFrom(method.getReturnType())
70                     && (method.getModifiers() & Modifier.PUBLIC) != 0) {
71                 mInjectionMap.put(method.getReturnType().getName(), method);
72             }
73         }
74     }
75 
76     /**
77      * Subcomponent that actually creates injected views.
78      */
79     @Subcomponent
80     public interface ViewInstanceCreator {
81 
82         /** Factory for creating a ViewInstanceCreator. */
83         @Subcomponent.Factory
84         interface Factory {
build( @indsInstance @amedVIEW_CONTEXT) Context context, @BindsInstance AttributeSet attributeSet)85             ViewInstanceCreator build(
86                     @BindsInstance @Named(VIEW_CONTEXT) Context context,
87                     @BindsInstance AttributeSet attributeSet);
88         }
89 
90         /**
91          * Creates the NotificationStackScrollLayout.
92          */
createNotificationStackScrollLayout()93         NotificationStackScrollLayout createNotificationStackScrollLayout();
94     }
95 
96 
97     private class InjectionFactory implements LayoutInflater.Factory2 {
98 
99         @Override
onCreateView(String name, Context context, AttributeSet attrs)100         public View onCreateView(String name, Context context, AttributeSet attrs) {
101             Method creationMethod = mInjectionMap.get(name);
102             if (creationMethod != null) {
103                 try {
104                     return (View) creationMethod.invoke(
105                             mViewInstanceCreatorFactory.build(context, attrs));
106                 } catch (IllegalAccessException e) {
107                     throw new InflateException("Could not inflate " + name, e);
108                 } catch (InvocationTargetException e) {
109                     throw new InflateException("Could not inflate " + name, e);
110                 }
111             }
112             return null;
113         }
114 
115         @Override
onCreateView(View parent, String name, Context context, AttributeSet attrs)116         public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
117             return onCreateView(name, context, attrs);
118         }
119     }
120 }
121