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

Commit af2076af authored by Geoffrey Pitsch's avatar Geoffrey Pitsch
Browse files

Mock PackageManager for TileLifecycleManagerTests

Slices ~10 seconds off the systemui target test time.

Wrapped calls to the different PackageManager APIs with
PackageManagerAdapter, which should change to a cleaner
abstraction as we write more tests.

Change-Id: I91ac9959de05a06ed484e49648203729159a482e
parent 5426dc13
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.systemui.qs.external;

import android.annotation.UserIdInt;
import android.app.AppGlobals;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.os.RemoteException;

// Adapter that wraps calls to PackageManager or IPackageManager for {@link TileLifecycleManager}.
// TODO: This is very much an intermediate step to allow for PackageManager mocking and should be
// abstracted into something more useful for other tests in systemui.
public class PackageManagerAdapter {
    private static final String TAG = "PackageManagerAdapter";

    private PackageManager mPackageManager;
    private IPackageManager mIPackageManager;

    // Uses the PackageManager for the provided context.
    // When necessary, uses the IPackagemanger in AppGlobals.
    public PackageManagerAdapter(Context context) {
        mPackageManager = context.getPackageManager();
        mIPackageManager = AppGlobals.getPackageManager();
    }

    public ServiceInfo getServiceInfo(ComponentName className, int flags, int userId)
            throws RemoteException {
        return mIPackageManager.getServiceInfo(className, flags, userId);
    }

    public ServiceInfo getServiceInfo(ComponentName component, int flags)
            throws PackageManager.NameNotFoundException {
        return mPackageManager.getServiceInfo(component, flags);
    }

    public PackageInfo getPackageInfoAsUser(String packageName, int flags, @UserIdInt int userId)
            throws PackageManager.NameNotFoundException {
        return mPackageManager.getPackageInfoAsUser(packageName, flags, userId);
    }
}
+19 −12
Original line number Diff line number Diff line
@@ -21,10 +21,9 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ServiceInfo;
import android.content.ServiceConnection;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
@@ -38,6 +37,7 @@ import android.service.quicksettings.TileService;
import android.support.annotation.VisibleForTesting;
import android.util.ArraySet;
import android.util.Log;
import com.android.systemui.qs.external.PackageManagerAdapter;

import libcore.util.Objects;

@@ -73,6 +73,7 @@ public class TileLifecycleManager extends BroadcastReceiver implements
    private final Intent mIntent;
    private final UserHandle mUser;
    private final IBinder mToken = new Binder();
    private final PackageManagerAdapter mPackageManagerAdapter;

    private Set<Integer> mQueuedMessages = new ArraySet<>();
    private QSTileServiceWrapper mWrapper;
