/*
 * Copyright (C) 2012 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.cts.verifier.managedprovisioning;

import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES;
import static android.os.UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY;

import android.Manifest;
import android.app.Activity;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.UserManager;
import android.provider.MediaStore;
import android.util.Log;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.core.util.Pair;

import com.android.cts.verifier.R;
import com.android.cts.verifier.managedprovisioning.ByodPresentMediaDialog.DialogCallback;

import java.io.File;
import java.util.ArrayList;

/**
 * A helper activity from the managed profile side that responds to requests from CTS verifier in
 * primary user. Profile owner APIs are accessible inside this activity (given this activity is
 * started within the work profile). Its current functionalities include making sure the profile
 * owner is setup correctly, removing the work profile upon request, and verifying the image and
 * video capture functionality.
 *
 * Note: We have to use a test activity because cross-profile intents only work for activities.
 */
public class ByodHelperActivity extends Activity
        implements DialogCallback, ActivityCompat.OnRequestPermissionsResultCallback {

    static final String TAG = "ByodHelperActivity";

    // Primary -> managed intent: query if the profile owner has been set up.
    public static final String ACTION_QUERY_PROFILE_OWNER = "com.android.cts.verifier.managedprovisioning.BYOD_QUERY";
    // Managed -> primary intent: update profile owner test status in primary's CtsVerifer
    public static final String ACTION_PROFILE_OWNER_STATUS = "com.android.cts.verifier.managedprovisioning.BYOD_STATUS";
    // Primary -> managed intent: request to delete the current profile
    public static final String ACTION_REMOVE_MANAGED_PROFILE = "com.android.cts.verifier.managedprovisioning.BYOD_REMOVE";
    // Primary -> managed intent: request to capture and check an image
    public static final String ACTION_CAPTURE_AND_CHECK_IMAGE = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_IMAGE";
    // Primary -> managed intent: request to capture and check a video with custom output path
    public static final String ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT";
    // Primary -> managed intent: request to capture and check a video without custom output path
    public static final String ACTION_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT";
    // Primary -> managed intent: request to capture and check an audio recording
    public static final String ACTION_CAPTURE_AND_CHECK_AUDIO = "com.android.cts.verifier.managedprovisioning.BYOD_CAPTURE_AND_CHECK_AUDIO";
    public static final String ACTION_KEYGUARD_DISABLED_FEATURES =
            "com.android.cts.verifier.managedprovisioning.BYOD_KEYGUARD_DISABLED_FEATURES";
    public static final String ACTION_LOCKNOW =
            "com.android.cts.verifier.managedprovisioning.BYOD_LOCKNOW";
    public static final String ACTION_TEST_NFC_BEAM = "com.android.cts.verifier.managedprovisioning.TEST_NFC_BEAM";

    public static final String EXTRA_PROVISIONED = "extra_provisioned";
    public static final String EXTRA_PARAMETER_1 = "extra_parameter_1";

    // Primary -> managed intent: check if the disk of the device is encrypted
    public static final String ACTION_CHECK_DISK_ENCRYPTION =
            "com.android.cts.verifier.managedprovisioning.action.BYOD_CHECK_DISK_ENCRYPTION";
    // Managed -> primary intent: update disk encryption status in primary's CtsVerifier
    public static final String ACTION_DISK_ENCRYPTION_STATUS =
            "com.android.cts.verifier.managedprovisioning.action.BYOD_DISK_ENCRYPTION_STATUS";
    // Int extra field indicating the encryption status of the device storage
    public static final String EXTRA_ENCRYPTION_STATUS = "extra_encryption_status";

    // Primary -> managed intent: set unknown sources restriction and install package
    public static final String ACTION_INSTALL_APK = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK";
    public static final String EXTRA_ALLOW_NON_MARKET_APPS = "allow_non_market_apps";
    public static final String ACTION_INSTALL_APK_WORK_PROFILE_GLOBAL_RESTRICTION = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK_WORK_PROFILE_GLOBAL_RESTRICTION";
    public static final String EXTRA_ALLOW_NON_MARKET_APPS_DEVICE_WIDE = "allow_non_market_apps_device_wide";

    // Primary -> managed intent: set unknown sources globally restriction
    public static final String ACTION_INSTALL_APK_PRIMARY_PROFILE_GLOBAL_RESTRICTION = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK_PRIMARY_PROFILE_GLOBAL_RESTRICTION";
    // Managed -> primary intent: install primary profile app with global unknown sources
    // restriction.
    public static final String ACTION_INSTALL_APK_IN_PRIMARY = "com.android.cts.verifier.managedprovisioning.BYOD_INSTALL_APK_IN_PRIMARY";

    // Primary -> managed intent: check if the required cross profile intent filters are set.
    public static final String ACTION_CHECK_INTENT_FILTERS =
            "com.android.cts.verifier.managedprovisioning.action.CHECK_INTENT_FILTERS";

    // Primary -> managed intent: will send a cross profile intent and check if the user sees an
    // intent picker dialog and can open the apps.
    public static final String ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG =
            "com.android.cts.verifier.managedprovisioning.action.TEST_CROSS_PROFILE_INTENTS_DIALOG";

    // Primary -> managed intent: will send an app link intent and check if the user sees a
    // dialog and can open the apps. This test is extremely similar to
    // ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG, but the intent used is a web intent, and there is
    // some behavior which is specific to web intents.
    public static final String ACTION_TEST_APP_LINKING_DIALOG =
            "com.android.cts.verifier.managedprovisioning.action.TEST_APP_LINKING_DIALOG";

    public static final String ACTION_NOTIFICATION =
            "com.android.cts.verifier.managedprovisioning.NOTIFICATION";
    public static final String ACTION_NOTIFICATION_ON_LOCKSCREEN =
            "com.android.cts.verifier.managedprovisioning.LOCKSCREEN_NOTIFICATION";
    public static final String ACTION_CLEAR_NOTIFICATION =
            "com.android.cts.verifier.managedprovisioning.CLEAR_NOTIFICATION";

    // Primary -> managed intent: set a user restriction
    public static final String ACTION_SET_USER_RESTRICTION =
            "com.android.cts.verifier.managedprovisioning.BYOD_SET_USER_RESTRICTION";

    // Primary -> managed intent: reset a user restriction
    public static final String ACTION_CLEAR_USER_RESTRICTION =
            "com.android.cts.verifier.managedprovisioning.BYOD_CLEAR_USER_RESTRICTION";

    // Primary -> managed intent: Start the selection of a work challenge
    public static final String ACTION_TEST_SELECT_WORK_CHALLENGE =
            "com.android.cts.verifier.managedprovisioning.TEST_SELECT_WORK_CHALLENGE";

    // Primary -> managed intent: Start the selection of a work challenge
    public static final String ACTION_TEST_PATTERN_WORK_CHALLENGE =
            "com.android.cts.verifier.managedprovisioning.TEST_PATTERN_WORK_CHALLENGE";

    // Primary -> managed intent: Start the selection of a parent profile password.
    public static final String ACTION_TEST_PARENT_PROFILE_PASSWORD =
            "com.android.cts.verifier.managedprovisioning.TEST_PARENT_PROFILE_PASSWORD";

    // Primary -> managed intent: Start the confirm credentials screen for the managed profile
    public static final String ACTION_LAUNCH_CONFIRM_WORK_CREDENTIALS =
            "com.android.cts.verifier.managedprovisioning.LAUNCH_CONFIRM_WORK_CREDENTIALS";

    public static final String ACTION_SET_ORGANIZATION_INFO =
            "com.android.cts.verifier.managedprovisioning.TEST_ORGANIZATION_INFO";

    public static final int RESULT_FAILED = RESULT_FIRST_USER;

    private static final int REQUEST_INSTALL_PACKAGE = 2;
    private static final int REQUEST_IMAGE_CAPTURE = 3;
    private static final int REQUEST_VIDEO_CAPTURE_WITH_EXTRA_OUTPUT = 4;
    private static final int REQUEST_VIDEO_CAPTURE_WITHOUT_EXTRA_OUTPUT = 5;
    private static final int REQUEST_AUDIO_CAPTURE = 6;
    private static final int REQUEST_POST_NOTIFICATIONS = 7;

    private static final String ORIGINAL_RESTRICTIONS_NAME = "original restrictions";

    private static final int NOTIFICATION_ID = 7;
    private static final String NOTIFICATION_CHANNEL_ID = TAG;

    private static final int EXECUTE_IMAGE_CAPTURE_TEST = 1;
    private static final int EXECUTE_VIDEO_CAPTURE_WITH_EXTRA_TEST = 2;
    private static final int EXECUTE_VIDEO_CAPTURE_WITHOUT_EXTRA_TEST = 3;

    private NotificationManager mNotificationManager;
    private Bundle mOriginalRestrictions;

    private ComponentName mAdminReceiverComponent;
    private DevicePolicyManager mDevicePolicyManager;

    private Uri mImageUri;
    private Uri mVideoUri;
    private File mImageFile;

    private ArrayList<File> mTempFiles = new ArrayList<File>();

    private Handler mMainThreadHandler;
    private int mNextNotificationVisibility;

    private void showNotification(int visibility) {
        mNextNotificationVisibility = visibility;

        if (hasPostNotificationsPermission()) {
            showNotificationInner();
        } else {
            requestPostNotificationsPermission(REQUEST_POST_NOTIFICATIONS);
        }
    }

    private void showNotificationInner() {
        final Notification notification = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
                .setSmallIcon(R.drawable.icon)
                .setContentTitle(getString(R.string.provisioning_byod_notification_title))
                .setContentText(getString(R.string.provisioning_byod_notification_title))
                .setVisibility(mNextNotificationVisibility)
                .setAutoCancel(true)
                .setPublicVersion(createPublicVersionNotification())
                .build();
        mNotificationManager.notify(NOTIFICATION_ID, notification);
    }

    private Notification createPublicVersionNotification() {
        return new Notification.Builder(this)
                .setSmallIcon(R.drawable.icon)
                .setContentTitle(getString(R.string.provisioning_byod_notification_public_title))
                .setAutoCancel(true)
                .build();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mMainThreadHandler = new Handler(getMainLooper());
        if (savedInstanceState != null) {
            Log.w(TAG, "Restored state");
            mOriginalRestrictions = savedInstanceState.getBundle(ORIGINAL_RESTRICTIONS_NAME);
        } else {
            mOriginalRestrictions = new Bundle();
        }

        mAdminReceiverComponent = new ComponentName(this, DeviceAdminTestReceiver.class.getName());
        mDevicePolicyManager = (DevicePolicyManager) getSystemService(
                Context.DEVICE_POLICY_SERVICE);
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        Intent intent = getIntent();
        String action = intent.getAction();
        Log.d(TAG, "ByodHelperActivity.onCreate: " + action);
        mNotificationManager.createNotificationChannel(new NotificationChannel(
                NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_ID,
                NotificationManager.IMPORTANCE_DEFAULT));

        // Queried by CtsVerifier in the primary side using startActivityForResult.
        if (action.equals(ACTION_QUERY_PROFILE_OWNER)) {
            Intent response = new Intent();
            response.putExtra(EXTRA_PROVISIONED, isProfileOwner());
            setResult(RESULT_OK, response);
            // Request to delete work profile.
        } else if (action.equals(ACTION_REMOVE_MANAGED_PROFILE)) {
            if (isProfileOwner()) {
                Log.d(TAG, "Clearing cross profile intents");
                mDevicePolicyManager.clearCrossProfileIntentFilters(mAdminReceiverComponent);
                mDevicePolicyManager.wipeData(0);
                showToast(R.string.provisioning_byod_profile_deleted);
            }
        } else if (action.equals(ACTION_CHECK_DISK_ENCRYPTION)) {
            final int status = mDevicePolicyManager.getStorageEncryptionStatus();
            final Intent response = new Intent(ACTION_DISK_ENCRYPTION_STATUS)
                    .putExtra(EXTRA_ENCRYPTION_STATUS, status);
            setResult(RESULT_OK, response);
        } else if (action.equals(ACTION_INSTALL_APK)) {
            boolean allowNonMarket = intent.getBooleanExtra(EXTRA_ALLOW_NON_MARKET_APPS, false);
            setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES, !allowNonMarket);
            startInstallerActivity(intent.getStringExtra(EXTRA_PARAMETER_1));
            // Not yet ready to finish - wait until the result comes back
            return;
        } else if (action.equals(ACTION_INSTALL_APK_WORK_PROFILE_GLOBAL_RESTRICTION)) {
            // Save original unknown sources setting to be restored later and clear it for now.
            setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
            boolean allowNonMarketGlobal = intent.getBooleanExtra(
                    EXTRA_ALLOW_NON_MARKET_APPS_DEVICE_WIDE, false);
            setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
                    !allowNonMarketGlobal);
            startInstallerActivity(intent.getStringExtra(EXTRA_PARAMETER_1));
            // Not yet ready to finish - wait until the result comes back
            return;
        } else if (action.equals(ACTION_INSTALL_APK_PRIMARY_PROFILE_GLOBAL_RESTRICTION)) {
            boolean allowNonMarketGlobal = intent.getExtras().getBoolean(
                    EXTRA_ALLOW_NON_MARKET_APPS_DEVICE_WIDE, false);
            setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY,
                    !allowNonMarketGlobal);
            setRestrictionAndSaveOriginal(DISALLOW_INSTALL_UNKNOWN_SOURCES, false);
            Intent installPersonalProfileIntent = new Intent(ACTION_INSTALL_APK_IN_PRIMARY);
            // Attempt to install an apk in the primary profile
            startActivityForResult(installPersonalProfileIntent, REQUEST_INSTALL_PACKAGE);
            return;
        } else if (action.equals(ACTION_CHECK_INTENT_FILTERS)) {
            // Queried by CtsVerifier in the primary side using startActivityForResult.
            final boolean intentFiltersSetForManagedIntents =
                    new IntentFiltersTestHelper(this).checkCrossProfileIntentFilters(
                            IntentFiltersTestHelper.FLAG_INTENTS_FROM_MANAGED);
            setResult(intentFiltersSetForManagedIntents? RESULT_OK : RESULT_FAILED, null);
        } else if (action.equals(ACTION_CAPTURE_AND_CHECK_IMAGE)) {
            if (hasCameraPermission()) {
                startCaptureImageIntent();
            } else {
                requestCameraPermission(EXECUTE_IMAGE_CAPTURE_TEST);
            }
            return;
        } else if (action.equals(ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT) ||
                action.equals(ACTION_CAPTURE_AND_CHECK_VIDEO_WITHOUT_EXTRA_OUTPUT)) {
            final int testRequestCode;
            if (action.equals(ACTION_CAPTURE_AND_CHECK_VIDEO_WITH_EXTRA_OUTPUT)) {
                testRequestCode = EXECUTE_VIDEO_CAPTURE_WITH_EXTRA_TEST;
            } else {
                testRequestCode = EXECUTE_VIDEO_CAPTURE_WITHOUT_EXTRA_TEST;
            }

            if (hasCameraPermission()) {
                startCaptureVideoActivity(testRequestCode);
            } else {
                requestCameraPermission(testRequestCode);
            }
            return;
        } else if (action.equals(ACTION_CAPTURE_AND_CHECK_AUDIO)) {
            Intent captureAudioIntent = getCaptureAudioIntent();
            if (captureAudioIntent.resolveActivity(getPackageManager()) != null) {
                startActivityForResult(captureAudioIntent, REQUEST_AUDIO_CAPTURE);
            } else {
                Log.e(TAG, "Capture audio intent could not be resolved in managed profile.");
                showToast(R.string.provisioning_byod_capture_media_error);
                finish();
            }
            return;
        } else if (ACTION_KEYGUARD_DISABLED_FEATURES.equals(action)) {
            final int value = intent.getIntExtra(EXTRA_PARAMETER_1,
                    DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE);
            mDevicePolicyManager.setKeyguardDisabledFeatures(mAdminReceiverComponent, value);
        } else if (ACTION_LOCKNOW.equals(action)) {
            mDevicePolicyManager.lockNow();
            setResult(RESULT_OK);
        } else if (action.equals(ACTION_TEST_NFC_BEAM)) {
            Intent testNfcBeamIntent = new Intent(this, NfcTestActivity.class);
            testNfcBeamIntent.putExtras(intent);
            startActivity(testNfcBeamIntent);
            finish();
            return;
        } else if (action.equals(ACTION_TEST_CROSS_PROFILE_INTENTS_DIALOG)) {
            sendIntentInsideChooser(new Intent(
                    CrossProfileTestActivity.ACTION_CROSS_PROFILE_TO_PERSONAL));
        } else if (action.equals(ACTION_TEST_APP_LINKING_DIALOG)) {
            mDevicePolicyManager.addUserRestriction(
                    DeviceAdminTestReceiver.getReceiverComponentName(),
                    UserManager.ALLOW_PARENT_PROFILE_APP_LINKING);
            Intent toSend = new Intent(Intent.ACTION_VIEW);
            toSend.setData(Uri.parse("http://com.android.cts.verifier"));
            sendIntentInsideChooser(toSend);
        } else if (action.equals(ACTION_SET_USER_RESTRICTION)) {
            final String restriction = intent.getStringExtra(EXTRA_PARAMETER_1);
            if (restriction != null) {
                mDevicePolicyManager.addUserRestriction(
                        DeviceAdminTestReceiver.getReceiverComponentName(), restriction);
            }
        } else if (action.equals(ACTION_CLEAR_USER_RESTRICTION)) {
            final String restriction = intent.getStringExtra(EXTRA_PARAMETER_1);
            if (restriction != null) {
                mDevicePolicyManager.clearUserRestriction(
                        DeviceAdminTestReceiver.getReceiverComponentName(), restriction);
            }
        } else if (action.equals(ACTION_NOTIFICATION)) {
            showNotification(Notification.VISIBILITY_PUBLIC);
        } else if (ACTION_NOTIFICATION_ON_LOCKSCREEN.equals(action)) {
            mDevicePolicyManager.lockNow();
            showNotification(Notification.VISIBILITY_PRIVATE);
        } else if (ACTION_CLEAR_NOTIFICATION.equals(action)) {
            mNotificationManager.cancel(NOTIFICATION_ID);
        } else if (ACTION_TEST_SELECT_WORK_CHALLENGE.equals(action)) {
            mDevicePolicyManager.setOrganizationName(mAdminReceiverComponent, getResources()
                    .getString(R.string.provisioning_byod_confirm_work_credentials_header));
            startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD));
        } else if (ACTION_LAUNCH_CONFIRM_WORK_CREDENTIALS.equals(action)) {
            KeyguardManager keyguardManager =
                    (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
            Intent launchIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, null);
            if (launchIntent != null) {
                startActivity(launchIntent);
            } else {
                showToast(R.string.provisioning_byod_no_secure_lockscreen);
            }
        } else if (ACTION_TEST_PATTERN_WORK_CHALLENGE.equals(action)) {
            startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD));
            // The remaining steps are manual.
        } else if (ACTION_SET_ORGANIZATION_INFO.equals(action)) {
            if(intent.hasExtra(OrganizationInfoTestActivity.EXTRA_ORGANIZATION_NAME)) {
                final String organizationName = intent
                        .getStringExtra(OrganizationInfoTestActivity.EXTRA_ORGANIZATION_NAME);
                mDevicePolicyManager.setOrganizationName(mAdminReceiverComponent, organizationName);
            }
        } else if (ACTION_TEST_PARENT_PROFILE_PASSWORD.equals(action)) {
            startActivity(new Intent(DevicePolicyManager.ACTION_SET_NEW_PARENT_PROFILE_PASSWORD));
        }
        // This activity has no UI and is only used to respond to CtsVerifier in the primary side.
        finish();
    }

    private void startCaptureVideoActivity(int testRequestCode) {
        Intent captureVideoIntent = getCaptureVideoIntent();
        int videoCaptureRequestId;
        if (testRequestCode == EXECUTE_VIDEO_CAPTURE_WITH_EXTRA_TEST) {
            mVideoUri = getTempUri("video.mp4").second;
            captureVideoIntent.putExtra(MediaStore.EXTRA_OUTPUT, mVideoUri);
            videoCaptureRequestId = REQUEST_VIDEO_CAPTURE_WITH_EXTRA_OUTPUT;
        } else {
            videoCaptureRequestId = REQUEST_VIDEO_CAPTURE_WITHOUT_EXTRA_OUTPUT;
        }
        if (captureVideoIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(captureVideoIntent, videoCaptureRequestId);
        } else {
            Log.e(TAG, "Capture video intent could not be resolved in managed profile.");
            showToast(R.string.provisioning_byod_capture_media_error);
            finish();
        }
    }

    private void startCaptureImageIntent() {
        Intent captureImageIntent = getCaptureImageIntent();
        Pair<File, Uri> pair = getTempUri("image.jpg");
        mImageFile = pair.first;
        mImageUri = pair.second;
        captureImageIntent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
        if (captureImageIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(captureImageIntent, REQUEST_IMAGE_CAPTURE);
        } else {
            Log.e(TAG, "Capture image intent could not be resolved in managed profile.");
            showToast(R.string.provisioning_byod_capture_media_error);
            finish();
        }
    }

    private void startInstallerActivity(String pathToApk) {
        // Start the installer activity until this activity is rendered to workaround a glitch.
        mMainThreadHandler.post(() -> {
            final Uri uri;
            if (pathToApk == null) {
                // By default we reinstall ourselves, e.g. request to install a non-market app
                uri = Uri.parse("package:" + getPackageName());
            } else {
                uri = FileProvider.getUriForFile(
                    this, Utils.FILE_PROVIDER_AUTHORITY, new File(pathToApk));
            }
            final Intent installIntent = new Intent(Intent.ACTION_INSTALL_PACKAGE)
                .setData(uri)
                .putExtra(Intent.EXTRA_NOT_UNKNOWN_SOURCE, true)
                .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
                .putExtra(Intent.EXTRA_RETURN_RESULT, true);
            startActivityForResult(installIntent, REQUEST_INSTALL_PACKAGE);
        });
    }

    @Override
    protected void onSaveInstanceState(final Bundle savedState) {
        super.onSaveInstanceState(savedState);

        savedState.putBundle(ORIGINAL_RESTRICTIONS_NAME, mOriginalRestrictions);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case REQUEST_INSTALL_PACKAGE: {
                Log.w(TAG, "Received REQUEST_INSTALL_PACKAGE, resultCode = " + resultCode);
                // Restore original settings for restrictions being changed before installs.
                restoreOriginalRestriction(DISALLOW_INSTALL_UNKNOWN_SOURCES);
                restoreOriginalRestriction(DISALLOW_INSTALL_UNKNOWN_SOURCES_GLOBALLY);
                finish();
                break;
            }
            case REQUEST_IMAGE_CAPTURE: {
                if (resultCode == RESULT_OK) {
                    ByodPresentMediaDialog.newImageInstance(mImageFile)
                            .show(getFragmentManager(), "ViewImageDialogFragment");
                } else {
                    // Failed capturing image.
                    finish();
                }
                break;
            }
            case REQUEST_VIDEO_CAPTURE_WITH_EXTRA_OUTPUT: {
                if (resultCode == RESULT_OK) {
                    ByodPresentMediaDialog.newVideoInstance(mVideoUri)
                            .show(getFragmentManager(), "PlayVideoDialogFragment");
                } else {
                    // Failed capturing video.
                    finish();
                }
                break;
            }
            case REQUEST_VIDEO_CAPTURE_WITHOUT_EXTRA_OUTPUT: {
                if (resultCode == RESULT_OK) {
                    ByodPresentMediaDialog.newVideoInstance(data.getData())
                            .show(getFragmentManager(), "PlayVideoDialogFragment");
                } else {
                    // Failed capturing video.
                    finish();
                }
                break;
            }
            case REQUEST_AUDIO_CAPTURE: {
                if (resultCode == RESULT_OK) {
                    ByodPresentMediaDialog.newAudioInstance(data.getData())
                            .show(getFragmentManager(), "PlayAudioDialogFragment");
                } else {
                    // Failed capturing audio.
                    finish();
                }
                break;
            }
            default: {
                super.onActivityResult(requestCode, resultCode, data);
                break;
            }
        }
    }

    @Override
    protected void onDestroy() {
        cleanUpTempUris();
        super.onDestroy();
    }

    public static Intent getCaptureImageIntent() {
        return new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    }

    public static Intent getCaptureVideoIntent() {
        return new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
    }

    public static Intent getCaptureAudioIntent() {
        return new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION);
    }

    public static Intent createLockIntent() {
        return new Intent(ACTION_LOCKNOW);
    }

    private Pair<File, Uri> getTempUri(String fileName) {
        final File file = new File(getFilesDir() + File.separator + "images"
                + File.separator + fileName);
        file.getParentFile().mkdirs(); //if the folder doesn't exists it is created
        mTempFiles.add(file);
        return new Pair<>(file, FileProvider.getUriForFile(
                this, Utils.FILE_PROVIDER_AUTHORITY, file));
    }

    private void cleanUpTempUris() {
        for (File file : mTempFiles) {
            file.delete();
        }
    }

    private boolean isProfileOwner() {
        return mDevicePolicyManager.isAdminActive(mAdminReceiverComponent) &&
                mDevicePolicyManager.isProfileOwnerApp(mAdminReceiverComponent.getPackageName());
    }

    private boolean isRestrictionSet(String restriction) {
        Bundle restrictions = mDevicePolicyManager.getUserRestrictions(mAdminReceiverComponent);
        // This defaults to false if there is no value already there. If a restriction was true,
        // the restriction would already be set.
        return restrictions.getBoolean(restriction, false);
    }

    private void setRestriction(String restriction, boolean enabled) {
        if (enabled) {
            mDevicePolicyManager.addUserRestriction(mAdminReceiverComponent, restriction);
        } else {
            mDevicePolicyManager.clearUserRestriction(mAdminReceiverComponent, restriction);
        }
    }

    private void setRestrictionAndSaveOriginal(String restriction, boolean enabled) {
        // Saves original restriction values in mOriginalRestrictions before changing its value.
        boolean original = isRestrictionSet(restriction);
        if (enabled != original) {
            setRestriction(restriction, enabled);
            mOriginalRestrictions.putBoolean(restriction, original);
        }
    }

    public void restoreOriginalRestriction(String restriction) {
        if (mOriginalRestrictions.containsKey(restriction)) {
            setRestriction(restriction, mOriginalRestrictions.getBoolean(restriction));
            mOriginalRestrictions.remove(restriction);
        }
    }

    private boolean hasCameraPermission() {
        return ContextCompat.checkSelfPermission(this, android.Manifest.permission.CAMERA)
                == PackageManager.PERMISSION_GRANTED;
    }

    private void requestCameraPermission(int requestCode) {
        ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.CAMERA},
                requestCode);
    }

    private boolean hasLocationPermission() {
        return ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED;
    }

    private void requestLocationPermission(int requestCode) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                requestCode);
    }

    private boolean hasPostNotificationsPermission() {
        return ContextCompat.checkSelfPermission(this, POST_NOTIFICATIONS)
                == PackageManager.PERMISSION_GRANTED;
    }

    private void requestPostNotificationsPermission(int requestCode) {
        ActivityCompat.requestPermissions(this,
                new String[]{Manifest.permission.POST_NOTIFICATIONS},
                requestCode);
    }

    /**
     * Launch the right test based on the request code, after validating the right permission
     * has been granted.
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grants) {
        // Test that the right permission was granted.
        switch(requestCode) {
            case EXECUTE_IMAGE_CAPTURE_TEST:
            case EXECUTE_VIDEO_CAPTURE_WITH_EXTRA_TEST:
            case EXECUTE_VIDEO_CAPTURE_WITHOUT_EXTRA_TEST:
                if (!permissions[0].equals(android.Manifest.permission.CAMERA)
                        || grants[0] != PackageManager.PERMISSION_GRANTED) {
                    Log.e(TAG, "The test needs camera permission.");
                    showToast(R.string.provisioning_byod_capture_media_error);
                    finish();
                    return;
                }
                break;
            case REQUEST_POST_NOTIFICATIONS:
                if (!permissions[0].equals(POST_NOTIFICATIONS)
                        || grants[0] != PackageManager.PERMISSION_GRANTED) {
                    Log.e(TAG, "The test needs notifications permission.");
                    finish();
                    return;
                }
                break;
        }

        // Execute the right test.
        switch (requestCode) {
            case EXECUTE_IMAGE_CAPTURE_TEST:
                startCaptureImageIntent();
                break;
            case EXECUTE_VIDEO_CAPTURE_WITH_EXTRA_TEST:
            case EXECUTE_VIDEO_CAPTURE_WITHOUT_EXTRA_TEST:
                startCaptureVideoActivity(requestCode);
                break;
            case REQUEST_POST_NOTIFICATIONS:
                showNotificationInner();
                break;
            default:
                Log.e(TAG, "Unknown action.");
                finish();
        }
    }

    private void sendIntentInsideChooser(Intent toSend) {
        toSend.putExtra(CrossProfileTestActivity.EXTRA_STARTED_FROM_WORK, true);
        Intent chooser = Intent.createChooser(toSend,
                getResources().getString(R.string.provisioning_cross_profile_chooser));
        startActivity(chooser);
    }

    @Override
    public void onDialogClose() {
        finish();
    }

    private void showToast(int messageId) {
        String message = getString(messageId);
        Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    }
}
