/*
 * Copyright (C) 2018 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 android.app.ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.FILTER_BY_PACKAGE_NAME;
import static android.app.AppOpsManager.FILTER_BY_UID;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_ERRORED;
import static android.app.AppOpsManager.MODE_FOREGROUND;
import static android.app.AppOpsManager.OP_COARSE_LOCATION;
import static android.app.AppOpsManager.OP_FLAGS_ALL;
import static android.app.AppOpsManager.OP_READ_SMS;
import static android.app.AppOpsManager.OP_WIFI_SCAN;
import static android.app.AppOpsManager.OP_WRITE_SMS;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;

import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.AppOpsManager.OpEntry;
import android.app.AppOpsManager.PackageOps;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManagerInternal;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Process;
import android.os.RemoteCallback;
import android.provider.Settings;

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

import com.android.dx.mockito.inline.extended.StaticMockitoSession;
import com.android.server.LocalServices;
import com.android.server.pm.parsing.pkg.AndroidPackage;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.quality.Strictness;

import java.io.File;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Unit tests for AppOpsService. Covers functionality that is difficult to test using CTS tests
 * or for which we can write more detailed unit tests than CTS tests (because the internal APIs are
 * more finegrained data than the public ones).
 */
@SmallTest
@RunWith(AndroidJUnit4.class)
public class AppOpsServiceTest {

    private static final String TAG = AppOpsServiceTest.class.getSimpleName();
    // State will be persisted into this XML file.
    private static final String APP_OPS_FILENAME = "appops-service-test.xml";

    private static final Context sContext = InstrumentationRegistry.getTargetContext();
    private static final String sMyPackageName = sContext.getOpPackageName();

    private File mAppOpsFile;
    private Handler mHandler;
    private AppOpsService mAppOpsService;
    private int mMyUid;
    private long mTestStartMillis;
    private StaticMockitoSession mMockingSession;

    private void setupAppOpsService() {
        mAppOpsService = new AppOpsService(mAppOpsFile, mHandler, spy(sContext));
        mAppOpsService.mHistoricalRegistry.systemReady(sContext.getContentResolver());

        // Always approve all permission checks
        doNothing().when(mAppOpsService.mContext).enforcePermission(anyString(), anyInt(),
                anyInt(), nullable(String.class));
    }

    @Before
    public void setUp() {
        mAppOpsFile = new File(sContext.getFilesDir(), APP_OPS_FILENAME);
        if (mAppOpsFile.exists()) {
            // Start with a clean state (persisted into XML).
            mAppOpsFile.delete();
        }

        HandlerThread handlerThread = new HandlerThread(TAG);
        handlerThread.start();
        mHandler = new Handler(handlerThread.getLooper());
        mMyUid = Process.myUid();

        initializeStaticMocks();

        setupAppOpsService();

        mTestStartMillis = System.currentTimeMillis();
    }

    @After
    public void resetStaticMocks() {
        mMockingSession.finishMocking();
    }

    private void initializeStaticMocks() {
        mMockingSession = mockitoSession()
                .strictness(Strictness.LENIENT)
                .spyStatic(LocalServices.class)
                .spyStatic(Settings.Global.class)
                .startMocking();

        // Mock LocalServices.getService(PackageManagerInternal.class).getPackage dependency
        // needed by AppOpsService
        PackageManagerInternal mockPackageManagerInternal = mock(PackageManagerInternal.class);
        AndroidPackage mockMyPkg = mock(AndroidPackage.class);
        when(mockMyPkg.isPrivileged()).thenReturn(false);
        when(mockMyPkg.getUid()).thenReturn(mMyUid);
        when(mockMyPkg.getAttributions()).thenReturn(Collections.emptyList());

        when(mockPackageManagerInternal.getPackage(sMyPackageName)).thenReturn(mockMyPkg);
        doReturn(mockPackageManagerInternal).when(
                () -> LocalServices.getService(PackageManagerInternal.class));

        // Mock behavior to use specific Settings.Global.APPOP_HISTORY_PARAMETERS
        doReturn(null).when(() -> Settings.Global.getString(any(ContentResolver.class),
                eq(Settings.Global.APPOP_HISTORY_PARAMETERS)));
    }

    @Test
    public void testGetOpsForPackage_noOpsLogged() {
        assertThat(getLoggedOps()).isNull();
    }

    @Test
    public void testNoteOperationAndGetOpsForPackage() {
        mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
        mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);

