From 48dbc393b48f7b2cf27b66e0b16da57ffaba4e7a Mon Sep 17 00:00:00 2001 From: Ruslan Tkhakokhov Date: Fri, 12 May 2023 01:01:51 +0000 Subject: [PATCH] Allow BackupManagerMonitorWrapper to wrap null values Check the underlying monitor value is not null before proxying the call in the onEvent() method. Bug: 282075312 Test: atest BackupManagerMonitorWrapperTest Change-Id: Iece25d81bc9ec765244898589222491c16ca629a --- .../backup/BackupManagerMonitorWrapper.java | 15 ++++- .../BackupManagerMonitorWrapperTest.java | 66 +++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java diff --git a/core/java/android/app/backup/BackupManagerMonitorWrapper.java b/core/java/android/app/backup/BackupManagerMonitorWrapper.java index 0b189958ef0ad..39bfb1bd7a55e 100644 --- a/core/java/android/app/backup/BackupManagerMonitorWrapper.java +++ b/core/java/android/app/backup/BackupManagerMonitorWrapper.java @@ -16,9 +16,12 @@ package android.app.backup; +import android.annotation.Nullable; import android.os.Bundle; import android.os.RemoteException; +import com.android.internal.annotations.VisibleForTesting; + /** * Wrapper around {@link BackupManagerMonitor} that helps with IPC between the caller of backup * APIs and the backup service. @@ -26,16 +29,24 @@ import android.os.RemoteException; * The caller implements {@link BackupManagerMonitor} and passes it into framework APIs that run on * the caller's process. Those framework APIs will then wrap it around this class when doing the * actual IPC. + * + * @hide */ -class BackupManagerMonitorWrapper extends IBackupManagerMonitor.Stub { +@VisibleForTesting +public class BackupManagerMonitorWrapper extends IBackupManagerMonitor.Stub { + @Nullable private final BackupManagerMonitor mMonitor; - BackupManagerMonitorWrapper(BackupManagerMonitor monitor) { + public BackupManagerMonitorWrapper(@Nullable BackupManagerMonitor monitor) { mMonitor = monitor; } @Override public void onEvent(final Bundle event) throws RemoteException { + if (mMonitor == null) { + // It's valid for the underlying monitor to be null, so just return. + return; + } mMonitor.onEvent(event); } } diff --git a/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java b/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java new file mode 100644 index 0000000000000..1f5e0cf52d5c8 --- /dev/null +++ b/core/tests/coretests/src/android/app/backup/BackupManagerMonitorWrapperTest.java @@ -0,0 +1,66 @@ +/* + * 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 android.app.backup; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.os.Bundle; +import android.platform.test.annotations.Presubmit; + +import androidx.test.runner.AndroidJUnit4; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@Presubmit +@RunWith(AndroidJUnit4.class) +public class BackupManagerMonitorWrapperTest { + @Mock + private BackupManagerMonitor mMonitor; + private BackupManagerMonitorWrapper mMonitorWrapper; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + + @Test + public void testOnEvent_propagatesToMonitor() throws Exception { + mMonitorWrapper = new BackupManagerMonitorWrapper(mMonitor); + Bundle eventBundle = new Bundle(); + + mMonitorWrapper.onEvent(eventBundle); + + verify(mMonitor, times(/* wantedNumberOfInvocations */ 1)).onEvent(eq(eventBundle)); + } + + @Test + public void testOnEvent_nullMonitor_eventIsIgnored() throws Exception { + mMonitorWrapper = new BackupManagerMonitorWrapper(/* monitor */ null); + + mMonitorWrapper.onEvent(new Bundle()); + + verify(mMonitor, never()).onEvent(any()); + } +}