Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 15142270 authored by Cyan Hsieh's avatar Cyan Hsieh
Browse files

Revert "Change SysemUIFactory to SystemUIInitializer."

Revert submission 18917521-b235624311-app-component

Reason for revert: Broken test b/238359875 and b/238372209
Reverted Changes:
I7029fb296:Change SysemUIFactory to SystemUIInitializer.
I082787983:Conform to new SystemUIInitializer pattern.
I923e5bbbc:Conform to new SystemUIInitializer pattern.
I7af1a39b2:Conform to new SystemUIInitializer pattern.
Iba9a5ba24:Conform to new SystemUIInitializer pattern.
I4fe83e292:Conform to new SystemUIInitializer pattern.
I7f54204ae:Conform to new SystemUIInitializer pattern.
I6246c6eb4:Conform to new SystemUIInitializer pattern.

Bug: 238359875
Bug: 238372209
Change-Id: I833ec524c4f6072d64eba55e22f0b37341d38f4f
parent 2983d174
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -9,8 +9,8 @@
-keep class com.android.systemui.statusbar.phone.CentralSurfaces
-keep class com.android.systemui.statusbar.tv.TvStatusBar
-keep class com.android.systemui.car.CarSystemUIFactory
-keep class com.android.systemui.SystemUIInitializer
-keep class com.android.systemui.tv.TvSystemUIInitializer
-keep class com.android.systemui.SystemUIFactory
-keep class com.android.systemui.tv.TvSystemUIFactory
-keep class * extends com.android.systemui.CoreStartable
-keep class * implements com.android.systemui.CoreStartable$Injector

+1 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@
<resources>
    <!-- SystemUIFactory component -->
    <string name="config_systemUIFactoryComponent" translatable="false">
        com.android.systemui.tv.TvSystemUIInitializer
        com.android.systemui.tv.TvSystemUIFactory
    </string>

    <!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
+1 −1
Original line number Diff line number Diff line
@@ -286,7 +286,7 @@
    <bool name="config_enableFullscreenUserSwitcher">false</bool>

    <!-- SystemUIFactory component -->
    <string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIInitializerImpl</string>
    <string name="config_systemUIFactoryComponent" translatable="false">com.android.systemui.SystemUIFactory</string>

    <!-- QS tile shape store width. negative implies fill configuration instead of stroke-->
    <dimen name="config_qsTileStrokeWidthActive">-1dp</dimen>
+148 −10
Original line number Diff line number Diff line
@@ -16,22 +16,160 @@

package com.android.systemui;

import android.app.Activity;
import android.app.Application;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentProvider;
import android.content.Context;
import android.content.Intent;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.AppComponentFactory;

import com.android.systemui.dagger.ContextComponentHelper;
import com.android.systemui.dagger.SysUIComponent;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.inject.Inject;

/**
 * Starts up SystemUI using the AOSP {@link SystemUIInitializerImpl}.
 * Implementation of AppComponentFactory that injects into constructors.
 *
 * This class sets up dependency injection when creating our application.
 *
 * This initializer relies on reflection to start everything up and should be considered deprecated.
 * Instead, create your own {@link SystemUIAppComponentFactoryBase}, specify it in your
 * AndroidManifest.xml and construct your own {@link SystemUIInitializer} directly.
 * Services support dependency injection into their constructors.
 *
 * @deprecated Define your own SystemUIAppComponentFactoryBase implementation and use that. This
 *             implementation may be changed or removed in future releases.
 * ContentProviders support injection into member variables - _not_ constructors.
 */
@Deprecated
public class SystemUIAppComponentFactory extends SystemUIAppComponentFactoryBase {
public class SystemUIAppComponentFactory extends AppComponentFactory {

    private static final String TAG = "AppComponentFactory";
    @Inject
    public ContextComponentHelper mComponentHelper;

    public SystemUIAppComponentFactory() {
        super();
    }

    @NonNull
    @Override
    public Application instantiateApplicationCompat(
            @NonNull ClassLoader cl, @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        Application app = super.instantiateApplicationCompat(cl, className);
        if (app instanceof ContextInitializer) {
            ((ContextInitializer) app).setContextAvailableCallback(
                    context -> {
                        SystemUIFactory.createFromConfig(context);
                        SystemUIFactory.getInstance().getSysUIComponent().inject(
                                SystemUIAppComponentFactory.this);
                    }
            );
        }

        return app;
    }

