/*
 * 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.settings.applications;

import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.os.UserHandle;
import android.os.UserManager;

import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.TestConfig;
import com.android.settings.testutils.shadow.ShadowUserManager;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowApplication;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Set;

import static com.android.settings.testutils.ApplicationTestUtils.buildInfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.anyObject;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

/**
 * Tests for {@link InstalledAppCounter}.
 */
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
        shadows = {ShadowUserManager.class})
public final class InstalledAppCounterTest {

    private final String APP_1 = "app1";
    private final String APP_2 = "app2";
    private final String APP_3 = "app3";
    private final String APP_4 = "app4";
    private final String APP_5 = "app5";
    private final String APP_6 = "app6";

    private final int MAIN_USER_ID = 0;
    private final int MANAGED_PROFILE_ID = 10;

    private final int PER_USER_UID_RANGE = 100000;
    private final int MAIN_USER_APP_UID = MAIN_USER_ID * PER_USER_UID_RANGE;
    private final int MANAGED_PROFILE_APP_UID = MANAGED_PROFILE_ID * PER_USER_UID_RANGE;

    @Mock
    private UserManager mUserManager;
    @Mock
    private Context mContext;
    @Mock
    private PackageManagerWrapper mPackageManager;

    private int mInstalledAppCount = -1;
    private ApplicationInfo mApp1;
    private ApplicationInfo mApp2;
    private ApplicationInfo mApp3;
    private ApplicationInfo mApp4;
    private ApplicationInfo mApp5;
    private ApplicationInfo mApp6;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);

        mApp1 = buildInfo(MAIN_USER_APP_UID, APP_1,
                ApplicationInfo.FLAG_UPDATED_SYSTEM_APP, 0 /* targetSdkVersion */);
        mApp2 = buildInfo(MAIN_USER_APP_UID, APP_2, 0 /* flags */,
                0 /* targetSdkVersion */);
        mApp3 = buildInfo(MAIN_USER_APP_UID, APP_3, ApplicationInfo.FLAG_SYSTEM,
                0 /* targetSdkVersion */);
        mApp4 = buildInfo(MAIN_USER_APP_UID, APP_4, ApplicationInfo.FLAG_SYSTEM,
                0 /* targetSdkVersion */);
        mApp5 = buildInfo(MANAGED_PROFILE_APP_UID, APP_5, 0 /* flags */,
                0 /* targetSdkVersion */);
        mApp6 = buildInfo(MANAGED_PROFILE_APP_UID, APP_6, ApplicationInfo.FLAG_SYSTEM,
                0 /* targetSdkVersion */);
    }

    private void expectQueryIntentActivities(int userId, String packageName, boolean launchable) {
        when(mPackageManager.queryIntentActivitiesAsUser(
                argThat(new IsLaunchIntentFor(packageName)),
                eq(PackageManager.GET_DISABLED_COMPONENTS | PackageManager.MATCH_DIRECT_BOOT_AWARE
                        | PackageManager.MATCH_DIRECT_BOOT_UNAWARE),
                eq(userId))).thenReturn(launchable ? Arrays.asList(new ResolveInfo())
                : new ArrayList<ResolveInfo>());
    }

    private void testCountInstalledAppsAcrossAllUsers(boolean async) {
        // There are two users.
        when(mUserManager.getProfiles(UserHandle.myUserId())).thenReturn(Arrays.asList(
                new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN),
                new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0)));
        configurePackageManager();

        // Count the number of all apps installed, irrespective of install reason.
        count(InstalledAppCounter.IGNORE_INSTALL_REASON, async);
        assertThat(mInstalledAppCount).isEqualTo(5);

        // Verify that installed packages were retrieved the current user and the user's managed
        // profile only.
        verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), eq(MAIN_USER_ID));
        verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(),
                eq(MANAGED_PROFILE_ID));
        verify(mPackageManager, atLeast(0)).queryIntentActivitiesAsUser(anyObject(), anyInt(),
                anyInt());
        verifyNoMoreInteractions(mPackageManager);

        // Count once more, considering apps installed by enterprise policy only.
        count(PackageManager.INSTALL_REASON_POLICY, async);
        assertThat(mInstalledAppCount).isEqualTo(3);
    }

    @Test
    public void testIncludeInCount() {
        configurePackageManager();
        assertThat(InstalledAppCounter.includeInCount(InstalledAppCounter.IGNORE_INSTALL_REASON,
                mPackageManager, mApp1)).isTrue();
        assertThat(InstalledAppCounter.includeInCount(InstalledAppCounter.IGNORE_INSTALL_REASON,
                mPackageManager, mApp2)).isTrue();
        assertThat(InstalledAppCounter.includeInCount(InstalledAppCounter.IGNORE_INSTALL_REASON,
                mPackageManager, mApp3)).isTrue();
        assertThat(InstalledAppCounter.includeInCount(InstalledAppCounter.IGNORE_INSTALL_REASON,
                mPackageManager, mApp4)).isFalse();
        assertThat(InstalledAppCounter.includeInCount(InstalledAppCounter.IGNORE_INSTALL_REASON,
                mPackageManager, mApp5)).isTrue();
        assertThat(InstalledAppCounter.includeInCount(InstalledAppCounter.IGNORE_INSTALL_REASON,
                mPackageManager, mApp6)).isTrue();

        assertThat(InstalledAppCounter.includeInCount(PackageManager.INSTALL_REASON_POLICY,
                mPackageManager, mApp1)).isTrue();
        assertThat(InstalledAppCounter.includeInCount(PackageManager.INSTALL_REASON_POLICY,
                mPackageManager, mApp2)).isFalse();
        assertThat(InstalledAppCounter.includeInCount(PackageManager.INSTALL_REASON_POLICY,
                mPackageManager, mApp3)).isTrue();
        assertThat(InstalledAppCounter.includeInCount(PackageManager.INSTALL_REASON_POLICY,
                mPackageManager, mApp4)).isFalse();
        assertThat(InstalledAppCounter.includeInCount(PackageManager.INSTALL_REASON_POLICY,
                mPackageManager, mApp5)).isTrue();
        assertThat(InstalledAppCounter.includeInCount(PackageManager.INSTALL_REASON_POLICY,
                mPackageManager, mApp6)).isFalse();
    }

    @Test
    public void testCountInstalledAppsAcrossAllUsersSync() {
        testCountInstalledAppsAcrossAllUsers(false /* async */);
    }

    @Test
    public void testCountInstalledAppsAcrossAllUsersAsync() {
        testCountInstalledAppsAcrossAllUsers(true /* async */);
    }

    private void count(int installReason, boolean async) {
        mInstalledAppCount = -1;
        final InstalledAppCounterTestable counter = new InstalledAppCounterTestable(installReason);
        if (async) {
            counter.execute();
            // Wait for the background task to finish.
            ShadowApplication.runBackgroundTasks();
        } else {
            counter.executeInForeground();
        }
    }

    private void configurePackageManager() {
        // The first user has four apps installed:
        // * app1 is an updated system app. It should be counted.
        // * app2 is a user-installed app. It should be counted.
        // * app3 is a system app that provides a launcher icon. It should be counted.
        // * app4 is a system app that provides no launcher icon. It should not be counted.
        when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
                | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
                | PackageManager.MATCH_ANY_USER,
                MAIN_USER_ID)).thenReturn(Arrays.asList(mApp1, mApp2, mApp3, mApp4));
        // For system apps, InstalledAppCounter checks whether they handle the default launcher
        // intent to decide whether to include them in the count of installed apps or not.
        expectQueryIntentActivities(MAIN_USER_ID, APP_3, true /* launchable */);
        expectQueryIntentActivities(MAIN_USER_ID, APP_4, false /* launchable */);

        // app1, app3 and app4 are installed by enterprise policy.
        final UserHandle mainUser = new UserHandle(MAIN_USER_ID);
        when(mPackageManager.getInstallReason(APP_1, mainUser))
                .thenReturn(PackageManager.INSTALL_REASON_POLICY);
        when(mPackageManager.getInstallReason(APP_2, mainUser))
                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
        when(mPackageManager.getInstallReason(APP_3, mainUser))
                .thenReturn(PackageManager.INSTALL_REASON_POLICY);
        when(mPackageManager.getInstallReason(APP_4, mainUser))
                .thenReturn(PackageManager.INSTALL_REASON_POLICY);

        // The second user has two apps installed:
        // * app5 is a user-installed app. It should be counted.
        // * app6 is a system app that provides a launcher icon. It should be counted.
        when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
                | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,MANAGED_PROFILE_ID))
                .thenReturn(Arrays.asList(mApp5, mApp6));
        expectQueryIntentActivities(MANAGED_PROFILE_ID, APP_6, true /* launchable */);

        // app5 is installed by enterprise policy.
        final UserHandle managedProfileUser = new UserHandle(MANAGED_PROFILE_ID);
        when(mPackageManager.getInstallReason(APP_5, managedProfileUser))
                .thenReturn(PackageManager.INSTALL_REASON_POLICY);
        when(mPackageManager.getInstallReason(APP_6, managedProfileUser))
                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
    }


    private class InstalledAppCounterTestable extends InstalledAppCounter {
        public InstalledAppCounterTestable(int installReason) {
            super(mContext, installReason, mPackageManager);
        }

        @Override
        protected void onCountComplete(int num) {
            mInstalledAppCount = num;
        }
    }

    private static class IsLaunchIntentFor extends ArgumentMatcher<Intent> {
        private final String mPackageName;

        IsLaunchIntentFor(String packageName) {
            mPackageName = packageName;
        }

        @Override
        public boolean matches(Object i) {
            final Intent intent = (Intent) i;
            if (intent == null) {
                return false;
            }
            if (!Intent.ACTION_MAIN.equals(intent.getAction())) {
                return false;
            }
            final Set<String> categories = intent.getCategories();
            if (categories == null || categories.size() != 1 ||
                    !categories.contains(Intent.CATEGORY_LAUNCHER)) {
                return false;
            }
            if (!mPackageName.equals(intent.getPackage())) {
                return false;
            }
            return true;
        }
    }
}
