/*
 * 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.server.accessibility;

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

import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.emptyArray;
import static org.hamcrest.Matchers.hasSize;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.AppOpsManager;
import android.appwidget.AppWidgetManagerInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.testing.DexmakerShareClassLoaderRule;
import android.util.ArraySet;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityWindowInfo;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;
import java.util.List;

/**
 * Tests for the AccessibilitySecurityPolicy
 */
public class AccessibilitySecurityPolicyTest {
    private static final String PACKAGE_NAME = "com.android.server.accessibility";
    private static final String PACKAGE_NAME2 = "com.android.server.accessibility2";
    private static final int WINDOWID = 0x000a;
    private static final int WINDOWID2 = 0x000b;
    private static final int APP_UID = 10400;

    private static final int[] ALWAYS_DISPATCH_EVENTS = {
            AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED,
            AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED,
            AccessibilityEvent.TYPE_ANNOUNCEMENT,
            AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START,
            AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END,
            AccessibilityEvent.TYPE_GESTURE_DETECTION_START,
            AccessibilityEvent.TYPE_GESTURE_DETECTION_END,
            AccessibilityEvent.TYPE_TOUCH_INTERACTION_START,
            AccessibilityEvent.TYPE_TOUCH_INTERACTION_END,
            AccessibilityEvent.TYPE_VIEW_HOVER_ENTER,
            AccessibilityEvent.TYPE_VIEW_HOVER_EXIT,
            AccessibilityEvent.TYPE_ASSIST_READING_CONTEXT,
            AccessibilityEvent.TYPE_WINDOWS_CHANGED,
    };
    private static final int[] OTHER_EVENTS = {
            AccessibilityEvent.TYPE_VIEW_CLICKED,
            AccessibilityEvent.TYPE_VIEW_LONG_CLICKED,
            AccessibilityEvent.TYPE_VIEW_SELECTED,
            AccessibilityEvent.TYPE_VIEW_FOCUSED,
            AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED,
            AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED,
            AccessibilityEvent.TYPE_VIEW_SCROLLED,
            AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED,
            AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED,
            AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED,
            AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY,
            AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED,
    };

    private AccessibilitySecurityPolicy mA11ySecurityPolicy;

    // To mock package-private class
    @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
            new DexmakerShareClassLoaderRule();

    @Mock private Context mMockContext;
    @Mock private PackageManager mMockPackageManager;
    @Mock private UserManager mMockUserManager;
    @Mock private AppOpsManager mMockAppOpsManager;
    @Mock private AccessibilityServiceConnection mMockA11yServiceConnection;
    @Mock private AccessibilityWindowManager mMockA11yWindowManager;
    @Mock private AppWidgetManagerInternal mMockAppWidgetManager;
    @Mock private AccessibilitySecurityPolicy.AccessibilityUserManager mMockA11yUserManager;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
        when(mMockContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
        when(mMockContext.getSystemService(Context.APP_OPS_SERVICE)).thenReturn(mMockAppOpsManager);

        mA11ySecurityPolicy = new AccessibilitySecurityPolicy(mMockContext, mMockA11yUserManager);
        mA11ySecurityPolicy.setAccessibilityWindowManager(mMockA11yWindowManager);
        mA11ySecurityPolicy.setAppWidgetManager(mMockAppWidgetManager);
    }

    @Test
    public void canDispatchAccessibilityEvent_alwaysDispatchEvents_returnTrue() {
        for (int i = 0; i < ALWAYS_DISPATCH_EVENTS.length; i++) {
            final AccessibilityEvent event = AccessibilityEvent.obtain(ALWAYS_DISPATCH_EVENTS[i]);
            assertTrue("Should dispatch [" + event + "]",
                    mA11ySecurityPolicy.canDispatchAccessibilityEventLocked(
                            UserHandle.USER_SYSTEM,
                            event));
        }
    }

    @Test
    public void canDispatchAccessibilityEvent_otherEvents_invalidWindowId_returnFalse() {
        final int invalidWindowId = WINDOWID;
        for (int i = 0; i < OTHER_EVENTS.length; i++) {
            final AccessibilityEvent event = AccessibilityEvent.obtain(OTHER_EVENTS[i]);
            event.setWindowId(invalidWindowId);
            assertFalse("Shouldn't dispatch [" + event + "]",
                    mA11ySecurityPolicy.canDispatchAccessibilityEventLocked(
                            UserHandle.USER_SYSTEM,
                            event));
        }
    }

