/*
 * Copyright (C) 2017 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;

import static org.junit.Assert.assertEquals;

import android.app.Activity;
import android.app.Instrumentation;
import android.app.UiAutomation;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.Point;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.view.Gravity;
import android.view.InputDevice;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

import com.android.compatibility.common.util.PollingCheck;

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

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

@MediumTest
@RunWith(AndroidJUnit4.class)
public class MotionEventTest {
    private static final String TAG = "MotionEventTest";
    private Activity mActivity;
    private Instrumentation mInstrumentation;

    @Rule
    public ActivityTestRule<MotionEventTestActivity> mActivityRule =
            new ActivityTestRule<>(MotionEventTestActivity.class);

    @Before
    public void setup() {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mActivity = mActivityRule.getActivity();
        PollingCheck.waitFor(mActivity::hasWindowFocus);
    }

    /**
     * Test for whether ACTION_OUTSIDE events contain information about whether touches are
     * obscured.
     *
     * If ACTION_OUTSIDE_EVENTS contain information about whether the touch is obscured, then a
     * pattern of invisible, untouchable, unfocusable application overlays can be placed across the
     * screen to determine approximate locations of touch events without the user knowing.
     */
    @Test
    public void testActionOutsideDoesNotContainedObscuredInformation() throws Exception {
        enableAppOps();
        final OnTouchListener listener = new OnTouchListener();
        final Point size = new Point();
        final View[] viewHolder = new View[1];
        mActivity.runOnUiThread(() -> {
            final WindowManager wm = mActivity.getSystemService(WindowManager.class);
            wm.getDefaultDisplay().getSize(size);

            WindowManager.LayoutParams wmlp = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
                    WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
                    WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |
                    WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
            wmlp.width = size.x / 4;
            wmlp.height = size.y / 4;
            wmlp.gravity = Gravity.TOP | Gravity.LEFT;
            wmlp.setTitle(mActivity.getPackageName());

            ViewGroup.LayoutParams vglp = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT);

            View v = new View(mActivity);
            v.setOnTouchListener(listener);
            v.setBackgroundColor(Color.GREEN);
            v.setLayoutParams(vglp);
            wm.addView(v, wmlp);

            wmlp.gravity = Gravity.TOP | Gravity.RIGHT;

            v = new View(mActivity);
            v.setBackgroundColor(Color.BLUE);
            v.setOnTouchListener(listener);
            v.setLayoutParams(vglp);
            viewHolder[0] = v;

            wm.addView(v, wmlp);
        });
        mInstrumentation.waitForIdleSync();

        FutureTask<Point> task = new FutureTask<>(() -> {
            final int[] viewLocation = new int[2];
            viewHolder[0].getLocationOnScreen(viewLocation);
            return new Point(viewLocation[0], viewLocation[1]);
        });
        mActivity.runOnUiThread(task);
        Point viewLocation = task.get(5, TimeUnit.SECONDS);
        injectTap(viewLocation.x, viewLocation.y);

        List<MotionEvent> outsideEvents = listener.getOutsideEvents();

        if (isRunningInVR()) {
            // In VR mode we should be prevented from seeing any events.
            assertEquals(0, outsideEvents.size());
        } else {
            assertEquals(2, outsideEvents.size());
            for (MotionEvent e : outsideEvents) {
                assertEquals(0, e.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED);
            }
        }
    }


    private void enableAppOps() {
        StringBuilder cmd = new StringBuilder();
        cmd.append("appops set ");
        cmd.append(mInstrumentation.getContext().getPackageName());
        cmd.append(" android:system_alert_window allow");
        mInstrumentation.getUiAutomation().executeShellCommand(cmd.toString());

        StringBuilder query = new StringBuilder();
        query.append("appops get ");
        query.append(mInstrumentation.getContext().getPackageName());
        query.append(" android:system_alert_window");
        String queryStr = query.toString();

        String result;
        do {
            ParcelFileDescriptor pfd =
                    mInstrumentation.getUiAutomation().executeShellCommand(queryStr);
            InputStream inputStream = new FileInputStream(pfd.getFileDescriptor());
            result = convertStreamToString(inputStream);
        } while (result.contains("No operations"));
    }

    private String convertStreamToString(InputStream is) {
        try (Scanner s = new Scanner(is).useDelimiter("\\A")) {
            return s.hasNext() ? s.next() : "";
        }
    }

    private void injectTap(int x, int y) {
        long downTime = SystemClock.uptimeMillis();
        injectEvent(MotionEvent.ACTION_DOWN, x, y, downTime);
        injectEvent(MotionEvent.ACTION_UP, x, y, downTime);
    }

    private void injectEvent(int action, int x, int y, long downTime) {
        final UiAutomation automation = mInstrumentation.getUiAutomation();
        final long eventTime = SystemClock.uptimeMillis();
        MotionEvent event = MotionEvent.obtain(downTime, eventTime, action, x, y, 0);
        event.setSource(InputDevice.SOURCE_TOUCHSCREEN);
        automation.injectInputEvent(event, true);
        event.recycle();
    }

    private static class OnTouchListener implements View.OnTouchListener {
        private List<MotionEvent> mOutsideEvents;

        public OnTouchListener() {
            mOutsideEvents = new ArrayList<>();
        }

        public boolean onTouch(View v, MotionEvent e) {
            if (e.getAction() == MotionEvent.ACTION_OUTSIDE) {
                mOutsideEvents.add(MotionEvent.obtain(e));
            }
            return true;
        }

        public List<MotionEvent> getOutsideEvents() {
            return mOutsideEvents;
        }
    }

    private boolean isRunningInVR() {
        final Context context = InstrumentationRegistry.getTargetContext();
        return (context.getResources().getConfiguration().uiMode &
                Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_VR_HEADSET;
    }
}
