/*
 * Copyright 2014, 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.managedprovisioning;

import android.app.AlarmManager;
import android.app.Service;
import android.app.admin.DeviceInitializerStatus;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.UserHandle;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;

import com.android.internal.app.LocalePicker;
import com.android.managedprovisioning.ProvisioningParams.PackageDownloadInfo;
import com.android.managedprovisioning.proxy.BluetoothConnectionService;
import com.android.managedprovisioning.task.AddWifiNetworkTask;
import com.android.managedprovisioning.task.BluetoothConnectTask;
import com.android.managedprovisioning.task.DeleteNonRequiredAppsTask;
import com.android.managedprovisioning.task.DownloadPackageTask;
import com.android.managedprovisioning.task.InstallPackageTask;
import com.android.managedprovisioning.task.SetDevicePolicyTask;
import com.android.managedprovisioning.task.WipeResetProtectionTask;

import java.lang.Runnable;
import java.util.Locale;

/**
 * This service does the work for the DeviceOwnerProvisioningActivity.
 * Feedback is sent back to the activity via intents.
 *
 * <p>
 * If the corresponding activity is killed and restarted, the service is
 * called twice. The service will not start the provisioning flow a second time, but instead
 * send a status update to the activity.
 * </p>
 */
public class DeviceOwnerProvisioningService extends Service {
    private static final boolean DEBUG = false; // To control logging.

    private static final String DEVICE_OWNER = "deviceOwner";
    private static final String DEVICE_INITIALIZER = "deviceInitializer";

    /**
     * Intent action to activate the CDMA phone connection by OTASP.
     * This is not necessary for a GSM phone connection, which is activated automatically.
     * String must agree with the constants in com.android.phone.InCallScreenShowActivation.
     */
    private static final String ACTION_PERFORM_CDMA_PROVISIONING =
            "com.android.phone.PERFORM_CDMA_PROVISIONING";

    // Intent actions and extras for communication from DeviceOwnerProvisioningService to Activity.
    protected static final String EXTRA_PROVISIONING_PARAMS =
            "ProvisioningParams";

    // Intent actions and extras for communication from DeviceOwnerProvisioningActivity to Service.
    protected static final String ACTION_PROVISIONING_SUCCESS =
            "com.android.managedprovisioning.provisioning_success";
    protected static final String ACTION_PROVISIONING_ERROR =
            "com.android.managedprovisioning.error";
    protected static final String EXTRA_USER_VISIBLE_ERROR_ID_KEY =
            "UserVisibleErrorMessage-Id";
    protected static final String ACTION_PROGRESS_UPDATE =
            "com.android.managedprovisioning.progress_update";
    protected static final String EXTRA_PROGRESS_MESSAGE_ID_KEY =
            "ProgressMessageId";
    protected static final String ACTION_REQUEST_WIFI_PICK =
            "com.android.managedprovisioning.request_wifi_pick";

    // Intent action used by the HomeReceiverActivity to notify this Service that a HOME intent was
    // received, which indicates that the Setup wizard has closed after provisioning completed.
    protected static final String ACTION_HOME_INDIRECT =
            "com.android.managedprovisioning.home_indirect";

    // Indicates whether provisioning has started.
    private boolean mProvisioningInFlight = false;

    // MessageId of the last progress message.
    private int mLastProgressMessage = -1;

    // MessageId of the last error message.
    private int mLastErrorMessage = -1;

    // Indicates whether provisioning has finished successfully (service waiting to stop).
    private volatile boolean mDone = false;

    // Provisioning tasks.
    private BluetoothConnectTask mBluetoothConnectTask;
    private AddWifiNetworkTask mAddWifiNetworkTask;
    private WipeResetProtectionTask mWipeResetProtectionTask;
    private DownloadPackageTask mDownloadPackageTask;
    private InstallPackageTask mInstallPackageTask;
    private SetDevicePolicyTask mSetDevicePolicyTask;
    private DeleteNonRequiredAppsTask mDeleteNonRequiredAppsTask;

    private ProvisioningParams mParams;

