summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2017-09-01 12:06:16 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2017-09-01 12:06:16 +0000
commita1f7fb9b5b7f090c0e070a878ae9b7c62733bced (patch)
tree3e57ac0ebae31ffbcbf8e4f35e3a67a997623e0a
parent4456a99918f00d6da50ffb98bfe6baf9e63c2bae (diff)
parentbd476eae4ba26389dc83402d0b0ae07d6d4e73c5 (diff)
Merge "Update TransportManager tests."
-rw-r--r--services/backup/java/com/android/server/backup/TransportManager.java2
-rw-r--r--services/robotests/Android.mk2
-rw-r--r--services/robotests/src/com/android/server/backup/TransportManagerTest.java165
-rw-r--r--services/robotests/src/com/android/server/backup/testing/BackupTransportStub.java179
-rw-r--r--services/robotests/src/com/android/server/backup/testing/DefaultPackageManagerWithQueryIntentServicesAsUser.java43
-rw-r--r--services/robotests/src/com/android/server/backup/testing/ShadowBackupTransportStub.java40
-rw-r--r--services/robotests/src/com/android/server/backup/testing/ShadowContextImplWithBindServiceAsUser.java48
-rw-r--r--services/robotests/src/com/android/server/backup/testing/TransportBoundListenerStub.java51
8 files changed, 481 insertions, 49 deletions
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java
index 321ef2652514..098bc0778ac1 100644
--- a/services/backup/java/com/android/server/backup/TransportManager.java
+++ b/services/backup/java/com/android/server/backup/TransportManager.java
@@ -455,7 +455,7 @@ public class TransportManager {
}
}
- interface TransportBoundListener {
+ public interface TransportBoundListener {
/** Should return true if this is a valid transport. */
boolean onTransportBound(IBackupTransport binder);
}
diff --git a/services/robotests/Android.mk b/services/robotests/Android.mk
index 3e82d3ee1d2f..717176247d36 100644
--- a/services/robotests/Android.mk
+++ b/services/robotests/Android.mk
@@ -73,4 +73,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \
LOCAL_TEST_PACKAGE := FrameworksServicesLib
+LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))backup/java
+
include prebuilts/misc/common/robolectric/run_robotests.mk
diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
index 0f7a091a8315..510fdba5fdf2 100644
--- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java
+++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java
@@ -18,32 +18,36 @@ package com.android.server.backup;
import static com.google.common.truth.Truth.assertThat;
-import android.annotation.RequiresPermission;
import android.content.ComponentName;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.os.UserHandle;
+import android.os.IBinder;
+import android.platform.test.annotations.Presubmit;
+
+import com.android.server.backup.testing.BackupTransportStub;
+import com.android.server.backup.testing.DefaultPackageManagerWithQueryIntentServicesAsUser;
+import com.android.server.backup.testing.ShadowBackupTransportStub;
+import com.android.server.backup.testing.ShadowContextImplWithBindServiceAsUser;
+import com.android.server.backup.testing.TransportBoundListenerStub;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import org.robolectric.annotation.Implementation;
-import org.robolectric.annotation.Implements;
-import org.robolectric.res.ResourceLoader;
-import org.robolectric.res.builder.DefaultPackageManager;
import org.robolectric.res.builder.RobolectricPackageManager;
-import org.robolectric.shadows.ShadowContextImpl;
+import org.robolectric.shadows.ShadowLog;
import org.robolectric.shadows.ShadowLooper;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
@@ -51,12 +55,18 @@ import java.util.List;
@Config(
manifest = Config.NONE,
sdk = 23,
- shadows = {TransportManagerTest.ShadowContextImplWithBindServiceAsUser.class}
+ shadows = {
+ ShadowContextImplWithBindServiceAsUser.class,
+ ShadowBackupTransportStub.class
+ }
)
+@Presubmit
public class TransportManagerTest {
private static final String PACKAGE_NAME = "some.package.name";
private static final String TRANSPORT1_NAME = "transport1.name";
private static final String TRANSPORT2_NAME = "transport2.name";
+ private static final List<String> TRANSPORTS_NAMES = Arrays.asList(
+ TRANSPORT1_NAME, TRANSPORT2_NAME);
private static final ComponentName TRANSPORT1_COMPONENT_NAME = new ComponentName(PACKAGE_NAME,
TRANSPORT1_NAME);
private static final ComponentName TRANSPORT2_COMPONENT_NAME = new ComponentName(PACKAGE_NAME,
@@ -66,72 +76,131 @@ public class TransportManagerTest {
private RobolectricPackageManager mPackageManager;
- @Mock private TransportManager.TransportBoundListener mTransportBoundListener;
+ @Mock private IBinder mTransport1BinderMock;
+ @Mock private IBinder mTransport2BinderMock;
+
+ private final BackupTransportStub mTransport1Stub = new BackupTransportStub(TRANSPORT1_NAME);
+ private final BackupTransportStub mTransport2Stub = new BackupTransportStub(TRANSPORT2_NAME);
+ private final TransportBoundListenerStub mTransportBoundListenerStub =
+ new TransportBoundListenerStub(true);
@Before
- public void setUp() {
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ ShadowLog.stream = System.out;
mPackageManager = new DefaultPackageManagerWithQueryIntentServicesAsUser(
RuntimeEnvironment.getAppResourceLoader());
RuntimeEnvironment.setRobolectricPackageManager(mPackageManager);
+
+ ShadowContextImplWithBindServiceAsUser.sComponentBinderMap.put(TRANSPORT1_COMPONENT_NAME,
+ mTransport1BinderMock);
+ ShadowContextImplWithBindServiceAsUser.sComponentBinderMap.put(TRANSPORT2_COMPONENT_NAME,
+ mTransport2BinderMock);
+ ShadowBackupTransportStub.sBinderTransportMap.put(mTransport1BinderMock, mTransport1Stub);
+ ShadowBackupTransportStub.sBinderTransportMap.put(mTransport2BinderMock, mTransport2Stub);
}
@Test
- public void onPackageAdded_bindsToAllTransports() {
- Intent intent = new Intent(TransportManager.SERVICE_ACTION_TRANSPORT_HOST);
- intent.setPackage(PACKAGE_NAME);
+ public void onPackageAdded_bindsToAllTransports() throws Exception {
+ setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES,
+ ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
- PackageInfo packageInfo = new PackageInfo();
- packageInfo.packageName = PACKAGE_NAME;
- packageInfo.applicationInfo = new ApplicationInfo();
- packageInfo.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
+ TransportManager transportManager = new TransportManager(
+ RuntimeEnvironment.application.getApplicationContext(),
+ new HashSet<>(TRANSPORTS_COMPONENT_NAMES),
+ null /* defaultTransport */,
+ mTransportBoundListenerStub,
+ ShadowLooper.getMainLooper());
+ transportManager.onPackageAdded(PACKAGE_NAME);
- mPackageManager.addPackage(packageInfo);
+ assertThat(transportManager.getAllTransportComponents()).asList().containsExactlyElementsIn(
+ TRANSPORTS_COMPONENT_NAMES);
+ assertThat(transportManager.getBoundTransportNames()).asList().containsExactlyElementsIn(
+ TRANSPORTS_NAMES);
+ assertThat(mTransportBoundListenerStub.isCalledForTransport(mTransport1Stub)).isTrue();
+ assertThat(mTransportBoundListenerStub.isCalledForTransport(mTransport2Stub)).isTrue();
+ }
- ResolveInfo transport1 = new ResolveInfo();
- transport1.serviceInfo = new ServiceInfo();
- transport1.serviceInfo.packageName = PACKAGE_NAME;
- transport1.serviceInfo.name = TRANSPORT1_NAME;
+ @Test
+ public void onPackageAdded_whitelistIsNull_doesNotBindToTransports() throws Exception {
+ setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES,
+ ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
- ResolveInfo transport2 = new ResolveInfo();
- transport2.serviceInfo = new ServiceInfo();
- transport2.serviceInfo.packageName = PACKAGE_NAME;
- transport2.serviceInfo.name = TRANSPORT2_NAME;
+ TransportManager transportManager = new TransportManager(
+ RuntimeEnvironment.application.getApplicationContext(),
+ null /* whitelist */,
+ null /* defaultTransport */,
+ mTransportBoundListenerStub,
+ ShadowLooper.getMainLooper());
+ transportManager.onPackageAdded(PACKAGE_NAME);
- mPackageManager.addResolveInfoForIntent(intent, Arrays.asList(transport1, transport2));
+ assertThat(transportManager.getAllTransportComponents()).isEmpty();
+ assertThat(transportManager.getBoundTransportNames()).isEmpty();
+ assertThat(mTransportBoundListenerStub.isCalled()).isFalse();
+ }
+
+ @Test
+ public void onPackageAdded_onlyOneTransportWhitelisted_onlyConnectsToWhitelistedTransport()
+ throws Exception {
+ setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES,
+ ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
TransportManager transportManager = new TransportManager(
RuntimeEnvironment.application.getApplicationContext(),
- new HashSet<>(TRANSPORTS_COMPONENT_NAMES),
- null,
- mTransportBoundListener,
+ new HashSet<>(Collections.singleton(TRANSPORT2_COMPONENT_NAME)),
+ null /* defaultTransport */,
+ mTransportBoundListenerStub,
ShadowLooper.getMainLooper());
transportManager.onPackageAdded(PACKAGE_NAME);
assertThat(transportManager.getAllTransportComponents()).asList().containsExactlyElementsIn(
- TRANSPORTS_COMPONENT_NAMES);
+ Collections.singleton(TRANSPORT2_COMPONENT_NAME));
+ assertThat(transportManager.getBoundTransportNames()).asList().containsExactlyElementsIn(
+ Collections.singleton(TRANSPORT2_NAME));
+ assertThat(mTransportBoundListenerStub.isCalledForTransport(mTransport1Stub)).isFalse();
+ assertThat(mTransportBoundListenerStub.isCalledForTransport(mTransport2Stub)).isTrue();
}
- private static class DefaultPackageManagerWithQueryIntentServicesAsUser extends
- DefaultPackageManager {
+ @Test
+ public void onPackageAdded_appIsNotPrivileged_doesNotBindToTransports() throws Exception {
+ setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES, 0);
- /* package */ DefaultPackageManagerWithQueryIntentServicesAsUser(
- ResourceLoader appResourceLoader) {
- super(appResourceLoader);
- }
+ TransportManager transportManager = new TransportManager(
+ RuntimeEnvironment.application.getApplicationContext(),
+ new HashSet<>(TRANSPORTS_COMPONENT_NAMES),
+ null /* defaultTransport */,
+ mTransportBoundListenerStub,
+ ShadowLooper.getMainLooper());
+ transportManager.onPackageAdded(PACKAGE_NAME);
- @Override
- public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
- return super.queryIntentServices(intent, flags);
- }
+ assertThat(transportManager.getAllTransportComponents()).isEmpty();
+ assertThat(transportManager.getBoundTransportNames()).isEmpty();
+ assertThat(mTransportBoundListenerStub.isCalled()).isFalse();
}
- @Implements(className = ShadowContextImpl.CLASS_NAME)
- public static class ShadowContextImplWithBindServiceAsUser extends ShadowContextImpl {
+ private void setUpPackageWithTransports(String packageName, List<String> transportNames,
+ int flags) throws Exception {
+ PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = packageName;
+ packageInfo.applicationInfo = new ApplicationInfo();
+ packageInfo.applicationInfo.privateFlags = flags;
+
+ mPackageManager.addPackage(packageInfo);
- @Implementation
- public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn,
- int flags, UserHandle user) {
- return true;
+ List<ResolveInfo> transportsInfo = new ArrayList<>();
+ for (String transportName : transportNames) {
+ ResolveInfo info = new ResolveInfo();
+ info.serviceInfo = new ServiceInfo();
+ info.serviceInfo.packageName = packageName;
+ info.serviceInfo.name = transportName;
+ transportsInfo.add(info);
}
+
+ Intent intent = new Intent(TransportManager.SERVICE_ACTION_TRANSPORT_HOST);
+ intent.setPackage(packageName);
+
+ mPackageManager.addResolveInfoForIntent(intent, transportsInfo);
}
+
}
diff --git a/services/robotests/src/com/android/server/backup/testing/BackupTransportStub.java b/services/robotests/src/com/android/server/backup/testing/BackupTransportStub.java
new file mode 100644
index 000000000000..ec09f908c90d
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/BackupTransportStub.java
@@ -0,0 +1,179 @@
+/*
+ * 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.testing;
+
+import android.app.backup.RestoreDescription;
+import android.app.backup.RestoreSet;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
+import android.os.RemoteException;
+
+import com.android.internal.backup.IBackupTransport;
+
+/**
+ * Stub backup transport, doing nothing and returning default values.
+ */
+public class BackupTransportStub implements IBackupTransport {
+
+ private final String mName;
+
+ public BackupTransportStub(String name) {
+ mName = name;
+ }
+
+ @Override
+ public IBinder asBinder() {
+ return null;
+ }
+
+ @Override
+ public String name() throws RemoteException {
+ return mName;
+ }
+
+ @Override
+ public Intent configurationIntent() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public String currentDestinationString() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public Intent dataManagementIntent() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public String dataManagementLabel() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public String transportDirName() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public long requestBackupTime() throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int initializeDevice() throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags)
+ throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int clearBackupData(PackageInfo packageInfo) throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int finishBackup() throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public RestoreSet[] getAvailableRestoreSets() throws RemoteException {
+ return new RestoreSet[0];
+ }
+
+ @Override
+ public long getCurrentRestoreSet() throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int startRestore(long token, PackageInfo[] packages) throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public RestoreDescription nextRestorePackage() throws RemoteException {
+ return null;
+ }
+
+ @Override
+ public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public void finishRestore() throws RemoteException {
+
+ }
+
+ @Override
+ public long requestFullBackupTime() throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket,
+ int flags)
+ throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int checkFullBackupSize(long size) throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int sendBackupData(int numBytes) throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public void cancelFullBackup() throws RemoteException {
+
+ }
+
+ @Override
+ public boolean isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup)
+ throws RemoteException {
+ return false;
+ }
+
+ @Override
+ public long getBackupQuota(String packageName, boolean isFullBackup)
+ throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) throws RemoteException {
+ return 0;
+ }
+
+ @Override
+ public int abortFullRestore() throws RemoteException {
+ return 0;
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/DefaultPackageManagerWithQueryIntentServicesAsUser.java b/services/robotests/src/com/android/server/backup/testing/DefaultPackageManagerWithQueryIntentServicesAsUser.java
new file mode 100644
index 000000000000..5a0967ba2420
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/DefaultPackageManagerWithQueryIntentServicesAsUser.java
@@ -0,0 +1,43 @@
+/*
+ * 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.testing;
+
+import android.content.Intent;
+import android.content.pm.ResolveInfo;
+
+import org.robolectric.res.ResourceLoader;
+import org.robolectric.res.builder.DefaultPackageManager;
+
+import java.util.List;
+
+/**
+ * Implementation of PackageManager for Robolectric which handles queryIntentServicesAsUser().
+ */
+public class DefaultPackageManagerWithQueryIntentServicesAsUser extends
+ DefaultPackageManager {
+
+ /* package */
+ public DefaultPackageManagerWithQueryIntentServicesAsUser(
+ ResourceLoader appResourceLoader) {
+ super(appResourceLoader);
+ }
+
+ @Override
+ public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
+ return super.queryIntentServices(intent, flags);
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowBackupTransportStub.java b/services/robotests/src/com/android/server/backup/testing/ShadowBackupTransportStub.java
new file mode 100644
index 000000000000..48a12f0f5435
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/ShadowBackupTransportStub.java
@@ -0,0 +1,40 @@
+/*
+ * 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.testing;
+
+import android.os.IBinder;
+
+import com.android.internal.backup.IBackupTransport;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Shadow IBackupTransport.Stub, returns a transport corresponding to the binder.
+ */
+@Implements(IBackupTransport.Stub.class)
+public class ShadowBackupTransportStub {
+ public static Map<IBinder, IBackupTransport> sBinderTransportMap = new HashMap<>();
+
+ @Implementation
+ public static IBackupTransport asInterface(IBinder obj) {
+ return sBinderTransportMap.get(obj);
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/ShadowContextImplWithBindServiceAsUser.java b/services/robotests/src/com/android/server/backup/testing/ShadowContextImplWithBindServiceAsUser.java
new file mode 100644
index 000000000000..77424294b1e0
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/ShadowContextImplWithBindServiceAsUser.java
@@ -0,0 +1,48 @@
+/*
+ * 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.testing;
+
+import android.annotation.RequiresPermission;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.IBinder;
+import android.os.UserHandle;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowContextImpl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Implementation of ContextImpl shadow, handling bindServiceAsUser().
+ */
+@Implements(className = ShadowContextImpl.CLASS_NAME)
+public class ShadowContextImplWithBindServiceAsUser extends ShadowContextImpl {
+ public static Map<ComponentName, IBinder> sComponentBinderMap = new HashMap<>();
+
+ @Implementation
+ public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn,
+ int flags, UserHandle user) {
+ ShadowApplication.getInstance().setComponentNameAndServiceForBindService(
+ service.getComponent(), sComponentBinderMap.get(service.getComponent()));
+ return bindService(service, conn, flags);
+ }
+}
diff --git a/services/robotests/src/com/android/server/backup/testing/TransportBoundListenerStub.java b/services/robotests/src/com/android/server/backup/testing/TransportBoundListenerStub.java
new file mode 100644
index 000000000000..e9f5978cc6d0
--- /dev/null
+++ b/services/robotests/src/com/android/server/backup/testing/TransportBoundListenerStub.java
@@ -0,0 +1,51 @@
+/*
+ * 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.testing;
+
+import com.android.internal.backup.IBackupTransport;
+import com.android.server.backup.TransportManager;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Stub implementation of TransportBoundListener, which returns given result and can tell whether
+ * it was called for given transport.
+ */
+public class TransportBoundListenerStub implements
+ TransportManager.TransportBoundListener {
+ private boolean mAlwaysReturnSuccess;
+ private Set<IBackupTransport> mTransportsCalledFor = new HashSet<>();
+
+ public TransportBoundListenerStub(boolean alwaysReturnSuccess) {
+ this.mAlwaysReturnSuccess = alwaysReturnSuccess;
+ }
+
+ @Override
+ public boolean onTransportBound(IBackupTransport binder) {
+ mTransportsCalledFor.add(binder);
+ return mAlwaysReturnSuccess;
+ }
+
+ public boolean isCalledForTransport(IBackupTransport binder) {
+ return mTransportsCalledFor.contains(binder);
+ }
+
+ public boolean isCalled() {
+ return !mTransportsCalledFor.isEmpty();
+ }
+}