Add BackupEncryptionService which provides an IntermediateEncryptingTransport

BackupEncryptionService (which is in a separate APK) provides a IntermediateTransport
which binds to the real transport.

We do this so that IntermediateEncryptingTransport can encrypt (decrypt) the
data when sending it (receiving it) from the real transport.
In this CL, IntermediateTransport does not do any encryption. It simply forwards
the data on. We will add the actual encryption in the next CL.

Bug: 139269919

Test: atest -v BackupEncryptionUnitTests
Test: atest -v RunBackupFrameworksServicesRoboTests
Test: atest -v $(find frameworks/base/services/tests/servicestests/src/com/android/server/backup -name '\''*Test.java'\'')'
Test: atest -v CtsBackupTestCases CtsBackupHostTestCases
Change-Id: I83a84ed3e638eb1dd165fffe406495f80ff930aa
diff --git a/packages/BackupEncryption/test/unittest/Android.bp b/packages/BackupEncryption/test/unittest/Android.bp
new file mode 100644
index 0000000..d7c510b
--- /dev/null
+++ b/packages/BackupEncryption/test/unittest/Android.bp
@@ -0,0 +1,22 @@
+android_test {
+    name: "BackupEncryptionUnitTests",
+    srcs: ["src/**/*.java"],
+    static_libs: [
+        "androidx.test.runner",
+        "androidx.test.rules",
+        "mockito-target-minus-junit4",
+        "platform-test-annotations",
+        "truth-prebuilt",
+        "testables",
+        "testng",
+    ],
+    libs: [
+        "android.test.mock",
+        "android.test.base",
+        "android.test.runner",
+        "BackupEncryption",
+    ],
+    test_suites: ["device-tests"],
+    instrumentation_for: "BackupEncryption",
+    certificate: "platform",
+}
\ No newline at end of file
diff --git a/packages/BackupEncryption/test/unittest/AndroidManifest.xml b/packages/BackupEncryption/test/unittest/AndroidManifest.xml
new file mode 100644
index 0000000..39ac8aa3
--- /dev/null
+++ b/packages/BackupEncryption/test/unittest/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.server.backup.encryption.unittests"
+          android:sharedUserId="android.uid.system" >
+    <application android:testOnly="true">
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <instrumentation
+        android:name="androidx.test.runner.AndroidJUnitRunner"
+        android:targetPackage="com.android.server.backup.encryption"
+        android:label="Backup Encryption Unit Tests" />
+</manifest>
\ No newline at end of file
diff --git a/packages/BackupEncryption/test/unittest/AndroidTest.xml b/packages/BackupEncryption/test/unittest/AndroidTest.xml
new file mode 100644
index 0000000..c9c812a
--- /dev/null
+++ b/packages/BackupEncryption/test/unittest/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 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.
+  -->
+<configuration description="Runs Backup Encryption Unit Tests.">
+    <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+        <option name="cleanup-apks" value="true" />
+        <option name="install-arg" value="-t" />
+        <option name="test-file-name" value="BackupEncryptionUnitTests.apk" />
+    </target_preparer>
+
+    <option name="test-tag" value="BackupEncryptionUnitTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="com.android.server.backup.encryption.unittests" />
+        <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+    </test>
+</configuration>
diff --git a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManagerTest.java b/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManagerTest.java
new file mode 100644
index 0000000..0d43a19
--- /dev/null
+++ b/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManagerTest.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2019 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.encryption.transport;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotSame;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.os.Bundle;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.backup.transport.TransportClient;
+import com.android.server.backup.transport.TransportClientManager;
+
+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 IntermediateEncryptingTransportManagerTest {
+    @Mock private TransportClient mTransportClient;
+    @Mock private TransportClientManager mTransportClientManager;
+
+    private final ComponentName mTransportComponent = new ComponentName("pkg", "class");
+    private final Bundle mExtras = new Bundle();
+    private Intent mEncryptingTransportIntent;
+    private IntermediateEncryptingTransportManager mIntermediateEncryptingTransportManager;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mExtras.putInt("test", 1);
+        mEncryptingTransportIntent =
+                TransportClientManager.getEncryptingTransportIntent(mTransportComponent)
+                        .putExtras(mExtras);
+        mIntermediateEncryptingTransportManager =
+                new IntermediateEncryptingTransportManager(mTransportClientManager);
+    }
+
+    @Test
+    public void testGet_createsClientWithRealTransportComponentAndExtras() {
+        when(mTransportClientManager.getTransportClient(any(), any(), any()))
+                .thenReturn(mTransportClient);
+
+        IntermediateEncryptingTransport intermediateEncryptingTransport =
+                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
+
+        assertEquals(mTransportClient, intermediateEncryptingTransport.getClient());
+        verify(mTransportClientManager, times(1))
+                .getTransportClient(eq(mTransportComponent), argThat(mExtras::kindofEquals), any());
+        verifyNoMoreInteractions(mTransportClientManager);
+    }
+
+    @Test
+    public void testGet_callTwice_returnsSameTransport() {
+        IntermediateEncryptingTransport transport1 =
+                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
+        IntermediateEncryptingTransport transport2 =
+                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
+
+        assertEquals(transport1, transport2);
+    }
+
+    @Test
+    public void testCleanup_disposesTransportClient() {
+        when(mTransportClientManager.getTransportClient(any(), any(), any()))
+                .thenReturn(mTransportClient);
+
+        IntermediateEncryptingTransport transport =
+                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
+        mIntermediateEncryptingTransportManager.cleanup(mEncryptingTransportIntent);
+
+        verify(mTransportClientManager, times(1)).getTransportClient(any(), any(), any());
+        verify(mTransportClientManager, times(1))
+                .disposeOfTransportClient(eq(mTransportClient), any());
+        verifyNoMoreInteractions(mTransportClientManager);
+    }
+
+    @Test
+    public void testCleanup_removesCachedTransport() {
+        when(mTransportClientManager.getTransportClient(any(), any(), any()))
+                .thenReturn(mTransportClient);
+
+        IntermediateEncryptingTransport transport1 =
+                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
+        mIntermediateEncryptingTransportManager.cleanup(mEncryptingTransportIntent);
+        IntermediateEncryptingTransport transport2 =
+                mIntermediateEncryptingTransportManager.get(mEncryptingTransportIntent);
+
+        assertNotSame(transport1, transport2);
+    }
+}
diff --git a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java b/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java
new file mode 100644
index 0000000..cc4b0ab
--- /dev/null
+++ b/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 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.encryption.transport;
+
+import static junit.framework.Assert.assertEquals;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.backup.IBackupTransport;
+import com.android.server.backup.transport.TransportClient;
+
+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 IntermediateEncryptingTransportTest {
+    @Mock private IBackupTransport mRealTransport;
+    @Mock private TransportClient mTransportClient;
+
+    private IntermediateEncryptingTransport mIntermediateEncryptingTransport;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        mIntermediateEncryptingTransport = new IntermediateEncryptingTransport(mTransportClient);
+    }
+
+    @Test
+    public void testGetDelegate_callsConnect() throws Exception {
+        when(mTransportClient.connect(anyString())).thenReturn(mRealTransport);
+
+        IBackupTransport ret = mIntermediateEncryptingTransport.getDelegate();
+
+        assertEquals(mRealTransport, ret);
+        verify(mTransportClient, times(1)).connect(anyString());
+        verifyNoMoreInteractions(mTransportClient);
+    }
+
+    @Test
+    public void testGetDelegate_callTwice_callsConnectOnce() throws Exception {
+        when(mTransportClient.connect(anyString())).thenReturn(mRealTransport);
+
+        IBackupTransport ret1 = mIntermediateEncryptingTransport.getDelegate();
+        IBackupTransport ret2 = mIntermediateEncryptingTransport.getDelegate();
+
+        assertEquals(mRealTransport, ret1);
+        assertEquals(mRealTransport, ret2);
+        verify(mTransportClient, times(1)).connect(anyString());
+        verifyNoMoreInteractions(mTransportClient);
+    }
+}