Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1f7fb9b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Update TransportManager tests."

parents 4456a999 bd476eae
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -455,7 +455,7 @@ public class TransportManager {
        }
    }

    interface TransportBoundListener {
    public interface TransportBoundListener {
        /** Should return true if this is a valid transport. */
        boolean onTransportBound(IBackupTransport binder);
    }
+2 −0
Original line number Diff line number Diff line
@@ -73,4 +73,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \

LOCAL_TEST_PACKAGE := FrameworksServicesLib

LOCAL_INSTRUMENT_SOURCE_DIRS := $(dir $(LOCAL_PATH))backup/java

include prebuilts/misc/common/robolectric/run_robotests.mk
+117 −48
Original line number Diff line number Diff line
@@ -18,32 +18,36 @@ package com.android.server.backup;

import static com.google.common.truth.Truth.assertThat;

import android.annotation.RequiresPermission;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.UserHandle;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;

import com.android.server.backup.testing.BackupTransportStub;
import com.android.server.backup.testing.DefaultPackageManagerWithQueryIntentServicesAsUser;
import com.android.server.backup.testing.ShadowBackupTransportStub;
import com.android.server.backup.testing.ShadowContextImplWithBindServiceAsUser;
import com.android.server.backup.testing.TransportBoundListenerStub;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
import org.robolectric.res.ResourceLoader;
import org.robolectric.res.builder.DefaultPackageManager;
import org.robolectric.res.builder.RobolectricPackageManager;
import org.robolectric.shadows.ShadowContextImpl;
import org.robolectric.shadows.ShadowLog;
import org.robolectric.shadows.ShadowLooper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

@@ -51,12 +55,18 @@ import java.util.List;
@Config(
        manifest = Config.NONE,
        sdk = 23,
        shadows = {TransportManagerTest.ShadowContextImplWithBindServiceAsUser.class}
        shadows = {
                ShadowContextImplWithBindServiceAsUser.class,
                ShadowBackupTransportStub.class
        }
)
@Presubmit
public class TransportManagerTest {
    private static final String PACKAGE_NAME = "some.package.name";
    private static final String TRANSPORT1_NAME = "transport1.name";
    private static final String TRANSPORT2_NAME = "transport2.name";
    private static final List<String> TRANSPORTS_NAMES = Arrays.asList(
            TRANSPORT1_NAME, TRANSPORT2_NAME);
    private static final ComponentName TRANSPORT1_COMPONENT_NAME = new ComponentName(PACKAGE_NAME,
            TRANSPORT1_NAME);
    private static final ComponentName TRANSPORT2_COMPONENT_NAME = new ComponentName(PACKAGE_NAME,
@@ -66,72 +76,131 @@ public class TransportManagerTest {

    private RobolectricPackageManager mPackageManager;

    @Mock private TransportManager.TransportBoundListener mTransportBoundListener;
    @Mock private IBinder mTransport1BinderMock;
    @Mock private IBinder mTransport2BinderMock;

    private final BackupTransportStub mTransport1Stub = new BackupTransportStub(TRANSPORT1_NAME);
    private final BackupTransportStub mTransport2Stub = new BackupTransportStub(TRANSPORT2_NAME);
    private final TransportBoundListenerStub mTransportBoundListenerStub =
            new TransportBoundListenerStub(true);

    @Before
    public void setUp() {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        ShadowLog.stream = System.out;
        mPackageManager = new DefaultPackageManagerWithQueryIntentServicesAsUser(
                RuntimeEnvironment.getAppResourceLoader());
        RuntimeEnvironment.setRobolectricPackageManager(mPackageManager);

        ShadowContextImplWithBindServiceAsUser.sComponentBinderMap.put(TRANSPORT1_COMPONENT_NAME,
                mTransport1BinderMock);
        ShadowContextImplWithBindServiceAsUser.sComponentBinderMap.put(TRANSPORT2_COMPONENT_NAME,
                mTransport2BinderMock);
        ShadowBackupTransportStub.sBinderTransportMap.put(mTransport1BinderMock, mTransport1Stub);
        ShadowBackupTransportStub.sBinderTransportMap.put(mTransport2BinderMock, mTransport2Stub);
    }

    @Test
    public void onPackageAdded_bindsToAllTransports() {
        Intent intent = new Intent(TransportManager.SERVICE_ACTION_TRANSPORT_HOST);
        intent.setPackage(PACKAGE_NAME);
    public void onPackageAdded_bindsToAllTransports() throws Exception {
        setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES,
                ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

        PackageInfo packageInfo = new PackageInfo();
        packageInfo.packageName = PACKAGE_NAME;
        packageInfo.applicationInfo = new ApplicationInfo();
        packageInfo.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
        TransportManager transportManager = new TransportManager(
                RuntimeEnvironment.application.getApplicationContext(),
                new HashSet<>(TRANSPORTS_COMPONENT_NAMES),
                null /* defaultTransport */,
                mTransportBoundListenerStub,
                ShadowLooper.getMainLooper());
        transportManager.onPackageAdded(PACKAGE_NAME);

        mPackageManager.addPackage(packageInfo);
        assertThat(transportManager.getAllTransportComponents()).asList().containsExactlyElementsIn(
                TRANSPORTS_COMPONENT_NAMES);
        assertThat(transportManager.getBoundTransportNames()).asList().containsExactlyElementsIn(
                TRANSPORTS_NAMES);
        assertThat(mTransportBoundListenerStub.isCalledForTransport(mTransport1Stub)).isTrue();
        assertThat(mTransportBoundListenerStub.isCalledForTransport(mTransport2Stub)).isTrue();
    }

        ResolveInfo transport1 = new ResolveInfo();
        transport1.serviceInfo = new ServiceInfo();
        transport1.serviceInfo.packageName = PACKAGE_NAME;
        transport1.serviceInfo.name = TRANSPORT1_NAME;
    @Test
    public void onPackageAdded_whitelistIsNull_doesNotBindToTransports() throws Exception {
        setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES,
                ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

        ResolveInfo transport2 = new ResolveInfo();
        transport2.serviceInfo = new ServiceInfo();
        transport2.serviceInfo.packageName = PACKAGE_NAME;
        transport2.serviceInfo.name = TRANSPORT2_NAME;
        TransportManager transportManager = new TransportManager(
                RuntimeEnvironment.application.getApplicationContext(),
                null /* whitelist */,
                null /* defaultTransport */,
                mTransportBoundListenerStub,
                ShadowLooper.getMainLooper());
        transportManager.onPackageAdded(PACKAGE_NAME);

        mPackageManager.addResolveInfoForIntent(intent, Arrays.asList(transport1, transport2));
        assertThat(transportManager.getAllTransportComponents()).isEmpty();
        assertThat(transportManager.getBoundTransportNames()).isEmpty();
        assertThat(mTransportBoundListenerStub.isCalled()).isFalse();
    }

    @Test
    public void onPackageAdded_onlyOneTransportWhitelisted_onlyConnectsToWhitelistedTransport()
            throws Exception {
        setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES,
                ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

        TransportManager transportManager = new TransportManager(
                RuntimeEnvironment.application.getApplicationContext(),
                new HashSet<>(TRANSPORTS_COMPONENT_NAMES),
                null,
                mTransportBoundListener,
                new HashSet<>(Collections.singleton(TRANSPORT2_COMPONENT_NAME)),
                null /* defaultTransport */,
                mTransportBoundListenerStub,
                ShadowLooper.getMainLooper());
        transportManager.onPackageAdded(PACKAGE_NAME);

        assertThat(transportManager.getAllTransportComponents()).asList().containsExactlyElementsIn(
                TRANSPORTS_COMPONENT_NAMES);
                Collections.singleton(TRANSPORT2_COMPONENT_NAME));
        assertThat(transportManager.getBoundTransportNames()).asList().containsExactlyElementsIn(
                Collections.singleton(TRANSPORT2_NAME));
        assertThat(mTransportBoundListenerStub.isCalledForTransport(mTransport1Stub)).isFalse();
        assertThat(mTransportBoundListenerStub.isCalledForTransport(mTransport2Stub)).isTrue();
    }

    private static class DefaultPackageManagerWithQueryIntentServicesAsUser extends
            DefaultPackageManager {
    @Test
    public void onPackageAdded_appIsNotPrivileged_doesNotBindToTransports() throws Exception {
        setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES, 0);

        /* package */ DefaultPackageManagerWithQueryIntentServicesAsUser(
                ResourceLoader appResourceLoader) {
            super(appResourceLoader);
        }
        TransportManager transportManager = new TransportManager(
                RuntimeEnvironment.application.getApplicationContext(),
                new HashSet<>(TRANSPORTS_COMPONENT_NAMES),
                null /* defaultTransport */,
                mTransportBoundListenerStub,
                ShadowLooper.getMainLooper());
        transportManager.onPackageAdded(PACKAGE_NAME);

        @Override
        public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
            return super.queryIntentServices(intent, flags);
        }
        assertThat(transportManager.getAllTransportComponents()).isEmpty();
        assertThat(transportManager.getBoundTransportNames()).isEmpty();
        assertThat(mTransportBoundListenerStub.isCalled()).isFalse();
    }

    @Implements(className = ShadowContextImpl.CLASS_NAME)
    public static class ShadowContextImplWithBindServiceAsUser extends ShadowContextImpl {
    private void setUpPackageWithTransports(String packageName, List<String> transportNames,
            int flags) throws Exception {
        PackageInfo packageInfo = new PackageInfo();
        packageInfo.packageName = packageName;
        packageInfo.applicationInfo = new ApplicationInfo();
        packageInfo.applicationInfo.privateFlags = flags;

        mPackageManager.addPackage(packageInfo);

        @Implementation
        public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn,
                int flags, UserHandle user) {
            return true;
        List<ResolveInfo> transportsInfo = new ArrayList<>();
        for (String transportName : transportNames) {
            ResolveInfo info = new ResolveInfo();
            info.serviceInfo = new ServiceInfo();
            info.serviceInfo.packageName = packageName;
            info.serviceInfo.name = transportName;
            transportsInfo.add(info);
        }

        Intent intent = new Intent(TransportManager.SERVICE_ACTION_TRANSPORT_HOST);
        intent.setPackage(packageName);

        mPackageManager.addResolveInfoForIntent(intent, transportsInfo);
    }

}
+179 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.backup.testing;

import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;

import com.android.internal.backup.IBackupTransport;

/**
 * Stub backup transport, doing nothing and returning default values.
 */
public class BackupTransportStub implements IBackupTransport {

    private final String mName;

    public BackupTransportStub(String name) {
        mName = name;
    }

    @Override
    public IBinder asBinder() {
        return null;
    }

    @Override
    public String name() throws RemoteException {
        return mName;
    }

    @Override
    public Intent configurationIntent() throws RemoteException {
        return null;
    }

    @Override
    public String currentDestinationString() throws RemoteException {
        return null;
    }

    @Override
    public Intent dataManagementIntent() throws RemoteException {
        return null;
    }

    @Override
    public String dataManagementLabel() throws RemoteException {
        return null;
    }

    @Override
    public String transportDirName() throws RemoteException {
        return null;
    }

    @Override
    public long requestBackupTime() throws RemoteException {
        return 0;
    }

    @Override
    public int initializeDevice() throws RemoteException {
        return 0;
    }

    @Override
    public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd, int flags)
            throws RemoteException {
        return 0;
    }

    @Override
    public int clearBackupData(PackageInfo packageInfo) throws RemoteException {
        return 0;
    }

    @Override
    public int finishBackup() throws RemoteException {
        return 0;
    }

    @Override
    public RestoreSet[] getAvailableRestoreSets() throws RemoteException {
        return new RestoreSet[0];
    }

    @Override
    public long getCurrentRestoreSet() throws RemoteException {
        return 0;
    }

    @Override
    public int startRestore(long token, PackageInfo[] packages) throws RemoteException {
        return 0;
    }

    @Override
    public RestoreDescription nextRestorePackage() throws RemoteException {
        return null;
    }

    @Override
    public int getRestoreData(ParcelFileDescriptor outFd) throws RemoteException {
        return 0;
    }

    @Override
    public void finishRestore() throws RemoteException {

    }

    @Override
    public long requestFullBackupTime() throws RemoteException {
        return 0;
    }

    @Override
    public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket,
            int flags)
            throws RemoteException {
        return 0;
    }

    @Override
    public int checkFullBackupSize(long size) throws RemoteException {
        return 0;
    }

    @Override
    public int sendBackupData(int numBytes) throws RemoteException {
        return 0;
    }

    @Override
    public void cancelFullBackup() throws RemoteException {

    }

    @Override
    public boolean isAppEligibleForBackup(PackageInfo targetPackage, boolean isFullBackup)
            throws RemoteException {
        return false;
    }

    @Override
    public long getBackupQuota(String packageName, boolean isFullBackup)
            throws RemoteException {
        return 0;
    }

    @Override
    public int getNextFullRestoreDataChunk(ParcelFileDescriptor socket) throws RemoteException {
        return 0;
    }

    @Override
    public int abortFullRestore() throws RemoteException {
        return 0;
    }
}
+43 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License
 */

package com.android.server.backup.testing;

import android.content.Intent;
import android.content.pm.ResolveInfo;

import org.robolectric.res.ResourceLoader;
import org.robolectric.res.builder.DefaultPackageManager;

import java.util.List;

/**
 * Implementation of PackageManager for Robolectric which handles queryIntentServicesAsUser().
 */
public class DefaultPackageManagerWithQueryIntentServicesAsUser extends
        DefaultPackageManager {

    /* package */
    public DefaultPackageManagerWithQueryIntentServicesAsUser(
            ResourceLoader appResourceLoader) {
        super(appResourceLoader);
    }

    @Override
    public List<ResolveInfo> queryIntentServicesAsUser(Intent intent, int flags, int userId) {
        return super.queryIntentServices(intent, flags);
    }
}
Loading