Add remaining tests for Trampoline.

Also a bit of refactoring on TrampolineTestable and enable it for
presubmits.

Bug: 37520021
Test: manually ran the unit test.
Change-Id: I20214b70d3eb35017d50983bd8bebef93b66e839
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index a4363cb..0fd0ea5 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -76,28 +76,45 @@
     volatile BackupManagerServiceInterface mService;
 
     public Trampoline(Context context) {
-        this(context,
-                SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false),
-                new File(new File(Environment.getDataDirectory(), "backup"),
-                        BACKUP_SUPPRESS_FILENAME));
-    }
-
-    protected Trampoline(Context context, boolean globalDisable, File suppressFile) {
         mContext = context;
-        mGlobalDisable = globalDisable;
-        mSuppressFile = suppressFile;
+        mGlobalDisable = isBackupDisabled();
+        mSuppressFile = getSuppressFile();
         mSuppressFile.getParentFile().mkdirs();
     }
 
     protected BackupManagerServiceInterface createService() {
-        boolean refactoredServiceEnabled = Settings.Global.getInt(mContext.getContentResolver(),
-            Settings.Global.BACKUP_REFACTORED_SERVICE_DISABLED, 1) == 0;
-        if (refactoredServiceEnabled) {
+        if (isRefactoredServiceEnabled()) {
             Slog.i(TAG, "Instantiating RefactoredBackupManagerService");
-            return new RefactoredBackupManagerService(mContext, this);
+            return createRefactoredBackupManagerService();
         }
 
         Slog.i(TAG, "Instantiating BackupManagerService");
+        return createBackupManagerService();
+    }
+
+    protected boolean isBackupDisabled() {
+        return SystemProperties.getBoolean(BACKUP_DISABLE_PROPERTY, false);
+    }
+
+    protected boolean isRefactoredServiceEnabled() {
+        return Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.BACKUP_REFACTORED_SERVICE_DISABLED, 1) == 0;
+    }
+
+    protected int binderGetCallingUid() {
+        return Binder.getCallingUid();
+    }
+
+    protected File getSuppressFile() {
+        return new File(new File(Environment.getDataDirectory(), "backup"),
+                BACKUP_SUPPRESS_FILENAME);
+    }
+
+    protected BackupManagerServiceInterface createRefactoredBackupManagerService() {
+        return new RefactoredBackupManagerService(mContext, this);
+    }
+
+    protected BackupManagerServiceInterface createBackupManagerService() {
         return new BackupManagerService(mContext, this);
     }
 
