diff options
4 files changed, 202 insertions, 15 deletions
diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java index 7e179e5d24f8..501ff293b535 100644 --- a/services/backup/java/com/android/server/backup/TransportManager.java +++ b/services/backup/java/com/android/server/backup/TransportManager.java @@ -26,6 +26,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.os.Bundle; import android.os.RemoteException; import android.os.UserHandle; import android.util.ArrayMap; @@ -57,6 +58,8 @@ public class TransportManager { @VisibleForTesting public static final String SERVICE_ACTION_TRANSPORT_HOST = "android.backup.TRANSPORT_HOST"; + private static final String EXTRA_TRANSPORT_REGISTRATION = "transport_registration"; + private final Intent mTransportServiceIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST); private final Context mContext; private final PackageManager mPackageManager; @@ -582,8 +585,12 @@ public class TransportManager { String transportString = transportComponent.flattenToShortString(); String callerLogString = "TransportManager.registerTransport()"; - TransportClient transportClient = - mTransportClientManager.getTransportClient(transportComponent, callerLogString); + + Bundle extras = new Bundle(); + extras.putBoolean(EXTRA_TRANSPORT_REGISTRATION, true); + + TransportClient transportClient = mTransportClientManager.getTransportClient( + transportComponent, extras, callerLogString); final IBackupTransport transport; try { transport = transportClient.connectOrThrow(callerLogString); diff --git a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java index 40419323ce0a..96e7d2f53610 100644 --- a/services/backup/java/com/android/server/backup/transport/TransportClientManager.java +++ b/services/backup/java/com/android/server/backup/transport/TransportClientManager.java @@ -22,10 +22,9 @@ import static com.android.server.backup.transport.TransportUtils.formatMessage; import android.content.ComponentName; import android.content.Context; import android.content.Intent; - +import android.os.Bundle; import com.android.server.backup.TransportManager; import com.android.server.backup.transport.TransportUtils.Priority; - import java.io.PrintWriter; import java.util.Map; import java.util.WeakHashMap; @@ -59,6 +58,32 @@ public class TransportClientManager { public TransportClient getTransportClient(ComponentName transportComponent, String caller) { Intent bindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(transportComponent); + + return getTransportClient(transportComponent, caller, bindIntent); + } + + /** + * Retrieves a {@link TransportClient} for the transport identified by {@param + * transportComponent} whose binding intent will have the {@param extras} extras. + * + * @param transportComponent The {@link ComponentName} of the transport. + * @param extras A {@link Bundle} of extras to pass to the binding intent. + * @param caller A {@link String} identifying the caller for logging/debugging purposes. Check + * {@link TransportClient#connectAsync(TransportConnectionListener, String)} for more + * details. + * @return A {@link TransportClient}. + */ + public TransportClient getTransportClient( + ComponentName transportComponent, Bundle extras, String caller) { + Intent bindIntent = + new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(transportComponent); + bindIntent.putExtras(extras); + + return getTransportClient(transportComponent, caller, bindIntent); + } + + private TransportClient getTransportClient( + ComponentName transportComponent, String caller, Intent bindIntent) { synchronized (mTransportClientsLock) { TransportClient transportClient = new TransportClient( diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java index 44ac8039bbed..503adb29471c 100644 --- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java +++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java @@ -19,14 +19,12 @@ package com.android.server.backup; import static com.android.server.backup.testing.TransportData.genericTransport; import static com.android.server.backup.testing.TransportTestUtils.mockTransport; import static com.android.server.backup.testing.TransportTestUtils.setUpTransportsForTransportManager; + import static com.google.common.truth.Truth.assertThat; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyList; -import static java.util.Collections.singletonList; -import static java.util.stream.Collectors.toList; -import static java.util.stream.Collectors.toSet; -import static java.util.stream.Stream.concat; + import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; @@ -35,6 +33,13 @@ import static org.mockito.Mockito.when; import static org.robolectric.shadow.api.Shadow.extract; import static org.testng.Assert.expectThrows; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toSet; +import static java.util.stream.Stream.concat; + import android.annotation.Nullable; import android.app.backup.BackupManager; import android.content.ComponentName; @@ -43,6 +48,7 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.platform.test.annotations.Presubmit; + import com.android.server.backup.testing.ShadowContextImplForBackup; import com.android.server.backup.testing.TransportData; import com.android.server.backup.testing.TransportTestUtils.TransportMock; @@ -54,11 +60,7 @@ import com.android.server.testing.FrameworkRobolectricTestRunner; import com.android.server.testing.SystemLoaderPackages; import com.android.server.testing.shadows.FrameworkShadowContextImpl; import com.android.server.testing.shadows.FrameworkShadowPackageManager; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Stream; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -69,6 +71,12 @@ import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowPackageManager; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; + @RunWith(FrameworkRobolectricTestRunner.class) @Config( manifest = Config.NONE, @@ -81,6 +89,12 @@ public class TransportManagerTest { private static final String PACKAGE_A = "some.package.a"; private static final String PACKAGE_B = "some.package.b"; + /** + * GMSCore depends on this constant so we define it here on top of the definition in + * {@link TransportManager} to verify this extra is passed + */ + private static final String EXTRA_TRANSPORT_REGISTRATION = "transport_registration"; + @Mock private OnTransportRegisteredListener mListener; @Mock private TransportClientManager mTransportClientManager; private TransportData mTransportA1; @@ -195,6 +209,22 @@ public class TransportManagerTest { } @Test + public void testRegisterTransports_passesRegistrationExtraToGetTransportClient() + throws Exception { + setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); + setUpTransports(mTransportA1); + TransportManager transportManager = createTransportManager(mTransportA1); + + transportManager.registerTransports(); + + verify(mTransportClientManager) + .getTransportClient( + eq(mTransportA1.getTransportComponent()), + argThat(bundle -> bundle.getBoolean(EXTRA_TRANSPORT_REGISTRATION)), + anyString()); + } + + @Test public void testOnPackageAdded_registerTransports() throws Exception { setUpPackage(PACKAGE_A, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); setUpTransports(mTransportA1); @@ -580,6 +610,9 @@ public class TransportManagerTest { when(mTransportClientManager.getTransportClient( eq(transport.getTransportComponent()), any())) .thenReturn(transportMock.transportClient); + when(mTransportClientManager.getTransportClient( + eq(transport.getTransportComponent()), any(), any())) + .thenReturn(transportMock.transportClient); transportMocks.add(transportMock); } return transportMocks; diff --git a/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java new file mode 100644 index 000000000000..5e3c9741ae70 --- /dev/null +++ b/services/robotests/src/com/android/server/backup/transport/TransportClientManagerTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2018 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.transport; + +import static com.android.server.backup.TransportManager.SERVICE_ACTION_TRANSPORT_HOST; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.argThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.Bundle; +import android.os.UserHandle; +import android.platform.test.annotations.Presubmit; +import com.android.server.testing.FrameworkRobolectricTestRunner; +import com.android.server.testing.SystemLoaderPackages; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentMatcher; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +@RunWith(FrameworkRobolectricTestRunner.class) +@Config(manifest = Config.NONE, sdk = 26) +@SystemLoaderPackages({"com.android.server.backup"}) +@Presubmit +public class TransportClientManagerTest { + + private static final String PACKAGE_NAME = "random.package.name"; + private static final String CLASS_NAME = "random.package.name.transport.Transport"; + + @Mock private Context mContext; + @Mock private TransportConnectionListener mTransportConnectionListener; + private TransportClientManager mTransportClientManager; + private ComponentName mTransportComponent; + private Intent mBindIntent; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mTransportClientManager = new TransportClientManager(mContext); + mTransportComponent = new ComponentName(PACKAGE_NAME, CLASS_NAME); + mBindIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(mTransportComponent); + + when(mContext.bindServiceAsUser( + any(Intent.class), + any(ServiceConnection.class), + anyInt(), + any(UserHandle.class))) + .thenReturn(true); + } + + @Test + public void testGetTransportClient_withExtras_createsTransportClientWithCorrectIntent() { + Bundle extras = new Bundle(); + extras.putBoolean("random_extra", true); + mBindIntent.putExtras(extras); + + TransportClient transportClient = + mTransportClientManager.getTransportClient(mTransportComponent, extras, "caller"); + + transportClient.connectAsync(mTransportConnectionListener, "caller"); + verify(mContext) + .bindServiceAsUser( + argThat(matchesIntentAndExtras(mBindIntent)), + any(ServiceConnection.class), + anyInt(), + any(UserHandle.class)); + } + + private ArgumentMatcher<Intent> matchesIntentAndExtras(Intent expectedIntent) { + return (Intent actualIntent) -> { + if (!expectedIntent.filterEquals(actualIntent)) { + return false; + } + + Bundle expectedExtras = expectedIntent.getExtras(); + Bundle actualExtras = actualIntent.getExtras(); + + if (expectedExtras == null && actualExtras == null) { + return true; + } + + if (expectedExtras == null || actualExtras == null) { + return false; + } + + if (expectedExtras.size() != actualExtras.size()) { + return false; + } + + for (String key : expectedExtras.keySet()) { + if (!expectedExtras.get(key).equals(actualExtras.get(key))) { + return false; + } + } + + return true; + }; + } +} |