        // Note an op that's allowed.
        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
        List<PackageOps> loggedOps = getLoggedOps();
        assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);

        // Note another op that's not allowed.
        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null);
        loggedOps = getLoggedOps();
        assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
        assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
    }

    /**
     * Tests the scenario where an operation's permission is controlled by another operation.
     * For example the results of a WIFI_SCAN can be used to infer the location of a user, so the
     * ACCESS_COARSE_LOCATION op is used to check whether WIFI_SCAN is allowed.
     */
    @Test
    public void testNoteOperationAndGetOpsForPackage_controlledByDifferentOp() {
        // This op controls WIFI_SCAN
        mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ALLOWED);

        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
                null)).isEqualTo(MODE_ALLOWED);

        assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, -1,
                MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);

        // Now set COARSE_LOCATION to ERRORED -> this will make WIFI_SCAN disabled as well.
        mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_ERRORED);
        assertThat(mAppOpsService.noteOperation(OP_WIFI_SCAN, mMyUid, sMyPackageName, null, false,
                null)).isEqualTo(MODE_ERRORED);

        assertContainsOp(getLoggedOps(), OP_WIFI_SCAN, mTestStartMillis, mTestStartMillis,
                MODE_ALLOWED /* default for WIFI_SCAN; this is not changed or used in this test */);
    }

    // Tests the dumping and restoring of the in-memory state to/from XML.
    @Test
    public void testStatePersistence() {
        mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
        mAppOpsService.setMode(OP_WRITE_SMS, mMyUid, sMyPackageName, MODE_ERRORED);
        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
        mAppOpsService.noteOperation(OP_WRITE_SMS, mMyUid, sMyPackageName, null, false, null);
        mAppOpsService.writeState();

        // Create a new app ops service, and initialize its state from XML.
        setupAppOpsService();
        mAppOpsService.readState();

        // Query the state of the 2nd service.
        List<PackageOps> loggedOps = getLoggedOps();
        assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
        assertContainsOp(loggedOps, OP_WRITE_SMS, -1, mTestStartMillis, MODE_ERRORED);
    }

    // Tests that ops are persisted during shutdown.
    @Test
    public void testShutdown() {
        mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);
        mAppOpsService.shutdown();

        // Create a new app ops service, and initialize its state from XML.
        setupAppOpsService();
        mAppOpsService.readState();

        // Query the state of the 2nd service.
        List<PackageOps> loggedOps = getLoggedOps();
        assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);
    }

    @Test
    public void testGetOpsForPackage() {
        mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);

        // Query all ops
        List<PackageOps> loggedOps = mAppOpsService.getOpsForPackage(
                mMyUid, sMyPackageName, null /* all ops */);
        assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);

        // Query specific ops
        loggedOps = mAppOpsService.getOpsForPackage(
                mMyUid, sMyPackageName, new int[]{OP_READ_SMS, OP_WRITE_SMS});
        assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);

        // Query unknown UID
        loggedOps = mAppOpsService.getOpsForPackage(mMyUid + 1, sMyPackageName, null /* all ops */);
        assertThat(loggedOps).isNull();

        // Query unknown package name
        loggedOps = mAppOpsService.getOpsForPackage(mMyUid, "fake.package", null /* all ops */);
        assertThat(loggedOps).isNull();

        // Query op code that's not been logged
        loggedOps = mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName,
                new int[]{OP_WRITE_SMS});
        assertThat(loggedOps).isNull();
    }

    @Test
    public void testPackageRemoved() {
        mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);

        List<PackageOps> loggedOps = getLoggedOps();
        assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);

        mAppOpsService.packageRemoved(mMyUid, sMyPackageName);
        assertThat(getLoggedOps()).isNull();
    }


    /*
    TODO ntmyren: re enable when we have time to rewrite test.
    @Test
    public void testPackageRemovedHistoricalOps() throws InterruptedException {
        mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);

        AppOpsManager.HistoricalOps historicalOps = new AppOpsManager.HistoricalOps(0, 15000);
        historicalOps.increaseAccessCount(OP_READ_SMS, mMyUid, sMyPackageName, null,
                AppOpsManager.UID_STATE_PERSISTENT, 0, 1);

        mAppOpsService.addHistoricalOps(historicalOps);

        AtomicReference<AppOpsManager.HistoricalOps> resultOpsRef = new AtomicReference<>();
        AtomicReference<CountDownLatch> latchRef = new AtomicReference<>(new CountDownLatch(1));
        RemoteCallback callback = new RemoteCallback(result -> {
            resultOpsRef.set(result.getParcelable(AppOpsManager.KEY_HISTORICAL_OPS));
            latchRef.get().countDown();
        });

        // First, do a fetch to ensure it's written
        mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, null,
                FILTER_BY_UID | FILTER_BY_PACKAGE_NAME, 0, Long.MAX_VALUE, 0, callback);

        latchRef.get().await(5, TimeUnit.SECONDS);
        assertThat(latchRef.get().getCount()).isEqualTo(0);
        assertThat(resultOpsRef.get().isEmpty()).isFalse();

        // Then, check it's deleted on removal
        mAppOpsService.packageRemoved(mMyUid, sMyPackageName);

        latchRef.set(new CountDownLatch(1));

        mAppOpsService.getHistoricalOps(mMyUid, sMyPackageName, null, null,
                FILTER_BY_UID | FILTER_BY_PACKAGE_NAME, 0, Long.MAX_VALUE, 0, callback);

        latchRef.get().await(5, TimeUnit.SECONDS);
        assertThat(latchRef.get().getCount()).isEqualTo(0);
        assertThat(resultOpsRef.get().isEmpty()).isTrue();
    }
     */

    @Test
    public void testUidRemoved() {
        mAppOpsService.setMode(OP_READ_SMS, mMyUid, sMyPackageName, MODE_ALLOWED);
        mAppOpsService.noteOperation(OP_READ_SMS, mMyUid, sMyPackageName, null, false, null);

        List<PackageOps> loggedOps = getLoggedOps();
        assertContainsOp(loggedOps, OP_READ_SMS, mTestStartMillis, -1, MODE_ALLOWED);

        mAppOpsService.uidRemoved(mMyUid);
        assertThat(getLoggedOps()).isNull();
    }

    private void setupProcStateTests() {
        // For the location proc state tests
        mAppOpsService.setMode(OP_COARSE_LOCATION, mMyUid, sMyPackageName, MODE_FOREGROUND);
        mAppOpsService.mConstants.FG_SERVICE_STATE_SETTLE_TIME = 0;
        mAppOpsService.mConstants.TOP_STATE_SETTLE_TIME = 0;
        mAppOpsService.mConstants.BG_STATE_SETTLE_TIME = 0;
    }

    @Test
    public void testUidProcStateChange_cachedToTopToCached() throws Exception {
        setupProcStateTests();

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        // Second time to make sure that settle time is overcome
        Thread.sleep(50);
        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);
    }

    @Test
    public void testUidProcStateChange_cachedToFgs() {
        setupProcStateTests();
        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);
    }

    @Test
    public void testUidProcStateChange_cachedToFgsLocation() {
        setupProcStateTests();

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isEqualTo(MODE_ALLOWED);
    }

    @Test
    public void testUidProcStateChange_topToFgs() throws Exception {
        setupProcStateTests();

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        // Second time to make sure that settle time is overcome
        Thread.sleep(50);
        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);
    }

    @Test
    public void testUidProcStateChange_topToFgsLocationToFgs() throws Exception {
        setupProcStateTests();

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_CACHED_EMPTY,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, ActivityManager.PROCESS_STATE_TOP,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        // Second time to make sure that settle time is overcome
        Thread.sleep(50);
        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_FOREGROUND_LOCATION);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isEqualTo(MODE_ALLOWED);

        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        // Second time to make sure that settle time is overcome
        Thread.sleep(50);
        mAppOpsService.updateUidProcState(mMyUid, PROCESS_STATE_FOREGROUND_SERVICE,
                ActivityManager.PROCESS_CAPABILITY_NONE);
        assertThat(mAppOpsService.noteOperation(OP_COARSE_LOCATION, mMyUid, sMyPackageName, null,
                false, null)).isNotEqualTo(MODE_ALLOWED);
    }

    private List<PackageOps> getLoggedOps() {
        return mAppOpsService.getOpsForPackage(mMyUid, sMyPackageName, null /* all ops */);
    }

    private void assertContainsOp(List<PackageOps> loggedOps, int opCode, long minMillis,
            long minRejectMillis, int mode) {

        boolean opLogged = false;
        for (PackageOps pkgOps : loggedOps) {
            assertWithMessage("Unexpected UID").that(mMyUid).isEqualTo(pkgOps.getUid());
            assertWithMessage("Unexpected package name").that(sMyPackageName).isEqualTo(
                    pkgOps.getPackageName());

            for (OpEntry opEntry : pkgOps.getOps()) {
                if (opCode != opEntry.getOp()) {
                    continue;
                }
                opLogged = true;

                assertWithMessage("Unexpected mode").that(mode).isEqualTo(opEntry.getMode());
                if (minMillis > 0) {
                    assertWithMessage("Unexpected timestamp")
                            .that(opEntry.getLastAccessTime(OP_FLAGS_ALL)).isAtLeast(minMillis);
                }
                if (minRejectMillis > 0) {
                    assertWithMessage("Unexpected rejection timestamp").that(
                            opEntry.getLastRejectTime(OP_FLAGS_ALL)).isAtLeast(minRejectMillis);
                }
            }
        }
        assertWithMessage("Op was not logged").that(opLogged).isTrue();
    }
}
