/*
 * Copyright (C) 2022 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 android.security.cts.CVE_2021_39796;

import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;

import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNoException;
import static org.junit.Assume.assumeNotNull;
import static org.junit.Assume.assumeTrue;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.provider.Settings;

import androidx.test.runner.AndroidJUnit4;
import androidx.test.uiautomator.By;
import androidx.test.uiautomator.UiDevice;
import androidx.test.uiautomator.Until;

import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.IOException;
import java.util.List;
import java.util.regex.Pattern;

@RunWith(AndroidJUnit4.class)
public class DeviceTest {
    private static final int LAUNCH_TIMEOUT_MS = 20000;

    private void startOverlayService() {
        Context context = getApplicationContext();
        assumeNotNull(context);
        Intent intent = new Intent(context, PocService.class);

        assumeTrue(context.getString(R.string.canNotDrawOverlaysMsg),
                Settings.canDrawOverlays(getApplicationContext()));
        try {
            context.startService(intent);
        } catch (Exception e) {
            assumeNoException(context.getString(R.string.overlayServiceNotStartedException), e);
        }
    }

    public void startVulnerableActivity() {
        Context context = getApplicationContext();
        Intent intent = new Intent();
        intent.setClassName(context.getString(R.string.vulnerablePkg),
                context.getString(R.string.vulnerableActivity));
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(intent);

        PackageManager pm = getApplicationContext().getPackageManager();
        List<ResolveInfo> ris = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
        String vulnerableActivityName = context.getString(R.string.vulnerablePkg) + "/"
                + context.getString(R.string.vulnerableActivity);

        assumeTrue(context.getString(R.string.activityNotFoundMsg) + vulnerableActivityName,
                ris.size() != 0);
        try {
            context.startActivity(intent);
        } catch (Exception e) {
            assumeNoException(context.getString(R.string.activityNotStartedException) + intent, e);
        }
    }

    @Test
    public void testOverlayButtonPresence() {
        Context context = getApplicationContext();
        UiDevice mDevice = UiDevice.getInstance(getInstrumentation());

        /* Start the overlay service */
        startOverlayService();

        /* Wait for the overlay window */
        Pattern overlayTextPattern = Pattern.compile(context.getString(R.string.overlayButtonText),
                Pattern.CASE_INSENSITIVE);
        assumeTrue(context.getString(R.string.overlayUiScreenError),
                mDevice.wait(Until.hasObject(By.text(overlayTextPattern)), LAUNCH_TIMEOUT_MS));

        /* Start the vulnerable activity */
        startVulnerableActivity();

        /* Wait until the object of launcher activity is gone */
        boolean overlayDisallowed = mDevice
                .wait(Until.gone(By.pkg(context.getString(R.string.testPkg))), LAUNCH_TIMEOUT_MS);

        /* Check if the currently running activity is the vulnerable activity */
        String activityDump = "";
        try {
            activityDump = mDevice.executeShellCommand(context.getString(R.string.dumpsysActivity)
                    + " " + context.getString(R.string.harmfulActivity));
        } catch (IOException e) {
            assumeNoException(context.getString(R.string.dumpsysActivityNotStartedException), e);
        }
        Pattern activityPattern =
                Pattern.compile(context.getString(R.string.mResumedTrue), Pattern.CASE_INSENSITIVE);
        assumeTrue(context.getString(R.string.vulActivityNotRunningError),
                activityPattern.matcher(activityDump).find());

        assertTrue(context.getString(R.string.errorMessage), overlayDisallowed);
    }
}
