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

Commit e9fb33f3 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Android (Google) Code Review
Browse files

Merge changes from topic "caitlinshk-contextinitializer" into main

* changes:
  [Pod] Move #overrideNotificationAppName out of SystemUIApplication.
  [Pod] Split ContextInitializer into 2 separate interfaces.
parents be9d8f77 c6a371d2
Loading
Loading
Loading
Loading
+30 −57
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.core.app.AppComponentFactory
import com.android.systemui.application.ApplicationContextInitializer
import com.android.systemui.application.ContentProviderContextInitializer
import com.android.systemui.dagger.ContextComponentHelper
import com.android.systemui.dagger.SysUIComponent
import com.android.tools.r8.keepanno.annotations.KeepTarget
@@ -37,8 +39,8 @@ import javax.inject.Inject
 *
 * This class sets up dependency injection when creating our application.
 *
 * Activities, Services, and BroadcastReceivers support dependency injection into
 * their constructors.
 * Activities, Services, and BroadcastReceivers support dependency injection into their
 * constructors.
 *
 * ContentProviders support injection into member variables - _not_ constructors.
 */
@@ -49,8 +51,7 @@ abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() {
        var systemUIInitializer: SystemUIInitializer? = null
    }

    @set:Inject
    lateinit var componentHelper: ContextComponentHelper
    @set:Inject lateinit var componentHelper: ContextComponentHelper

    /**
     * Returns a new [SystemUIInitializer].
@@ -60,7 +61,8 @@ abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() {
    protected abstract fun createSystemUIInitializer(context: Context): SystemUIInitializer

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

                systemUIInitializer = initializer
                return initializer
@@ -80,27 +80,28 @@ abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() {

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

        return app
    }

    @UsesReflection(KeepTarget(instanceOfClassConstant = SysUIComponent::class, methodName = "inject"))
    @UsesReflection(
        KeepTarget(instanceOfClassConstant = SysUIComponent::class, methodName = "inject")
    )
    override fun instantiateProviderCompat(cl: ClassLoader, className: String): ContentProvider {
        val contentProvider = super.instantiateProviderCompat(cl, className)
        if (contentProvider is ContextInitializer) {
        if (contentProvider is ContentProviderContextInitializer) {
            contentProvider.setContextAvailableCallback { context ->
                val initializer = createSystemUIInitializerInternal(context)
                val rootComponent = initializer.sysUIComponent
                try {
                    val injectMethod = rootComponent.javaClass
                        .getMethod("inject", contentProvider.javaClass)
                    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)
@@ -118,7 +119,7 @@ abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() {
    override fun instantiateActivityCompat(
        cl: ClassLoader,
        className: String,
        intent: Intent?
        intent: Intent?,
    ): Activity {
        if (!this::componentHelper.isInitialized) {
            // This shouldn't happen, but is seen on occasion.
@@ -132,7 +133,7 @@ abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() {
    override fun instantiateServiceCompat(
        cl: ClassLoader,
        className: String,
        intent: Intent?
        intent: Intent?,
    ): Service {
        if (!this::componentHelper.isInitialized) {
            // This shouldn't happen, but does when a device is freshly formatted.
@@ -146,7 +147,7 @@ abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() {
    override fun instantiateReceiverCompat(
        cl: ClassLoader,
        className: String,
        intent: Intent?
        intent: Intent?,
    ): BroadcastReceiver {
        if (!this::componentHelper.isInitialized) {
            // This shouldn't happen, but does when a device is freshly formatted.
@@ -156,32 +157,4 @@ abstract class SystemUIAppComponentFactoryBase : AppComponentFactory() {
        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)
    }
}
+5 −17
Original line number Diff line number Diff line
@@ -20,13 +20,11 @@ import android.animation.Animator;
import android.annotation.SuppressLint;
import android.app.ActivityThread;
import android.app.Application;
import android.app.Notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Process;
import android.os.Trace;
import android.tracing.perfetto.InitArguments;
@@ -42,6 +40,8 @@ import androidx.annotation.VisibleForTesting;
import com.airbnb.lottie.Lottie;
import com.airbnb.lottie.LottieConfig;
import com.android.internal.protolog.ProtoLog;
import com.android.systemui.application.ApplicationContextAvailableCallback;
import com.android.systemui.application.ApplicationContextInitializer;
import com.android.systemui.dagger.GlobalRootComponent;
import com.android.systemui.dagger.SysUIComponent;
import com.android.systemui.dump.DumpManager;
@@ -67,7 +67,7 @@ import javax.inject.Provider;
 * Application class for SystemUI.
 */
public class SystemUIApplication extends Application implements
        SystemUIAppComponentFactoryBase.ContextInitializer, HasWMComponent {
        ApplicationContextInitializer, HasWMComponent {

    public static final String TAG = "SystemUIService";
    private static final boolean DEBUG = false;
@@ -79,7 +79,7 @@ public class SystemUIApplication extends Application implements
     */
    private CoreStartable[] mServices;
    private boolean mServicesStarted;
    private SystemUIAppComponentFactoryBase.ContextAvailableCallback mContextAvailableCallback;
    private ApplicationContextAvailableCallback mContextAvailableCallback;
    private SysUIComponent mSysUIComponent;
    private SystemUIInitializer mInitializer;
    private ProcessWrapper mProcessWrapper;
@@ -492,22 +492,10 @@ public class SystemUIApplication extends Application implements

    @Override
    public void setContextAvailableCallback(
            @NonNull SystemUIAppComponentFactoryBase.ContextAvailableCallback callback) {
            @NonNull ApplicationContextAvailableCallback callback) {
        mContextAvailableCallback = callback;
    }

    /** Update a notifications application name. */
    public static void overrideNotificationAppName(Context context, Notification.Builder n,
            boolean system) {
        final Bundle extras = new Bundle();
        String appName = system
                ? context.getString(com.android.internal.R.string.notification_app_name_system)
                : context.getString(com.android.internal.R.string.notification_app_name_settings);
        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME, appName);

        n.addExtras(extras);
    }

    @NonNull
    @Override
    public WMComponent getWMComponent() {
+31 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.application

import android.content.Context
import com.android.systemui.SystemUIInitializer

/**
 * An Interface for [Application] classes that can be notified when an Application Context becomes
 * available.
 *
 * An instance of this will be passed to implementers of [ApplicationContextInitializer].
 */
fun interface ApplicationContextAvailableCallback {
    /** Notifies when the Application Context is available. */
    fun onContextAvailable(context: Context): SystemUIInitializer
}
+34 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.application

/**
 * Interface for classes that can be constructed by the system before a context is available.
 *
 * This is intended for [Application] implementations that may not have a Context until some point
 * after construction or are themselves a [Context].
 *
 * Implementers will be passed a [ApplicationContextAvailableCallback] that they should call as soon
 * as an Application Context is ready.
 */
interface ApplicationContextInitializer {
    /**
     * Called to supply the [ApplicationContextAvailableCallback] that should be called when an
     * Application [Context] is available.
     */
    fun setContextAvailableCallback(callback: ApplicationContextAvailableCallback)
}
+30 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.application

import android.content.Context

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