/*
 * 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.pm;

import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OP_CAMERA;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
import static android.app.AppOpsManager.opToName;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import android.app.AppGlobals;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.IPackageManager;
import android.content.pm.LauncherApps;
import android.content.pm.PackageManager;
import android.content.pm.SuspendDialogInfo;
import android.content.res.Resources;
import android.os.BaseBundle;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.support.test.uiautomator.By;
import android.support.test.uiautomator.UiDevice;
import android.support.test.uiautomator.UiObject2;
import android.support.test.uiautomator.Until;
import android.util.Log;
import android.view.IWindowManager;
import android.view.WindowManagerGlobal;

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

import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.servicestests.apps.suspendtestapp.SuspendTestActivity;
import com.android.servicestests.apps.suspendtestapp.SuspendTestReceiver;

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

import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class SuspendPackagesTest {
    private static final String TAG = SuspendPackagesTest.class.getSimpleName();
    private static final String TEST_APP_LABEL = "Suspend Test App";
    private static final String TEST_APP_PACKAGE_NAME = SuspendTestReceiver.PACKAGE_NAME;
    private static final String[] PACKAGES_TO_SUSPEND = new String[]{TEST_APP_PACKAGE_NAME};

    public static final String INSTRUMENTATION_PACKAGE = "com.android.frameworks.servicestests";
    public static final String ACTION_REPORT_MY_PACKAGE_SUSPENDED =
            INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_SUSPENDED";
    public static final String ACTION_REPORT_MY_PACKAGE_UNSUSPENDED =
            INSTRUMENTATION_PACKAGE + ".action.REPORT_MY_PACKAGE_UNSUSPENDED";
    public static final String ACTION_REPORT_TEST_ACTIVITY_STARTED =
            INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STARTED";
    public static final String ACTION_REPORT_TEST_ACTIVITY_STOPPED =
            INSTRUMENTATION_PACKAGE + ".action.REPORT_TEST_ACTIVITY_STOPPED";
    public static final String ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED =
            INSTRUMENTATION_PACKAGE + ".action.REPORT_MORE_DETAILS_ACTIVITY_STARTED";
    public static final String ACTION_FINISH_TEST_ACTIVITY =
            INSTRUMENTATION_PACKAGE + ".action.FINISH_TEST_ACTIVITY";
    public static final String EXTRA_RECEIVED_PACKAGE_NAME =
            SuspendPackagesTest.INSTRUMENTATION_PACKAGE + ".extra.RECEIVED_PACKAGE_NAME";


    private Context mContext;
    private PackageManager mPackageManager;
    private LauncherApps mLauncherApps;
    private Handler mReceiverHandler;
    private AppCommunicationReceiver mAppCommsReceiver;
    private StubbedCallback mTestCallback;
    private UiDevice mUiDevice;
    private ComponentName mDeviceAdminComponent;
    private boolean mPoSet;
    private boolean mDoSet;

    private static final class AppCommunicationReceiver extends BroadcastReceiver {
        private Context context;
        private boolean registered;
        private SynchronousQueue<Intent> intentQueue = new SynchronousQueue<>();

        AppCommunicationReceiver(Context context) {
            this.context = context;
        }

        void register(Handler handler, String... actions) {
            registered = true;
            final IntentFilter intentFilter = new IntentFilter();
            for (String action : actions) {
                intentFilter.addAction(action);
            }
            context.registerReceiver(this, intentFilter, null, handler);
        }

        void unregister() {
            if (registered) {
                context.unregisterReceiver(this);
            }
        }

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.d(TAG, "AppCommunicationReceiver#onReceive: " + intent.getAction());
            try {
                intentQueue.offer(intent, 5, TimeUnit.SECONDS);
            } catch (InterruptedException ie) {
                throw new RuntimeException("Receiver thread interrupted", ie);
            }
        }

        Intent pollForIntent(long secondsToWait) {
            if (!registered) {
                throw new IllegalStateException("Receiver not registered");
            }
            final Intent intent;
            try {
                intent = intentQueue.poll(secondsToWait, TimeUnit.SECONDS);
            } catch (InterruptedException ie) {
                throw new RuntimeException("Interrupted while waiting for app broadcast", ie);
            }
            return intent;
        }

        void drainPendingBroadcasts() {
            while (pollForIntent(5) != null) ;
        }

        Intent receiveIntentFromApp() {
            final Intent intentReceived = pollForIntent(5);
            assertNotNull("No intent received from app within 5 seconds", intentReceived);
            return intentReceived;
        }
    }

    @Before
    public void setUp() {
        mContext = InstrumentationRegistry.getTargetContext();
        mPackageManager = mContext.getPackageManager();
        mLauncherApps = (LauncherApps) mContext.getSystemService(Context.LAUNCHER_APPS_SERVICE);
        mReceiverHandler = new Handler(Looper.getMainLooper());
        mUiDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
        mDeviceAdminComponent = new ComponentName(mContext,
                "com.android.server.devicepolicy.DummyDeviceAdmins$Admin1");
        IPackageManager ipm = AppGlobals.getPackageManager();
        try {
            // Otherwise implicit broadcasts will not be delivered.
            ipm.setPackageStoppedState(TEST_APP_PACKAGE_NAME, false, mContext.getUserId());
        } catch (RemoteException e) {
            e.rethrowAsRuntimeException();
        }
        unsuspendTestPackage();
        mAppCommsReceiver = new AppCommunicationReceiver(mContext);
    }

    /**
     * Care should be taken when used with {@link #mAppCommsReceiver} in the same test as both use
     * the same handler.
     */
    private Bundle requestAppAction(String action) throws InterruptedException {
        final AtomicReference<Bundle> result = new AtomicReference<>();
        final CountDownLatch receiverLatch = new CountDownLatch(1);
        final ComponentName testReceiverComponent = new ComponentName(TEST_APP_PACKAGE_NAME,
                SuspendTestReceiver.class.getCanonicalName());
        final Intent broadcastIntent = new Intent(action)
                .setComponent(testReceiverComponent)
                .setFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        mContext.sendOrderedBroadcast(broadcastIntent, null, new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                result.set(getResultExtras(true));
                receiverLatch.countDown();
            }
        }, mReceiverHandler, 0, null, null);

        assertTrue("Test receiver timed out ", receiverLatch.await(5, TimeUnit.SECONDS));
        return result.get();
    }

    private PersistableBundle getExtras(String keyPrefix, long lval, String sval, double dval) {
        final PersistableBundle extras = new PersistableBundle(3);
        extras.putLong(keyPrefix + ".LONG_VALUE", lval);
        extras.putDouble(keyPrefix + ".DOUBLE_VALUE", dval);
        extras.putString(keyPrefix + ".STRING_VALUE", sval);
        return extras;
    }

    private void suspendTestPackage(PersistableBundle appExtras, PersistableBundle launcherExtras,
            SuspendDialogInfo dialogInfo) {
        final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
                PACKAGES_TO_SUSPEND, true, appExtras, launcherExtras, dialogInfo);
        assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
    }

    private void unsuspendTestPackage() {
        final String[] unchangedPackages = mPackageManager.setPackagesSuspended(
                PACKAGES_TO_SUSPEND, false, null, null, (SuspendDialogInfo) null);
        assertTrue("setPackagesSuspended returned non-empty list", unchangedPackages.length == 0);
    }

    private void startTestAppActivity() {
        final Intent testActivity = new Intent()
                .setComponent(new ComponentName(TEST_APP_PACKAGE_NAME,
                        SuspendTestActivity.class.getCanonicalName()))
                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        mContext.startActivity(testActivity);
    }

    private static boolean areSameExtras(BaseBundle expected, BaseBundle received) {
        if (expected != null) {
            expected.get(""); // hack to unparcel the bundles.
        }
        if (received != null) {
            received.get("");
        }
        return BaseBundle.kindofEquals(expected, received);
    }

    private static void assertSameExtras(String message, BaseBundle expected, BaseBundle received) {
        if (!areSameExtras(expected, received)) {
            fail(message + ": [expected: " + expected + "; received: " + received + "]");
        }
    }

    @Test
    public void testIsPackageSuspended() throws Exception {
        suspendTestPackage(null, null, null);
        assertTrue("isPackageSuspended is false",
                mPackageManager.isPackageSuspended(TEST_APP_PACKAGE_NAME));
    }

    @Test
    public void testSuspendedStateFromApp() throws Exception {
        Bundle resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
        assertFalse(resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED, true));
        assertNull(resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));

        final PersistableBundle appExtras = getExtras("testSuspendedStateFromApp", 20, "20", 0.2);
        suspendTestPackage(appExtras, null, null);

        resultFromApp = requestAppAction(SuspendTestReceiver.ACTION_GET_SUSPENDED_STATE);
        assertTrue("resultFromApp:suspended is false",
                resultFromApp.getBoolean(SuspendTestReceiver.EXTRA_SUSPENDED));
        final Bundle receivedAppExtras =
                resultFromApp.getBundle(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS);
        assertSameExtras("Received app extras different to the ones supplied",
                appExtras, receivedAppExtras);
    }

    @Test
    public void testMyPackageSuspendedUnsuspended() {
        mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED,
                ACTION_REPORT_MY_PACKAGE_UNSUSPENDED);
        mAppCommsReceiver.drainPendingBroadcasts();
        final PersistableBundle appExtras = getExtras("testMyPackageSuspendBroadcasts", 1, "1", .1);
        suspendTestPackage(appExtras, null, null);
        Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
                ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
        assertSameExtras("Received app extras different to the ones supplied", appExtras,
                intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
        unsuspendTestPackage();
        intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals("MY_PACKAGE_UNSUSPENDED delivery not reported",
                ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
    }

    @Test
    public void testUpdatingAppExtras() {
        mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_SUSPENDED);
        final PersistableBundle extras1 = getExtras("testMyPackageSuspendedOnChangingExtras", 1,
                "1", 0.1);
        suspendTestPackage(extras1, null, null);
        Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
                ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
        assertSameExtras("Received app extras different to the ones supplied", extras1,
                intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
        final PersistableBundle extras2 = getExtras("testMyPackageSuspendedOnChangingExtras", 2,
                "2", 0.2);
        suspendTestPackage(extras2, null, null);
        intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals("MY_PACKAGE_SUSPENDED delivery not reported",
                ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
        assertSameExtras("Received app extras different to the updated extras", extras2,
                intentFromApp.getBundleExtra(SuspendTestReceiver.EXTRA_SUSPENDED_APP_EXTRAS));
    }

    @Test
    public void testCannotSuspendSelf() {
        final String[] unchangedPkgs = mPackageManager.setPackagesSuspended(
                new String[]{mContext.getOpPackageName()}, true, null, null,
                (SuspendDialogInfo) null);
        assertTrue(unchangedPkgs.length == 1);
        assertEquals(mContext.getOpPackageName(), unchangedPkgs[0]);
    }

    @Test
    public void testActivityStoppedOnSuspend() {
        mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_TEST_ACTIVITY_STARTED,
                ACTION_REPORT_TEST_ACTIVITY_STOPPED);
        startTestAppActivity();
        Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals("Test activity start not reported",
                ACTION_REPORT_TEST_ACTIVITY_STARTED, intentFromApp.getAction());
        suspendTestPackage(null, null, null);
        intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals("Test activity stop not reported on suspending the test app",
                ACTION_REPORT_TEST_ACTIVITY_STOPPED, intentFromApp.getAction());
    }

    @Test
    public void testGetLauncherExtrasNonNull() {
        final Bundle extrasWhenUnsuspended = mLauncherApps.getSuspendedPackageLauncherExtras(
                TEST_APP_PACKAGE_NAME, mContext.getUser());
        assertNull("Non null extras when package unsuspended:", extrasWhenUnsuspended);
        final PersistableBundle launcherExtras = getExtras("testGetLauncherExtras", 1, "1", 0.1);
        suspendTestPackage(null, launcherExtras, null);
        final Bundle receivedExtras = mLauncherApps.getSuspendedPackageLauncherExtras(
                TEST_APP_PACKAGE_NAME, mContext.getUser());
        assertSameExtras("Received launcher extras different to the ones supplied", launcherExtras,
                receivedExtras);
    }

    @Test
    public void testGetLauncherExtrasNull() {
        suspendTestPackage(null, null, null);
        final Bundle extrasWhenNoneGiven = mLauncherApps.getSuspendedPackageLauncherExtras(
                TEST_APP_PACKAGE_NAME, mContext.getUser());
        assertNull("Non null extras when null extras provided:", extrasWhenNoneGiven);
    }

    @Test
    public void testGetLauncherExtrasInvalidPackage() {
        final Bundle extrasForInvalidPackage = mLauncherApps.getSuspendedPackageLauncherExtras(
                "test.nonexistent.packagename", mContext.getUser());
        assertNull("Non null extras for an invalid package:", extrasForInvalidPackage);
    }

    @Test
    public void testOnPackagesSuspendedNewAndOld() throws InterruptedException {
        final PersistableBundle suppliedExtras = getExtras(
                "testOnPackagesSuspendedNewAndOld", 2, "2", 0.2);
        final AtomicReference<String> overridingBothCallbackResult = new AtomicReference<>("");
        final CountDownLatch twoCallbackLatch = new CountDownLatch(2);
        mTestCallback = new StubbedCallback() {
            @Override
            public void onPackagesSuspended(String[] packageNames, UserHandle user) {
                overridingBothCallbackResult.set(overridingBothCallbackResult.get()
                        + "Old callback called even when the new one is overriden. ");
                twoCallbackLatch.countDown();
            }

            @Override
            public void onPackagesSuspended(String[] packageNames, UserHandle user,
                    Bundle launcherExtras) {
                final StringBuilder errorString = new StringBuilder();
                if (!Arrays.equals(packageNames, PACKAGES_TO_SUSPEND)) {
                    errorString.append("Received unexpected packageNames in onPackagesSuspended:");
                    for (String packageName : packageNames) {
                        errorString.append(" " + packageName);
                    }
                    errorString.append(". ");
                }
                if (user.getIdentifier() != mContext.getUserId()) {
                    errorString.append("Received wrong user " + user.getIdentifier() + ". ");
                }
                if (!areSameExtras(launcherExtras, suppliedExtras)) {
                    errorString.append("Unexpected launcherExtras, supplied: " + suppliedExtras
                            + ", received: " + launcherExtras + ". ");
                }
                overridingBothCallbackResult.set(overridingBothCallbackResult.get()
                        + errorString.toString());
                twoCallbackLatch.countDown();
            }
        };
        mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
        suspendTestPackage(null, suppliedExtras, null);
        assertFalse("Both callbacks were invoked", twoCallbackLatch.await(5, TimeUnit.SECONDS));
        twoCallbackLatch.countDown();
        assertTrue("No callback was invoked", twoCallbackLatch.await(2, TimeUnit.SECONDS));
        final String result = overridingBothCallbackResult.get();
        assertTrue("Callbacks did not complete as expected: " + result, result.isEmpty());
    }

    @Test
    public void testOnPackagesSuspendedOld() throws InterruptedException {
        final PersistableBundle suppliedExtras = getExtras(
                "testOnPackagesSuspendedOld", 2, "2", 0.2);
        final AtomicReference<String> overridingOneCallbackResult = new AtomicReference<>("");
        final CountDownLatch oneCallbackLatch = new CountDownLatch(1);
        mTestCallback = new StubbedCallback() {
            @Override
            public void onPackagesSuspended(String[] packageNames, UserHandle user) {
                final StringBuilder errorString = new StringBuilder();
                if (!Arrays.equals(packageNames, PACKAGES_TO_SUSPEND)) {
                    errorString.append("Received unexpected packageNames in onPackagesSuspended:");
                    for (String packageName : packageNames) {
                        errorString.append(" " + packageName);
                    }
                    errorString.append(". ");
                }
                if (user.getIdentifier() != mContext.getUserId()) {
                    errorString.append("Received wrong user " + user.getIdentifier() + ". ");
                }
                overridingOneCallbackResult.set(overridingOneCallbackResult.get()
                        + errorString.toString());
                oneCallbackLatch.countDown();
            }
        };
        mLauncherApps.registerCallback(mTestCallback, mReceiverHandler);
        suspendTestPackage(null, suppliedExtras, null);
        assertTrue("Callback not invoked", oneCallbackLatch.await(5, TimeUnit.SECONDS));
        final String result = overridingOneCallbackResult.get();
        assertTrue("Callback did not complete as expected: " + result, result.isEmpty());
    }

    private void turnScreenOn() throws Exception {
        if (!mUiDevice.isScreenOn()) {
            mUiDevice.wakeUp();
        }
        final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
        wm.dismissKeyguard(null, null);
    }

    @Test
    public void testInterceptorActivity() throws Exception {
        turnScreenOn();
        mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED,
                ACTION_REPORT_TEST_ACTIVITY_STARTED);
        final String testMessage = "This is a test message to report suspension of %1$s";
        suspendTestPackage(null, null,
                new SuspendDialogInfo.Builder().setMessage(testMessage).build());
        startTestAppActivity();
        assertNull("No broadcast was expected from app", mAppCommsReceiver.pollForIntent(2));
        assertNotNull("Given dialog message not shown", mUiDevice.wait(
                Until.findObject(By.text(String.format(testMessage, TEST_APP_LABEL))), 5000));
        final String buttonText = mContext.getResources().getString(Resources.getSystem()
                .getIdentifier("app_suspended_more_details", "string", "android"));
        final UiObject2 moreDetailsButton = mUiDevice.findObject(
                By.clickable(true).text(buttonText));
        assertNotNull(buttonText + " button not shown", moreDetailsButton);
        moreDetailsButton.click();
        final Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals(buttonText + " activity start not reported",
                ACTION_REPORT_MORE_DETAILS_ACTIVITY_STARTED, intentFromApp.getAction());
        final String receivedPackageName = intentFromApp.getStringExtra(
                EXTRA_RECEIVED_PACKAGE_NAME);
        assertEquals("Wrong package name received by " + buttonText + " activity",
                TEST_APP_PACKAGE_NAME, receivedPackageName);
    }

    private boolean setProfileOwner() throws IOException {
        final String result = mUiDevice.executeShellCommand("dpm set-profile-owner --user cur "
                + mDeviceAdminComponent.flattenToString());
        return mPoSet = result.trim().startsWith("Success");
    }

    private boolean setDeviceOwner() throws IOException {
        final String result = mUiDevice.executeShellCommand("dpm set-device-owner --user cur "
                + mDeviceAdminComponent.flattenToString());
        return mDoSet = result.trim().startsWith("Success");
    }

    private void removeProfileOrDeviceOwner() throws IOException {
        if (mPoSet || mDoSet) {
            mUiDevice.executeShellCommand("dpm remove-active-admin --user cur "
                    + mDeviceAdminComponent.flattenToString());
            mPoSet = mDoSet = false;
        }
    }

    @Test
    public void testCanSuspendWhenProfileOwner() throws IOException {
        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
        assertTrue("Profile-owner could not be set", setProfileOwner());
        suspendTestPackage(null, null, null);
    }

    @Test
    public void testCanSuspendWhenDeviceOwner() throws IOException {
        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
        assertTrue("Device-owner could not be set", setDeviceOwner());
        suspendTestPackage(null, null, null);
    }

    @Test
    public void testPackageUnsuspendedOnAddingDeviceOwner() throws IOException {
        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
        mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
                ACTION_REPORT_MY_PACKAGE_SUSPENDED);
        mAppCommsReceiver.drainPendingBroadcasts();
        suspendTestPackage(null, null, null);
        Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
        assertTrue("Device-owner could not be set", setDeviceOwner());
        intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
    }

    @Test
    public void testPackageUnsuspendedOnAddingProfileOwner() throws IOException {
        assumeTrue(mPackageManager.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN));
        mAppCommsReceiver.register(mReceiverHandler, ACTION_REPORT_MY_PACKAGE_UNSUSPENDED,
                ACTION_REPORT_MY_PACKAGE_SUSPENDED);
        mAppCommsReceiver.drainPendingBroadcasts();
        suspendTestPackage(null, null, null);
        Intent intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals(ACTION_REPORT_MY_PACKAGE_SUSPENDED, intentFromApp.getAction());
        assertTrue("Profile-owner could not be set", setProfileOwner());
        intentFromApp = mAppCommsReceiver.receiveIntentFromApp();
        assertEquals(ACTION_REPORT_MY_PACKAGE_UNSUSPENDED, intentFromApp.getAction());
    }

    @Test
    public void testCameraBlockedOnSuspend() throws Exception {
        assertOpBlockedOnSuspend(OP_CAMERA);
    }

    @Test
    public void testPlayAudioBlockedOnSuspend() throws Exception {
        assertOpBlockedOnSuspend(OP_PLAY_AUDIO);
    }

    @Test
    public void testRecordAudioBlockedOnSuspend() throws Exception {
        assertOpBlockedOnSuspend(OP_RECORD_AUDIO);
    }

    private void assertOpBlockedOnSuspend(int code) throws Exception {
        final IAppOpsService iAppOps = IAppOpsService.Stub.asInterface(
                ServiceManager.getService(Context.APP_OPS_SERVICE));
        final CountDownLatch latch = new CountDownLatch(1);
        final IAppOpsCallback watcher = new IAppOpsCallback.Stub() {
            @Override
            public void opChanged(int op, int uid, String packageName) {
                if (op == code && packageName.equals(TEST_APP_PACKAGE_NAME)) {
                    latch.countDown();
                }
            }
        };
        iAppOps.startWatchingMode(code, TEST_APP_PACKAGE_NAME, watcher);
        final int testPackageUid = mPackageManager.getPackageUid(TEST_APP_PACKAGE_NAME, 0);
        int opMode = iAppOps.checkOperation(code, testPackageUid, TEST_APP_PACKAGE_NAME);
        assertEquals("Op " + opToName(code) + " disallowed for unsuspended package", MODE_ALLOWED,
                opMode);
        suspendTestPackage(null, null, null);
        assertTrue("AppOpsWatcher did not callback", latch.await(5, TimeUnit.SECONDS));
        opMode = iAppOps.checkOperation(code, testPackageUid, TEST_APP_PACKAGE_NAME);
        assertEquals("Op " + opToName(code) + " allowed for suspended package", MODE_IGNORED,
                opMode);
        iAppOps.stopWatchingMode(watcher);
    }

    @After
    public void tearDown() throws IOException {
        mAppCommsReceiver.unregister();
        if (mTestCallback != null) {
            mLauncherApps.unregisterCallback(mTestCallback);
        }
        removeProfileOrDeviceOwner();
        mContext.sendBroadcast(new Intent(ACTION_FINISH_TEST_ACTIVITY)
                .setPackage(TEST_APP_PACKAGE_NAME));
    }

    private static abstract class StubbedCallback extends LauncherApps.Callback {

        @Override
        public void onPackageRemoved(String packageName, UserHandle user) {
        }

        @Override
        public void onPackageAdded(String packageName, UserHandle user) {
        }

        @Override
        public void onPackageChanged(String packageName, UserHandle user) {
        }

        @Override
        public void onPackagesAvailable(String[] packageNames, UserHandle user, boolean replacing) {

        }

        @Override
        public void onPackagesUnavailable(String[] packageNames, UserHandle user,
                boolean replacing) {
        }
    }
}
