From 98b17a6146ccbf6f8f122d489d09fa40b6f42067 Mon Sep 17 00:00:00 2001 From: Bernardo Rufino Date: Wed, 9 May 2018 09:25:35 +0100 Subject: [PATCH] Add getCurrentTransportComponent() API Bug: 73640944 Test: atest RunFrameworksServicesRoboTests Change-Id: I62193d63367c3b7564ccd41f5b103a7076764e3f --- api/system-current.txt | 1 + .../android/app/backup/BackupManager.java | 21 ++++++++ .../android/app/backup/IBackupManager.aidl | 12 +++-- .../server/backup/BackupManagerService.java | 19 +++++++ .../backup/BackupManagerServiceInterface.java | 5 ++ .../com/android/server/backup/Trampoline.java | 13 ++++- .../server/backup/TransportManager.java | 28 ++++++++++ .../backup/BackupManagerServiceTest.java | 52 +++++++++++++++++-- .../server/backup/TransportManagerTest.java | 37 +++++++++++-- .../backup/testing/TransportTestUtils.java | 3 ++ 10 files changed, 177 insertions(+), 14 deletions(-) diff --git a/api/system-current.txt b/api/system-current.txt index 1322a39495a32..242e6f2698610 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -484,6 +484,7 @@ package android.app.backup { method public long getAvailableRestoreToken(java.lang.String); method public android.content.Intent getConfigurationIntent(java.lang.String); method public java.lang.String getCurrentTransport(); + method public android.content.ComponentName getCurrentTransportComponent(); method public android.content.Intent getDataManagementIntent(java.lang.String); method public java.lang.String getDataManagementLabel(java.lang.String); method public java.lang.String getDestinationString(java.lang.String); diff --git a/core/java/android/app/backup/BackupManager.java b/core/java/android/app/backup/BackupManager.java index debc32bd83eb1..8e923933d1935 100644 --- a/core/java/android/app/backup/BackupManager.java +++ b/core/java/android/app/backup/BackupManager.java @@ -442,6 +442,27 @@ public class BackupManager { return null; } + /** + * Returns the {@link ComponentName} of the host service of the selected transport or {@code + * null} if no transport selected or if the transport selected is not registered. + * + * @hide + */ + @SystemApi + @RequiresPermission(android.Manifest.permission.BACKUP) + @Nullable + public ComponentName getCurrentTransportComponent() { + checkServiceBinder(); + if (sService != null) { + try { + return sService.getCurrentTransportComponent(); + } catch (RemoteException e) { + Log.e(TAG, "getCurrentTransportComponent() couldn't connect"); + } + } + return null; + } + /** * Request a list of all available backup transports' names. * diff --git a/core/java/android/app/backup/IBackupManager.aidl b/core/java/android/app/backup/IBackupManager.aidl index f3ca74656e8ca..1c55d8add45bf 100644 --- a/core/java/android/app/backup/IBackupManager.aidl +++ b/core/java/android/app/backup/IBackupManager.aidl @@ -244,8 +244,6 @@ interface IBackupManager { * {@code null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}. * @throws SecurityException If the UID of the calling process differs from the package UID of * {@code transportComponent} or if the caller does NOT have BACKUP permission. - * - * @hide */ void updateTransportAttributes(in ComponentName transportComponent, in String name, in Intent configurationIntent, in String currentDestinationString, @@ -257,6 +255,13 @@ interface IBackupManager { */ String getCurrentTransport(); + /** + * Returns the {@link ComponentName} of the host service of the selected transport or {@code + * null} if no transport selected or if the transport selected is not registered. Callers must + * hold the android.permission.BACKUP permission to use this method. + */ + ComponentName getCurrentTransportComponent(); + /** * Request a list of all available backup transports' names. Callers must * hold the android.permission.BACKUP permission to use this method. @@ -296,8 +301,6 @@ interface IBackupManager { * the transport's name that is returned by {@link BackupTransport#name()}. * @param listener A listener object to get a callback on the transport being selected. It may * be {@code null}. - * - * @hide */ void selectBackupTransportAsync(in ComponentName transport, ISelectBackupTransportCallback listener); @@ -364,7 +367,6 @@ interface IBackupManager { * @param result In the case of a full backup measure operation, the estimated * total file size that would result from the operation. Unused in all other * cases. - * {@hide} */ void opComplete(int token, long result); diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index bd51af270dd86..d7db4717acdcf 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -2901,6 +2901,25 @@ public class BackupManagerService implements BackupManagerServiceInterface { return currentTransport; } + /** + * Returns the {@link ComponentName} of the host service of the selected transport or {@code + * null} if no transport selected or if the transport selected is not registered. + */ + @Override + @Nullable + public ComponentName getCurrentTransportComponent() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.BACKUP, "getCurrentTransportComponent"); + long oldId = Binder.clearCallingIdentity(); + try { + return mTransportManager.getCurrentTransportComponent(); + } catch (TransportNotRegisteredException e) { + return null; + } finally { + Binder.restoreCallingIdentity(oldId); + } + } + // Report all known, available backup transports @Override public String[] listAllTransports() { diff --git a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java index aabe7f6118455..f2219a0187655 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java +++ b/services/backup/java/com/android/server/backup/BackupManagerServiceInterface.java @@ -16,6 +16,7 @@ package com.android.server.backup; +import android.annotation.Nullable; import android.app.IBackupAgent; import android.app.backup.IBackupManager; import android.app.backup.IBackupManagerMonitor; @@ -132,6 +133,10 @@ public interface BackupManagerServiceInterface { // Report the name of the currently active transport String getCurrentTransport(); + // Report the component name of the host service of the currently active transport + @Nullable + ComponentName getCurrentTransportComponent(); + // Report all known, available backup transports String[] listAllTransports(); diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java index 2abeaa693becc..787d667afe51e 100644 --- a/services/backup/java/com/android/server/backup/Trampoline.java +++ b/services/backup/java/com/android/server/backup/Trampoline.java @@ -19,8 +19,8 @@ package com.android.server.backup; import android.annotation.Nullable; import android.app.backup.BackupManager; import android.app.backup.IBackupManager; -import android.app.backup.IBackupObserver; import android.app.backup.IBackupManagerMonitor; +import android.app.backup.IBackupObserver; import android.app.backup.IFullBackupRestoreObserver; import android.app.backup.IRestoreSession; import android.app.backup.ISelectBackupTransportCallback; @@ -341,6 +341,17 @@ public class Trampoline extends IBackupManager.Stub { return (svc != null) ? svc.getCurrentTransport() : null; } + /** + * Returns the {@link ComponentName} of the host service of the selected transport or + * {@code null} if no transport selected or if the transport selected is not registered. + */ + @Override + @Nullable + public ComponentName getCurrentTransportComponent() { + BackupManagerServiceInterface svc = mService; + return (svc != null) ? svc.getCurrentTransportComponent() : null; + } + @Override public String[] listAllTransports() throws RemoteException { BackupManagerServiceInterface svc = mService; diff --git a/services/backup/java/com/android/server/backup/TransportManager.java b/services/backup/java/com/android/server/backup/TransportManager.java index 64e24d819c275..ddce6bbfd47d2 100644 --- a/services/backup/java/com/android/server/backup/TransportManager.java +++ b/services/backup/java/com/android/server/backup/TransportManager.java @@ -176,11 +176,29 @@ public class TransportManager { return mTransportWhitelist; } + /** Returns the name of the selected transport or {@code null} if no transport selected. */ @Nullable public String getCurrentTransportName() { return mCurrentTransportName; } + /** + * Returns the {@link ComponentName} of the host service of the selected transport or + * {@code null} if no transport selected. + * + * @throws TransportNotRegisteredException if the selected transport is not registered. + */ + @Nullable + public ComponentName getCurrentTransportComponent() + throws TransportNotRegisteredException { + synchronized (mTransportLock) { + if (mCurrentTransportName == null) { + return null; + } + return getRegisteredTransportComponentOrThrowLocked(mCurrentTransportName); + } + } + /** * Returns the transport name associated with {@code transportComponent}. * @@ -324,6 +342,16 @@ public class TransportManager { } } + @GuardedBy("mTransportLock") + private ComponentName getRegisteredTransportComponentOrThrowLocked(String transportName) + throws TransportNotRegisteredException { + ComponentName transportComponent = getRegisteredTransportComponentLocked(transportName); + if (transportComponent == null) { + throw new TransportNotRegisteredException(transportName); + } + return transportComponent; + } + @GuardedBy("mTransportLock") private TransportDescription getRegisteredTransportDescriptionOrThrowLocked( ComponentName transportComponent) throws TransportNotRegisteredException { diff --git a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java index 340100f955843..8399aaf26927d 100644 --- a/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java +++ b/services/robotests/src/com/android/server/backup/BackupManagerServiceTest.java @@ -76,10 +76,9 @@ import java.util.List; @RunWith(FrameworkRobolectricTestRunner.class) @Config( - manifest = Config.NONE, - sdk = 26, - shadows = {ShadowAppBackupUtils.class, ShadowBackupPolicyEnforcer.class} -) + manifest = Config.NONE, + sdk = 26, + shadows = {ShadowAppBackupUtils.class, ShadowBackupPolicyEnforcer.class}) @SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class BackupManagerServiceTest { @@ -406,6 +405,51 @@ public class BackupManagerServiceTest { mContext.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT); } + /* Tests for transport attributes */ + + @Test + public void testGetCurrentTransportComponent() throws Exception { + mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); + when(mTransportManager.getCurrentTransportComponent()) + .thenReturn(mTransport.getTransportComponent()); + BackupManagerService backupManagerService = createInitializedBackupManagerService(); + + ComponentName transportComponent = backupManagerService.getCurrentTransportComponent(); + + assertThat(transportComponent).isEqualTo(mTransport.getTransportComponent()); + } + + @Test + public void testGetCurrentTransportComponent_whenNoTransportSelected() throws Exception { + mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); + when(mTransportManager.getCurrentTransportComponent()).thenReturn(null); + BackupManagerService backupManagerService = createInitializedBackupManagerService(); + + ComponentName transportComponent = backupManagerService.getCurrentTransportComponent(); + + assertThat(transportComponent).isNull(); + } + + @Test + public void testGetCurrentTransportComponent_whenTransportNotRegistered() throws Exception { + mShadowContext.grantPermissions(android.Manifest.permission.BACKUP); + when(mTransportManager.getCurrentTransportComponent()) + .thenThrow(TransportNotRegisteredException.class); + BackupManagerService backupManagerService = createInitializedBackupManagerService(); + + ComponentName transportComponent = backupManagerService.getCurrentTransportComponent(); + + assertThat(transportComponent).isNull(); + } + + @Test + public void testGetCurrentTransportComponent_withoutPermission() throws Exception { + mShadowContext.denyPermissions(android.Manifest.permission.BACKUP); + BackupManagerService backupManagerService = createInitializedBackupManagerService(); + + expectThrows(SecurityException.class, backupManagerService::getCurrentTransportComponent); + } + /* Tests for updating transport attributes */ private static final int PACKAGE_UID = 10; diff --git a/services/robotests/src/com/android/server/backup/TransportManagerTest.java b/services/robotests/src/com/android/server/backup/TransportManagerTest.java index c2e7595640f47..051a4a037816f 100644 --- a/services/robotests/src/com/android/server/backup/TransportManagerTest.java +++ b/services/robotests/src/com/android/server/backup/TransportManagerTest.java @@ -77,10 +77,9 @@ import java.util.stream.Stream; @RunWith(FrameworkRobolectricTestRunner.class) @Config( - manifest = Config.NONE, - sdk = 26, - shadows = {FrameworkShadowContextImpl.class} -) + manifest = Config.NONE, + sdk = 26, + shadows = {FrameworkShadowContextImpl.class}) @SystemLoaderPackages({"com.android.server.backup"}) @Presubmit public class TransportManagerTest { @@ -393,6 +392,36 @@ public class TransportManagerTest { assertThat(transport2).isEqualTo(mTransportA1.transportName); } + @Test + public void testGetCurrentTransportComponent() throws Exception { + TransportManager transportManager = + createTransportManagerWithRegisteredTransports(mTransportA1); + + ComponentName transportComponent = transportManager.getCurrentTransportComponent(); + + assertThat(transportComponent).isEqualTo(mTransportA1.getTransportComponent()); + } + + @Test + public void testGetCurrentTransportComponent_whenNoTransportSelected() throws Exception { + TransportManager transportManager = + createTransportManagerWithRegisteredTransports(null, mTransportA1); + + ComponentName transportComponent = transportManager.getCurrentTransportComponent(); + + assertThat(transportComponent).isNull(); + } + + @Test + public void testGetCurrentTransportComponent_whenTransportNotRegistered() throws Exception { + TransportManager transportManager = + createTransportManagerWithRegisteredTransports(mTransportA1.unregistered()); + + expectThrows( + TransportNotRegisteredException.class, + transportManager::getCurrentTransportComponent); + } + @Test public void testGetTransportClient_forRegisteredTransport() throws Exception { TransportManager transportManager = diff --git a/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java index 1fbadd4a7eb49..584413157dac4 100644 --- a/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java +++ b/services/robotests/src/com/android/server/backup/testing/TransportTestUtils.java @@ -55,6 +55,9 @@ public class TransportTestUtils { ShadowPackageManager shadowPackageManager, TransportData... transports) throws Exception { for (TransportData transport : transports) { + if (transport.transportStatus == TransportStatus.UNREGISTERED) { + continue; + } ComponentName transportComponent = transport.getTransportComponent(); String packageName = transportComponent.getPackageName(); ResolveInfo resolveInfo = resolveInfo(transportComponent);