diff options
5 files changed, 136 insertions, 7 deletions
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index c1a7f6882d18..dc4caaa5a168 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -10520,7 +10520,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF Slog.v(TAG, "selectBackupTransportAsync() called with transport " + transport.flattenToShortString()); - mTransportManager.ensureTransportReady(transport, new SelectBackupTransportCallback() { + mTransportManager.ensureTransportReady(transport, new TransportManager.TransportReadyCallback() { @Override public void onSuccess(String transportName) { mTransportManager.selectTransport(transportName); diff --git a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java index 83b6693e7a70..10b03f98ce9a 100644 --- a/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java +++ b/services/backup/java/com/android/server/backup/RefactoredBackupManagerService.java @@ -2808,7 +2808,7 @@ public class RefactoredBackupManagerService implements BackupManagerServiceInter Slog.v(TAG, "selectBackupTransportAsync() called with transport " + transport.flattenToShortString()); - mTransportManager.ensureTransportReady(transport, new SelectBackupTransportCallback() { + mTransportManager.ensureTransportReady(transport, new TransportManager.TransportReadyCallback() { @Override public void onSuccess(String transportName) { mTransportManager.selectTransport(transportName); diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java index 098bc0778ac1..9aae38416bd1 100644 --- a/services/backup/java/com/android/server/backup/TransportManager.java +++ b/services/backup/java/com/android/server/backup/TransportManager.java @@ -95,6 +95,22 @@ public class TransportManager { @GuardedBy("mTransportLock") private final Map<String, ComponentName> mBoundTransports = new ArrayMap<>(); + /** + * Callback interface for {@link #ensureTransportReady(ComponentName, TransportReadyCallback)}. + */ + public interface TransportReadyCallback { + + /** + * Will be called when the transport is ready. + */ + void onSuccess(String transportName); + + /** + * Will be called when it's not possible to make transport ready. + */ + void onFailure(int reason); + } + TransportManager(Context context, Set<ComponentName> whitelist, String defaultTransport, TransportBoundListener listener, Looper looper) { mContext = context; @@ -217,7 +233,7 @@ public class TransportManager { } void ensureTransportReady(ComponentName transportComponent, - SelectBackupTransportCallback listener) { + TransportReadyCallback listener) { synchronized (mTransportLock) { TransportConnection conn = mValidTransports.get(transportComponent); if (conn == null) { @@ -326,7 +342,7 @@ public class TransportManager { // Hold mTransportsLock to access these fields so as to provide a consistent view of them. private IBackupTransport mBinder; - private final List<SelectBackupTransportCallback> mListeners = new ArrayList<>(); + private final List<TransportReadyCallback> mListeners = new ArrayList<>(); private String mTransportName; private final ComponentName mTransportComponent; @@ -359,7 +375,7 @@ public class TransportManager { if (success) { Slog.d(TAG, "Bound to transport: " + componentShortString); mBoundTransports.put(mTransportName, component); - for (SelectBackupTransportCallback listener : mListeners) { + for (TransportReadyCallback listener : mListeners) { listener.onSuccess(mTransportName); } // cancel rebinding on timeout for this component as we've already connected @@ -372,7 +388,7 @@ public class TransportManager { mContext.unbindService(this); mValidTransports.remove(component); mBinder = null; - for (SelectBackupTransportCallback listener : mListeners) { + for (TransportReadyCallback listener : mListeners) { listener.onFailure(BackupManager.ERROR_TRANSPORT_INVALID); } } @@ -432,7 +448,7 @@ public class TransportManager { } } - private void addListener(SelectBackupTransportCallback listener) { + private void addListener(TransportReadyCallback listener) { synchronized (mTransportLock) { if (mBinder == null) { // We are waiting for bind to complete. If mBinder is set to null after the bind diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java index f345da2b548c..2824b35636b7 100644 --- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java +++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; +import android.app.backup.BackupManager; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ApplicationInfo; @@ -34,6 +35,7 @@ import com.android.server.backup.testing.DefaultPackageManagerWithQueryIntentSer import com.android.server.backup.testing.ShadowBackupTransportStub; import com.android.server.backup.testing.ShadowContextImplForBackup; import com.android.server.backup.testing.TransportBoundListenerStub; +import com.android.server.backup.testing.TransportReadyCallbackStub; import org.junit.After; import org.junit.Before; @@ -75,6 +77,9 @@ public class TransportManagerTest { private final TransportBoundListenerStub mTransportBoundListenerStub = new TransportBoundListenerStub(true); + private final TransportReadyCallbackStub mTransportReadyCallbackStub = + new TransportReadyCallbackStub(); + @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -417,6 +422,59 @@ public class TransportManagerTest { assertThat(transportManager.selectTransport(mTransport1.name)).isEqualTo(mTransport2.name); } + @Test + public void ensureTransportReady_transportNotYetBound_callsListenerOnFailure() + throws Exception { + setUpPackageWithTransports(PACKAGE_NAME, Arrays.asList(mTransport1, mTransport2), + ApplicationInfo.PRIVATE_FLAG_PRIVILEGED); + + TransportManager transportManager = new TransportManager( + RuntimeEnvironment.application.getApplicationContext(), + new HashSet<>(Arrays.asList(mTransport1.componentName, mTransport2.componentName)), + mTransport1.name, + mTransportBoundListenerStub, + ShadowLooper.getMainLooper()); + + transportManager.ensureTransportReady(mTransport1.componentName, + mTransportReadyCallbackStub); + + assertThat(mTransportReadyCallbackStub.getSuccessCalls()).isEmpty(); + assertThat(mTransportReadyCallbackStub.getFailureCalls()).containsExactlyElementsIn( + Collections.singleton( + BackupManager.ERROR_TRANSPORT_UNAVAILABLE)); + } + + @Test + public void ensureTransportReady_transportCannotBeBound_callsListenerOnFailure() + throws Exception { + TransportManager transportManager = + createTransportManagerAndSetUpTransports(Collections.singletonList(mTransport2), + Collections.singletonList(mTransport1), mTransport1.name); + + transportManager.ensureTransportReady(mTransport1.componentName, + mTransportReadyCallbackStub); + + assertThat(mTransportReadyCallbackStub.getSuccessCalls()).isEmpty(); + assertThat(mTransportReadyCallbackStub.getFailureCalls()).containsExactlyElementsIn( + Collections.singleton( + BackupManager.ERROR_TRANSPORT_UNAVAILABLE)); + } + + @Test + public void ensureTransportReady_transportsAlreadyBound_callsListenerOnSuccess() + throws Exception { + TransportManager transportManager = + createTransportManagerAndSetUpTransports(Collections.singletonList(mTransport2), + Collections.singletonList(mTransport1), mTransport1.name); + + transportManager.ensureTransportReady(mTransport2.componentName, + mTransportReadyCallbackStub); + + assertThat(mTransportReadyCallbackStub.getSuccessCalls()).containsExactlyElementsIn( + Collections.singleton(mTransport2.name)); + assertThat(mTransportReadyCallbackStub.getFailureCalls()).isEmpty(); + } + private void setUpPackageWithTransports(String packageName, List<TransportInfo> transports, int flags) throws Exception { PackageInfo packageInfo = new PackageInfo(); diff --git a/services/robotests/src/com/android/server/backup/testing/TransportReadyCallbackStub.java b/services/robotests/src/com/android/server/backup/testing/TransportReadyCallbackStub.java new file mode 100644 index 000000000000..bbe7eba149c6 --- /dev/null +++ b/services/robotests/src/com/android/server/backup/testing/TransportReadyCallbackStub.java @@ -0,0 +1,55 @@ +/* + * 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.server.backup.TransportManager; + +import java.util.HashSet; +import java.util.Set; + +/** + * Stub implementation of TransportReadyCallback, which can tell which calls were made. + */ +public class TransportReadyCallbackStub implements + TransportManager.TransportReadyCallback { + private final Set<String> mSuccessCalls = new HashSet<>(); + private final Set<Integer> mFailureCalls = new HashSet<>(); + + @Override + public void onSuccess(String transportName) { + mSuccessCalls.add(transportName); + } + + @Override + public void onFailure(int reason) { + mFailureCalls.add(reason); + } + + /** + * Returns set of transport names for which {@link #onSuccess(String)} was called. + */ + public Set<String> getSuccessCalls() { + return mSuccessCalls; + } + + /** + * Returns set of reasons for which {@link #onFailure(int)} } was called. + */ + public Set<Integer> getFailureCalls() { + return mFailureCalls; + } +} |