    @NonNull
    @Override
    public ContentProvider instantiateProviderCompat(
            @NonNull ClassLoader cl, @NonNull String className)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {

        ContentProvider contentProvider = super.instantiateProviderCompat(cl, className);
        if (contentProvider instanceof ContextInitializer) {
            ((ContextInitializer) contentProvider).setContextAvailableCallback(
                    context -> {
                        SystemUIFactory.createFromConfig(context);
                        SysUIComponent rootComponent =
                                SystemUIFactory.getInstance().getSysUIComponent();
                        try {
                            Method injectMethod = rootComponent.getClass()
                                    .getMethod("inject", contentProvider.getClass());
                            injectMethod.invoke(rootComponent, contentProvider);
                        } catch (NoSuchMethodException
                                | IllegalAccessException
                                | InvocationTargetException e) {
                            Log.w(TAG, "No injector for class: " + contentProvider.getClass(), e);
                        }
                    }
            );
        }

        return contentProvider;
    }

    @NonNull
    @Override
    public Activity instantiateActivityCompat(@NonNull ClassLoader cl, @NonNull String className,
            @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        if (mComponentHelper == null) {
            // This shouldn't happen, but is seen on occasion.
            // Bug filed against framework to take a look: http://b/141008541
            SystemUIFactory.getInstance().getSysUIComponent().inject(
                    SystemUIAppComponentFactory.this);
        }
        Activity activity = mComponentHelper.resolveActivity(className);
        if (activity != null) {
            return activity;
        }
        return super.instantiateActivityCompat(cl, className, intent);
    }

    @NonNull
    @Override
    public Service instantiateServiceCompat(
            @NonNull ClassLoader cl, @NonNull String className, Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        if (mComponentHelper == null) {
            // This shouldn't happen, but does when a device is freshly formatted.
            // Bug filed against framework to take a look: http://b/141008541
            SystemUIFactory.getInstance().getSysUIComponent().inject(
                    SystemUIAppComponentFactory.this);
        }
        Service service = mComponentHelper.resolveService(className);
        if (service != null) {
            return service;
        }
        return super.instantiateServiceCompat(cl, className, intent);
    }

    @NonNull
    @Override
    protected SystemUIInitializer createSystemUIInitializer(Context context) {
        return SystemUIInitializerFactory.createWithContext(context);
    public BroadcastReceiver instantiateReceiverCompat(@NonNull ClassLoader cl,
            @NonNull String className, @Nullable Intent intent)
            throws InstantiationException, IllegalAccessException, ClassNotFoundException {
        if (mComponentHelper == null) {
            // This shouldn't happen, but does when a device is freshly formatted.
            // Bug filed against framework to take a look: http://b/141008541
            SystemUIFactory.getInstance().getSysUIComponent().inject(
                    SystemUIAppComponentFactory.this);
        }
        BroadcastReceiver receiver = mComponentHelper.resolveBroadcastReceiver(className);
        if (receiver != null) {
            return receiver;
        }

        return super.instantiateReceiverCompat(cl, className, intent);
    }

    /**
     * A callback that receives a Context when one is ready.
     */
    public interface ContextAvailableCallback {
        void onContextAvailable(Context context);
    }

    /**
     * Implemented in classes that get started by the system before a context is available.
     */
    public interface ContextInitializer {
        void setContextAvailableCallback(ContextAvailableCallback callback);
    }
}
+0 −183
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.android.systemui

import android.app.Activity
import android.app.Application
import android.app.Service
import android.content.BroadcastReceiver
import android.content.ContentProvider
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.core.app.AppComponentFactory
import com.android.systemui.dagger.ContextComponentHelper
import java.lang.reflect.InvocationTargetException
import java.util.concurrent.ExecutionException
import javax.inject.Inject

/**
 * Implementation of AppComponentFactory that injects into constructors.
 *
 * This class sets up dependency injection when creating our application.
 *
 * Activities, Services, and BroadcastReceivers support dependency injection into
 * their constructors.
 *
 * ContentProviders support injection into member variables - _not_ constructors.
 */
abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() {
    companion object {
        private const val TAG = "AppComponentFactory"
        // Must be static due to http://b/141008541.
        var systemUIInitializer: SystemUIInitializer? = null
    }

    @set:Inject
    lateinit var componentHelper: ContextComponentHelper

    /**
     * Returns a new [SystemUIInitializer].
     *
     * The returned implementation should be specific to your build.
     */
    protected abstract fun createSystemUIInitializer(context: Context): SystemUIInitializer

    private fun createSystemUIInitializerInternal(context: Context): SystemUIInitializer {
        return systemUIInitializer ?: run {
            val initializer = createSystemUIInitializer(context.applicationContext)
            try {
                initializer.init(false)
            } catch (exception: ExecutionException) {
                throw RuntimeException("Failed to initialize SysUI", exception)
            } catch (exception: InterruptedException) {
                throw RuntimeException("Failed to initialize SysUI", exception)
            }
            initializer.sysUIComponent.inject(
                this@SystemUIAppComponentFactoryBase
            )

            systemUIInitializer = initializer
            return initializer
        }
    }

    override fun instantiateApplicationCompat(cl: ClassLoader, className: String): Application {
        val app = super.instantiateApplicationCompat(cl, className)
        if (app !is ContextInitializer) {
            throw RuntimeException("App must implement ContextInitializer")
        } else {
            app.setContextAvailableCallback { context ->
                createSystemUIInitializerInternal(context)
            }
        }

        return app
    }

    override fun instantiateProviderCompat(cl: ClassLoader, className: String): ContentProvider {
        val contentProvider = super.instantiateProviderCompat(cl, className)
        if (contentProvider is ContextInitializer) {
            contentProvider.setContextAvailableCallback { context ->
                val initializer = createSystemUIInitializerInternal(context)
                val rootComponent = initializer.sysUIComponent
                try {
                    val injectMethod = rootComponent.javaClass
                        .getMethod("inject", contentProvider.javaClass)
                    injectMethod.invoke(rootComponent, contentProvider)
                } catch (e: NoSuchMethodException) {
                    Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e)
                } catch (e: IllegalAccessException) {
                    Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e)
                } catch (e: InvocationTargetException) {
                    Log.w(TAG, "No injector for class: " + contentProvider.javaClass, e)
                }
                initializer
            }
        }
        return contentProvider
    }

