Merge "Set LayoutInflatorFactory to Notification RemoteViews" into udc-qpr-dev am: f9c01162b8
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23845567 Change-Id: Iea5a99f9d64908edfcf7addf3fba1ffccd11a29d Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.statusbar.notification.row
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import com.android.systemui.Dumpable
|
||||||
|
import com.android.systemui.dump.DumpManager
|
||||||
|
import com.android.systemui.statusbar.notification.row.NotificationRowModule.NOTIF_REMOTEVIEWS_FACTORIES
|
||||||
|
import com.android.systemui.util.asIndenting
|
||||||
|
import com.android.systemui.util.withIncreasedIndent
|
||||||
|
import java.io.PrintWriter
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Named
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of [NotifLayoutInflaterFactory]. This class uses a set of
|
||||||
|
* [NotifRemoteViewsFactory] objects to create replacement views for Notification RemoteViews.
|
||||||
|
*/
|
||||||
|
open class NotifLayoutInflaterFactory
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
dumpManager: DumpManager,
|
||||||
|
@Named(NOTIF_REMOTEVIEWS_FACTORIES)
|
||||||
|
private val remoteViewsFactories: Set<@JvmSuppressWildcards NotifRemoteViewsFactory>
|
||||||
|
) : LayoutInflater.Factory2, Dumpable {
|
||||||
|
init {
|
||||||
|
dumpManager.registerNormalDumpable(TAG, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
parent: View?,
|
||||||
|
name: String,
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet
|
||||||
|
): View? {
|
||||||
|
var view: View? = null
|
||||||
|
var handledFactory: NotifRemoteViewsFactory? = null
|
||||||
|
for (layoutFactory in remoteViewsFactories) {
|
||||||
|
view = layoutFactory.instantiate(parent, name, context, attrs)
|
||||||
|
if (view != null) {
|
||||||
|
check(handledFactory == null) {
|
||||||
|
"${layoutFactory.javaClass.name} tries to produce view. However, " +
|
||||||
|
"${handledFactory?.javaClass?.name} produced view for $name before."
|
||||||
|
}
|
||||||
|
handledFactory = layoutFactory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logOnCreateView(name, view, handledFactory)
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? =
|
||||||
|
onCreateView(null, name, context, attrs)
|
||||||
|
|
||||||
|
override fun dump(pw: PrintWriter, args: Array<out String>) {
|
||||||
|
val indentingPW = pw.asIndenting()
|
||||||
|
|
||||||
|
indentingPW.appendLine("$TAG ReplacementFactories:")
|
||||||
|
indentingPW.withIncreasedIndent {
|
||||||
|
remoteViewsFactories.forEach { indentingPW.appendLine(it.javaClass.simpleName) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logOnCreateView(
|
||||||
|
name: String,
|
||||||
|
replacedView: View?,
|
||||||
|
factory: NotifRemoteViewsFactory?
|
||||||
|
) {
|
||||||
|
if (SPEW && replacedView != null && factory != null) {
|
||||||
|
Log.d(TAG, "$factory produced view for $name: $replacedView")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
private const val TAG = "NotifLayoutInflaterFac"
|
||||||
|
private val SPEW = Log.isLoggable(TAG, Log.VERBOSE)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.statusbar.notification.row
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
|
/** Interface used to create replacement view instances in Notification RemoteViews. */
|
||||||
|
interface NotifRemoteViewsFactory {
|
||||||
|
|
||||||
|
/** return the replacement view instance for the given view name */
|
||||||
|
fun instantiate(parent: View?, name: String, context: Context, attrs: AttributeSet): View?
|
||||||
|
}
|
||||||
@@ -79,6 +79,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
private final ConversationNotificationProcessor mConversationProcessor;
|
private final ConversationNotificationProcessor mConversationProcessor;
|
||||||
private final Executor mBgExecutor;
|
private final Executor mBgExecutor;
|
||||||
private final SmartReplyStateInflater mSmartReplyStateInflater;
|
private final SmartReplyStateInflater mSmartReplyStateInflater;
|
||||||
|
private final NotifLayoutInflaterFactory mNotifLayoutInflaterFactory;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
NotificationContentInflater(
|
NotificationContentInflater(
|
||||||
@@ -87,13 +88,15 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
ConversationNotificationProcessor conversationProcessor,
|
ConversationNotificationProcessor conversationProcessor,
|
||||||
MediaFeatureFlag mediaFeatureFlag,
|
MediaFeatureFlag mediaFeatureFlag,
|
||||||
@Background Executor bgExecutor,
|
@Background Executor bgExecutor,
|
||||||
SmartReplyStateInflater smartRepliesInflater) {
|
SmartReplyStateInflater smartRepliesInflater,
|
||||||
|
NotifLayoutInflaterFactory notifLayoutInflaterFactory) {
|
||||||
mRemoteViewCache = remoteViewCache;
|
mRemoteViewCache = remoteViewCache;
|
||||||
mRemoteInputManager = remoteInputManager;
|
mRemoteInputManager = remoteInputManager;
|
||||||
mConversationProcessor = conversationProcessor;
|
mConversationProcessor = conversationProcessor;
|
||||||
mIsMediaInQS = mediaFeatureFlag.getEnabled();
|
mIsMediaInQS = mediaFeatureFlag.getEnabled();
|
||||||
mBgExecutor = bgExecutor;
|
mBgExecutor = bgExecutor;
|
||||||
mSmartReplyStateInflater = smartRepliesInflater;
|
mSmartReplyStateInflater = smartRepliesInflater;
|
||||||
|
mNotifLayoutInflaterFactory = notifLayoutInflaterFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -137,7 +140,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
callback,
|
callback,
|
||||||
mRemoteInputManager.getRemoteViewsOnClickHandler(),
|
mRemoteInputManager.getRemoteViewsOnClickHandler(),
|
||||||
mIsMediaInQS,
|
mIsMediaInQS,
|
||||||
mSmartReplyStateInflater);
|
mSmartReplyStateInflater,
|
||||||
|
mNotifLayoutInflaterFactory);
|
||||||
if (mInflateSynchronously) {
|
if (mInflateSynchronously) {
|
||||||
task.onPostExecute(task.doInBackground());
|
task.onPostExecute(task.doInBackground());
|
||||||
} else {
|
} else {
|
||||||
@@ -160,7 +164,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
bindParams.isLowPriority,
|
bindParams.isLowPriority,
|
||||||
bindParams.usesIncreasedHeight,
|
bindParams.usesIncreasedHeight,
|
||||||
bindParams.usesIncreasedHeadsUpHeight,
|
bindParams.usesIncreasedHeadsUpHeight,
|
||||||
packageContext);
|
packageContext,
|
||||||
|
mNotifLayoutInflaterFactory);
|
||||||
|
|
||||||
result = inflateSmartReplyViews(result, reInflateFlags, entry,
|
result = inflateSmartReplyViews(result, reInflateFlags, entry,
|
||||||
row.getContext(), packageContext,
|
row.getContext(), packageContext,
|
||||||
@@ -298,7 +303,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
|
|
||||||
private static InflationProgress createRemoteViews(@InflationFlag int reInflateFlags,
|
private static InflationProgress createRemoteViews(@InflationFlag int reInflateFlags,
|
||||||
Notification.Builder builder, boolean isLowPriority, boolean usesIncreasedHeight,
|
Notification.Builder builder, boolean isLowPriority, boolean usesIncreasedHeight,
|
||||||
boolean usesIncreasedHeadsUpHeight, Context packageContext) {
|
boolean usesIncreasedHeadsUpHeight, Context packageContext,
|
||||||
|
NotifLayoutInflaterFactory notifLayoutInflaterFactory) {
|
||||||
InflationProgress result = new InflationProgress();
|
InflationProgress result = new InflationProgress();
|
||||||
|
|
||||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
|
if ((reInflateFlags & FLAG_CONTENT_VIEW_CONTRACTED) != 0) {
|
||||||
@@ -316,7 +322,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) {
|
if ((reInflateFlags & FLAG_CONTENT_VIEW_PUBLIC) != 0) {
|
||||||
result.newPublicView = builder.makePublicContentView(isLowPriority);
|
result.newPublicView = builder.makePublicContentView(isLowPriority);
|
||||||
}
|
}
|
||||||
|
setNotifsViewsInflaterFactory(result, notifLayoutInflaterFactory);
|
||||||
result.packageContext = packageContext;
|
result.packageContext = packageContext;
|
||||||
result.headsUpStatusBarText = builder.getHeadsUpStatusBarText(false /* showingPublic */);
|
result.headsUpStatusBarText = builder.getHeadsUpStatusBarText(false /* showingPublic */);
|
||||||
result.headsUpStatusBarTextPublic = builder.getHeadsUpStatusBarText(
|
result.headsUpStatusBarTextPublic = builder.getHeadsUpStatusBarText(
|
||||||
@@ -324,6 +330,22 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void setNotifsViewsInflaterFactory(InflationProgress result,
|
||||||
|
NotifLayoutInflaterFactory notifLayoutInflaterFactory) {
|
||||||
|
setRemoteViewsInflaterFactory(result.newContentView, notifLayoutInflaterFactory);
|
||||||
|
setRemoteViewsInflaterFactory(result.newExpandedView,
|
||||||
|
notifLayoutInflaterFactory);
|
||||||
|
setRemoteViewsInflaterFactory(result.newHeadsUpView, notifLayoutInflaterFactory);
|
||||||
|
setRemoteViewsInflaterFactory(result.newPublicView, notifLayoutInflaterFactory);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void setRemoteViewsInflaterFactory(RemoteViews remoteViews,
|
||||||
|
NotifLayoutInflaterFactory notifLayoutInflaterFactory) {
|
||||||
|
if (remoteViews != null) {
|
||||||
|
remoteViews.setLayoutInflaterFactory(notifLayoutInflaterFactory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static CancellationSignal apply(
|
private static CancellationSignal apply(
|
||||||
Executor bgExecutor,
|
Executor bgExecutor,
|
||||||
boolean inflateSynchronously,
|
boolean inflateSynchronously,
|
||||||
@@ -348,7 +370,6 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
public void setResultView(View v) {
|
public void setResultView(View v) {
|
||||||
result.inflatedContentView = v;
|
result.inflatedContentView = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RemoteViews getRemoteView() {
|
public RemoteViews getRemoteView() {
|
||||||
return result.newContentView;
|
return result.newContentView;
|
||||||
@@ -356,7 +377,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
};
|
};
|
||||||
applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
|
applyRemoteView(bgExecutor, inflateSynchronously, result, reInflateFlags, flag,
|
||||||
remoteViewCache, entry, row, isNewView, remoteViewClickHandler, callback,
|
remoteViewCache, entry, row, isNewView, remoteViewClickHandler, callback,
|
||||||
privateLayout, privateLayout.getContractedChild(),
|
privateLayout, privateLayout.getContractedChild(),
|
||||||
privateLayout.getVisibleWrapper(
|
privateLayout.getVisibleWrapper(
|
||||||
NotificationContentView.VISIBLE_TYPE_CONTRACTED),
|
NotificationContentView.VISIBLE_TYPE_CONTRACTED),
|
||||||
runningInflations, applyCallback);
|
runningInflations, applyCallback);
|
||||||
@@ -758,8 +779,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
* @param oldView The old view that was applied to the existing view before
|
* @param oldView The old view that was applied to the existing view before
|
||||||
* @return {@code true} if the RemoteViews are the same and the view can be reused to reapply.
|
* @return {@code true} if the RemoteViews are the same and the view can be reused to reapply.
|
||||||
*/
|
*/
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static boolean canReapplyRemoteView(final RemoteViews newView,
|
static boolean canReapplyRemoteView(final RemoteViews newView,
|
||||||
final RemoteViews oldView) {
|
final RemoteViews oldView) {
|
||||||
return (newView == null && oldView == null) ||
|
return (newView == null && oldView == null) ||
|
||||||
(newView != null && oldView != null
|
(newView != null && oldView != null
|
||||||
@@ -800,6 +821,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
private final ConversationNotificationProcessor mConversationProcessor;
|
private final ConversationNotificationProcessor mConversationProcessor;
|
||||||
private final boolean mIsMediaInQS;
|
private final boolean mIsMediaInQS;
|
||||||
private final SmartReplyStateInflater mSmartRepliesInflater;
|
private final SmartReplyStateInflater mSmartRepliesInflater;
|
||||||
|
private final NotifLayoutInflaterFactory mNotifLayoutInflaterFactory;
|
||||||
|
|
||||||
private AsyncInflationTask(
|
private AsyncInflationTask(
|
||||||
Executor bgExecutor,
|
Executor bgExecutor,
|
||||||
@@ -815,7 +837,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
InflationCallback callback,
|
InflationCallback callback,
|
||||||
RemoteViews.InteractionHandler remoteViewClickHandler,
|
RemoteViews.InteractionHandler remoteViewClickHandler,
|
||||||
boolean isMediaFlagEnabled,
|
boolean isMediaFlagEnabled,
|
||||||
SmartReplyStateInflater smartRepliesInflater) {
|
SmartReplyStateInflater smartRepliesInflater,
|
||||||
|
NotifLayoutInflaterFactory notifLayoutInflaterFactory) {
|
||||||
mEntry = entry;
|
mEntry = entry;
|
||||||
mRow = row;
|
mRow = row;
|
||||||
mBgExecutor = bgExecutor;
|
mBgExecutor = bgExecutor;
|
||||||
@@ -831,6 +854,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
mConversationProcessor = conversationProcessor;
|
mConversationProcessor = conversationProcessor;
|
||||||
mIsMediaInQS = isMediaFlagEnabled;
|
mIsMediaInQS = isMediaFlagEnabled;
|
||||||
|
mNotifLayoutInflaterFactory = notifLayoutInflaterFactory;
|
||||||
entry.setInflationTask(this);
|
entry.setInflationTask(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -874,7 +898,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
|
|||||||
}
|
}
|
||||||
InflationProgress inflationProgress = createRemoteViews(mReInflateFlags,
|
InflationProgress inflationProgress = createRemoteViews(mReInflateFlags,
|
||||||
recoveredBuilder, mIsLowPriority, mUsesIncreasedHeight,
|
recoveredBuilder, mIsLowPriority, mUsesIncreasedHeight,
|
||||||
mUsesIncreasedHeadsUpHeight, packageContext);
|
mUsesIncreasedHeadsUpHeight, packageContext,
|
||||||
|
mNotifLayoutInflaterFactory);
|
||||||
InflatedSmartReplyState previousSmartReplyState = mRow.getExistingSmartReplyState();
|
InflatedSmartReplyState previousSmartReplyState = mRow.getExistingSmartReplyState();
|
||||||
InflationProgress result = inflateSmartReplyViews(
|
InflationProgress result = inflateSmartReplyViews(
|
||||||
inflationProgress,
|
inflationProgress,
|
||||||
|
|||||||
@@ -17,15 +17,26 @@
|
|||||||
package com.android.systemui.statusbar.notification.row;
|
package com.android.systemui.statusbar.notification.row;
|
||||||
|
|
||||||
import com.android.systemui.dagger.SysUISingleton;
|
import com.android.systemui.dagger.SysUISingleton;
|
||||||
|
import com.android.systemui.flags.FeatureFlags;
|
||||||
|
|
||||||
import dagger.Binds;
|
import dagger.Binds;
|
||||||
import dagger.Module;
|
import dagger.Module;
|
||||||
|
import dagger.Provides;
|
||||||
|
import dagger.multibindings.ElementsIntoSet;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dagger Module containing notification row and view inflation implementations.
|
* Dagger Module containing notification row and view inflation implementations.
|
||||||
*/
|
*/
|
||||||
@Module
|
@Module
|
||||||
public abstract class NotificationRowModule {
|
public abstract class NotificationRowModule {
|
||||||
|
public static final String NOTIF_REMOTEVIEWS_FACTORIES =
|
||||||
|
"notif_remoteviews_factories";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides notification row content binder instance.
|
* Provides notification row content binder instance.
|
||||||
*/
|
*/
|
||||||
@@ -41,4 +52,15 @@ public abstract class NotificationRowModule {
|
|||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
public abstract NotifRemoteViewCache provideNotifRemoteViewCache(
|
public abstract NotifRemoteViewCache provideNotifRemoteViewCache(
|
||||||
NotifRemoteViewCacheImpl cacheImpl);
|
NotifRemoteViewCacheImpl cacheImpl);
|
||||||
|
|
||||||
|
/** Provides view factories to be inflated in notification content. */
|
||||||
|
@Provides
|
||||||
|
@ElementsIntoSet
|
||||||
|
@Named(NOTIF_REMOTEVIEWS_FACTORIES)
|
||||||
|
static Set<NotifRemoteViewsFactory> provideNotifRemoteViewsFactories(
|
||||||
|
FeatureFlags featureFlags
|
||||||
|
) {
|
||||||
|
final Set<NotifRemoteViewsFactory> replacementFactories = new HashSet<>();
|
||||||
|
return replacementFactories;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.statusbar.notification.row
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import android.testing.TestableLooper.RunWithLooper
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.LinearLayout
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.dump.DumpManager
|
||||||
|
import junit.framework.Assert.assertEquals
|
||||||
|
import junit.framework.Assert.assertNotNull
|
||||||
|
import junit.framework.Assert.assertNull
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
/** Tests for [NotifLayoutInflaterFactory] */
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
@RunWithLooper
|
||||||
|
class NotifLayoutInflaterFactoryTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
@Mock private lateinit var attrs: AttributeSet
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun before() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun onCreateView_notMatchingViews_returnNull() {
|
||||||
|
// GIVEN
|
||||||
|
val layoutInflaterFactory =
|
||||||
|
createNotifLayoutInflaterFactoryImpl(
|
||||||
|
setOf(
|
||||||
|
createReplacementViewFactory("TextView") { context, attrs ->
|
||||||
|
FrameLayout(context)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
val createView = layoutInflaterFactory.onCreateView("ImageView", mContext, attrs)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
assertNull(createView)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun onCreateView_matchingViews_returnReplacementView() {
|
||||||
|
// GIVEN
|
||||||
|
val layoutInflaterFactory =
|
||||||
|
createNotifLayoutInflaterFactoryImpl(
|
||||||
|
setOf(
|
||||||
|
createReplacementViewFactory("TextView") { context, attrs ->
|
||||||
|
FrameLayout(context)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
val createView = layoutInflaterFactory.onCreateView("TextView", mContext, attrs)
|
||||||
|
|
||||||
|
// THEN
|
||||||
|
assertNotNull(createView)
|
||||||
|
assertEquals(requireNotNull(createView)::class.java, FrameLayout::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalStateException::class)
|
||||||
|
fun onCreateView_multipleFactory_throwIllegalStateException() {
|
||||||
|
// GIVEN
|
||||||
|
val layoutInflaterFactory =
|
||||||
|
createNotifLayoutInflaterFactoryImpl(
|
||||||
|
setOf(
|
||||||
|
createReplacementViewFactory("TextView") { context, attrs ->
|
||||||
|
FrameLayout(context)
|
||||||
|
},
|
||||||
|
createReplacementViewFactory("TextView") { context, attrs ->
|
||||||
|
LinearLayout(context)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// WHEN
|
||||||
|
layoutInflaterFactory.onCreateView("TextView", mContext, attrs)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNotifLayoutInflaterFactoryImpl(
|
||||||
|
replacementViewFactories: Set<@JvmSuppressWildcards NotifRemoteViewsFactory>
|
||||||
|
) = NotifLayoutInflaterFactory(DumpManager(), replacementViewFactories)
|
||||||
|
|
||||||
|
private fun createReplacementViewFactory(
|
||||||
|
replacementName: String,
|
||||||
|
createView: (context: Context, attrs: AttributeSet) -> View
|
||||||
|
) =
|
||||||
|
object : NotifRemoteViewsFactory {
|
||||||
|
override fun instantiate(
|
||||||
|
parent: View?,
|
||||||
|
name: String,
|
||||||
|
context: Context,
|
||||||
|
attrs: AttributeSet
|
||||||
|
): View? =
|
||||||
|
if (replacementName == name) {
|
||||||
|
createView(context, attrs)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -92,6 +92,7 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
|
|||||||
@Mock private ConversationNotificationProcessor mConversationNotificationProcessor;
|
@Mock private ConversationNotificationProcessor mConversationNotificationProcessor;
|
||||||
@Mock private InflatedSmartReplyState mInflatedSmartReplyState;
|
@Mock private InflatedSmartReplyState mInflatedSmartReplyState;
|
||||||
@Mock private InflatedSmartReplyViewHolder mInflatedSmartReplies;
|
@Mock private InflatedSmartReplyViewHolder mInflatedSmartReplies;
|
||||||
|
@Mock private NotifLayoutInflaterFactory mNotifLayoutInflaterFactory;
|
||||||
|
|
||||||
private final SmartReplyStateInflater mSmartReplyStateInflater =
|
private final SmartReplyStateInflater mSmartReplyStateInflater =
|
||||||
new SmartReplyStateInflater() {
|
new SmartReplyStateInflater() {
|
||||||
@@ -130,7 +131,8 @@ public class NotificationContentInflaterTest extends SysuiTestCase {
|
|||||||
mConversationNotificationProcessor,
|
mConversationNotificationProcessor,
|
||||||
mock(MediaFeatureFlag.class),
|
mock(MediaFeatureFlag.class),
|
||||||
mock(Executor.class),
|
mock(Executor.class),
|
||||||
mSmartReplyStateInflater);
|
mSmartReplyStateInflater,
|
||||||
|
mNotifLayoutInflaterFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -158,7 +158,8 @@ public class NotificationTestHelper {
|
|||||||
mock(ConversationNotificationProcessor.class),
|
mock(ConversationNotificationProcessor.class),
|
||||||
mock(MediaFeatureFlag.class),
|
mock(MediaFeatureFlag.class),
|
||||||
mock(Executor.class),
|
mock(Executor.class),
|
||||||
new MockSmartReplyInflater());
|
new MockSmartReplyInflater(),
|
||||||
|
mock(NotifLayoutInflaterFactory.class));
|
||||||
contentBinder.setInflateSynchronously(true);
|
contentBinder.setInflateSynchronously(true);
|
||||||
mBindStage = new RowContentBindStage(contentBinder,
|
mBindStage = new RowContentBindStage(contentBinder,
|
||||||
mock(NotifInflationErrorManager.class),
|
mock(NotifInflationErrorManager.class),
|
||||||
|
|||||||
Reference in New Issue
Block a user