Merge "Add unit tests for com.android.server.backup.utils"
diff --git a/services/backup/java/com/android/server/backup/restore/RestoreDeleteObserver.java b/services/backup/java/com/android/server/backup/restore/RestoreDeleteObserver.java
index 5bc3eca..12be84c 100644
--- a/services/backup/java/com/android/server/backup/restore/RestoreDeleteObserver.java
+++ b/services/backup/java/com/android/server/backup/restore/RestoreDeleteObserver.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.restore;
 
 import android.content.pm.IPackageDeleteObserver;
diff --git a/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java b/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
index 4cb0abc..6c9a222 100644
--- a/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
+++ b/services/backup/java/com/android/server/backup/restore/RestoreFileRunnable.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.restore;
 
 import android.app.IBackupAgent;
diff --git a/services/backup/java/com/android/server/backup/restore/RestoreInstallObserver.java b/services/backup/java/com/android/server/backup/restore/RestoreInstallObserver.java
index eff857a..3d506f1 100644
--- a/services/backup/java/com/android/server/backup/restore/RestoreInstallObserver.java
+++ b/services/backup/java/com/android/server/backup/restore/RestoreInstallObserver.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.restore;
 
 import android.app.PackageInstallObserver;
diff --git a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
index a32635e..20f7b12 100644
--- a/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/AppBackupUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 import android.content.pm.ApplicationInfo;
diff --git a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
index 53addfc..3b9b692 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupManagerMonitorUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
@@ -54,6 +70,15 @@
         return null;
     }
 