    override fun instantiateActivityCompat(
        cl: ClassLoader,
        className: String,
        intent: Intent?
    ): Activity {
        if (!this::componentHelper.isInitialized) {
            // This shouldn't happen, but is seen on occasion.
            // Bug filed against framework to take a look: http://b/141008541
            systemUIInitializer?.sysUIComponent?.inject(this@SystemUIAppComponentFactoryBase)
        }
        return componentHelper.resolveActivity(className)
            ?: super.instantiateActivityCompat(cl, className, intent)
    }

    override fun instantiateServiceCompat(
        cl: ClassLoader,
        className: String,
        intent: Intent?
    ): Service {
        if (!this::componentHelper.isInitialized) {
            // This shouldn't happen, but does when a device is freshly formatted.
            // Bug filed against framework to take a look: http://b/141008541
            systemUIInitializer?.sysUIComponent?.inject(this@SystemUIAppComponentFactoryBase)
        }
        return componentHelper.resolveService(className)
            ?: super.instantiateServiceCompat(cl, className, intent)
    }

    override fun instantiateReceiverCompat(
        cl: ClassLoader,
        className: String,
        intent: Intent?
    ): BroadcastReceiver {
        if (!this::componentHelper.isInitialized) {
            // This shouldn't happen, but does when a device is freshly formatted.
            // Bug filed against framework to take a look: http://b/141008541
            systemUIInitializer?.sysUIComponent?.inject(this@SystemUIAppComponentFactoryBase)
        }
        return componentHelper.resolveBroadcastReceiver(className)
            ?: super.instantiateReceiverCompat(cl, className, intent)
    }

    /**
     * An Interface for classes that can be notified when an Application Context becomes available.
     *
     * An instance of this will be passed to implementers of [ContextInitializer].
     */
    fun interface ContextAvailableCallback {
        /** Notifies when the Application Context is available.  */
        fun onContextAvailable(context: Context): SystemUIInitializer
    }

    /**
     * Interface for classes that can be constructed by the system before a context is available.
     *
     * This is intended for [Application] and [ContentProvider] implementations that
     * either may not have a Context until some point after construction or are themselves
     * a [Context].
     *
     * Implementers will be passed a [ContextAvailableCallback] that they should call as soon
     * as an Application Context is ready.
     */
    interface ContextInitializer {
        /**
         * Called to supply the [ContextAvailableCallback] that should be called when an
         * Application [Context] is available.
         */
        fun setContextAvailableCallback(callback: ContextAvailableCallback)
    }
}
Loading