diff options
12 files changed, 103 insertions, 43 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java index 8fabe7aa9eb6..62826d806adc 100644 --- a/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java +++ b/packages/SystemUI/src/com/android/systemui/ContextComponentHelper.java @@ -16,10 +16,12 @@ package com.android.systemui; +import android.app.Service; + /** * Interface necessary to make Dagger happy. See {@link ContextComponentResolver}. */ public interface ContextComponentHelper { /** Turns a classname into an instance of the class or returns null. */ - <T> T resolve(String className); + Service resolveService(String className); } diff --git a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java index 09bccd993f39..e8f019688997 100644 --- a/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java +++ b/packages/SystemUI/src/com/android/systemui/ContextComponentResolver.java @@ -16,6 +16,8 @@ package com.android.systemui; +import android.app.Service; + import java.util.Map; import javax.inject.Inject; @@ -25,21 +27,26 @@ import javax.inject.Provider; * Used during Service and Activity instantiation to make them injectable. */ public class ContextComponentResolver implements ContextComponentHelper { - private final Map<Class<?>, Provider<Object>> mCreators; + private final Map<Class<?>, Provider<Service>> mServiceCreators; @Inject - ContextComponentResolver(Map<Class<?>, Provider<Object>> creators) { - mCreators = creators; + ContextComponentResolver( + Map<Class<?>, Provider<Service>> serviceCreators) { + mServiceCreators = serviceCreators; } /** - * Looks up the class name to see if Dagger has an instance of it. + * Looks up the Service class name to see if Dagger has an instance of it. */ @Override - public <T> T resolve(String className) { - for (Map.Entry<Class<?>, Provider<Object>> p : mCreators.entrySet()) { + public Service resolveService(String className) { + return resolve(className, mServiceCreators); + } + + private <T> T resolve(String className, Map<Class<?>, Provider<T>> creators) { + for (Map.Entry<Class<?>, Provider<T>> p : creators.entrySet()) { if (p.getKey().getName().equals(className)) { - return (T) p.getValue().get(); + return p.getValue().get(); } } diff --git a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java index 6282c6e5282f..131a0f8c81a9 100644 --- a/packages/SystemUI/src/com/android/systemui/ServiceBinder.java +++ b/packages/SystemUI/src/com/android/systemui/ServiceBinder.java @@ -16,6 +16,8 @@ package com.android.systemui; +import android.app.Service; + import com.android.systemui.doze.DozeService; import dagger.Binds; @@ -36,6 +38,5 @@ public abstract class ServiceBinder { @Binds @IntoMap @ClassKey(DozeService.class) - public abstract Object bindDozeService(DozeService service); - + public abstract Service bindDozeService(DozeService service); } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java index 00ae99295768..6a59fa19b0eb 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIAppComponentFactory.java @@ -18,16 +18,25 @@ package com.android.systemui; import android.app.Application; import android.app.Service; +import android.content.ContentProvider; +import android.content.Context; import android.content.Intent; -import androidx.core.app.CoreComponentFactory; +import androidx.annotation.NonNull; +import androidx.core.app.AppComponentFactory; import javax.inject.Inject; /** * Implementation of AppComponentFactory that injects into constructors. + * + * This class sets up dependency injection when creating our application. + * + * Services support dependency injection into their constructors. + * + * ContentProviders support injection into member variables - _not_ constructors. */ -public class SystemUIAppComponentFactory extends CoreComponentFactory { +public class SystemUIAppComponentFactory extends AppComponentFactory { @Inject public ContextComponentHelper mComponentHelper; @@ -36,12 +45,14 @@ public class SystemUIAppComponentFactory extends CoreComponentFactory { super(); } + @NonNull @Override - public Application instantiateApplication(ClassLoader cl, String className) + public Application instantiateApplicationCompat( + @NonNull ClassLoader cl, @NonNull String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { - Application app = super.instantiateApplication(cl, className); - if (app instanceof SystemUIApplication) { - ((SystemUIApplication) app).setContextAvailableCallback( + Application app = super.instantiateApplicationCompat(cl, className); + if (app instanceof ContextProvider) { + ((ContextProvider) app).setContextAvailableCallback( context -> { SystemUIFactory.createFromConfig(context); SystemUIFactory.getInstance().getRootComponent().inject( @@ -53,24 +64,43 @@ public class SystemUIAppComponentFactory extends CoreComponentFactory { return app; } + @NonNull @Override - public Service instantiateService(ClassLoader cl, String className, Intent intent) + public ContentProvider instantiateProviderCompat( + @NonNull ClassLoader cl, @NonNull String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException { - Service service = mComponentHelper.resolve(className); - if (service != null) { - return checkCompatWrapper(service); + + ContentProvider contentProvider = super.instantiateProviderCompat(cl, className); + if (contentProvider instanceof ContextProvider) { + ((ContextProvider) contentProvider).setContextAvailableCallback( + context -> { + SystemUIFactory.createFromConfig(context); + SystemUIFactory.getInstance().getRootComponent().inject( + contentProvider); + } + ); } - return super.instantiateService(cl, className, intent); + + return contentProvider; } - static <T> T checkCompatWrapper(T obj) { - if (obj instanceof CompatWrapped) { - T wrapper = (T) ((CompatWrapped) obj).getWrapper(); - if (wrapper != null) { - return wrapper; - } + @NonNull + @Override + public Service instantiateServiceCompat( + @NonNull ClassLoader cl, @NonNull String className, Intent intent) + throws InstantiationException, IllegalAccessException, ClassNotFoundException { + Service service = mComponentHelper.resolveService(className); + if (service != null) { + return service; } + return super.instantiateServiceCompat(cl, className, intent); + } + + interface ContextAvailableCallback { + void onContextAvailable(Context context); + } - return obj; + interface ContextProvider { + void setContextAvailableCallback(ContextAvailableCallback callback); } } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java index 0b1fe6994c3d..aafc67ecd496 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java @@ -48,7 +48,8 @@ import java.util.Map; /** * Application class for SystemUI. */ -public class SystemUIApplication extends Application implements SysUiServiceProvider { +public class SystemUIApplication extends Application implements SysUiServiceProvider, + SystemUIAppComponentFactory.ContextProvider { public static final String TAG = "SystemUIService"; private static final boolean DEBUG = false; @@ -60,7 +61,7 @@ public class SystemUIApplication extends Application implements SysUiServiceProv private boolean mServicesStarted; private boolean mBootCompleted; private final Map<Class<?>, Object> mComponents = new HashMap<>(); - private ContextAvailableCallback mContextAvailableCallback; + private SystemUIAppComponentFactory.ContextAvailableCallback mContextAvailableCallback; @Override public void onCreate() { @@ -290,11 +291,10 @@ public class SystemUIApplication extends Application implements SysUiServiceProv return mServices; } - void setContextAvailableCallback(ContextAvailableCallback callback) { + @Override + public void setContextAvailableCallback( + SystemUIAppComponentFactory.ContextAvailableCallback callback) { mContextAvailableCallback = callback; } - interface ContextAvailableCallback { - void onContextAvailable(Context context); - } } diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java index b67d7dff4d79..39617ecd2770 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java @@ -24,13 +24,13 @@ import android.os.Looper; import android.util.Log; import android.view.ViewGroup; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.colorextraction.ColorExtractor.GradientColors; import com.android.internal.util.function.TriConsumer; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.keyguard.DismissCallbackRegistry; -import com.android.systemui.model.SysUiState; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.KeyguardIndicationController; @@ -70,6 +70,10 @@ public class SystemUIFactory { } public static void createFromConfig(Context context) { + if (mFactory != null) { + return; + } + final String clsName = context.getString(R.string.config_systemUIFactoryComponent); if (clsName == null || clsName.length() == 0) { throw new RuntimeException("No SystemUIFactory component configured"); @@ -86,6 +90,11 @@ public class SystemUIFactory { } } + @VisibleForTesting + static void cleanup() { + mFactory = null; + } + public SystemUIFactory() {} private void init(Context context) { diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java index f18c8b2c3da6..ad04f18c6ec2 100644 --- a/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java +++ b/packages/SystemUI/src/com/android/systemui/SystemUIRootComponent.java @@ -16,6 +16,8 @@ package com.android.systemui; +import android.content.ContentProvider; + import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; import com.android.systemui.fragments.FragmentService; @@ -76,7 +78,12 @@ public interface SystemUIRootComponent { boolean allowNotificationLongPressName(); /** - * Injects into the supplied argument. + * Member injection into the supplied argument. */ void inject(SystemUIAppComponentFactory factory); + + /** + * Member injection into the supplied argument. + */ + void inject(ContentProvider contentProvider); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java index 256cfb28d4de..a245d4112798 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java @@ -42,7 +42,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = new DexmakerShareClassLoaderRule(); - protected final TestableDependency mDependency = new TestableDependency(mContext); + protected TestableDependency mDependency; protected SysuiTestableContext mSysuiContext; private Instrumentation mRealInstrumentation; @@ -53,6 +53,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { @Before public void SysuiSetup() { SystemUIFactory.createFromConfig(mContext); + mDependency = new TestableDependency(mContext); // TODO: Figure out another way to give reference to a SysuiTestableContext. mSysuiContext = (SysuiTestableContext) mContext; @@ -69,6 +70,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest { public void SysuiTeardown() { InstrumentationRegistry.registerInstance(mRealInstrumentation, InstrumentationRegistry.getArguments()); + SystemUIFactory.cleanup(); } @Override diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java index 8d93f967be4f..e4f33e25a341 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java @@ -55,12 +55,13 @@ public abstract class SysuiTestCase { @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule = new DexmakerShareClassLoaderRule(); - public TestableDependency mDependency = new TestableDependency(mContext); + public TestableDependency mDependency; private Instrumentation mRealInstrumentation; @Before public void SysuiSetup() throws Exception { SystemUIFactory.createFromConfig(mContext); + mDependency = new TestableDependency(mContext); mRealInstrumentation = InstrumentationRegistry.getInstrumentation(); Instrumentation inst = spy(mRealInstrumentation); @@ -82,6 +83,7 @@ public abstract class SysuiTestCase { InstrumentationRegistry.getArguments()); // Reset the assert's main looper. Assert.sMainLooper = Looper.getMainLooper(); + SystemUIFactory.cleanup(); } protected LeakCheck getLeakCheck() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java index d35fc30da6c4..7fa1dbeafced 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/DismissCallbackRegistryTest.java @@ -38,12 +38,13 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class DismissCallbackRegistryTest extends SysuiTestCase { - private final DismissCallbackRegistry mDismissCallbackRegistry = new DismissCallbackRegistry(); + private DismissCallbackRegistry mDismissCallbackRegistry; private @Mock IKeyguardDismissCallback mMockCallback; private @Mock IKeyguardDismissCallback mMockCallback2; @Before public void setUp() throws Exception { + mDismissCallbackRegistry = new DismissCallbackRegistry(); MockitoAnnotations.initMocks(this); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java index 75aae017316c..33d3ac848f0f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java @@ -82,8 +82,7 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { private FragmentController mControllerExternalDisplay; private SysuiTestableContext mSysuiTestableContextExternal; - private OverviewProxyService mOverviewProxyService = - mDependency.injectMockDependency(OverviewProxyService.class); + private OverviewProxyService mOverviewProxyService; private CommandQueue mCommandQueue; private SysUiState mMockSysUiState; @@ -115,6 +114,8 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest { public void setupFragment() throws Exception { setupSysuiDependency(); createRootView(); + mOverviewProxyService = + mDependency.injectMockDependency(OverviewProxyService.class); TestableLooper.get(this).runWithLooper(() -> { mHandler = new Handler(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java index cf084287a7b7..d6b38ff4936f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarRotationContextTest.java @@ -30,7 +30,6 @@ import androidx.test.runner.AndroidJUnit4; import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestableContext; -import com.android.systemui.TestableDependency; import com.android.systemui.statusbar.policy.KeyButtonDrawable; import com.android.systemui.statusbar.policy.RotationLockController; @@ -50,7 +49,6 @@ public class NavigationBarRotationContextTest extends SysuiTestCase { @Rule public final SysuiTestableContext mContext = new SysuiTestableContext( InstrumentationRegistry.getContext(), getLeakCheck()); - private final TestableDependency mDependency = new TestableDependency(mContext); private RotationButtonController mRotationButtonController; private RotationButton mRotationButton; |