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

Commit bd476eae authored by Artem Iglikov's avatar Artem Iglikov
Browse files

Update TransportManager tests.

This applies changes that disappeared for some reason from ag/2314382

Bug: 37616038
Test: make RunFrameworksServicesRoboTests
Change-Id: Iabfafd8c6afaac7304194f7645d08ef9e6f3b3aa
parent f4627b88
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line 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. */
        /** Should return true if this is a valid transport. */
        boolean onTransportBound(IBackupTransport binder);
        boolean onTransportBound(IBackupTransport binder);
    }
    }
+2 −0
Original line number Original line Diff line number Diff line
@@ -73,4 +73,6 @@ LOCAL_STATIC_JAVA_LIBRARIES := \


LOCAL_TEST_PACKAGE := FrameworksServicesLib
LOCAL_TEST_PACKAGE := FrameworksServicesLib


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

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


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


import android.annotation.RequiresPermission;
import android.content.ComponentName;
import android.content.ComponentName;
import android.content.Intent;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.ApplicationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
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.Before;
import org.junit.Test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
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.res.builder.RobolectricPackageManager;
import org.robolectric.shadows.ShadowContextImpl;
import org.robolectric.shadows.ShadowLog;
import org.robolectric.shadows.ShadowLooper;
import org.robolectric.shadows.ShadowLooper;


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


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


    private RobolectricPackageManager mPackageManager;
    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
    @Before
    public void setUp() {
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        ShadowLog.stream = System.out;
        mPackageManager = new DefaultPackageManagerWithQueryIntentServicesAsUser(
        mPackageManager = new DefaultPackageManagerWithQueryIntentServicesAsUser(
                RuntimeEnvironment.getAppResourceLoader());
                RuntimeEnvironment.getAppResourceLoader());
        RuntimeEnvironment.setRobolectricPackageManager(mPackageManager);
        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
    @Test
    public void onPackageAdded_bindsToAllTransports() {
    public void onPackageAdded_bindsToAllTransports() throws Exception {
        Intent intent = new Intent(TransportManager.SERVICE_ACTION_TRANSPORT_HOST);
        setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES,
        intent.setPackage(PACKAGE_NAME);
                ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);


        PackageInfo packageInfo = new PackageInfo();
        TransportManager transportManager = new TransportManager(
        packageInfo.packageName = PACKAGE_NAME;
                RuntimeEnvironment.application.getApplicationContext(),
        packageInfo.applicationInfo = new ApplicationInfo();
                new HashSet<>(TRANSPORTS_COMPONENT_NAMES),
        packageInfo.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
                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();
    @Test
        transport1.serviceInfo = new ServiceInfo();
    public void onPackageAdded_whitelistIsNull_doesNotBindToTransports() throws Exception {
        transport1.serviceInfo.packageName = PACKAGE_NAME;
        setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES,
        transport1.serviceInfo.name = TRANSPORT1_NAME;
                ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);


        ResolveInfo transport2 = new ResolveInfo();
        TransportManager transportManager = new TransportManager(
        transport2.serviceInfo = new ServiceInfo();
                RuntimeEnvironment.application.getApplicationContext(),
        transport2.serviceInfo.packageName = PACKAGE_NAME;
                null /* whitelist */,
        transport2.serviceInfo.name = TRANSPORT2_NAME;
                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(
        TransportManager transportManager = new TransportManager(
                RuntimeEnvironment.application.getApplicationContext(),
                RuntimeEnvironment.application.getApplicationContext(),
                new HashSet<>(TRANSPORTS_COMPONENT_NAMES),
                new HashSet<>(Collections.singleton(TRANSPORT2_COMPONENT_NAME)),
                null,
                null /* defaultTransport */,
                mTransportBoundListener,
                mTransportBoundListenerStub,
                ShadowLooper.getMainLooper());
                ShadowLooper.getMainLooper());
        transportManager.onPackageAdded(PACKAGE_NAME);
        transportManager.onPackageAdded(PACKAGE_NAME);


        assertThat(transportManager.getAllTransportComponents()).asList().containsExactlyElementsIn(
        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
    @Test
            DefaultPackageManager {
    public void onPackageAdded_appIsNotPrivileged_doesNotBindToTransports() throws Exception {
        setUpPackageWithTransports(PACKAGE_NAME, TRANSPORTS_NAMES, 0);


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


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


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

        mPackageManager.addPackage(packageInfo);


        @Implementation
        List<ResolveInfo> transportsInfo = new ArrayList<>();
        public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn,
        for (String transportName : transportNames) {
                int flags, UserHandle user) {
            ResolveInfo info = new ResolveInfo();
            return true;
            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 Original line 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 Original line 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