1 /* 2 * Copyright (C) 2023 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.statusbar.notification.row 18 19 import android.content.Context 20 import android.util.AttributeSet 21 import android.util.Log 22 import android.view.LayoutInflater 23 import android.view.View 24 import com.android.systemui.Dumpable 25 import com.android.systemui.dump.DumpManager 26 import com.android.systemui.statusbar.notification.row.NotificationRowModule.NOTIF_REMOTEVIEWS_FACTORIES 27 import com.android.systemui.util.asIndenting 28 import com.android.systemui.util.withIncreasedIndent 29 import java.io.PrintWriter 30 import javax.inject.Inject 31 import javax.inject.Named 32 33 /** 34 * Implementation of [NotifLayoutInflaterFactory]. This class uses a set of 35 * [NotifRemoteViewsFactory] objects to create replacement views for Notification RemoteViews. 36 */ 37 open class NotifLayoutInflaterFactory 38 @Inject 39 constructor( 40 dumpManager: DumpManager, 41 @Named(NOTIF_REMOTEVIEWS_FACTORIES) 42 private val remoteViewsFactories: Set<@JvmSuppressWildcards NotifRemoteViewsFactory> 43 ) : LayoutInflater.Factory2, Dumpable { 44 init { 45 dumpManager.registerNormalDumpable(TAG, this) 46 } 47 onCreateViewnull48 override fun onCreateView( 49 parent: View?, 50 name: String, 51 context: Context, 52 attrs: AttributeSet 53 ): View? { 54 var view: View? = null 55 var handledFactory: NotifRemoteViewsFactory? = null 56 for (layoutFactory in remoteViewsFactories) { 57 view = layoutFactory.instantiate(parent, name, context, attrs) 58 if (view != null) { 59 check(handledFactory == null) { 60 "${layoutFactory.javaClass.name} tries to produce view. However, " + 61 "${handledFactory?.javaClass?.name} produced view for $name before." 62 } 63 handledFactory = layoutFactory 64 } 65 } 66 logOnCreateView(name, view, handledFactory) 67 return view 68 } 69 onCreateViewnull70 override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? = 71 onCreateView(null, name, context, attrs) 72 73 override fun dump(pw: PrintWriter, args: Array<out String>) { 74 val indentingPW = pw.asIndenting() 75 76 indentingPW.appendLine("$TAG ReplacementFactories:") 77 indentingPW.withIncreasedIndent { 78 remoteViewsFactories.forEach { indentingPW.appendLine(it.javaClass.simpleName) } 79 } 80 } 81 logOnCreateViewnull82 private fun logOnCreateView( 83 name: String, 84 replacedView: View?, 85 factory: NotifRemoteViewsFactory? 86 ) { 87 if (SPEW && replacedView != null && factory != null) { 88 Log.d(TAG, "$factory produced view for $name: $replacedView") 89 } 90 } 91 92 private companion object { 93 private const val TAG = "NotifLayoutInflaterFac" 94 private val SPEW = Log.isLoggable(TAG, Log.VERBOSE) 95 } 96 } 97