+    /**
+     * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will
+     * be created.
+     *
+     * @param extras - bundle where to add key-value to, if null a new bundle will be created.
+     * @param key - key.
+     * @param value - value.
+     * @return extras if it was not null and new bundle otherwise.
+     */
     public static Bundle putMonitoringExtra(Bundle extras, String key, String value) {
         if (extras == null) {
             extras = new Bundle();
@@ -62,14 +87,15 @@
         return extras;
     }
 
-    private static Bundle putMonitoringExtra(Bundle extras, String key, int value) {
-        if (extras == null) {
-            extras = new Bundle();
-        }
-        extras.putInt(key, value);
-        return extras;
-    }
-
+    /**
+     * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will
+     * be created.
+     *
+     * @param extras - bundle where to add key-value to, if null a new bundle will be created.
+     * @param key - key.
+     * @param value - value.
+     * @return extras if it was not null and new bundle otherwise.
+     */
     public static Bundle putMonitoringExtra(Bundle extras, String key, long value) {
         if (extras == null) {
             extras = new Bundle();
@@ -78,6 +104,15 @@
         return extras;
     }
 
+    /**
+     * Adds given key-value pair in the bundle and returns the bundle. If bundle was null it will
+     * be created.
+     *
+     * @param extras - bundle where to add key-value to, if null a new bundle will be created.
+     * @param key - key.
+     * @param value - value.
+     * @return extras if it was not null and new bundle otherwise.
+     */
     public static Bundle putMonitoringExtra(Bundle extras, String key, boolean value) {
         if (extras == null) {
             extras = new Bundle();
diff --git a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
index b5e5e08..eb939a8 100644
--- a/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/BackupObserverUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 import android.app.backup.BackupProgress;
diff --git a/services/backup/java/com/android/server/backup/utils/BytesReadListener.java b/services/backup/java/com/android/server/backup/utils/BytesReadListener.java
index 1595153..34d85ff 100644
--- a/services/backup/java/com/android/server/backup/utils/BytesReadListener.java
+++ b/services/backup/java/com/android/server/backup/utils/BytesReadListener.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 /**
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
index 0c868af..1b511860 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupRestoreObserverUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 import android.app.backup.IFullBackupRestoreObserver;
diff --git a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
index bfb4b25..4072a5e 100644
--- a/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/FullBackupUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 import android.content.pm.PackageInfo;
diff --git a/services/backup/java/com/android/server/backup/utils/PasswordUtils.java b/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
index c90ec594..5ae79e2 100644
--- a/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/PasswordUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 import android.util.Slog;
diff --git a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
index cdda68e..c277c03 100644
--- a/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
+++ b/services/backup/java/com/android/server/backup/utils/RestoreUtils.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 import android.content.pm.ApplicationInfo;
diff --git a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
index 25832c9..12c1af2 100644
--- a/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
+++ b/services/backup/java/com/android/server/backup/utils/TarBackupReader.java
@@ -1,3 +1,19 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
 
 import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
new file mode 100644
index 0000000..267b34f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/AppBackupUtilsTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.pm.ApplicationInfo;
+import android.os.Process;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.android.server.backup.RefactoredBackupManagerService;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class AppBackupUtilsTest {
+    private static final String CUSTOM_BACKUP_AGENT_NAME = "custom.backup.agent";
+    private static final String TEST_PACKAGE_NAME = "test_package";
+
+    @Test
+    public void appIsEligibleForBackup_backupNotAllowed_returnsFalse() {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags = 0;
+        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+        applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isFalse();
+    }
+
+    @Test
+    public void appIsEligibleForBackup_systemAppWithoutCustomBackupAgent_returnsFalse() {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.SYSTEM_UID;
+        applicationInfo.backupAgentName = null;
+        applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isFalse();
+    }
+
+    @Test
+    public void appIsEligibleForBackup_sharedStorageBackupPackage_returnsFalse() {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.SYSTEM_UID;
+        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+        applicationInfo.packageName = RefactoredBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE;
+
+        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isFalse();
+    }
+
+    @Test
+    public void appIsEligibleForBackup_systemAppWithCustomBackupAgent_returnsTrue() {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.SYSTEM_UID;
+        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+        applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isTrue();
+    }
+
+    @Test
+    public void appIsEligibleForBackup_nonSystemAppWithoutCustomBackupAgent_returnsTrue() {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+        applicationInfo.backupAgentName = null;
+        applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isTrue();
+    }
+
+    @Test
+    public void appIsEligibleForBackup_nonSystemAppWithCustomBackupAgent_returnsTrue() {
+        ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.flags |= ApplicationInfo.FLAG_ALLOW_BACKUP;
+        applicationInfo.uid = Process.FIRST_APPLICATION_UID;
+        applicationInfo.backupAgentName = CUSTOM_BACKUP_AGENT_NAME;
+        applicationInfo.packageName = TEST_PACKAGE_NAME;
+
+        boolean isEligible = AppBackupUtils.appIsEligibleForBackup(applicationInfo);
+
+        assertThat(isEligible).isTrue();
+    }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
new file mode 100644
index 0000000..d33a035
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/BackupManagerMonitorUtilsTest.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
+
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_CATEGORY;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_ID;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_NAME;
+import static android.app.backup.BackupManagerMonitor.EXTRA_LOG_EVENT_PACKAGE_VERSION;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IBackupManagerMonitor;
+import android.content.pm.PackageInfo;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class BackupManagerMonitorUtilsTest {
+    @Mock private IBackupManagerMonitor mMonitorMock;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void monitorEvent_monitorIsNull_returnsNull() throws Exception {
+        IBackupManagerMonitor result = BackupManagerMonitorUtils.monitorEvent(null, 0, null, 0,
+                null);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void monitorEvent_monitorOnEventThrows_returnsNull() throws Exception {
+        doThrow(new RemoteException()).when(mMonitorMock).onEvent(any(Bundle.class));
+
+        IBackupManagerMonitor result = BackupManagerMonitorUtils.monitorEvent(mMonitorMock, 0, null,
+                0, null);
+
+        verify(mMonitorMock).onEvent(any(Bundle.class));
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void monitorEvent_packageAndExtrasAreNull_fillsBundleCorrectly() throws Exception {
+        IBackupManagerMonitor result = BackupManagerMonitorUtils.monitorEvent(mMonitorMock, 1, null,
+                2, null);
+
+        assertThat(result).isEqualTo(mMonitorMock);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mMonitorMock).onEvent(bundleCaptor.capture());
+        Bundle eventBundle = bundleCaptor.getValue();
+        assertThat(eventBundle.size()).isEqualTo(2);
+        assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_ID)).isEqualTo(1);
+        assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_CATEGORY)).isEqualTo(2);
+    }
+
+    @Test
+    public void monitorEvent_packageAndExtrasAreNotNull_fillsBundleCorrectly() throws Exception {
+        PackageInfo packageInfo = new PackageInfo();
+        packageInfo.packageName = "test.package";
+        packageInfo.versionCode = 3;
+        Bundle extras = new Bundle();
+        extras.putInt("key1", 4);
+        extras.putString("key2", "value2");
+
+        IBackupManagerMonitor result = BackupManagerMonitorUtils.monitorEvent(mMonitorMock, 1,
+                packageInfo, 2, extras);
+
+        assertThat(result).isEqualTo(mMonitorMock);
+        ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+        verify(mMonitorMock).onEvent(bundleCaptor.capture());
+        Bundle eventBundle = bundleCaptor.getValue();
+        assertThat(eventBundle.size()).isEqualTo(6);
+        assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_ID)).isEqualTo(1);
+        assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_CATEGORY)).isEqualTo(2);
+        assertThat(eventBundle.getString(EXTRA_LOG_EVENT_PACKAGE_NAME)).isEqualTo("test.package");
+        assertThat(eventBundle.getInt(EXTRA_LOG_EVENT_PACKAGE_VERSION)).isEqualTo(3);
+        assertThat(eventBundle.getInt("key1")).isEqualTo(4);
+        assertThat(eventBundle.getString("key2")).isEqualTo("value2");
+    }
+
+    @Test
+    public void putMonitoringExtraString_bundleExists_fillsBundleCorrectly() throws Exception {
+        Bundle bundle = new Bundle();
+
+        Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(bundle, "key", "value");
+
+        assertThat(result).isEqualTo(bundle);
+        assertThat(result.size()).isEqualTo(1);
+        assertThat(result.getString("key")).isEqualTo("value");
+    }
+
+    @Test
+    public void putMonitoringExtraString_bundleDoesNotExist_fillsBundleCorrectly()
+            throws Exception {
+        Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(null, "key", "value");
+
+        assertThat(result).isNotNull();
+        assertThat(result.size()).isEqualTo(1);
+        assertThat(result.getString("key")).isEqualTo("value");
+    }
+
+
+    @Test
+    public void putMonitoringExtraLong_bundleExists_fillsBundleCorrectly() throws Exception {
+        Bundle bundle = new Bundle();
+
+        Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(bundle, "key", 123);
+
+        assertThat(result).isEqualTo(bundle);
+        assertThat(result.size()).isEqualTo(1);
+        assertThat(result.getLong("key")).isEqualTo(123);
+    }
+
+    @Test
+    public void putMonitoringExtraLong_bundleDoesNotExist_fillsBundleCorrectly() throws Exception {
+        Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(null, "key", 123);
+
+        assertThat(result).isNotNull();
+        assertThat(result.size()).isEqualTo(1);
+        assertThat(result.getLong("key")).isEqualTo(123);
+    }
+
+    @Test
+    public void putMonitoringExtraBoolean_bundleExists_fillsBundleCorrectly() throws Exception {
+        Bundle bundle = new Bundle();
+
+        Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(bundle, "key", true);
+
+        assertThat(result).isEqualTo(bundle);
+        assertThat(result.size()).isEqualTo(1);
+        assertThat(result.getBoolean("key")).isTrue();
+    }
+
+    @Test
+    public void putMonitoringExtraBoolean_bundleDoesNotExist_fillsBundleCorrectly()
+            throws Exception {
+        Bundle result = BackupManagerMonitorUtils.putMonitoringExtra(null, "key", true);
+
+        assertThat(result).isNotNull();
+        assertThat(result.size()).isEqualTo(1);
+        assertThat(result.getBoolean("key")).isTrue();
+    }
+
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java
new file mode 100644
index 0000000..336b11a
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/BackupObserverUtilsTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.BackupProgress;
+import android.app.backup.IBackupObserver;
+import android.os.RemoteException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class BackupObserverUtilsTest {
+    private static final String PACKAGE_NAME = "some.package";
+
+    @Mock
+    private IBackupObserver mBackupObserverMock;
+    private final BackupProgress mBackupProgress = new BackupProgress(0, 0);
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void sendBackupOnUpdate_observerIsNull_doesNotThrow() throws Exception {
+        BackupObserverUtils.sendBackupOnUpdate(null, PACKAGE_NAME, mBackupProgress);
+
+        // Should not throw.
+    }
+
+    @Test
+    public void sendBackupOnUpdate_callsObserver() throws Exception {
+        BackupObserverUtils.sendBackupOnUpdate(mBackupObserverMock, PACKAGE_NAME, mBackupProgress);
+
+        verify(mBackupObserverMock).onUpdate(PACKAGE_NAME, mBackupProgress);
+    }
+
+    @Test
+    public void sendBackupOnUpdate_handlesRemoteException() throws Exception {
+        doThrow(new RemoteException()).when(mBackupObserverMock).onUpdate(PACKAGE_NAME,
+                mBackupProgress);
+
+        BackupObserverUtils.sendBackupOnUpdate(mBackupObserverMock, PACKAGE_NAME, mBackupProgress);
+
+        verify(mBackupObserverMock).onUpdate(PACKAGE_NAME, mBackupProgress);
+    }
+
+    @Test
+    public void sendBackupOnPackageResult_observerIsNull_doesNotThrow() throws Exception {
+        BackupObserverUtils.sendBackupOnPackageResult(null, PACKAGE_NAME, 1);
+
+        // Should not throw.
+    }
+
+    @Test
+    public void sendBackupOnPackageResult_callsObserver() throws Exception {
+        BackupObserverUtils.sendBackupOnPackageResult(mBackupObserverMock, PACKAGE_NAME, 1);
+
+        verify(mBackupObserverMock).onResult(PACKAGE_NAME, 1);
+    }
+
+    @Test
+    public void sendBackupOnPackageResult_handlesRemoteException() throws Exception {
+        doThrow(new RemoteException()).when(mBackupObserverMock).onResult(PACKAGE_NAME, 1);
+
+        BackupObserverUtils.sendBackupOnPackageResult(mBackupObserverMock, PACKAGE_NAME, 1);
+
+        verify(mBackupObserverMock).onResult(PACKAGE_NAME, 1);
+    }
+
+    @Test
+    public void sendBackupFinished_observerIsNull_doesNotThrow() throws Exception {
+        BackupObserverUtils.sendBackupFinished(null, 1);
+
+        // Should not throw.
+    }
+
+    @Test
+    public void sendBackupFinished_callsObserver() throws Exception {
+        BackupObserverUtils.sendBackupFinished(mBackupObserverMock, 1);
+
+        verify(mBackupObserverMock).backupFinished(1);
+    }
+
+    @Test
+    public void sendBackupFinished_handlesRemoteException() throws Exception {
+        doThrow(new RemoteException()).when(mBackupObserverMock).onResult(PACKAGE_NAME, 1);
+
+        BackupObserverUtils.sendBackupFinished(mBackupObserverMock, 1);
+
+        verify(mBackupObserverMock).backupFinished(1);
+    }
+}
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java b/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java
new file mode 100644
index 0000000..dced00e
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/backup/utils/FullBackupRestoreObserverUtilsTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2017 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.server.backup.utils;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.verify;
+
+import android.app.backup.IFullBackupRestoreObserver;
+import android.os.RemoteException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+public class FullBackupRestoreObserverUtilsTest {
+    private static final String PACKAGE_NAME = "some.package";
+    @Mock
+    private IFullBackupRestoreObserver mFullBackupRestoreObserverMock;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
+    @Test
+    public void sendStartRestore_observerIsNull_returnsNull() throws Exception {
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendStartRestore(null);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void sendStartRestore_callsObserver() throws Exception {
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendStartRestore(
+                mFullBackupRestoreObserverMock);
+
+        assertThat(result).isEqualTo(mFullBackupRestoreObserverMock);
+        verify(mFullBackupRestoreObserverMock).onStartRestore();
+    }
+
+    @Test
+    public void sendStartRestore_observerThrows_returnsNull() throws Exception {
+        doThrow(new RemoteException()).when(mFullBackupRestoreObserverMock).onStartRestore();
+
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendStartRestore(
+                mFullBackupRestoreObserverMock);
+
+        assertThat(result).isNull();
+        verify(mFullBackupRestoreObserverMock).onStartRestore();
+    }
+
+    @Test
+    public void sendOnRestorePackage_observerIsNull_returnsNull() throws Exception {
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendOnRestorePackage(
+                null, PACKAGE_NAME);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void sendOnRestorePackage_callsObserver() throws Exception {
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendOnRestorePackage(
+                mFullBackupRestoreObserverMock, PACKAGE_NAME);
+
+        assertThat(result).isEqualTo(mFullBackupRestoreObserverMock);
+        verify(mFullBackupRestoreObserverMock).onRestorePackage(PACKAGE_NAME);
+    }
+
+    @Test
+    public void sendOnRestorePackage_observerThrows_returnsNull() throws Exception {
+        doThrow(new RemoteException()).when(mFullBackupRestoreObserverMock).onRestorePackage(
+                PACKAGE_NAME);
+
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendOnRestorePackage(
+                mFullBackupRestoreObserverMock, PACKAGE_NAME);
+
+        assertThat(result).isNull();
+        verify(mFullBackupRestoreObserverMock).onRestorePackage(PACKAGE_NAME);
+    }
+
+    @Test
+    public void sendEndRestore_observerIsNull_returnsNull() throws Exception {
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendEndRestore(null);
+
+        assertThat(result).isNull();
+    }
+
+    @Test
+    public void sendEndRestore_callsObserver() throws Exception {
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendEndRestore(
+                mFullBackupRestoreObserverMock);
+
+        assertThat(result).isEqualTo(mFullBackupRestoreObserverMock);
+        verify(mFullBackupRestoreObserverMock).onEndRestore();
+    }
+
+    @Test
+    public void sendEndRestore_observerThrows_returnsNull() throws Exception {
+        doThrow(new RemoteException()).when(mFullBackupRestoreObserverMock).onEndRestore();
+
+        IFullBackupRestoreObserver result = FullBackupRestoreObserverUtils.sendEndRestore(
+                mFullBackupRestoreObserverMock);
+
+        assertThat(result).isNull();
+        verify(mFullBackupRestoreObserverMock).onEndRestore();
+    }
+}
\ No newline at end of file