1 /* 2 * Copyright (C) 2019 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.app.Activity; 20 import android.app.Application; 21 import android.app.Service; 22 import android.content.BroadcastReceiver; 23 import android.content.ContentProvider; 24 import android.content.Context; 25 import android.content.Intent; 26 27 import androidx.annotation.NonNull; 28 import androidx.annotation.Nullable; 29 import androidx.core.app.AppComponentFactory; 30 31 import com.android.systemui.dagger.ContextComponentHelper; 32 33 import javax.inject.Inject; 34 35 /** 36 * Implementation of AppComponentFactory that injects into constructors. 37 * 38 * This class sets up dependency injection when creating our application. 39 * 40 * Services support dependency injection into their constructors. 41 * 42 * ContentProviders support injection into member variables - _not_ constructors. 43 */ 44 public class SystemUIAppComponentFactory extends AppComponentFactory { 45 46 private static final String TAG = "AppComponentFactory"; 47 @Inject 48 public ContextComponentHelper mComponentHelper; 49 SystemUIAppComponentFactory()50 public SystemUIAppComponentFactory() { 51 super(); 52 } 53 54 @NonNull 55 @Override instantiateApplicationCompat( @onNull ClassLoader cl, @NonNull String className)56 public Application instantiateApplicationCompat( 57 @NonNull ClassLoader cl, @NonNull String className) 58 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 59 Application app = super.instantiateApplicationCompat(cl, className); 60 if (app instanceof ContextInitializer) { 61 ((ContextInitializer) app).setContextAvailableCallback( 62 context -> { 63 SystemUIFactory.createFromConfig(context); 64 SystemUIFactory.getInstance().getRootComponent().inject( 65 SystemUIAppComponentFactory.this); 66 } 67 ); 68 } 69 70 return app; 71 } 72 73 @NonNull 74 @Override instantiateProviderCompat( @onNull ClassLoader cl, @NonNull String className)75 public ContentProvider instantiateProviderCompat( 76 @NonNull ClassLoader cl, @NonNull String className) 77 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 78 79 ContentProvider contentProvider = super.instantiateProviderCompat(cl, className); 80 if (contentProvider instanceof ContextInitializer) { 81 ((ContextInitializer) contentProvider).setContextAvailableCallback( 82 context -> { 83 SystemUIFactory.createFromConfig(context); 84 SystemUIFactory.getInstance().getRootComponent().inject( 85 contentProvider); 86 } 87 ); 88 } 89 90 return contentProvider; 91 } 92 93 @NonNull 94 @Override instantiateActivityCompat(@onNull ClassLoader cl, @NonNull String className, @Nullable Intent intent)95 public Activity instantiateActivityCompat(@NonNull ClassLoader cl, @NonNull String className, 96 @Nullable Intent intent) 97 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 98 if (mComponentHelper == null) { 99 // This shouldn't happen, but is seen on occasion. 100 // Bug filed against framework to take a look: http://b/141008541 101 SystemUIFactory.getInstance().getRootComponent().inject( 102 SystemUIAppComponentFactory.this); 103 } 104 Activity activity = mComponentHelper.resolveActivity(className); 105 if (activity != null) { 106 return activity; 107 } 108 return super.instantiateActivityCompat(cl, className, intent); 109 } 110 111 @NonNull 112 @Override instantiateServiceCompat( @onNull ClassLoader cl, @NonNull String className, Intent intent)113 public Service instantiateServiceCompat( 114 @NonNull ClassLoader cl, @NonNull String className, Intent intent) 115 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 116 if (mComponentHelper == null) { 117 // This shouldn't happen, but does when a device is freshly formatted. 118 // Bug filed against framework to take a look: http://b/141008541 119 SystemUIFactory.getInstance().getRootComponent().inject( 120 SystemUIAppComponentFactory.this); 121 } 122 Service service = mComponentHelper.resolveService(className); 123 if (service != null) { 124 return service; 125 } 126 return super.instantiateServiceCompat(cl, className, intent); 127 } 128 129 @NonNull 130 @Override instantiateReceiverCompat(@onNull ClassLoader cl, @NonNull String className, @Nullable Intent intent)131 public BroadcastReceiver instantiateReceiverCompat(@NonNull ClassLoader cl, 132 @NonNull String className, @Nullable Intent intent) 133 throws InstantiationException, IllegalAccessException, ClassNotFoundException { 134 if (mComponentHelper == null) { 135 // This shouldn't happen, but does when a device is freshly formatted. 136 // Bug filed against framework to take a look: http://b/141008541 137 SystemUIFactory.getInstance().getRootComponent().inject( 138 SystemUIAppComponentFactory.this); 139 } 140 BroadcastReceiver receiver = mComponentHelper.resolveBroadcastReceiver(className); 141 if (receiver != null) { 142 return receiver; 143 } 144 145 return super.instantiateReceiverCompat(cl, className, intent); 146 } 147 148 /** 149 * A callback that receives a Context when one is ready. 150 */ 151 public interface ContextAvailableCallback { onContextAvailable(Context context)152 void onContextAvailable(Context context); 153 } 154 155 /** 156 * Implemented in classes that get started by the system before a context is available. 157 */ 158 public interface ContextInitializer { setContextAvailableCallback(ContextAvailableCallback callback)159 void setContextAvailableCallback(ContextAvailableCallback callback); 160 } 161 } 162