    @Test
    public void canDispatchAccessibilityEvent_otherEvents_windowIdIsActive_returnTrue() {
        when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM))
                .thenReturn(WINDOWID);
        for (int i = 0; i < OTHER_EVENTS.length; i++) {
            final AccessibilityEvent event = AccessibilityEvent.obtain(OTHER_EVENTS[i]);
            event.setWindowId(WINDOWID);
            assertTrue("Should dispatch [" + event + "]",
                    mA11ySecurityPolicy.canDispatchAccessibilityEventLocked(
                            UserHandle.USER_SYSTEM,
                            event));
        }
    }

    @Test
    public void canDispatchAccessibilityEvent_otherEvents_windowIdExist_returnTrue() {
        when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM))
                .thenReturn(WINDOWID2);
        when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))
                .thenReturn(AccessibilityWindowInfo.obtain());
        for (int i = 0; i < OTHER_EVENTS.length; i++) {
            final AccessibilityEvent event = AccessibilityEvent.obtain(OTHER_EVENTS[i]);
            event.setWindowId(WINDOWID);
            assertTrue("Should dispatch [" + event + "]",
                    mA11ySecurityPolicy.canDispatchAccessibilityEventLocked(
                            UserHandle.USER_SYSTEM,
                            event));
        }
    }

    @Test
    public void resolveValidReportedPackage_nullPkgName_returnNull() {
        assertNull(mA11ySecurityPolicy.resolveValidReportedPackageLocked(
                null, Process.SYSTEM_UID, UserHandle.USER_SYSTEM));
    }

    @Test
    public void resolveValidReportedPackage_uidIsSystem_returnPkgName() {
        assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked(
                PACKAGE_NAME, Process.SYSTEM_UID, UserHandle.USER_SYSTEM),
                PACKAGE_NAME);
    }

    @Test
    public void resolveValidReportedPackage_uidAndPkgNameMatched_returnPkgName()
            throws PackageManager.NameNotFoundException {
        when(mMockPackageManager.getPackageUidAsUser(PACKAGE_NAME, UserHandle.USER_SYSTEM))
                .thenReturn(APP_UID);

        assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked(
                PACKAGE_NAME, APP_UID, UserHandle.USER_SYSTEM),
                PACKAGE_NAME);
    }

    @Test
    public void resolveValidReportedPackage_uidIsWidgetHost_pkgNameIsAppWidget_returnPkgName()
            throws PackageManager.NameNotFoundException {
        final int widgetHostUid = APP_UID;
        final String hostPackageName = PACKAGE_NAME;
        final String widgetPackageName = PACKAGE_NAME2;
        final ArraySet<String> widgetPackages = new ArraySet<>();
        widgetPackages.add(widgetPackageName);

        when(mMockAppWidgetManager.getHostedWidgetPackages(widgetHostUid))
                .thenReturn(widgetPackages);
        when(mMockPackageManager.getPackageUidAsUser(hostPackageName, UserHandle.USER_SYSTEM))
                .thenReturn(widgetHostUid);

        assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked(
                widgetPackageName, widgetHostUid, UserHandle.USER_SYSTEM),
                widgetPackageName);
    }

    @Test
    public void resolveValidReportedPackage_pkgNameIsInvalid_returnFirstCorrectPkgName()
            throws PackageManager.NameNotFoundException {
        final String invalidPackageName = "x";
        final String[] uidPackages = {PACKAGE_NAME, PACKAGE_NAME2};
        when(mMockPackageManager.getPackagesForUid(APP_UID))
                .thenReturn(uidPackages);
        when(mMockPackageManager.getPackageUidAsUser(invalidPackageName, UserHandle.USER_SYSTEM))
                .thenThrow(PackageManager.NameNotFoundException.class);
        when(mMockAppWidgetManager.getHostedWidgetPackages(APP_UID))
                .thenReturn(new ArraySet<>());

        assertEquals(mA11ySecurityPolicy.resolveValidReportedPackageLocked(
                invalidPackageName, APP_UID, UserHandle.USER_SYSTEM),
                PACKAGE_NAME);
    }

    @Test
    public void computeValidReportedPackages_uidIsSystem_returnEmptyArray() {
        assertThat(mA11ySecurityPolicy.computeValidReportedPackages(
                PACKAGE_NAME, Process.SYSTEM_UID), emptyArray());
    }

    @Test
    public void computeValidReportedPackages_uidIsAppWidgetHost_returnTargetAndWidgetName() {
        final int widgetHostUid = APP_UID;
        final String targetPackageName =  PACKAGE_NAME;
        final String widgetPackageName = PACKAGE_NAME2;
        final ArraySet<String> widgetPackages = new ArraySet<>();
        widgetPackages.add(widgetPackageName);
        when(mMockAppWidgetManager.getHostedWidgetPackages(widgetHostUid))
                .thenReturn(widgetPackages);

        List<String> packages = Arrays.asList(mA11ySecurityPolicy.computeValidReportedPackages(
                targetPackageName, widgetHostUid));
        assertThat(packages, hasSize(2));
        assertThat(packages, containsInAnyOrder(targetPackageName, widgetPackageName));
    }

    @Test
    public void canGetAccessibilityNodeInfo_windowIdNotExist_returnFalse() {
        final int invalidWindowId = WINDOWID;
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);

        assertFalse(mA11ySecurityPolicy.canGetAccessibilityNodeInfoLocked(UserHandle.USER_SYSTEM,
                mMockA11yServiceConnection, invalidWindowId));
    }

    @Test
    public void canGetAccessibilityNodeInfo_hasCapAndWindowIsActive_returnTrue() {
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
        when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM))
                .thenReturn(WINDOWID);

        assertTrue(mA11ySecurityPolicy.canGetAccessibilityNodeInfoLocked(UserHandle.USER_SYSTEM,
                mMockA11yServiceConnection, WINDOWID));
    }

    @Test
    public void canGetAccessibilityNodeInfo_hasCapAndWindowExist_returnTrue() {
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
        when(mMockA11yWindowManager.getActiveWindowId(UserHandle.USER_SYSTEM))
                .thenReturn(WINDOWID2);
        when(mMockA11yWindowManager.findA11yWindowInfoByIdLocked(WINDOWID))
                .thenReturn(AccessibilityWindowInfo.obtain());

        assertTrue(mA11ySecurityPolicy.canGetAccessibilityNodeInfoLocked(UserHandle.USER_SYSTEM,
                mMockA11yServiceConnection, WINDOWID));
    }

    @Test
    public void canRetrieveWindows_retrieveWindowsFlagIsFalse_returnFalse() {
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);

        assertFalse(mA11ySecurityPolicy.canRetrieveWindowsLocked(mMockA11yServiceConnection));
    }

    @Test
    public void canRetrieveWindows_hasCapabilityAndRetrieveWindowsFlag_returnTrue() {
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
        mMockA11yServiceConnection.mRetrieveInteractiveWindows = true;

        assertTrue(mA11ySecurityPolicy.canRetrieveWindowsLocked(mMockA11yServiceConnection));
    }

    @Test
    public void canRetrieveWindowContent_hasCapability_returnTrue() {
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);

        assertTrue(mA11ySecurityPolicy.canRetrieveWindowContentLocked(mMockA11yServiceConnection));
    }

    @Test
    public void canControlMagnification_hasCapability_returnTrue() {
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_CONTROL_MAGNIFICATION);

        assertTrue(mA11ySecurityPolicy.canControlMagnification(mMockA11yServiceConnection));
    }

    @Test
    public void canPerformGestures_hasCapability_returnTrue() {
        assertFalse(mA11ySecurityPolicy.canPerformGestures(mMockA11yServiceConnection));
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_PERFORM_GESTURES);

        assertTrue(mA11ySecurityPolicy.canPerformGestures(mMockA11yServiceConnection));
    }

    @Test
    public void canCaptureFingerprintGestures_hasCapability_returnTrue() {
        assertFalse(mA11ySecurityPolicy.canCaptureFingerprintGestures(mMockA11yServiceConnection));
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES);

        assertTrue(mA11ySecurityPolicy.canCaptureFingerprintGestures(mMockA11yServiceConnection));
    }

    @Test
    public void canTakeScreenshot_hasCapability_returnTrue() {
        when(mMockA11yServiceConnection.getCapabilities())
                .thenReturn(AccessibilityServiceInfo.CAPABILITY_CAN_TAKE_SCREENSHOT);

        assertTrue(mA11ySecurityPolicy.canTakeScreenshotLocked(mMockA11yServiceConnection));
    }

    @Test
    public void resolveProfileParent_userIdIsCurrentUser_returnCurrentUser() {
        final int currentUserId = 10;
        final int userId = currentUserId;
        when(mMockA11yUserManager.getCurrentUserIdLocked())
                .thenReturn(currentUserId);

        assertEquals(mA11ySecurityPolicy.resolveProfileParentLocked(userId),
                currentUserId);
    }

    @Test
    public void resolveProfileParent_userIdNotCurrentUser_shouldGetProfileParent() {
        final int userId = 15;
        final int currentUserId = 20;
        when(mMockA11yUserManager.getCurrentUserIdLocked()).thenReturn(currentUserId);

        mA11ySecurityPolicy.resolveProfileParentLocked(userId);
        verify(mMockUserManager).getProfileParent(userId);
    }

    @Test
    public void resolveCallingUserId_userIdIsCallingUser_shouldResolveProfileParent() {
        final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy);
        final int callingUserId = UserHandle.getUserId(Process.myUid());
        final int userId = callingUserId;

        spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(userId);
        verify(spySecurityPolicy).resolveProfileParentLocked(userId);
    }

    @Test
    public void resolveCallingUserId_callingParentIsCurrentUser_returnCurrentUser() {
        final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy);
        final int callingUserId = UserHandle.getUserId(Process.myUid());
        final int callingParentId = 20;
        final int currentUserId = callingParentId;
        when(mMockA11yUserManager.getCurrentUserIdLocked())
                .thenReturn(currentUserId);
        doReturn(callingParentId).when(spySecurityPolicy).resolveProfileParentLocked(
                callingUserId);

        assertEquals(spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
                UserHandle.USER_CURRENT_OR_SELF), currentUserId);

    }

    @Test(expected = SecurityException.class)
    public void resolveCallingUserId_callingParentNotCurrentUserAndNoPerm_shouldException() {
        final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy);
        final int callingUserId = UserHandle.getUserId(Process.myUid());
        final int callingParentId = 20;
        final int currentUserId = 30;
        when(mMockA11yUserManager.getCurrentUserIdLocked())
                .thenReturn(currentUserId);
        doReturn(callingParentId).when(spySecurityPolicy).resolveProfileParentLocked(
                callingUserId);
        when(mMockContext.checkCallingPermission(any()))
                .thenReturn(PackageManager.PERMISSION_DENIED);

        spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
                UserHandle.USER_CURRENT_OR_SELF);
    }

    @Test(expected = IllegalArgumentException.class)
    public void resolveCallingUserId_callingParentNotCurrentUser_userIdIsInvalid_shouldException() {
        final AccessibilitySecurityPolicy spySecurityPolicy = Mockito.spy(mA11ySecurityPolicy);
        final int callingUserId = UserHandle.getUserId(Process.myUid());
        final int callingParentId = 20;
        final int currentUserId = 30;
        final int invalidUserId = 40;
        when(mMockA11yUserManager.getCurrentUserIdLocked())
                .thenReturn(currentUserId);
        doReturn(callingParentId).when(spySecurityPolicy).resolveProfileParentLocked(
                callingUserId);
        when(mMockContext.checkCallingPermission(any()))
                .thenReturn(PackageManager.PERMISSION_GRANTED);

        spySecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(invalidUserId);
    }

    @Test
    public void canRegisterService_shouldCheckAppOps() {
        final ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.applicationInfo = new ApplicationInfo();
        serviceInfo.packageName = PACKAGE_NAME;
        serviceInfo.name = AccessibilitySecurityPolicyTest.class.getSimpleName();

        assertFalse(mA11ySecurityPolicy.canRegisterService(serviceInfo));
        serviceInfo.permission = android.Manifest.permission.BIND_ACCESSIBILITY_SERVICE;
        mA11ySecurityPolicy.canRegisterService(serviceInfo);
        verify(mMockAppOpsManager).noteOpNoThrow(AppOpsManager.OPSTR_BIND_ACCESSIBILITY_SERVICE,
                serviceInfo.applicationInfo.uid, serviceInfo.packageName);
    }

    @Test
    public void checkAccessibilityAccess_shouldCheckAppOps() {
        final AccessibilityServiceInfo mockServiceInfo = Mockito.mock(
                AccessibilityServiceInfo.class);
        final ResolveInfo mockResolveInfo = Mockito.mock(
                ResolveInfo.class);
        final ServiceInfo serviceInfo = new ServiceInfo();
        serviceInfo.applicationInfo = new ApplicationInfo();
        serviceInfo.applicationInfo.uid = APP_UID;
        mockResolveInfo.serviceInfo = serviceInfo;

        when(mMockA11yServiceConnection.getServiceInfo()).thenReturn(mockServiceInfo);
        when(mockServiceInfo.getResolveInfo()).thenReturn(mockResolveInfo);
        when(mMockA11yServiceConnection.getComponentName())
                .thenReturn(new ComponentName(
                        PACKAGE_NAME, AccessibilitySecurityPolicyTest.class.getSimpleName()));

        mA11ySecurityPolicy.checkAccessibilityAccess(mMockA11yServiceConnection);
        verify(mMockAppOpsManager).noteOpNoThrow(AppOpsManager.OPSTR_ACCESS_ACCESSIBILITY,
                APP_UID, PACKAGE_NAME);
    }
}
