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

import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.server.am.ProtoExtractors.extract;
import static android.server.am.StateLogger.log;
import static android.server.am.StateLogger.logE;
import static android.view.Display.DEFAULT_DISPLAY;

import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.ParcelFileDescriptor;
import android.os.SystemClock;
import android.view.nano.DisplayInfoProto;

import androidx.test.InstrumentationRegistry;

import com.android.server.wm.nano.AppTransitionProto;
import com.android.server.wm.nano.AppWindowTokenProto;
import com.android.server.wm.nano.ConfigurationContainerProto;
import com.android.server.wm.nano.DisplayProto;
import com.android.server.wm.nano.IdentifierProto;
import com.android.server.wm.nano.PinnedStackControllerProto;
import com.android.server.wm.nano.StackProto;
import com.android.server.wm.nano.TaskProto;
import com.android.server.wm.nano.WindowContainerProto;
import com.android.server.wm.nano.WindowManagerServiceDumpProto;
import com.android.server.wm.nano.WindowStateAnimatorProto;
import com.android.server.wm.nano.WindowStateProto;
import com.android.server.wm.nano.WindowSurfaceControllerProto;
import com.android.server.wm.nano.WindowTokenProto;

import com.google.protobuf.nano.InvalidProtocolBufferNanoException;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class WindowManagerState {
    private static final String DUMPSYS_WINDOW = "dumpsys window -a --proto";

    private static final String STARTING_WINDOW_PREFIX = "Starting ";
    private static final String DEBUGGER_WINDOW_PREFIX = "Waiting For Debugger: ";

    // Windows in z-order with the top most at the front of the list.
    private List<WindowState> mWindowStates = new ArrayList();
    // Stacks in z-order with the top most at the front of the list, starting with primary display.
    private final List<WindowStack> mStacks = new ArrayList();
    // Stacks on all attached displays, in z-order with the top most at the front of the list.
    private final Map<Integer, List<WindowStack>> mDisplayStacks
            = new HashMap<>();
    private List<Display> mDisplays = new ArrayList();
    private String mFocusedWindow = null;
    private String mFocusedApp = null;
    private Rect mDefaultPinnedStackBounds = new Rect();
    private Rect mPinnedStackMovementBounds = new Rect();
    private final LinkedList<String> mSysDump = new LinkedList();
    private int mRotation;
    private boolean mIsDockedStackMinimized;

    public void computeState() {
        // It is possible the system is in the middle of transition to the right state when we get
        // the dump. We try a few times to get the information we need before giving up.
        int retriesLeft = 3;
        boolean retry = false;
        byte[] dump = null;

        log("==============================");
        log("      WindowManagerState      ");
        log("==============================");
        do {
            if (retry) {
                log("***Incomplete WM state. Retrying...");
                // Wait half a second between retries for window manager to finish transitioning...
                SystemClock.sleep(500);
            }

            dump = executeShellCommand(DUMPSYS_WINDOW);
            try {
                parseSysDumpProto(dump);
            } catch (InvalidProtocolBufferNanoException ex) {
                throw new RuntimeException("Failed to parse dumpsys:\n"
                        + new String(dump, StandardCharsets.UTF_8), ex);
            }

            retry = mWindowStates.isEmpty() || mFocusedApp == null;
        } while (retry && retriesLeft-- > 0);

        if (mWindowStates.isEmpty()) {
            logE("No Windows found...");
        }
        if (mFocusedWindow == null) {
            logE("No Focused Window...");
        }
        if (mFocusedApp == null) {
            logE("No Focused App...");
        }
    }

    private byte[] executeShellCommand(String cmd) {
        try {
            ParcelFileDescriptor pfd =
                    InstrumentationRegistry.getInstrumentation().getUiAutomation()
                            .executeShellCommand(cmd);
            byte[] buf = new byte[512];
            int bytesRead;
            FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
            ByteArrayOutputStream stdout = new ByteArrayOutputStream();
            while ((bytesRead = fis.read(buf)) != -1) {
                stdout.write(buf, 0, bytesRead);
            }
            fis.close();
            return stdout.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    private void parseSysDumpProto(byte[] sysDump) throws InvalidProtocolBufferNanoException {
        reset();
        WindowManagerServiceDumpProto state = WindowManagerServiceDumpProto.parseFrom(sysDump);
        List<WindowState> allWindows = new ArrayList<>();
        Map<String, WindowState> windowMap = new HashMap<>();
        if (state.focusedWindow != null) {
            mFocusedWindow = state.focusedWindow.title;
        }
        mFocusedApp = state.focusedApp;
        for (int i = 0; i < state.rootWindowContainer.displays.length; i++) {
            DisplayProto displayProto = state.rootWindowContainer.displays[i];
            final Display display = new Display(displayProto);
            mDisplays.add(display);
            allWindows.addAll(display.getWindows());
            List<WindowStack> stacks = new ArrayList<>();
            for (int j = 0; j < displayProto.stacks.length; j++) {
                StackProto stackProto = displayProto.stacks[j];
                final WindowStack stack = new WindowStack(stackProto);
                mStacks.add(stack);
                stacks.add(stack);
                allWindows.addAll(stack.getWindows());
            }
            mDisplayStacks.put(display.mDisplayId, stacks);

            // use properties from the default display only
            if (display.getDisplayId() == DEFAULT_DISPLAY) {
                if (displayProto.dockedStackDividerController != null) {
                    mIsDockedStackMinimized =
                            displayProto.dockedStackDividerController.minimizedDock;
                }
                PinnedStackControllerProto pinnedStackProto = displayProto.pinnedStackController;
                if (pinnedStackProto != null) {
                    mDefaultPinnedStackBounds = extract(pinnedStackProto.defaultBounds);
                    mPinnedStackMovementBounds = extract(pinnedStackProto.movementBounds);
                }
            }
        }
        for (WindowState w : allWindows) {
            windowMap.put(w.getToken(), w);
        }
        for (int i = 0; i < state.rootWindowContainer.windows.length; i++) {
            IdentifierProto identifierProto = state.rootWindowContainer.windows[i];
            String hash_code = Integer.toHexString(identifierProto.hashCode);
            mWindowStates.add(windowMap.get(hash_code));
        }
        mRotation = state.rotation;
        AppTransitionProto appTransitionProto = state.appTransition;
    }

    public void getMatchingVisibleWindowState(final String windowName, List<WindowState> windowList) {
        windowList.clear();
        for (WindowState ws : mWindowStates) {
            if (ws.isShown() && windowName.equals(ws.getName())) {
                windowList.add(ws);
            }
        }
    }

    public WindowState getWindowByPackageName(String packageName, int windowType) {
        for (WindowState ws : mWindowStates) {
            final String name = ws.getName();
            if (name == null || !name.contains(packageName)) {
                continue;
            }
            if (windowType != ws.getType()) {
                continue;
            }
            return ws;
        }

        return null;
    }

    public void getWindowsByPackageName(String packageName, List<Integer> restrictToTypeList,
            List<WindowState> outWindowList) {
        outWindowList.clear();
        for (WindowState ws : mWindowStates) {
            final String name = ws.getName();
            if (name == null || !name.contains(packageName)) {
                continue;
            }
            if (restrictToTypeList != null && !restrictToTypeList.contains(ws.getType())) {
                continue;
            }
            outWindowList.add(ws);
        }
    }

    Display getDisplay(int displayId) {
        for (Display display : mDisplays) {
            if (displayId == display.getDisplayId()) {
                return display;
            }
        }
        return null;
    }

    List<Display> getDisplays() {
        return mDisplays;
    }

    String getFrontWindow() {
        if (mWindowStates == null || mWindowStates.isEmpty()) {
            return null;
        }
        return mWindowStates.get(0).getName();
    }

    public String getFocusedWindow() {
        return mFocusedWindow;
    }

    public String getFocusedApp() {
        return mFocusedApp;
    }

    public int getRotation() {
        return mRotation;
    }

    /**
     * Check if at least one window which matches provided window name is visible.
     */
    boolean isWindowVisible(String windowName) {
        for (WindowState window : mWindowStates) {
            if (window.getName().equals(windowName)) {
                if (window.isShown()) {
                    return true;
                }
            }
        }
        return false;
    }

    WindowStack getStack(int stackId) {
        for (WindowStack stack : mStacks) {
            if (stackId == stack.mStackId) {
                return stack;
            }
        }
        return null;
    }

    public boolean isDockedStackMinimized() {
        return mIsDockedStackMinimized;
    }

    public int getZOrder(WindowState w) {
        return mWindowStates.size() - mWindowStates.indexOf(w);
    }

    private void reset() {
        mSysDump.clear();
        mStacks.clear();
        mDisplays.clear();
        mWindowStates.clear();
        mDisplayStacks.clear();
        mFocusedWindow = null;
        mFocusedApp = null;
        mIsDockedStackMinimized = false;
        mDefaultPinnedStackBounds.setEmpty();
        mPinnedStackMovementBounds.setEmpty();
        mRotation = 0;
    }

    static class WindowStack extends WindowContainer {

        int mStackId;
        ArrayList<WindowTask> mTasks = new ArrayList<>();
        boolean mWindowAnimationBackgroundSurfaceShowing;

        WindowStack(StackProto proto) {
            super(proto.windowContainer);
            mStackId = proto.id;
            mFullscreen = proto.fillsParent;
            mBounds = extract(proto.bounds);
            for (int i = 0; i < proto.tasks.length; i++) {
                TaskProto taskProto = proto.tasks[i];
                WindowTask task = new WindowTask(taskProto);
                mTasks.add(task);
                mSubWindows.addAll(task.getWindows());
            }
            mWindowAnimationBackgroundSurfaceShowing = proto.animationBackgroundSurfaceIsDimming;
        }

        WindowTask getTask(int taskId) {
            for (WindowTask task : mTasks) {
                if (taskId == task.mTaskId) {
                    return task;
                }
            }
            return null;
        }
    }

    static class WindowTask extends WindowContainer {

        int mTaskId;
        Rect mTempInsetBounds;
        List<String> mAppTokens = new ArrayList<>();

        WindowTask(TaskProto proto) {
            super(proto.windowContainer);
            mTaskId = proto.id;
            mFullscreen = proto.fillsParent;
            mBounds = extract(proto.bounds);
            for (int i = 0; i < proto.appWindowTokens.length; i++) {
                AppWindowTokenProto appWindowTokenProto = proto.appWindowTokens[i];
                mAppTokens.add(appWindowTokenProto.name);
                WindowTokenProto windowTokenProto = appWindowTokenProto.windowToken;
                for (int j = 0; j < windowTokenProto.windows.length; j++) {
                    WindowStateProto windowProto = windowTokenProto.windows[j];
                    WindowState window = new WindowState(windowProto);
                    mSubWindows.add(window);
                    mSubWindows.addAll(window.getWindows());
                }
            }
            mTempInsetBounds = extract(proto.tempInsetBounds);
        }
    }

    static class ConfigurationContainer {
        final Configuration mOverrideConfiguration = new Configuration();
        final Configuration mFullConfiguration = new Configuration();
        final Configuration mMergedOverrideConfiguration = new Configuration();

        ConfigurationContainer(ConfigurationContainerProto proto) {
            if (proto == null) {
                return;
            }
            mOverrideConfiguration.setTo(extract(proto.overrideConfiguration));
            mFullConfiguration.setTo(extract(proto.fullConfiguration));
            mMergedOverrideConfiguration.setTo(extract(proto.mergedOverrideConfiguration));
        }

        int getWindowingMode() {
            if (mFullConfiguration == null) {
                return WINDOWING_MODE_UNDEFINED;
            }
            return mFullConfiguration.windowConfiguration.getWindowingMode();
        }

        int getActivityType() {
            if (mFullConfiguration == null) {
                return ACTIVITY_TYPE_UNDEFINED;
            }
            return mFullConfiguration.windowConfiguration.getActivityType();
        }
    }

    static abstract class WindowContainer extends ConfigurationContainer {

        protected boolean mFullscreen;
        protected Rect mBounds;
        protected int mOrientation;
        protected List<WindowState> mSubWindows = new ArrayList<>();

        WindowContainer(WindowContainerProto proto) {
            super(proto.configurationContainer);
            mOrientation = proto.orientation;
        }

        Rect getBounds() {
            return mBounds;
        }

        boolean isFullscreen() {
            return mFullscreen;
        }

        List<WindowState> getWindows() {
            return mSubWindows;
        }
    }

    static class Display extends WindowContainer {

        private final int mDisplayId;
        private Rect mDisplayRect = new Rect();
        private Rect mAppRect = new Rect();
        private int mDpi;
        private String mName;

        public Display(DisplayProto proto) {
            super(proto.windowContainer);
            mDisplayId = proto.id;
            for (int i = 0; i < proto.aboveAppWindows.length; i++) {
                addWindowsFromTokenProto(proto.aboveAppWindows[i]);
            }
            for (int i = 0; i < proto.belowAppWindows.length; i++) {
                addWindowsFromTokenProto(proto.belowAppWindows[i]);
            }
            for (int i = 0; i < proto.imeWindows.length; i++) {
                addWindowsFromTokenProto(proto.imeWindows[i]);
            }
            mDpi = proto.dpi;
            DisplayInfoProto infoProto = proto.displayInfo;
            if (infoProto != null) {
                mDisplayRect.set(0, 0, infoProto.logicalWidth, infoProto.logicalHeight);
                mAppRect.set(0, 0, infoProto.appWidth, infoProto.appHeight);
                mName = infoProto.name;
            }
        }

        private void addWindowsFromTokenProto(WindowTokenProto proto) {
            for (int j = 0; j < proto.windows.length; j++) {
                WindowStateProto windowProto = proto.windows[j];
                WindowState childWindow = new WindowState(windowProto);
                mSubWindows.add(childWindow);
                mSubWindows.addAll(childWindow.getWindows());
            }
        }

        int getDisplayId() {
            return mDisplayId;
        }

        int getDpi() {
            return mDpi;
        }

        Rect getDisplayRect() {
            return mDisplayRect;
        }

        String getName() {
            return mName;
        }

        @Override
        public String toString() {
            return "Display #" + mDisplayId + ": name=" + mName + " mDisplayRect=" + mDisplayRect
                    + " mAppRect=" + mAppRect;
        }
    }

    public static class WindowState extends WindowContainer {

        private static final int WINDOW_TYPE_STARTING = 1;
        private static final int WINDOW_TYPE_EXITING = 2;
        private static final int WINDOW_TYPE_DEBUGGER = 3;

        private String mName;
        private final String mAppToken;
        private final int mWindowType;
        private int mType = 0;
        private int mDisplayId;
        private int mStackId;
        private boolean mShown;
        private Rect mContainingFrame = new Rect();
        private Rect mParentFrame = new Rect();
        private Rect mContentFrame = new Rect();
        private Rect mFrame = new Rect();
        private Rect mCrop = new Rect();

        WindowState(WindowStateProto proto) {
            super(proto.windowContainer);
            IdentifierProto identifierProto = proto.identifier;
            mName = identifierProto.title;
            mAppToken = Integer.toHexString(identifierProto.hashCode);
            mDisplayId = proto.displayId;
            mStackId = proto.stackId;
            if (proto.attributes != null) {
                mType = proto.attributes.type;
            }
            WindowStateAnimatorProto animatorProto = proto.animator;
            if (animatorProto != null) {
                if (animatorProto.surface != null) {
                    WindowSurfaceControllerProto surfaceProto = animatorProto.surface;
                    mShown = surfaceProto.shown;
                }
                mCrop = extract(animatorProto.lastClipRect);
            }
            mFrame = extract(proto.frame);
            mContainingFrame = extract(proto.containingFrame);
            mParentFrame = extract(proto.parentFrame);
            mContentFrame = extract(proto.contentFrame);
            if (mName.startsWith(STARTING_WINDOW_PREFIX)) {
                mWindowType = WINDOW_TYPE_STARTING;
                // Existing code depends on the prefix being removed
                mName = mName.substring(STARTING_WINDOW_PREFIX.length());
            } else if (proto.animatingExit) {
                mWindowType = WINDOW_TYPE_EXITING;
            } else if (mName.startsWith(DEBUGGER_WINDOW_PREFIX)) {
                mWindowType = WINDOW_TYPE_STARTING;
                mName = mName.substring(DEBUGGER_WINDOW_PREFIX.length());
            } else {
                mWindowType = 0;
            }
            for (int i = 0; i < proto.childWindows.length; i++) {
                WindowStateProto childProto = proto.childWindows[i];
                WindowState childWindow = new WindowState(childProto);
                mSubWindows.add(childWindow);
                mSubWindows.addAll(childWindow.getWindows());
            }
        }

        public String getName() {
            return mName;
        }

        String getToken() {
            return mAppToken;
        }

        int getDisplayId() {
            return mDisplayId;
        }

        int getStackId() {
            return mStackId;
        }

        public Rect getFrame() {
            return mFrame;
        }

        public Rect getContentFrame() {
            return mContentFrame;
        }

        Rect getCrop() {
            return mCrop;
        }

        public boolean isShown() {
            return mShown;
        }

        public int getType() {
            return mType;
        }

        private String getWindowTypeSuffix(int windowType) {
            switch (windowType) {
                case WINDOW_TYPE_STARTING:
                    return " STARTING";
                case WINDOW_TYPE_EXITING:
                    return " EXITING";
                case WINDOW_TYPE_DEBUGGER:
                    return " DEBUGGER";
                default:
                    break;
            }
            return "";
        }

        @Override
        public String toString() {
            return "WindowState: {" + mAppToken + " " + mName
                    + getWindowTypeSuffix(mWindowType) + "}" + " type=" + mType
                    + " cf=" + mContainingFrame + " pf=" + mParentFrame;
        }
    }
}