@@ -124,7 +141,7 @@
 
     public void setBackupServiceActive(final int userHandle, boolean makeActive) {
         // Only the DPM should be changing the active state of backup
-        final int caller = Binder.getCallingUid();
+        final int caller = binderGetCallingUid();
         if (caller != Process.SYSTEM_UID
                 && caller != Process.ROOT_UID) {
             throw new SecurityException("No permission to configure backup activity");
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index ddbbcd6..1896cda 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -20,12 +20,13 @@
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
 
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.Mockito.when;
 
-import android.app.Instrumentation;
 import android.app.backup.BackupManager;
 import android.app.backup.IBackupManagerMonitor;
 import android.app.backup.IBackupObserver;
@@ -33,25 +34,29 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.IBinder;
 import android.os.ParcelFileDescriptor;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.support.test.InstrumentationRegistry;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.SmallTest;
 import android.support.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.PrintWriter;
 
-// TODO: Tests for createService().
-// TODO: Tests for setBackupServiceActive().
-// TODO: Tests for dump().
+@SmallTest
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class TrampolineTest {
     private static final String PACKAGE_NAME = "some.package.name";
@@ -71,16 +76,21 @@
             new ComponentName("package1", "class1"),
             new ComponentName("package2", "class2")
     };
+    private final int NON_USER_SYSTEM = UserHandle.USER_SYSTEM + 1;
 
-    @Mock private BackupManagerServiceInterface mBackupManagerServiceMock;
+    @Mock private BackupManagerService mBackupManagerServiceMock;
+    @Mock private RefactoredBackupManagerService mRefactoredBackupManagerServiceMock;
     @Mock private Context mContextMock;
     @Mock private File mSuppressFileMock;
     @Mock private File mSuppressFileParentMock;
     @Mock private IBinder mAgentMock;
-    @Mock private ParcelFileDescriptor mFileDescriptorMock;
+    @Mock private ParcelFileDescriptor mParcelFileDescriptorMock;
     @Mock private IFullBackupRestoreObserver mFullBackupRestoreObserverMock;
     @Mock private IBackupObserver mBackupObserverMock;
     @Mock private IBackupManagerMonitor mBackupManagerMonitorMock;
+    @Mock private PrintWriter mPrintWriterMock;
+
+    private FileDescriptor mFileDescriptorStub = new FileDescriptor();
 
     private TrampolineTestable mTrampoline;
 
@@ -88,14 +98,21 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        mTrampoline = new TrampolineTestable(mContextMock);
+        TrampolineTestable.sRefactoredBackupManagerServiceMock =
+                mRefactoredBackupManagerServiceMock;
+        TrampolineTestable.sBackupManagerServiceMock = mBackupManagerServiceMock;
+        TrampolineTestable.sSuppressFile = mSuppressFileMock;
+        TrampolineTestable.sCallingUid = Process.SYSTEM_UID;
+        TrampolineTestable.sRefactoredServiceEnabled = false;
+        TrampolineTestable.sBackupDisabled = false;
 
         when(mSuppressFileMock.getParentFile()).thenReturn(mSuppressFileParentMock);
+
+        mTrampoline = new TrampolineTestable(mContextMock);
     }
 
     @Test
     public void constructor_createsSuppressFileDirectory() {
-        new TrampolineTestable(mContextMock, false, mSuppressFileMock);
         verify(mSuppressFileParentMock).mkdirs();
     }
 
@@ -110,16 +127,16 @@
     // other user trying to initialize it leaves it non-active.
     @Test
     public void initialize_forNonUserSystem_nonInitialized() {
-        int nonUserSystem = UserHandle.USER_SYSTEM + 1;
-        mTrampoline.initialize(nonUserSystem);
+        mTrampoline.initialize(NON_USER_SYSTEM);
 
-        assertFalse(mTrampoline.isBackupServiceActive(nonUserSystem));
+        assertFalse(mTrampoline.isBackupServiceActive(NON_USER_SYSTEM));
     }
 
     @Test
     public void initialize_globallyDisabled_nonInitialized() {
-        TrampolineTestable trampoline = new TrampolineTestable(mContextMock,
-                true /* globalDisable */, mSuppressFileMock);
+        TrampolineTestable.sBackupDisabled = true;
+
+        TrampolineTestable trampoline = new TrampolineTestable(mContextMock);
         trampoline.initialize(UserHandle.USER_SYSTEM);
 
         assertFalse(trampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
@@ -130,8 +147,7 @@
     public void initialize_suppressFileExists_nonInitialized() {
         when(mSuppressFileMock.exists()).thenReturn(true);
 
-        TrampolineTestable trampoline = new TrampolineTestable(mContextMock,
-                false /* globalDisable */, mSuppressFileMock);
+        TrampolineTestable trampoline = new TrampolineTestable(mContextMock);
         trampoline.initialize(UserHandle.USER_SYSTEM);
 
         assertFalse(trampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
@@ -143,6 +159,122 @@
     }
 
     @Test
+    public void createService_refactoredServiceEnabled() {
+        TrampolineTestable.sRefactoredServiceEnabled = true;
+
+        assertEquals(mRefactoredBackupManagerServiceMock, mTrampoline.createService());
+    }
+
+    @Test
+    public void createService_refactoredServiceDisabled() {
+        TrampolineTestable.sRefactoredServiceEnabled = false;
+
+        assertEquals(mBackupManagerServiceMock, mTrampoline.createService());
+    }
+
+    @Test
+    public void setBackupServiceActive_callerSystemUid_serviceCreated() {
+        TrampolineTestable.sCallingUid = Process.SYSTEM_UID;
+
+        mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+
+        assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+    }
+
+    @Test
+    public void setBackupServiceActive_callerRootUid_serviceCreated() {
+        TrampolineTestable.sCallingUid = Process.ROOT_UID;
+
+        mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+
+        assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+    }
+
+    @Test
+    public void setBackupServiceActive_callerNonRootNonSystem_securityExceptionThrown() {
+        TrampolineTestable.sCallingUid = Process.FIRST_APPLICATION_UID;
+
+        try {
+            mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+            fail();
+        } catch (SecurityException expected) {
+        }
+
+        assertFalse(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+    }
+
+    @Test
+    public void setBackupServiceActive_backupDisabled_ignored() {
+        TrampolineTestable.sBackupDisabled = true;
+        TrampolineTestable trampoline = new TrampolineTestable(mContextMock);
+
+        trampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+
+        assertFalse(trampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+    }
+
+    @Test
+    public void setBackupServiceActive_nonUserSystem_ignored() {
+        mTrampoline.setBackupServiceActive(NON_USER_SYSTEM, true);
+
+        assertFalse(mTrampoline.isBackupServiceActive(NON_USER_SYSTEM));
+    }
+
+    @Test
+    public void setBackupServiceActive_alreadyActive_ignored() {
+        mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+        assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+        assertEquals(1, mTrampoline.getCreateServiceCallsCount());
+
+        mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+        assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+        assertEquals(1, mTrampoline.getCreateServiceCallsCount());
+    }
+
+    @Test
+    public void setBackupServiceActive_makeActive_serviceCreatedAndSuppressFileDeleted() {
+        mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, true);
+
+        assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+        verify(mSuppressFileMock).delete();
+    }
+
+    @Test
+    public void setBackupServiceActive_makeNonActive_serviceDeletedAndSuppressFileCreated()
+            throws IOException {
+        mTrampoline.initialize(UserHandle.USER_SYSTEM);
+        assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+
+        mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
+
+        assertFalse(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+        verify(mSuppressFileMock).createNewFile();
+    }
+
+    @Test
+    public void
+    setBackupServiceActive_makeNonActive_serviceDeletedAndSuppressFileCreated_ioExceptionHandled()
+            throws IOException {
+        when(mSuppressFileMock.createNewFile()).thenThrow(new IOException());
+        mTrampoline.initialize(UserHandle.USER_SYSTEM);
+        assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+
+        mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
+
+        assertFalse(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+        verify(mSuppressFileMock).createNewFile();
+    }
+
+    @Test
+    public void setBackupServiceActive_makeNonActive_alreadyNonActive_ignored() throws IOException {
+        reset(mSuppressFileMock);
+
+        mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
+
+        verifyNoMoreInteractions(mSuppressFileMock);
+    }
+
+    @Test
     public void dataChanged_calledBeforeInitialize_ignored() throws RemoteException {
         mTrampoline.dataChanged(PACKAGE_NAME);
         verifyNoMoreInteractions(mBackupManagerServiceMock);
@@ -300,7 +432,8 @@
 
     @Test
     public void adbBackup_calledBeforeInitialize_ignored() throws RemoteException {
-        mTrampoline.adbBackup(mFileDescriptorMock, true, true, true, true, true, true, true, true,
+        mTrampoline.adbBackup(mParcelFileDescriptorMock, true, true, true, true, true, true, true,
+                true,
                 PACKAGE_NAMES);
         verifyNoMoreInteractions(mBackupManagerServiceMock);
     }
@@ -308,9 +441,11 @@
     @Test
     public void adbBackup_forwarded() throws RemoteException {
         mTrampoline.initialize(UserHandle.USER_SYSTEM);
-        mTrampoline.adbBackup(mFileDescriptorMock, true, true, true, true, true, true, true, true,
+        mTrampoline.adbBackup(mParcelFileDescriptorMock, true, true, true, true, true, true, true,
+                true,
                 PACKAGE_NAMES);
-        verify(mBackupManagerServiceMock).adbBackup(mFileDescriptorMock, true, true, true, true,
+        verify(mBackupManagerServiceMock).adbBackup(mParcelFileDescriptorMock, true, true, true,
+                true,
                 true, true, true, true, PACKAGE_NAMES);
     }
 
@@ -329,15 +464,15 @@
 
     @Test
     public void adbRestore_calledBeforeInitialize_ignored() throws RemoteException {
-        mTrampoline.adbRestore(mFileDescriptorMock);
+        mTrampoline.adbRestore(mParcelFileDescriptorMock);
         verifyNoMoreInteractions(mBackupManagerServiceMock);
     }
 
     @Test
     public void adbRestore_forwarded() throws RemoteException {
         mTrampoline.initialize(UserHandle.USER_SYSTEM);
-        mTrampoline.adbRestore(mFileDescriptorMock);
-        verify(mBackupManagerServiceMock).adbRestore(mFileDescriptorMock);
+        mTrampoline.adbRestore(mParcelFileDescriptorMock);
+        verify(mBackupManagerServiceMock).adbRestore(mParcelFileDescriptorMock);
     }
 
     @Test
@@ -629,18 +764,94 @@
         verify(mBackupManagerServiceMock).endFullBackup();
     }
 
-    private class TrampolineTestable extends Trampoline {
-        public TrampolineTestable(Context context) {
-            super(context);
-        }
+    @Test
+    public void dump_callerDoesNotHavePermission_ignored() throws RemoteException {
+        when(mContextMock.checkCallingOrSelfPermission(
+                android.Manifest.permission.DUMP)).thenReturn(
+                PackageManager.PERMISSION_DENIED);
 
-        public TrampolineTestable(Context context, boolean globalDisable, File suppressFile) {
-            super(context, globalDisable, suppressFile);
+        mTrampoline.initialize(UserHandle.USER_SYSTEM);
+
+        mTrampoline.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]);
+
+        verifyNoMoreInteractions(mBackupManagerServiceMock);
+    }
+
+    @Test
+    public void dump_calledBeforeInitialize_ignored() throws RemoteException {
+        when(mContextMock.checkCallingOrSelfPermission(
+                android.Manifest.permission.DUMP)).thenReturn(
+                PackageManager.PERMISSION_GRANTED);
+
+        mTrampoline.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]);
+
+        verifyNoMoreInteractions(mBackupManagerServiceMock);
+    }
+
+    @Test
+    public void dump_callerHasPermission_forwarded() throws RemoteException {
+        when(mContextMock.checkCallingOrSelfPermission(
+                android.Manifest.permission.DUMP)).thenReturn(
+                PackageManager.PERMISSION_GRANTED);
+
+        mTrampoline.initialize(UserHandle.USER_SYSTEM);
+
+        mTrampoline.dump(mFileDescriptorStub, mPrintWriterMock, null);
+
+        verify(mBackupManagerServiceMock).dump(mFileDescriptorStub, mPrintWriterMock, null);
+    }
+
+    private static class TrampolineTestable extends Trampoline {
+        static boolean sBackupDisabled = false;
+        static boolean sRefactoredServiceEnabled = false;
+        static File sSuppressFile = null;
+        static int sCallingUid = -1;
+        static BackupManagerService sBackupManagerServiceMock = null;
+        static RefactoredBackupManagerService sRefactoredBackupManagerServiceMock = null;
+        private int mCreateServiceCallsCount = 0;
+
+        TrampolineTestable(Context context) {
+            super(context);
         }
 
         @Override
         protected BackupManagerServiceInterface createService() {
-            return mBackupManagerServiceMock;
+            mCreateServiceCallsCount++;
+            return super.createService();
+        }
+
+        @Override
+        public boolean isBackupDisabled() {
+            return sBackupDisabled;
+        }
+
+        @Override
+        public File getSuppressFile() {
+            return sSuppressFile;
+        }
+
+        @Override
+        protected int binderGetCallingUid() {
+            return sCallingUid;
+        }
+
+        @Override
+        protected boolean isRefactoredServiceEnabled() {
+            return sRefactoredServiceEnabled;
+        }
+
+        @Override
+        protected BackupManagerServiceInterface createRefactoredBackupManagerService() {
+            return sRefactoredBackupManagerServiceMock;
+        }
+
+        @Override
+        protected BackupManagerServiceInterface createBackupManagerService() {
+            return sBackupManagerServiceMock;
+        }
+
+        int getCreateServiceCallsCount() {
+            return mCreateServiceCallsCount;
         }
     }
 }