    @Override
    public int onStartCommand(final Intent intent, int flags, int startId) {
        if (DEBUG) ProvisionLogger.logd("Device owner provisioning service ONSTARTCOMMAND.");

        synchronized (this) { // Make operations on mProvisioningInFlight atomic.
            if (mProvisioningInFlight) {
                if (DEBUG) ProvisionLogger.logd("Provisioning already in flight.");

                sendProgressUpdateToActivity();

                // Send error message if currently in error state.
                if (mLastErrorMessage >= 0) {
                    sendError();
                }

                // Send success if provisioning was successful.
                if (mDone) {
                    onProvisioningSuccess();
                }
            } else {
                mProvisioningInFlight = true;
                if (DEBUG) ProvisionLogger.logd("First start of the service.");
                progressUpdate(R.string.progress_data_process);

                // Load the ProvisioningParams (from message in Intent).
                mParams = (ProvisioningParams) intent.getParcelableExtra(EXTRA_PROVISIONING_PARAMS);

                // Do the work on a separate thread.
                new Thread(new Runnable() {
                        public void run() {
                            initializeProvisioningEnvironment(mParams);
                            startDeviceOwnerProvisioning(mParams);
                        }
                    }).start();
            }
        }
        return START_NOT_STICKY;
    }

    /**
     * This is the core method of this class. It goes through every provisioning step.
     * Each task checks if it is required and executes if it is.
     */
    private void startDeviceOwnerProvisioning(final ProvisioningParams params) {
        if (DEBUG) ProvisionLogger.logd("Starting device owner provisioning");

        // Construct Tasks. Do not start them yet.
        mBluetoothConnectTask = new BluetoothConnectTask(this, params.bluetoothInfo,
                !TextUtils.isEmpty(params.wifiInfo.ssid),
                new BluetoothConnectTask.Callback() {
                        @Override
                        public void onSuccess() {
                            progressUpdate(R.string.progress_connect_to_wifi);
                            mAddWifiNetworkTask.run();
                        }
                        @Override
                        public void onError() {
                            error(R.string.device_owner_error_bluetooth);
                        }
                });

        mAddWifiNetworkTask = new AddWifiNetworkTask(this, params.wifiInfo,
                new AddWifiNetworkTask.Callback() {
                       @Override
                       public void onSuccess() {
                           progressUpdate(R.string.progress_wipe_frp);
                           mWipeResetProtectionTask.run();
                       }

                       @Override
                       public void onError(){
                           error(R.string.device_owner_error_wifi);
                           statusUpdate(DeviceInitializerStatus.STATUS_ERROR_CONNECT_WIFI);
                           }
                       });

        mWipeResetProtectionTask = new WipeResetProtectionTask(this, params.frpChallengeBundle,
                new WipeResetProtectionTask.Callback() {
                    @Override
                    public void onSuccess() {
                        progressUpdate(R.string.progress_download);
                        mDownloadPackageTask.run();
                    }
                    @Override
                    public void onError() {
                        error(R.string.device_owner_error_frp);
                        statusUpdate(DeviceInitializerStatus.
                                STATUS_ERROR_RESET_PROTECTION_BLOCKING_PROVISIONING);
                    }
                });

        mDownloadPackageTask = new DownloadPackageTask(this,
                new DownloadPackageTask.Callback() {
                        @Override
                        public void onSuccess() {
                            progressUpdate(R.string.progress_install);
                            mInstallPackageTask.addInstallIfNecessary(
                                    params.inferDeviceAdminPackageName(),
                                    mDownloadPackageTask.getDownloadedPackageLocation(
                                            DEVICE_OWNER));
                            mInstallPackageTask.addInstallIfNecessary(
                                    params.getDeviceInitializerPackageName(),
                                    mDownloadPackageTask.getDownloadedPackageLocation(
                                            DEVICE_INITIALIZER));
                            mInstallPackageTask.run();
                        }

                        @Override
                        public void onError(int errorCode) {
                            switch(errorCode) {
                                case DownloadPackageTask.ERROR_HASH_MISMATCH:
                                    error(R.string.device_owner_error_hash_mismatch);
                                    break;
                                case DownloadPackageTask.ERROR_DOWNLOAD_FAILED:
                                    error(R.string.device_owner_error_download_failed);
                                    break;
                                default:
                                    error(R.string.device_owner_error_general);
                                    break;
                            }
                            statusUpdate(DeviceInitializerStatus.STATUS_ERROR_DOWNLOAD_PACKAGE);
                        }
                    });

        // Add packages to download to the DownloadPackageTask.
        mDownloadPackageTask.addDownloadIfNecessary(params.inferDeviceAdminPackageName(),
                params.deviceAdminDownloadInfo, DEVICE_OWNER);
        mDownloadPackageTask.addDownloadIfNecessary(params.getDeviceInitializerPackageName(),
                params.deviceInitializerDownloadInfo, DEVICE_INITIALIZER);

        mInstallPackageTask = new InstallPackageTask(this,
                new InstallPackageTask.Callback() {
                    @Override
                    public void onSuccess() {
                        progressUpdate(R.string.progress_set_owner);
                        try {
                            // Now that the app has been installed, we can look for the device admin
                            // component in it.
                            mSetDevicePolicyTask.run(mParams.inferDeviceAdminComponentName(
                                    DeviceOwnerProvisioningService.this));
                        } catch (Utils.IllegalProvisioningArgumentException e) {
                            error(R.string.device_owner_error_general);
                            ProvisionLogger.loge("Failed to infer the device admin component name",
                                    e);
                            return;
                        }
                    }

                    @Override
                    public void onError(int errorCode) {
                        switch(errorCode) {
                            case InstallPackageTask.ERROR_PACKAGE_INVALID:
                                error(R.string.device_owner_error_package_invalid);
                                break;
                            case InstallPackageTask.ERROR_INSTALLATION_FAILED:
                                error(R.string.device_owner_error_installation_failed);
                                break;
                            case InstallPackageTask.ERROR_PACKAGE_NAME_INVALID:
                                error(R.string.device_owner_error_package_name_invalid);
                                break;
                            default:
                                error(R.string.device_owner_error_general);
                                break;
                        }
                        statusUpdate(DeviceInitializerStatus.STATUS_ERROR_INSTALL_PACKAGE);
                    }
                });

        mSetDevicePolicyTask = new SetDevicePolicyTask(this,
                getResources().getString(R.string.default_owned_device_username),
                params.deviceInitializerComponentName,
                getResources().getString(R.string.default_owned_device_username),
                new SetDevicePolicyTask.Callback() {
                    @Override
                    public void onSuccess() {
                        mDeleteNonRequiredAppsTask.run();
                    }

                    @Override
                    public void onError(int errorCode) {
                        switch(errorCode) {
                            case SetDevicePolicyTask.ERROR_PACKAGE_NOT_INSTALLED:
                                error(R.string.device_owner_error_package_not_installed);
                                break;
                            case SetDevicePolicyTask.ERROR_NO_RECEIVER:
                                error(R.string.device_owner_error_package_invalid);
                                break;
                            default:
                                error(R.string.device_owner_error_general);
                                break;
                        }
                        statusUpdate(DeviceInitializerStatus.STATUS_ERROR_SET_DEVICE_POLICY);
                    }
                });

        mDeleteNonRequiredAppsTask = new DeleteNonRequiredAppsTask(
                this, params.inferDeviceAdminPackageName(), R.array.required_apps_managed_device,
                R.array.vendor_required_apps_managed_device, true /* creating new profile */,
                UserHandle.USER_OWNER, params.leaveAllSystemAppsEnabled,
                new DeleteNonRequiredAppsTask.Callback() {
                    @Override
                    public void onSuccess() {
                        // Done with provisioning. Success.
                        onProvisioningSuccess();
                    }

                    @Override
                    public void onError() {
                        error(R.string.device_owner_error_general);
                        statusUpdate(DeviceInitializerStatus.STATUS_ERROR_DELETE_APPS);
                    }
                });

        // Start first task, which starts next task in its callback, etc.
        progressUpdate(R.string.progress_start_bluetooth);
        mBluetoothConnectTask.run();
    }