@@ -88,14 +89,21 @@ public class TileLifecycleManager extends BroadcastReceiver implements
    // Return value from bindServiceAsUser, determines whether safe to call unbind.
    private boolean mIsBound;

    public TileLifecycleManager(Handler handler, Context context, IQSService service,
            Tile tile, Intent intent, UserHandle user) {
    public TileLifecycleManager(Handler handler, Context context, IQSService service, Tile tile,
            Intent intent, UserHandle user) {
        this(handler, context, service, tile, intent, user, new PackageManagerAdapter(context));
    }

    @VisibleForTesting
    TileLifecycleManager(Handler handler, Context context, IQSService service, Tile tile,
            Intent intent, UserHandle user, PackageManagerAdapter packageManagerAdapter) {
        mContext = context;
        mHandler = handler;
        mIntent = intent;
        mIntent.putExtra(TileService.EXTRA_SERVICE, service.asBinder());
        mIntent.putExtra(TileService.EXTRA_TOKEN, mToken);
        mUser = user;
        mPackageManagerAdapter = packageManagerAdapter;
        if (DEBUG) Log.d(TAG, "Creating " + mIntent + " " + mUser);
    }

@@ -111,11 +119,11 @@ public class TileLifecycleManager extends BroadcastReceiver implements

    public boolean isActiveTile() {
        try {
            ServiceInfo info = mContext.getPackageManager().getServiceInfo(mIntent.getComponent(),
            ServiceInfo info = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
                    PackageManager.MATCH_UNINSTALLED_PACKAGES | PackageManager.GET_META_DATA);
            return info.metaData != null
                    && info.metaData.getBoolean(TileService.META_DATA_ACTIVE_TILE, false);
        } catch (NameNotFoundException e) {
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }
@@ -261,8 +269,7 @@ public class TileLifecycleManager extends BroadcastReceiver implements
    }

    private boolean checkComponentState() {
        PackageManager pm = mContext.getPackageManager();
        if (!isPackageAvailable(pm) || !isComponentAvailable(pm)) {
        if (!isPackageAvailable() || !isComponentAvailable()) {
            startPackageListening();
            return false;
        }
@@ -311,10 +318,10 @@ public class TileLifecycleManager extends BroadcastReceiver implements
        }
    }

    private boolean isComponentAvailable(PackageManager pm) {
    private boolean isComponentAvailable() {
        String packageName = mIntent.getComponent().getPackageName();
        try {
            ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(mIntent.getComponent(),
            ServiceInfo si = mPackageManagerAdapter.getServiceInfo(mIntent.getComponent(),
                    0, mUser.getIdentifier());
            if (DEBUG && si == null) Log.d(TAG, "Can't find component " + mIntent.getComponent());
            return si != null;
@@ -324,10 +331,10 @@ public class TileLifecycleManager extends BroadcastReceiver implements
        return false;
    }

    private boolean isPackageAvailable(PackageManager pm) {
    private boolean isPackageAvailable() {
        String packageName = mIntent.getComponent().getPackageName();
        try {
            pm.getPackageInfoAsUser(packageName, 0, mUser.getIdentifier());
            mPackageManagerAdapter.getPackageInfoAsUser(packageName, 0, mUser.getIdentifier());
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            if (DEBUG) Log.d(TAG, "Package not available: " + packageName, e);
+44 −13
Original line number Diff line number Diff line
@@ -15,13 +15,24 @@
 */
package com.android.systemui.qs.external;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.when;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.pm.PackageInfo;
import android.content.pm.ServiceInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -31,6 +42,7 @@ import android.os.UserHandle;
import android.service.quicksettings.IQSService;
import android.service.quicksettings.IQSTileService;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
@@ -42,10 +54,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;

import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class TileLifecycleManagerTests extends SysuiTestCase {
@@ -57,10 +65,13 @@ public class TileLifecycleManagerTests extends SysuiTestCase {
    private TileLifecycleManager mStateManager;
    private final Object mBroadcastLock = new Object();
    private final ArraySet<String> mCallbacks = new ArraySet<>();
    private final PackageManagerAdapter mMockPackageManagerAdapter =
            Mockito.mock(PackageManagerAdapter.class);
    private boolean mBound;

    @Before
    public void setUp() throws Exception {
        setPackageEnabled(true);
        mThread = new HandlerThread("TestThread");
        mThread.start();
        mHandler = new Handler(mThread.getLooper());
@@ -68,7 +79,8 @@ public class TileLifecycleManagerTests extends SysuiTestCase {
        mStateManager = new TileLifecycleManager(mHandler, getContext(),
                Mockito.mock(IQSService.class), new Tile(),
                new Intent().setComponent(component),
                new UserHandle(UserHandle.myUserId()));
                new UserHandle(UserHandle.myUserId()),
                mMockPackageManagerAdapter);
        mCallbacks.clear();
        getContext().registerReceiver(mReceiver, new IntentFilter(TILE_UPDATE_BROADCAST));
    }
@@ -82,6 +94,22 @@ public class TileLifecycleManagerTests extends SysuiTestCase {
        getContext().unregisterReceiver(mReceiver);
    }

    private void setPackageEnabled(boolean enabled) throws Exception {
        ServiceInfo defaultServiceInfo = null;
        if (enabled) {
            defaultServiceInfo = new ServiceInfo();
            defaultServiceInfo.metaData = new Bundle();
            defaultServiceInfo.metaData.putBoolean(TileService.META_DATA_ACTIVE_TILE, true);
        }
        when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt(), anyInt()))
                .thenReturn(defaultServiceInfo);
        when(mMockPackageManagerAdapter.getServiceInfo(any(), anyInt()))
                .thenReturn(defaultServiceInfo);
        PackageInfo defaultPackageInfo = new PackageInfo();
        when(mMockPackageManagerAdapter.getPackageInfoAsUser(anyString(), anyInt(), anyInt()))
                .thenReturn(defaultPackageInfo);
    }

    @Test
    public void testSync() {
        syncWithHandler();
@@ -181,19 +209,22 @@ public class TileLifecycleManagerTests extends SysuiTestCase {
    }

    @Test
    public void testComponentEnabling() {
    public void testComponentEnabling() throws Exception {
        mStateManager.onTileAdded();
        mStateManager.onStartListening();

        PackageManager pm = getContext().getPackageManager();
        pm.setComponentEnabledSetting(new ComponentName(getContext(), FakeTileService.class),
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);

        setPackageEnabled(false);
        bindService();
        // Package not available, should be listening for package changes.
        assertTrue(mStateManager.mReceiverRegistered);

        pm.setComponentEnabledSetting(new ComponentName(getContext(), FakeTileService.class),
                PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
        // Package is re-enabled.
        setPackageEnabled(true);
        mStateManager.onReceive(
                mContext,
                new Intent(
                        Intent.ACTION_PACKAGE_CHANGED,
                        Uri.fromParts("package", getContext().getPackageName(), null)));
        waitForCallback("onCreate");
    }