diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/BackupEncryptionService.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/BackupEncryptionService.java deleted file mode 100644 index 84fb0e62dbcaf..0000000000000 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/BackupEncryptionService.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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; - -import android.app.Service; -import android.content.Intent; -import android.os.IBinder; -import android.util.Log; - -import com.android.internal.backup.IBackupTransport; -import com.android.server.backup.encryption.transport.IntermediateEncryptingTransport; -import com.android.server.backup.encryption.transport.IntermediateEncryptingTransportManager; - -/** - * This service provides encryption of backup data. For an intent used to bind to this service, it - * provides an {@link IntermediateEncryptingTransport} which is an implementation of {@link - * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from the - * real {@link IBackupTransport}. - */ -public class BackupEncryptionService extends Service { - public static final String TAG = "BackupEncryption"; - private static IntermediateEncryptingTransportManager sTransportManager = null; - - @Override - public void onCreate() { - Log.i(TAG, "onCreate:" + this); - if (sTransportManager == null) { - Log.i(TAG, "Creating IntermediateEncryptingTransportManager"); - sTransportManager = new IntermediateEncryptingTransportManager(this); - } - } - - @Override - public void onDestroy() { - Log.i(TAG, "onDestroy:" + this); - } - - @Override - public IBinder onBind(Intent intent) { - // TODO (b141536117): Check connection with TransportClient.connect and return null on fail. - return sTransportManager.get(intent); - } - - @Override - public boolean onUnbind(Intent intent) { - sTransportManager.cleanup(intent); - return false; - } -} diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java index 1d841b4a2c8f4..db2dd2f34ec1e 100644 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java +++ b/packages/BackupEncryption/src/com/android/server/backup/encryption/KeyValueEncrypter.java @@ -16,8 +16,6 @@ package com.android.server.backup.encryption; -import static com.android.server.backup.encryption.BackupEncryptionService.TAG; - import android.content.Context; import android.os.ParcelFileDescriptor; import android.util.Log; @@ -36,6 +34,8 @@ import java.security.SecureRandom; import java.util.Map; public class KeyValueEncrypter { + private static final String TAG = "KeyValueEncrypter"; + private final Context mContext; private final EncryptionKeyHelper mKeyHelper; diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java deleted file mode 100644 index c3cb335db89e9..0000000000000 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransport.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * 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 com.android.server.backup.encryption.BackupEncryptionService.TAG; - -import android.app.backup.BackupTransport; -import android.app.backup.RestoreDescription; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.backup.IBackupTransport; -import com.android.server.backup.encryption.KeyValueEncrypter; -import com.android.server.backup.transport.DelegatingTransport; -import com.android.server.backup.transport.TransportClient; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.concurrent.atomic.AtomicReference; - -/** - * This is an implementation of {@link IBackupTransport} that encrypts (or decrypts) the data when - * sending it (or receiving it) from the {@link IBackupTransport} returned by {@link - * TransportClient.connect(String)}. - */ -public class IntermediateEncryptingTransport extends DelegatingTransport { - private static final String BACKUP_TEMP_DIR = "backup"; - private static final String RESTORE_TEMP_DIR = "restore"; - - private final TransportClient mTransportClient; - private final Object mConnectLock = new Object(); - private final Context mContext; - private volatile IBackupTransport mRealTransport; - private AtomicReference mNextRestorePackage = new AtomicReference<>(); - private final KeyValueEncrypter mKeyValueEncrypter; - private final boolean mShouldEncrypt; - - IntermediateEncryptingTransport( - TransportClient transportClient, Context context, boolean shouldEncrypt) { - this(transportClient, context, new KeyValueEncrypter(context), shouldEncrypt); - } - - @VisibleForTesting - IntermediateEncryptingTransport( - TransportClient transportClient, Context context, KeyValueEncrypter keyValueEncrypter, - boolean shouldEncrypt) { - mTransportClient = transportClient; - mContext = context; - mKeyValueEncrypter = keyValueEncrypter; - mShouldEncrypt = shouldEncrypt; - } - - @Override - protected IBackupTransport getDelegate() throws RemoteException { - if (mRealTransport == null) { - connect(); - } - Log.d(TAG, "real transport = " + mRealTransport.name()); - return mRealTransport; - } - - @Override - public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags) - throws RemoteException { - if (!mShouldEncrypt) { - return super.performBackup(packageInfo, inFd, flags); - } - - File encryptedStorageFile = getBackupTempStorage(packageInfo.packageName); - if (encryptedStorageFile == null) { - return BackupTransport.TRANSPORT_ERROR; - } - - // Encrypt the backup data and write it into a temp file. - try (OutputStream encryptedOutput = new FileOutputStream(encryptedStorageFile)) { - mKeyValueEncrypter.encryptKeyValueData(packageInfo.packageName, inFd, - encryptedOutput); - } catch (Throwable e) { - Log.e(TAG, "Failed to encrypt backup data: ", e); - return BackupTransport.TRANSPORT_ERROR; - } - - // Pass the temp file to the real transport for backup. - try (FileInputStream encryptedInput = new FileInputStream(encryptedStorageFile)) { - return super.performBackup( - packageInfo, ParcelFileDescriptor.dup(encryptedInput.getFD()), flags); - } catch (IOException e) { - Log.e(TAG, "Failed to read encrypted data from temp storage: ", e); - return BackupTransport.TRANSPORT_ERROR; - } - } - - @Override - public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException { - if (!mShouldEncrypt) { - return super.getRestoreData(outFd); - } - - String nextRestorePackage = mNextRestorePackage.get(); - if (nextRestorePackage == null) { - Log.e(TAG, "No next restore package set"); - return BackupTransport.TRANSPORT_ERROR; - } - - File encryptedStorageFile = getRestoreTempStorage(nextRestorePackage); - if (encryptedStorageFile == null) { - return BackupTransport.TRANSPORT_ERROR; - } - - // Get encrypted restore data from the real transport and write it into a temp file. - try (FileOutputStream outputStream = new FileOutputStream(encryptedStorageFile)) { - int status = super.getRestoreData(ParcelFileDescriptor.dup(outputStream.getFD())); - if (status != BackupTransport.TRANSPORT_OK) { - Log.e(TAG, "Failed to read restore data from transport, status = " + status); - return status; - } - } catch (IOException e) { - Log.e(TAG, "Failed to write encrypted data to temp storage: ", e); - return BackupTransport.TRANSPORT_ERROR; - } - - // Decrypt the data and write it into the fd given by the real transport. - try (InputStream inputStream = new FileInputStream(encryptedStorageFile)) { - mKeyValueEncrypter.decryptKeyValueData(nextRestorePackage, inputStream, outFd); - encryptedStorageFile.delete(); - } catch (Exception e) { - Log.e(TAG, "Failed to decrypt restored data: ", e); - return BackupTransport.TRANSPORT_ERROR; - } - - return BackupTransport.TRANSPORT_OK; - } - - @Override - public RestoreDescription nextRestorePackage() throws RemoteException { - if (!mShouldEncrypt) { - return super.nextRestorePackage(); - } - - RestoreDescription restoreDescription = super.nextRestorePackage(); - mNextRestorePackage.set(restoreDescription.getPackageName()); - - return restoreDescription; - } - - @VisibleForTesting - protected File getBackupTempStorage(String packageName) { - return getTempStorage(packageName, BACKUP_TEMP_DIR); - } - - @VisibleForTesting - protected File getRestoreTempStorage(String packageName) { - return getTempStorage(packageName, RESTORE_TEMP_DIR); - } - - private File getTempStorage(String packageName, String operationType) { - File encryptedDir = new File(mContext.getFilesDir(), operationType); - encryptedDir.mkdir(); - File encryptedFile = new File(encryptedDir, packageName); - try { - encryptedFile.createNewFile(); - } catch (IOException e) { - Log.e(TAG, "Failed to create temp file for encrypted data: ", e); - } - return encryptedFile; - } - - private void connect() throws RemoteException { - Log.i(TAG, "connecting " + mTransportClient); - synchronized (mConnectLock) { - if (mRealTransport == null) { - mRealTransport = mTransportClient.connect("IntermediateEncryptingTransport"); - if (mRealTransport == null) { - throw new RemoteException("Could not connect: " + mTransportClient); - } - } - } - } - - @VisibleForTesting - TransportClient getClient() { - return mTransportClient; - } - - @VisibleForTesting - void setNextRestorePackage(String nextRestorePackage) { - mNextRestorePackage.set(nextRestorePackage); - } -} diff --git a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java b/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java deleted file mode 100644 index 7c4082c2a54d0..0000000000000 --- a/packages/BackupEncryption/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManager.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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 com.android.server.backup.encryption.BackupEncryptionService.TAG; - -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.os.UserHandle; -import android.util.Log; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.backup.IBackupTransport; -import com.android.internal.widget.LockPatternUtils; -import com.android.server.backup.transport.TransportClientManager; -import com.android.server.backup.transport.TransportStats; - -import java.util.HashMap; -import java.util.Map; - -/** Handles creation and cleanup of {@link IntermediateEncryptingTransport} instances. */ -public class IntermediateEncryptingTransportManager { - private static final String CALLER = "IntermediateEncryptingTransportManager"; - private final TransportClientManager mTransportClientManager; - private final Object mTransportsLock = new Object(); - private final Map mTransports = new HashMap<>(); - private Context mContext; - - @VisibleForTesting - IntermediateEncryptingTransportManager(TransportClientManager transportClientManager) { - mTransportClientManager = transportClientManager; - } - - public IntermediateEncryptingTransportManager(Context context) { - this(new TransportClientManager(UserHandle.myUserId(), context, new TransportStats())); - mContext = context; - } - - /** - * Extract the {@link ComponentName} corresponding to the real {@link IBackupTransport}, and - * provide a {@link IntermediateEncryptingTransport} which is an implementation of {@link - * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from - * the real {@link IBackupTransport}. - * - * @param intent {@link Intent} created with a call to {@link - * TransportClientManager.getEncryptingTransportIntent(ComponentName)}. - * @return - */ - public IntermediateEncryptingTransport get(Intent intent) { - Intent transportIntent = TransportClientManager.getRealTransportIntent(intent); - Log.i(TAG, "get: intent:" + intent + " transportIntent:" + transportIntent); - synchronized (mTransportsLock) { - return mTransports.computeIfAbsent( - transportIntent.getComponent(), c -> create(transportIntent)); - } - } - - /** Create an instance of {@link IntermediateEncryptingTransport}. */ - private IntermediateEncryptingTransport create(Intent realTransportIntent) { - Log.d(TAG, "create: intent:" + realTransportIntent); - - LockPatternUtils patternUtils = new LockPatternUtils(mContext); - boolean shouldEncrypt = - realTransportIntent.getComponent().getClassName().contains("EncryptedLocalTransport") - && (patternUtils.isLockPatternEnabled(UserHandle.myUserId()) - || patternUtils.isLockPasswordEnabled(UserHandle.myUserId())); - - return new IntermediateEncryptingTransport( - mTransportClientManager.getTransportClient( - realTransportIntent.getComponent(), - realTransportIntent.getExtras(), - CALLER), - mContext, - shouldEncrypt); - } - - /** - * Cleanup the {@link IntermediateEncryptingTransport} which was created by a call to {@link - * #get(Intent)} with this {@link Intent}. - */ - public void cleanup(Intent intent) { - Intent transportIntent = TransportClientManager.getRealTransportIntent(intent); - Log.i(TAG, "cleanup: intent:" + intent + " transportIntent:" + transportIntent); - - IntermediateEncryptingTransport transport; - synchronized (mTransportsLock) { - transport = mTransports.remove(transportIntent.getComponent()); - } - if (transport != null) { - mTransportClientManager.disposeOfTransportClient(transport.getClient(), CALLER); - } else { - Log.i(TAG, "Could not find IntermediateEncryptingTransport"); - } - } -} 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 deleted file mode 100644 index 0d43a190cd074..0000000000000 --- a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportManagerTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 deleted file mode 100644 index a85b2e4498a6d..0000000000000 --- a/packages/BackupEncryption/test/unittest/src/com/android/server/backup/encryption/transport/IntermediateEncryptingTransportTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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.any; -import static org.mockito.ArgumentMatchers.anyString; -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.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -import android.app.backup.BackupTransport; -import android.content.Context; -import android.content.pm.PackageInfo; -import android.os.ParcelFileDescriptor; -import android.platform.test.annotations.Presubmit; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.backup.IBackupTransport; -import com.android.server.backup.encryption.KeyValueEncrypter; -import com.android.server.backup.transport.TransportClient; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.io.File; - -@Presubmit -@RunWith(AndroidJUnit4.class) -public class IntermediateEncryptingTransportTest { - private static final String TEST_PACKAGE_NAME = "test_package"; - - private IntermediateEncryptingTransport mIntermediateEncryptingTransport; - private final PackageInfo mTestPackage = new PackageInfo(); - - @Mock private IBackupTransport mRealTransport; - @Mock private TransportClient mTransportClient; - @Mock private ParcelFileDescriptor mParcelFileDescriptor; - @Mock private KeyValueEncrypter mKeyValueEncrypter; - @Mock private Context mContext; - - @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder(); - - private File mTempFile; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - - mIntermediateEncryptingTransport = - new IntermediateEncryptingTransport( - mTransportClient, mContext, mKeyValueEncrypter, true); - mTestPackage.packageName = TEST_PACKAGE_NAME; - mTempFile = mTemporaryFolder.newFile(); - - when(mTransportClient.connect(anyString())).thenReturn(mRealTransport); - when(mRealTransport.getRestoreData(any())).thenReturn(BackupTransport.TRANSPORT_OK); - } - - @Test - public void testGetDelegate_callsConnect() throws Exception { - 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); - } - - @Test - public void testPerformBackup_shouldEncryptTrue_encryptsDataAndPassesToDelegate() - throws Exception { - mIntermediateEncryptingTransport = - new TestIntermediateTransport(mTransportClient, mContext, mKeyValueEncrypter, true); - - mIntermediateEncryptingTransport.performBackup(mTestPackage, mParcelFileDescriptor, 0); - - verify(mKeyValueEncrypter, times(1)) - .encryptKeyValueData(eq(TEST_PACKAGE_NAME), eq(mParcelFileDescriptor), any()); - verify(mRealTransport, times(1)).performBackup(eq(mTestPackage), any(), eq(0)); - } - - @Test - public void testPerformBackup_shouldEncryptFalse_doesntEncryptDataAndPassedToDelegate() - throws Exception { - mIntermediateEncryptingTransport = - new TestIntermediateTransport( - mTransportClient, mContext, mKeyValueEncrypter, false); - - mIntermediateEncryptingTransport.performBackup(mTestPackage, mParcelFileDescriptor, 0); - - verifyZeroInteractions(mKeyValueEncrypter); - verify(mRealTransport, times(1)) - .performBackup(eq(mTestPackage), eq(mParcelFileDescriptor), eq(0)); - } - - @Test - public void testGetRestoreData_shouldEncryptTrue_decryptsDataAndPassesToDelegate() - throws Exception { - mIntermediateEncryptingTransport = - new TestIntermediateTransport(mTransportClient, mContext, mKeyValueEncrypter, true); - mIntermediateEncryptingTransport.setNextRestorePackage(TEST_PACKAGE_NAME); - - mIntermediateEncryptingTransport.getRestoreData(mParcelFileDescriptor); - - verify(mKeyValueEncrypter, times(1)) - .decryptKeyValueData(eq(TEST_PACKAGE_NAME), any(), eq(mParcelFileDescriptor)); - verify(mRealTransport, times(1)).getRestoreData(any()); - } - - @Test - public void testGetRestoreData_shouldEncryptFalse_doesntDecryptDataAndPassesToDelegate() - throws Exception { - mIntermediateEncryptingTransport = - new TestIntermediateTransport( - mTransportClient, mContext, mKeyValueEncrypter, false); - mIntermediateEncryptingTransport.setNextRestorePackage(TEST_PACKAGE_NAME); - - mIntermediateEncryptingTransport.getRestoreData(mParcelFileDescriptor); - - verifyZeroInteractions(mKeyValueEncrypter); - verify(mRealTransport, times(1)).getRestoreData(eq(mParcelFileDescriptor)); - } - - private final class TestIntermediateTransport extends IntermediateEncryptingTransport { - TestIntermediateTransport( - TransportClient transportClient, - Context context, - KeyValueEncrypter keyValueEncrypter, - boolean shouldEncrypt) { - super(transportClient, context, keyValueEncrypter, shouldEncrypt); - } - - @Override - protected File getBackupTempStorage(String packageName) { - return mTempFile; - } - - @Override - protected File getRestoreTempStorage(String packageName) { - return mTempFile; - } - } -} diff --git a/services/backup/backuplib/java/com/android/server/backup/transport/DelegatingTransport.java b/services/backup/backuplib/java/com/android/server/backup/transport/DelegatingTransport.java deleted file mode 100644 index ab870803e60dc..0000000000000 --- a/services/backup/backuplib/java/com/android/server/backup/transport/DelegatingTransport.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * 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.transport; - -import android.app.backup.BackupAgent; -import android.app.backup.BackupTransport; -import android.app.backup.RestoreDescription; -import android.app.backup.RestoreSet; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; - -import com.android.internal.backup.IBackupTransport; - -/** - * Delegates all transport methods to the delegate() implemented in the derived class. - */ -public abstract class DelegatingTransport extends IBackupTransport.Stub { - protected abstract IBackupTransport getDelegate() throws RemoteException; - - /** - * Ask the transport for the name under which it should be registered. This will - * typically be its host service's component name, but need not be. - */ - @Override - public String name() throws RemoteException { - return getDelegate().name(); - } - - /** - * Ask the transport for an Intent that can be used to launch any internal - * configuration Activity that it wishes to present. For example, the transport - * may offer a UI for allowing the user to supply login credentials for the - * transport's off-device backend. - * - * If the transport does not supply any user-facing configuration UI, it should - * return null from this method. - * - * @return An Intent that can be passed to Context.startActivity() in order to - * launch the transport's configuration UI. This method will return null - * if the transport does not offer any user-facing configuration UI. - */ - @Override - public Intent configurationIntent() throws RemoteException { - return getDelegate().configurationIntent(); - } - - /** - * On demand, supply a one-line string that can be shown to the user that - * describes the current backend destination. For example, a transport that - * can potentially associate backup data with arbitrary user accounts should - * include the name of the currently-active account here. - * - * @return A string describing the destination to which the transport is currently - * sending data. This method should not return null. - */ - @Override - public String currentDestinationString() throws RemoteException { - return getDelegate().currentDestinationString(); - } - - /** - * Ask the transport for an Intent that can be used to launch a more detailed - * secondary data management activity. For example, the configuration intent might - * be one for allowing the user to select which account they wish to associate - * their backups with, and the management intent might be one which presents a - * UI for managing the data on the backend. - * - *

In the Settings UI, the configuration intent will typically be invoked - * when the user taps on the preferences item labeled with the current - * destination string, and the management intent will be placed in an overflow - * menu labelled with the management label string. - * - *

If the transport does not supply any user-facing data management - * UI, then it should return {@code null} from this method. - * - * @return An intent that can be passed to Context.startActivity() in order to - * launch the transport's data-management UI. This method will return - * {@code null} if the transport does not offer any user-facing data - * management UI. - */ - @Override - public Intent dataManagementIntent() throws RemoteException { - return getDelegate().dataManagementIntent(); - } - - /** - * On demand, supply a short {@link CharSequence} that can be shown to the user as the - * label on - * an overflow menu item used to invoke the data management UI. - * - * @return A {@link CharSequence} to be used as the label for the transport's data management - * affordance. If the transport supplies a data management intent, this - * method must not return {@code null}. - */ - @Override - public CharSequence dataManagementIntentLabel() throws RemoteException { - return getDelegate().dataManagementIntentLabel(); - } - - /** - * Ask the transport where, on local device storage, to keep backup state blobs. - * This is per-transport so that mock transports used for testing can coexist with - * "live" backup services without interfering with the live bookkeeping. The - * returned string should be a name that is expected to be unambiguous among all - * available backup transports; the name of the class implementing the transport - * is a good choice. This MUST be constant. - * - * @return A unique name, suitable for use as a file or directory name, that the - * Backup Manager could use to disambiguate state files associated with - * different backup transports. - */ - @Override - public String transportDirName() throws RemoteException { - return getDelegate().transportDirName(); - } - - /** - * Verify that this is a suitable time for a backup pass. This should return zero - * if a backup is reasonable right now, some positive value otherwise. This method - * will be called outside of the {@link #startSession}/{@link #endSession} pair. - * - *

If this is not a suitable time for a backup, the transport should return a - * backoff delay, in milliseconds, after which the Backup Manager should try again. - * - * @return Zero if this is a suitable time for a backup pass, or a positive time delay - * in milliseconds to suggest deferring the backup pass for a while. - */ - @Override - public long requestBackupTime() throws RemoteException { - return getDelegate().requestBackupTime(); - } - - /** - * Initialize the server side storage for this device, erasing all stored data. - * The transport may send the request immediately, or may buffer it. After - * this is called, {@link #finishBackup} must be called to ensure the request - * is sent and received successfully. - * - * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far) or - * {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure). - */ - @Override - public int initializeDevice() throws RemoteException { - return getDelegate().initializeDevice(); - } - - /** - * Send one application's data to the backup destination. The transport may send - * the data immediately, or may buffer it. After this is called, {@link #finishBackup} - * must be called to ensure the data is sent and recorded successfully. - * - * @param packageInfo The identity of the application whose data is being backed up. - * This specifically includes the signature list for the package. - * @param inFd Descriptor of file with data that resulted from invoking the application's - * BackupService.doBackup() method. This may be a pipe rather than a file on - * persistent media, so it may not be seekable. - * @param flags Some of {@link BackupTransport#FLAG_USER_INITIATED}. - * @return one of {@link BackupConstants#TRANSPORT_OK} (OK so far), - * {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure), or - * {@link BackupConstants#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has - * become lost due to inactive expiry or some other reason and needs re-initializing) - */ - @Override - public int performBackup(PackageInfo packageInfo, - ParcelFileDescriptor inFd, int flags) throws RemoteException { - return getDelegate().performBackup(packageInfo, inFd, flags); - } - - /** - * Erase the give application's data from the backup destination. This clears - * out the given package's data from the current backup set, making it as though - * the app had never yet been backed up. After this is called, {@link finishBackup} - * must be called to ensure that the operation is recorded successfully. - * - * @return the same error codes as {@link #performBackup}. - * @param packageInfo - */ - @Override - public int clearBackupData(PackageInfo packageInfo) throws RemoteException { - return getDelegate().clearBackupData(packageInfo); - } - - /** - * Finish sending application data to the backup destination. This must be - * called after {@link #performBackup} or {@link clearBackupData} to ensure that - * all data is sent. Only when this method returns true can a backup be assumed - * to have succeeded. - * - * @return the same error codes as {@link #performBackup}. - */ - @Override - public int finishBackup() throws RemoteException { - return getDelegate().finishBackup(); - } - - /** - * Get the set of all backups currently available over this transport. - * - * @return Descriptions of the set of restore images available for this device, - * or null if an error occurred (the attempt should be rescheduled). - **/ - @Override - public RestoreSet[] getAvailableRestoreSets() throws RemoteException { - return getDelegate().getAvailableRestoreSets(); - } - - /** - * Get the identifying token of the backup set currently being stored from - * this device. This is used in the case of applications wishing to restore - * their last-known-good data. - * - * @return A token that can be passed to {@link #startRestore}, or 0 if there - * is no backup set available corresponding to the current device state. - */ - @Override - public long getCurrentRestoreSet() throws RemoteException { - return getDelegate().getCurrentRestoreSet(); - } - - /** - * Start restoring application data from backup. After calling this function, - * alternate calls to {@link #nextRestorePackage} and {@link #nextRestoreData} - * to walk through the actual application data. - * - * @param token A backup token as returned by {@link #getAvailableRestoreSets} - * or {@link #getCurrentRestoreSet}. - * @param packages List of applications to restore (if data is available). - * Application data will be restored in the order given. - * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call - * {@link #nextRestorePackage}) or {@link BackupConstants#TRANSPORT_ERROR} - * (an error occurred, the restore should be aborted and rescheduled). - */ - @Override - public int startRestore(long token, PackageInfo[] packages) throws RemoteException { - return getDelegate().startRestore(token, packages); - } - - /** - * Get the package name of the next application with data in the backup store, plus - * a description of the structure of the restored archive: either TYPE_KEY_VALUE for - * an original-API key/value dataset, or TYPE_FULL_STREAM for a tarball-type archive stream. - * - *

If the package name in the returned RestoreDescription object is the singleton - * {@link RestoreDescription#NO_MORE_PACKAGES}, it indicates that no further data is available - * in the current restore session: all packages described in startRestore() have been - * processed. - * - *

If this method returns {@code null}, it means that a transport-level error has - * occurred and the entire restore operation should be abandoned. - * - * @return A RestoreDescription object containing the name of one of the packages - * supplied to {@link #startRestore} plus an indicator of the data type of that - * restore data; or {@link RestoreDescription#NO_MORE_PACKAGES} to indicate that - * no more packages can be restored in this session; or {@code null} to indicate - * a transport-level error. - */ - @Override - public RestoreDescription nextRestorePackage() throws RemoteException { - return getDelegate().nextRestorePackage(); - } - - /** - * Get the data for the application returned by {@link #nextRestorePackage}. - * - * @param outFd An open, writable file into which the backup data should be stored. - * @return the same error codes as {@link #startRestore}. - */ - @Override - public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException { - return getDelegate().getRestoreData(outFd); - } - - /** - * End a restore session (aborting any in-process data transfer as necessary), - * freeing any resources and connections used during the restore process. - */ - @Override - public void finishRestore() throws RemoteException { - getDelegate().finishRestore(); - } - - @Override - public long requestFullBackupTime() throws RemoteException { - return getDelegate().requestFullBackupTime(); - } - - @Override - public int performFullBackup(PackageInfo targetPackage, - ParcelFileDescriptor socket, int flags) throws RemoteException { - return getDelegate().performFullBackup(targetPackage, socket, flags); - } - - @Override - public int checkFullBackupSize(long size) throws RemoteException { - return getDelegate().checkFullBackupSize(size); - } - - @Override - public int sendBackupData(int numBytes) throws RemoteException { - return getDelegate().sendBackupData(numBytes); - } - - @Override - public void cancelFullBackup() throws RemoteException { - getDelegate().cancelFullBackup(); - } - - /** - * Ask the transport whether this app is eligible for backup. - * - * @param targetPackage The identity of the application. - * @param isFullBackup If set, transport should check if app is eligible for full data backup, - * otherwise to check if eligible for key-value backup. - * @return Whether this app is eligible for backup. - */ - @Override - public boolean isAppEligibleForBackup(PackageInfo targetPackage, - boolean isFullBackup) throws RemoteException { - return getDelegate().isAppEligibleForBackup(targetPackage, isFullBackup); - } - - /** - * Ask the transport about current quota for backup size of the package. - * - * @param packageName ID of package to provide the quota. - * @param isFullBackup If set, transport should return limit for full data backup, otherwise - * for key-value backup. - * @return Current limit on full data backup size in bytes. - */ - @Override - public long getBackupQuota(String packageName, boolean isFullBackup) throws RemoteException { - return getDelegate().getBackupQuota(packageName, isFullBackup); - } - - /** - * Ask the transport to provide data for the "current" package being restored. This - * is the package that was just reported by {@link #nextRestorePackage()} as having - * {@link RestoreDescription#TYPE_FULL_STREAM} data. - * - * The transport writes some data to the socket supplied to this call, and returns - * the number of bytes written. The system will then read that many bytes and - * stream them to the application's agent for restore, then will call this method again - * to receive the next chunk of the archive. This sequence will be repeated until the - * transport returns zero indicating that all of the package's data has been delivered - * (or returns a negative value indicating some sort of hard error condition at the - * transport level). - * - *

After this method returns zero, the system will then call - * {@link #getNextFullRestorePackage()} to begin the restore process for the next - * application, and the sequence begins again. - * - *

The transport should always close this socket when returning from this method. - * Do not cache this socket across multiple calls or you may leak file descriptors. - * - * @param socket The file descriptor that the transport will use for delivering the - * streamed archive. The transport must close this socket in all cases when returning - * from this method. - * @return 0 when no more data for the current package is available. A positive value - * indicates the presence of that many bytes to be delivered to the app. Any negative - * return value is treated as equivalent to {@link BackupTransport#TRANSPORT_ERROR}, - * indicating a fatal error condition that precludes further restore operations - * on the current dataset. - */ - @Override - public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) throws RemoteException { - return getDelegate().getNextFullRestoreDataChunk(socket); - } - - /** - * If the OS encounters an error while processing {@link RestoreDescription#TYPE_FULL_STREAM} - * data for restore, it will invoke this method to tell the transport that it should - * abandon the data download for the current package. The OS will then either call - * {@link #nextRestorePackage()} again to move on to restoring the next package in the - * set being iterated over, or will call {@link #finishRestore()} to shut down the restore - * operation. - * - * @return {@link #TRANSPORT_OK} if the transport was successful in shutting down the - * current stream cleanly, or {@link #TRANSPORT_ERROR} to indicate a serious - * transport-level failure. If the transport reports an error here, the entire restore - * operation will immediately be finished with no further attempts to restore app data. - */ - @Override - public int abortFullRestore() throws RemoteException { - return getDelegate().abortFullRestore(); - } - - /** - * Returns flags with additional information about the transport, which is accessible to the - * {@link BackupAgent}. This allows the agent to decide what to backup or - * restore based on properties of the transport. - * - *

For supported flags see {@link BackupAgent}. - */ - @Override - public int getTransportFlags() throws RemoteException { - return getDelegate().getTransportFlags(); - } -} diff --git a/services/backup/backuplib/java/com/android/server/backup/transport/TransportClientManager.java b/services/backup/backuplib/java/com/android/server/backup/transport/TransportClientManager.java index 72b1ee741d955..f907e0855a3ea 100644 --- a/services/backup/backuplib/java/com/android/server/backup/transport/TransportClientManager.java +++ b/services/backup/backuplib/java/com/android/server/backup/transport/TransportClientManager.java @@ -41,12 +41,6 @@ import java.util.function.Function; */ public class TransportClientManager { private static final String TAG = "TransportClientManager"; - private static final String SERVICE_ACTION_ENCRYPTING_TRANSPORT = - "android.encryption.BACKUP_ENCRYPTION"; - private static final ComponentName ENCRYPTING_TRANSPORT = new ComponentName( - "com.android.server.backup.encryption", - "com.android.server.backup.encryption.BackupEncryptionService"); - private static final String ENCRYPTING_TRANSPORT_REAL_TRANSPORT_KEY = "transport"; private final @UserIdInt int mUserId; private final Context mContext; @@ -56,17 +50,6 @@ public class TransportClientManager { private Map mTransportClientsCallerMap = new WeakHashMap<>(); private final Function mIntentFunction; - /** - * Return an {@link Intent} which resolves to an intermediate {@link IBackupTransport} that - * encrypts (or decrypts) the data when sending it (or receiving it) from the {@link - * IBackupTransport} for the given {@link ComponentName}. - */ - public static Intent getEncryptingTransportIntent(ComponentName tranportComponent) { - return new Intent(SERVICE_ACTION_ENCRYPTING_TRANSPORT) - .setComponent(ENCRYPTING_TRANSPORT) - .putExtra(ENCRYPTING_TRANSPORT_REAL_TRANSPORT_KEY, tranportComponent); - } - /** * Return an {@link Intent} which resolves to the {@link IBackupTransport} for the {@link * ComponentName}. @@ -75,32 +58,6 @@ public class TransportClientManager { return new Intent(SERVICE_ACTION_TRANSPORT_HOST).setComponent(transportComponent); } - /** - * Given a {@link Intent} originally created by {@link - * #getEncryptingTransportIntent(ComponentName)}, returns the {@link Intent} which resolves to - * the {@link IBackupTransport} for that {@link ComponentName}. - */ - public static Intent getRealTransportIntent(Intent encryptingTransportIntent) { - ComponentName transportComponent = encryptingTransportIntent.getParcelableExtra( - ENCRYPTING_TRANSPORT_REAL_TRANSPORT_KEY); - Intent intent = getRealTransportIntent(transportComponent) - .putExtras(encryptingTransportIntent.getExtras()); - intent.removeExtra(ENCRYPTING_TRANSPORT_REAL_TRANSPORT_KEY); - return intent; - } - - /** - * Create a {@link TransportClientManager} such that {@link #getTransportClient(ComponentName, - * Bundle, String)} returns a {@link TransportClient} which connects to an intermediate {@link - * IBackupTransport} that encrypts (or decrypts) the data when sending it (or receiving it) from - * the {@link IBackupTransport} for the given {@link ComponentName}. - */ - public static TransportClientManager createEncryptingClientManager(@UserIdInt int userId, - Context context, TransportStats transportStats) { - return new TransportClientManager(userId, context, transportStats, - TransportClientManager::getEncryptingTransportIntent); - } - public TransportClientManager(@UserIdInt int userId, Context context, TransportStats transportStats) { this(userId, context, transportStats, TransportClientManager::getRealTransportIntent); diff --git a/services/tests/servicestests/src/com/android/server/backup/transport/DelegatingTransportTest.java b/services/tests/servicestests/src/com/android/server/backup/transport/DelegatingTransportTest.java deleted file mode 100644 index bae11eb86b323..0000000000000 --- a/services/tests/servicestests/src/com/android/server/backup/transport/DelegatingTransportTest.java +++ /dev/null @@ -1,386 +0,0 @@ -/* - * 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.transport; - -import static junit.framework.Assert.assertEquals; - -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.app.backup.RestoreDescription; -import android.app.backup.RestoreSet; -import android.content.Intent; -import android.content.pm.PackageInfo; -import android.os.ParcelFileDescriptor; -import android.os.RemoteException; -import android.platform.test.annotations.Presubmit; - -import androidx.test.runner.AndroidJUnit4; - -import com.android.internal.backup.IBackupTransport; - -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 DelegatingTransportTest { - @Mock private IBackupTransport mBackupTransport; - @Mock private PackageInfo mPackageInfo; - @Mock private ParcelFileDescriptor mFd; - - private final String mPackageName = "testpackage"; - private final RestoreSet mRestoreSet = new RestoreSet(); - private final int mFlags = 1; - private final long mRestoreToken = 10; - private final long mSize = 100; - private final int mNumBytes = 1000; - private DelegatingTransport mDelegatingTransport; - - @Before - public void setUp() throws Exception { - MockitoAnnotations.initMocks(this); - mDelegatingTransport = new DelegatingTransport() { - @Override - protected IBackupTransport getDelegate() { - return mBackupTransport; - } - }; - } - - @Test - public void testName() throws RemoteException { - String exp = "dummy"; - when(mBackupTransport.name()).thenReturn(exp); - - String ret = mDelegatingTransport.name(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).name(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testConfigurationIntent() throws RemoteException { - Intent exp = new Intent("dummy"); - when(mBackupTransport.configurationIntent()).thenReturn(exp); - - Intent ret = mDelegatingTransport.configurationIntent(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).configurationIntent(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testCurrentDestinationString() throws RemoteException { - String exp = "dummy"; - when(mBackupTransport.currentDestinationString()).thenReturn(exp); - - String ret = mDelegatingTransport.currentDestinationString(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).currentDestinationString(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testDataManagementIntent() throws RemoteException { - Intent exp = new Intent("dummy"); - when(mBackupTransport.dataManagementIntent()).thenReturn(exp); - - Intent ret = mDelegatingTransport.dataManagementIntent(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).dataManagementIntent(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testDataManagementIntentLabel() throws RemoteException { - String exp = "dummy"; - when(mBackupTransport.dataManagementIntentLabel()).thenReturn(exp); - - CharSequence ret = mDelegatingTransport.dataManagementIntentLabel(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).dataManagementIntentLabel(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testTransportDirName() throws RemoteException { - String exp = "dummy"; - when(mBackupTransport.transportDirName()).thenReturn(exp); - - String ret = mDelegatingTransport.transportDirName(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).transportDirName(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testRequestBackupTime() throws RemoteException { - long exp = 1000L; - when(mBackupTransport.requestBackupTime()).thenReturn(exp); - - long ret = mDelegatingTransport.requestBackupTime(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).requestBackupTime(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testInitializeDevice() throws RemoteException { - int exp = 1000; - when(mBackupTransport.initializeDevice()).thenReturn(exp); - - long ret = mDelegatingTransport.initializeDevice(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).initializeDevice(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testPerformBackup() throws RemoteException { - int exp = 1000; - when(mBackupTransport.performBackup(mPackageInfo, mFd, mFlags)).thenReturn(exp); - - int ret = mDelegatingTransport.performBackup(mPackageInfo, mFd, mFlags); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).performBackup(mPackageInfo, mFd, mFlags); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testClearBackupData() throws RemoteException { - int exp = 1000; - when(mBackupTransport.clearBackupData(mPackageInfo)).thenReturn(exp); - - int ret = mDelegatingTransport.clearBackupData(mPackageInfo); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).clearBackupData(mPackageInfo); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testFinishBackup() throws RemoteException { - int exp = 1000; - when(mBackupTransport.finishBackup()).thenReturn(exp); - - int ret = mDelegatingTransport.finishBackup(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).finishBackup(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testGetAvailableRestoreSets() throws RemoteException { - RestoreSet[] exp = new RestoreSet[] {mRestoreSet}; - when(mBackupTransport.getAvailableRestoreSets()).thenReturn(exp); - - RestoreSet[] ret = mDelegatingTransport.getAvailableRestoreSets(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).getAvailableRestoreSets(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testGetCurrentRestoreSet() throws RemoteException { - long exp = 1000; - when(mBackupTransport.getCurrentRestoreSet()).thenReturn(exp); - - long ret = mDelegatingTransport.getCurrentRestoreSet(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).getCurrentRestoreSet(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testStartRestore() throws RemoteException { - int exp = 1000; - PackageInfo[] packageInfos = {mPackageInfo}; - when(mBackupTransport.startRestore(mRestoreToken, packageInfos)).thenReturn(exp); - - int ret = mDelegatingTransport.startRestore(mRestoreToken, packageInfos); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).startRestore(mRestoreToken, packageInfos); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testNextRestorePackage() throws RemoteException { - RestoreDescription exp = new RestoreDescription(mPackageName, 1); - when(mBackupTransport.nextRestorePackage()).thenReturn(exp); - - RestoreDescription ret = mDelegatingTransport.nextRestorePackage(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).nextRestorePackage(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testGetRestoreData() throws RemoteException { - int exp = 1000; - when(mBackupTransport.getRestoreData(mFd)).thenReturn(exp); - - int ret = mDelegatingTransport.getRestoreData(mFd); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).getRestoreData(mFd); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void tesFinishRestore() throws RemoteException { - mDelegatingTransport.finishRestore(); - - verify(mBackupTransport, times(1)).finishRestore(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testRequestFullBackupTime() throws RemoteException { - long exp = 1000L; - when(mBackupTransport.requestFullBackupTime()).thenReturn(exp); - - long ret = mDelegatingTransport.requestFullBackupTime(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).requestFullBackupTime(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testPerformFullBackup() throws RemoteException { - int exp = 1000; - when(mBackupTransport.performFullBackup(mPackageInfo, mFd, mFlags)).thenReturn(exp); - - int ret = mDelegatingTransport.performFullBackup(mPackageInfo, mFd, mFlags); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).performFullBackup(mPackageInfo, mFd, mFlags); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testCheckFullBackupSize() throws RemoteException { - int exp = 1000; - when(mBackupTransport.checkFullBackupSize(mSize)).thenReturn(exp); - - int ret = mDelegatingTransport.checkFullBackupSize(mSize); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).checkFullBackupSize(mSize); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testSendBackupData() throws RemoteException { - int exp = 1000; - when(mBackupTransport.sendBackupData(mNumBytes)).thenReturn(exp); - - int ret = mDelegatingTransport.sendBackupData(mNumBytes); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).sendBackupData(mNumBytes); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testCancelFullBackup() throws RemoteException { - mDelegatingTransport.cancelFullBackup(); - - verify(mBackupTransport, times(1)).cancelFullBackup(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testIsAppEligibleForBackup() throws RemoteException { - boolean exp = true; - when(mBackupTransport.isAppEligibleForBackup(mPackageInfo, true)).thenReturn(exp); - - boolean ret = mDelegatingTransport.isAppEligibleForBackup(mPackageInfo, true); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).isAppEligibleForBackup(mPackageInfo, true); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testGetBackupQuota() throws RemoteException { - long exp = 1000; - when(mBackupTransport.getBackupQuota(mPackageName, true)).thenReturn(exp); - - long ret = mDelegatingTransport.getBackupQuota(mPackageName, true); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).getBackupQuota(mPackageName, true); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testGetNextFullRestoreDataChunk() throws RemoteException { - int exp = 1000; - when(mBackupTransport.getNextFullRestoreDataChunk(mFd)).thenReturn(exp); - - int ret = mDelegatingTransport.getNextFullRestoreDataChunk(mFd); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).getNextFullRestoreDataChunk(mFd); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testAbortFullRestore() throws RemoteException { - int exp = 1000; - when(mBackupTransport.abortFullRestore()).thenReturn(exp); - - int ret = mDelegatingTransport.abortFullRestore(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).abortFullRestore(); - verifyNoMoreInteractions(mBackupTransport); - } - - @Test - public void testGetTransportFlags() throws RemoteException { - int exp = 1000; - when(mBackupTransport.getTransportFlags()).thenReturn(exp); - - int ret = mDelegatingTransport.getTransportFlags(); - - assertEquals(exp, ret); - verify(mBackupTransport, times(1)).getTransportFlags(); - verifyNoMoreInteractions(mBackupTransport); - } -}