    private void error(int dialogMessage) {
        mLastErrorMessage = dialogMessage;
        sendError();
        // Wait for stopService() call from the activity.
    }

    private void statusUpdate(int statusCode) {
        BluetoothConnectionService.sendStatusUpdate(this, statusCode);
    }

    private void sendError() {
        if (DEBUG) {
            ProvisionLogger.logd("Reporting Error: " + getResources()
                .getString(mLastErrorMessage));
        }
        Intent intent = new Intent(ACTION_PROVISIONING_ERROR);
        intent.setClass(this, DeviceOwnerProvisioningActivity.ServiceMessageReceiver.class);
        intent.putExtra(EXTRA_USER_VISIBLE_ERROR_ID_KEY, mLastErrorMessage);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    private void progressUpdate(int progressMessage) {
        if (DEBUG) {
            ProvisionLogger.logd("Reporting progress update: " + getResources()
                .getString(progressMessage));
        }
        mLastProgressMessage = progressMessage;
        sendProgressUpdateToActivity();
    }

    private void sendProgressUpdateToActivity() {
        Intent intent = new Intent(ACTION_PROGRESS_UPDATE);
        intent.putExtra(EXTRA_PROGRESS_MESSAGE_ID_KEY, mLastProgressMessage);
        intent.setClass(this, DeviceOwnerProvisioningActivity.ServiceMessageReceiver.class);
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }

    private void onProvisioningSuccess() {
        if (DEBUG) ProvisionLogger.logd("Reporting success.");
        mDone = true;

        // Persist mParams so HomeReceiverActivity can later retrieve them to finalize provisioning.
        // This is necessary to deal with accidental reboots during DIA setup, which happens between
        // the end of this method and HomeReceiverActivity captures the home intent.
        IntentStore store = BootReminder.getDeviceOwnerFinalizingIntentStore(this);
        Bundle resumeBundle = new Bundle();
        (new MessageParser()).addProvisioningParamsToBundle(resumeBundle, mParams);
        store.save(resumeBundle);

        // Enable the HomeReceiverActivity, since the DeviceOwnerProvisioningActivity will shutdown
        // the Setup wizard soon, which will result in a home intent that should be caught by the
        // HomeReceiverActivity.
        PackageManager pm = getPackageManager();
        pm.setComponentEnabledSetting(new ComponentName(DeviceOwnerProvisioningService.this,
                        HomeReceiverActivity.class), PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
                PackageManager.DONT_KILL_APP);

        Intent successIntent = new Intent(ACTION_PROVISIONING_SUCCESS);
        successIntent.setClass(this, DeviceOwnerProvisioningActivity.ServiceMessageReceiver.class);
        LocalBroadcastManager.getInstance(this).sendBroadcast(successIntent);
        // Wait for stopService() call from the activity.
    }

    private void initializeProvisioningEnvironment(ProvisioningParams params) {
        setTimeAndTimezone(params.timeZone, params.localTime);
        setLocale(params.locale);

        // Start CDMA activation to enable phone calls.
        final Intent intent = new Intent(ACTION_PERFORM_CDMA_PROVISIONING);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        if (DEBUG) ProvisionLogger.logd("Starting cdma activation activity");
        startActivity(intent); // Activity will be a Nop if not a CDMA device.
    }

    private void setTimeAndTimezone(String timeZone, long localTime) {
        try {
            final AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
            if (timeZone != null) {
                if (DEBUG) ProvisionLogger.logd("Setting time zone to " + timeZone);
                am.setTimeZone(timeZone);
            }
            if (localTime > 0) {
                if (DEBUG) ProvisionLogger.logd("Setting time to " + localTime);
                am.setTime(localTime);
            }
        } catch (Exception e) {
            ProvisionLogger.loge("Alarm manager failed to set the system time/timezone.");
            // Do not stop provisioning process, but ignore this error.
        }
    }

    private void setLocale(Locale locale) {
        if (locale == null || locale.equals(Locale.getDefault())) {
            return;
        }
        try {
            if (DEBUG) ProvisionLogger.logd("Setting locale to " + locale);
            // If locale is different from current locale this results in a configuration change,
            // which will trigger the restarting of the activity.
            LocalePicker.updateLocale(locale);
        } catch (Exception e) {
            ProvisionLogger.loge("Failed to set the system locale.");
            // Do not stop provisioning process, but ignore this error.
        }
    }

    @Override
    public void onCreate () {
        if (DEBUG) ProvisionLogger.logd("Device owner provisioning service ONCREATE.");
    }

    @Override
    public void onDestroy () {
        if (DEBUG) ProvisionLogger.logd("Device owner provisioning service ONDESTROY");
        if (mAddWifiNetworkTask != null) {
            mAddWifiNetworkTask.cleanUp();
        }
        if (mDownloadPackageTask != null) {
            mDownloadPackageTask.cleanUp();
        }
        if (mBluetoothConnectTask != null) {
            mBluetoothConnectTask.cleanUp();
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

