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

Commit 9028d41a authored by Beverly's avatar Beverly
Browse files

SysUi can mock static methods + coordinator tests

- Add ability to mock static methods in SystemUI (In SystemUI, use
  mockito-target-extended-minus-junit4 and add libdexmakerjvmtiagent
  and libstaticjvmtiagent jni libraries to SystemUI tests bp/mk files
  so that we have static-mocking abilities)
- Add tests for new Coordinators

Test: atest SystemUiTests
Bug: 145134683
Change-Id: I0450a07c6d465c6d1f7d74acddb054538540785a
parent 3ae892b1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -127,7 +127,7 @@ android_library {
        "SystemUI-proto",
        "metrics-helper-lib",
        "androidx.test.rules", "hamcrest-library",
        "mockito-target-inline-minus-junit4",
        "mockito-target-extended-minus-junit4",
        "testables",
        "truth-prebuilt",
        "dagger2-2.19",
+8 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;

import android.app.INotificationManager;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.hardware.display.AmbientDisplayConfiguration;
import android.hardware.display.NightDisplayListener;
import android.os.Handler;
@@ -147,6 +148,13 @@ public class DependencyProvider {
                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
    }

    /** */
    @Singleton
    @Provides
    public IPackageManager provideIPackageManager() {
        return IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
    }

    /** */
    @Singleton
    @Provides
+7 −6
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.notification.collection.coordinator;

import android.Manifest;
import android.app.AppGlobals;
import android.app.Notification;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
@@ -43,10 +42,13 @@ public class DeviceProvisionedCoordinator implements Coordinator {
    private static final String TAG = "DeviceProvisionedCoordinator";

    private final DeviceProvisionedController mDeviceProvisionedController;
    private final IPackageManager mIPackageManager;

    @Inject
    public DeviceProvisionedCoordinator(DeviceProvisionedController deviceProvisionedController) {
    public DeviceProvisionedCoordinator(DeviceProvisionedController deviceProvisionedController,
            IPackageManager packageManager) {
        mDeviceProvisionedController = deviceProvisionedController;
        mIPackageManager = packageManager;
    }

    @Override
@@ -70,17 +72,16 @@ public class DeviceProvisionedCoordinator implements Coordinator {
     * marking them as relevant for setup are allowed to show when device is unprovisioned
     */
    private boolean showNotificationEvenIfUnprovisioned(StatusBarNotification sbn) {
        final boolean hasPermission = checkUidPermission(AppGlobals.getPackageManager(),
        final boolean hasPermission = checkUidPermission(
                Manifest.permission.NOTIFICATION_DURING_SETUP,
                sbn.getUid()) == PackageManager.PERMISSION_GRANTED;
        return hasPermission
                && sbn.getNotification().extras.getBoolean(Notification.EXTRA_ALLOW_DURING_SETUP);
    }

    private static int checkUidPermission(IPackageManager packageManager, String permission,
            int uid) {
    private int checkUidPermission(String permission, int uid) {
        try {
            return packageManager.checkUidPermission(permission, uid);
            return mIPackageManager.checkUidPermission(permission, uid);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+2 −1
Original line number Diff line number Diff line
@@ -32,7 +32,8 @@ LOCAL_MULTILIB := both

LOCAL_JNI_SHARED_LIBRARIES := \
    libdexmakerjvmtiagent \
    libmultiplejvmtiagentsinterferenceagent
    libmultiplejvmtiagentsinterferenceagent \
    libstaticjvmtiagent

LOCAL_JAVA_LIBRARIES := \
    android.test.runner \
+152 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 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.statusbar.notification.collection.coordinator;

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

import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.Manifest;
import android.app.ActivityManagerInternal;
import android.app.Notification;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.RemoteException;

import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationEntryBuilder;
import com.android.systemui.statusbar.RankingBuilder;
import com.android.systemui.statusbar.notification.collection.NotifListBuilderImpl;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.MockitoSession;

@SmallTest
@RunWith(AndroidJUnit4.class)
public class DeviceProvisionedCoordinatorTest extends SysuiTestCase {
    private static final int NOTIF_UID = 0;

    private static final String SHOW_WHEN_UNPROVISIONED_FLAG =
            Notification.EXTRA_ALLOW_DURING_SETUP;
    private static final String SETUP_NOTIF_PERMISSION =
            Manifest.permission.NOTIFICATION_DURING_SETUP;

    private MockitoSession mMockitoSession;

    @Mock private ActivityManagerInternal mActivityMangerInternal;
    @Mock private IPackageManager mIPackageManager;
    @Mock private DeviceProvisionedController mDeviceProvisionedController;
    @Mock private NotifListBuilderImpl mNotifListBuilder;
    private Notification mNotification;
    private NotificationEntry mEntry;
    private DeviceProvisionedCoordinator mDeviceProvisionedCoordinator;
    private NotifFilter mDeviceProvisionedFilter;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mDeviceProvisionedCoordinator = new DeviceProvisionedCoordinator(
                mDeviceProvisionedController, mIPackageManager);

        mNotification = new Notification();
        mEntry = new NotificationEntryBuilder()
                .setNotification(mNotification)
                .setUid(NOTIF_UID)
                .build();

        ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
        mDeviceProvisionedCoordinator.attach(null, mNotifListBuilder);
        verify(mNotifListBuilder, times(1)).addFilter(filterCaptor.capture());
        mDeviceProvisionedFilter = filterCaptor.getValue();
    }

    @Test
    public void deviceProvisioned() {
        // GIVEN device is provisioned
        when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);

        // THEN don't filter out the notification
        assertFalse(mDeviceProvisionedFilter.shouldFilterOut(mEntry, 0));
    }

    @Test
    public void deviceUnprovisioned() {
        // GIVEN device is unprovisioned
        when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(false);

        // THEN filter out the notification
        assertTrue(mDeviceProvisionedFilter.shouldFilterOut(mEntry, 0));
    }

    @Test
    public void deviceUnprovisionedCanBypass() throws RemoteException {
        // GIVEN device is unprovisioned
        when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(false);

        // GIVEN notification has a flag to allow the notification during setup
        Bundle extras = new Bundle();
        extras.putBoolean(SHOW_WHEN_UNPROVISIONED_FLAG, true);
        mNotification.extras = extras;

        // GIVEN notification has the permission to display during setup
        when(mIPackageManager.checkUidPermission(SETUP_NOTIF_PERMISSION, NOTIF_UID))
                .thenReturn(PackageManager.PERMISSION_GRANTED);

        // THEN don't filter out the notification
        assertFalse(mDeviceProvisionedFilter.shouldFilterOut(mEntry, 0));
    }

    @Test
    public void deviceUnprovisionedTryBypassWithoutPermission() throws RemoteException {
        // GIVEN device is unprovisioned
        when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(false);

        // GIVEN notification has a flag to allow the notification during setup
        Bundle extras = new Bundle();
        extras.putBoolean(SHOW_WHEN_UNPROVISIONED_FLAG, true);
        mNotification.extras = extras;

        // GIVEN notification does NOT have permission to display during setup
        when(mIPackageManager.checkUidPermission(SETUP_NOTIF_PERMISSION, NOTIF_UID))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        // THEN filter out the notification
        assertTrue(mDeviceProvisionedFilter.shouldFilterOut(mEntry, 0));
    }

    private RankingBuilder getRankingForUnfilteredNotif() {
        return new RankingBuilder()
                .setKey(mEntry.getKey())
                .setSuppressedVisualEffects(0)
                .setSuspended(false);
    }
}
Loading