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

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import android.app.AppOpsManager;
import android.content.Context;
import android.content.res.AssetManager;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.util.SparseArray;
import android.util.Xml;

import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.xmlpull.v1.XmlPullParser;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * Tests app ops version upgrades
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AppOpsUpgradeTest {
    private static final String TAG = AppOpsUpgradeTest.class.getSimpleName();
    private static final String APP_OPS_UNVERSIONED_ASSET_PATH =
            "AppOpsUpgradeTest/appops-unversioned.xml";
    private static final String APP_OPS_FILENAME = "appops-test.xml";
    private static final int NON_DEFAULT_OPS_IN_FILE = 4;
    private static final int CURRENT_VERSION = 1;

    private File mAppOpsFile;
    private Context mContext;
    private Handler mHandler;

    private void extractAppOpsFile() {
        mAppOpsFile.getParentFile().mkdirs();
        if (mAppOpsFile.exists()) {
            mAppOpsFile.delete();
        }
        try (FileOutputStream out = new FileOutputStream(mAppOpsFile);
             InputStream in = mContext.getAssets().open(APP_OPS_UNVERSIONED_ASSET_PATH,
                     AssetManager.ACCESS_BUFFER)) {
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = in.read(buffer)) >= 0) {
                out.write(buffer, 0, bytesRead);
            }
            out.flush();
            Log.d(TAG, "Successfully copied xml to " + mAppOpsFile.getAbsolutePath());
        } catch (IOException exc) {
            Log.e(TAG, "Exception while copying appops xml", exc);
            fail();
        }
    }

    private void assertSameModes(SparseArray<AppOpsService.UidState> uidStates, int op1, int op2) {
        int numberOfNonDefaultOps = 0;
        final int defaultModeOp1 = AppOpsManager.opToDefaultMode(op1);
        final int defaultModeOp2 = AppOpsManager.opToDefaultMode(op2);
        for(int i = 0; i < uidStates.size(); i++) {
            final AppOpsService.UidState uidState = uidStates.valueAt(i);
            if (uidState.opModes != null) {
                final int uidMode1 = uidState.opModes.get(op1, defaultModeOp1);
                final int uidMode2 = uidState.opModes.get(op2, defaultModeOp2);
                assertEquals(uidMode1, uidMode2);
                if (uidMode1 != defaultModeOp1) {
                    numberOfNonDefaultOps++;
                }
            }
            if (uidState.pkgOps == null) {
                continue;
            }
            for (int j = 0; j < uidState.pkgOps.size(); j++) {
                final AppOpsService.Ops ops = uidState.pkgOps.valueAt(j);
                if (ops == null) {
                    continue;
                }
                final AppOpsService.Op _op1 = ops.get(op1);
                final AppOpsService.Op _op2 = ops.get(op2);
                final int mode1 = (_op1 == null) ? defaultModeOp1 : _op1.getMode();
                final int mode2 = (_op2 == null) ? defaultModeOp2 : _op2.getMode();
                assertEquals(mode1, mode2);
                if (mode1 != defaultModeOp1) {
                    numberOfNonDefaultOps++;
                }
            }
        }
        assertEquals(numberOfNonDefaultOps, NON_DEFAULT_OPS_IN_FILE);
    }

    @Before
    public void setUp() {
        mContext = InstrumentationRegistry.getTargetContext();
        mAppOpsFile = new File(mContext.getFilesDir(), APP_OPS_FILENAME);
        extractAppOpsFile();
        HandlerThread handlerThread = new HandlerThread(TAG);
        handlerThread.start();
        mHandler = new Handler(handlerThread.getLooper());
    }

    @Test
    public void testUpgradeFromNoVersion() throws Exception {
        AppOpsDataParser parser = new AppOpsDataParser(mAppOpsFile);
        assertTrue(parser.parse());
        assertEquals(AppOpsDataParser.NO_VERSION, parser.mVersion);
        AppOpsService testService = new AppOpsService(mAppOpsFile, mHandler); // trigger upgrade
        assertSameModes(testService.mUidStates, AppOpsManager.OP_RUN_IN_BACKGROUND,
                AppOpsManager.OP_RUN_ANY_IN_BACKGROUND);
        testService.mContext = mContext;
        mHandler.removeCallbacks(testService.mWriteRunner);
        testService.writeState();
        assertTrue(parser.parse());
        assertEquals(CURRENT_VERSION, parser.mVersion);
    }

    /**
     * Class to parse data from the appops xml. Currently only parses and holds the version number.
     * Other fields may be added as and when required for testing.
     */
    private static final class AppOpsDataParser {
        static final int NO_VERSION = -1;
        int mVersion;
        private File mFile;

        AppOpsDataParser(File file) {
            mFile = file;
            mVersion = NO_VERSION;
        }

        boolean parse() {
            try (FileInputStream stream = new FileInputStream(mFile)) {
                XmlPullParser parser = Xml.newPullParser();
                parser.setInput(stream, StandardCharsets.UTF_8.name());
                int type;
                while ((type = parser.next()) != XmlPullParser.START_TAG
                        && type != XmlPullParser.END_DOCUMENT) {
                    ;
                }
                if (type != XmlPullParser.START_TAG) {
                    throw new IllegalStateException("no start tag found");
                }
                final String versionString = parser.getAttributeValue(null, "v");
                if (versionString != null) {
                    mVersion = Integer.parseInt(versionString);
                }
            } catch (Exception e) {
                Log.e(TAG, "Failed while parsing test appops xml", e);
                return false;
            }
            return true;
        }
    }
}
