/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.oemlock;

import android.Manifest;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.oemlock.V1_0.IOemLock;
import android.os.Binder;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.UserManagerInternal.UserRestrictionsListener;
import android.service.oemlock.IOemLockService;
import android.util.Slog;

import com.android.server.LocalServices;
import com.android.server.PersistentDataBlockManagerInternal;
import com.android.server.SystemService;
import com.android.server.pm.UserRestrictionsUtils;

/**
 * Service for managing the OEM lock state of the device.
 *
 * The OemLock HAL will be used if it is available, otherwise the persistent data block will be
 * used.
 */
public class OemLockService extends SystemService {
    private static final String TAG = "OemLock";

    private static final String FLASH_LOCK_PROP = "ro.boot.flash.locked";
    private static final String FLASH_LOCK_UNLOCKED = "0";

    private Context mContext;
    private OemLock mOemLock;

    public static boolean isHalPresent() {
        return VendorLock.getOemLockHalService() != null;
    }

    /** Select the OEM lock implementation */
    private static OemLock getOemLock(Context context) {
        final IOemLock oemLockHal = VendorLock.getOemLockHalService();
        if (oemLockHal != null) {
            Slog.i(TAG, "Using vendor lock via the HAL");
            return new VendorLock(context, oemLockHal);
        } else {
            Slog.i(TAG, "Using persistent data block based lock");
            return new PersistentDataBlockLock(context);
        }
    }

    public OemLockService(Context context) {
        this(context, getOemLock(context));
    }

    OemLockService(Context context, OemLock oemLock) {
        super(context);
        mContext = context;
        mOemLock = oemLock;

        LocalServices.getService(UserManagerInternal.class)
                .addUserRestrictionsListener(mUserRestrictionsListener);
    }

    @Override
    public void onStart() {
        publishBinderService(Context.OEM_LOCK_SERVICE, mService);
    }

    private final UserRestrictionsListener mUserRestrictionsListener =
            new UserRestrictionsListener() {
        @Override
        public void onUserRestrictionsChanged(int userId, Bundle newRestrictions,
                Bundle prevRestrictions) {
            // The admin can prevent OEM unlock with the DISALLOW_FACTORY_RESET user restriction
            if (UserRestrictionsUtils.restrictionsChanged(prevRestrictions, newRestrictions,
                     UserManager.DISALLOW_FACTORY_RESET)) {
                final boolean unlockAllowedByAdmin =
                        !newRestrictions.getBoolean(UserManager.DISALLOW_FACTORY_RESET);
                if (!unlockAllowedByAdmin) {
                    mOemLock.setOemUnlockAllowedByDevice(false);
                    setPersistentDataBlockOemUnlockAllowedBit(false);
                }
            }
        }
    };

    /**
     * Implements the binder interface for the service.
     *
     * This checks for the relevant permissions before forwarding the call to the OEM lock
     * implementation being used on this device.
     */
    private final IBinder mService = new IOemLockService.Stub() {
        @Override
        @Nullable
        public String getLockName() {
            enforceManageCarrierOemUnlockPermission();

            final long token = Binder.clearCallingIdentity();
            try {
                return mOemLock.getLockName();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
            enforceManageCarrierOemUnlockPermission();
            enforceUserIsAdmin();

            final long token = Binder.clearCallingIdentity();
            try {
                mOemLock.setOemUnlockAllowedByCarrier(allowed, signature);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean isOemUnlockAllowedByCarrier() {
            enforceManageCarrierOemUnlockPermission();

            final long token = Binder.clearCallingIdentity();
            try {
              return mOemLock.isOemUnlockAllowedByCarrier();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        // The user has the final say so if they allow unlock, then the device allows the bootloader
        // to OEM unlock it.
        @Override
        public void setOemUnlockAllowedByUser(boolean allowedByUser) {
            if (ActivityManager.isUserAMonkey()) {
                // Prevent a monkey from changing this
                return;
            }

            enforceManageUserOemUnlockPermission();
            enforceUserIsAdmin();

            final long token = Binder.clearCallingIdentity();
            try {
                if (!isOemUnlockAllowedByAdmin()) {
                    throw new SecurityException("Admin does not allow OEM unlock");
                }

                if (!mOemLock.isOemUnlockAllowedByCarrier()) {
                    throw new SecurityException("Carrier does not allow OEM unlock");
                }

                mOemLock.setOemUnlockAllowedByDevice(allowedByUser);
                setPersistentDataBlockOemUnlockAllowedBit(allowedByUser);
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean isOemUnlockAllowedByUser() {
            enforceManageUserOemUnlockPermission();

            final long token = Binder.clearCallingIdentity();
            try {
                return mOemLock.isOemUnlockAllowedByDevice();
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        /** Currently MasterClearConfirm will call isOemUnlockAllowed()
         * to sync PersistentDataBlockOemUnlockAllowedBit which
         * is needed before factory reset
         * TODO: Figure out better place to run sync e.g. adding new API
         */
        @Override
        public boolean isOemUnlockAllowed() {
            enforceOemUnlockReadPermission();

            final long token = Binder.clearCallingIdentity();
            try {
                boolean allowed = mOemLock.isOemUnlockAllowedByCarrier()
                        && mOemLock.isOemUnlockAllowedByDevice();
                setPersistentDataBlockOemUnlockAllowedBit(allowed);
                return allowed;
            } finally {
                Binder.restoreCallingIdentity(token);
            }
        }

        @Override
        public boolean isDeviceOemUnlocked() {
            enforceOemUnlockReadPermission();

            String locked = SystemProperties.get(FLASH_LOCK_PROP);
            switch (locked) {
                case FLASH_LOCK_UNLOCKED:
                    return true;
                default:
                    return false;
            }
        }
    };

    /**
     * Always synchronize the OemUnlockAllowed bit to the FRP partition, which
     * is used to erase FRP information on a unlockable device.
     */
    private void setPersistentDataBlockOemUnlockAllowedBit(boolean allowed) {
        final PersistentDataBlockManagerInternal pdbmi
                = LocalServices.getService(PersistentDataBlockManagerInternal.class);
        // if mOemLock is PersistentDataBlockLock, then the bit should have already been set
        if (pdbmi != null && !(mOemLock instanceof PersistentDataBlockLock)) {
            Slog.i(TAG, "Update OEM Unlock bit in pst partition to " + allowed);
            pdbmi.forceOemUnlockEnabled(allowed);
        }
    }

    private boolean isOemUnlockAllowedByAdmin() {
        return !UserManager.get(mContext)
                .hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET, UserHandle.SYSTEM);
    }

    private void enforceManageCarrierOemUnlockPermission() {
        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE,
                "Can't manage OEM unlock allowed by carrier");
    }

    private void enforceManageUserOemUnlockPermission() {
        mContext.enforceCallingOrSelfPermission(
                Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE,
                "Can't manage OEM unlock allowed by user");
    }

    private void enforceOemUnlockReadPermission() {
        if (mContext.checkCallingOrSelfPermission(Manifest.permission.READ_OEM_UNLOCK_STATE)
                == PackageManager.PERMISSION_DENIED
                && mContext.checkCallingOrSelfPermission(Manifest.permission.OEM_UNLOCK_STATE)
                == PackageManager.PERMISSION_DENIED) {
            throw new SecurityException("Can't access OEM unlock state. Requires "
                    + "READ_OEM_UNLOCK_STATE or OEM_UNLOCK_STATE permission.");
        }
    }

    private void enforceUserIsAdmin() {
        final int userId = UserHandle.getCallingUserId();
        final long token = Binder.clearCallingIdentity();
        try {
            if (!UserManager.get(mContext).isUserAdmin(userId)) {
                throw new SecurityException("Must be an admin user");
            }
        } finally {
            Binder.restoreCallingIdentity(token);
        }
    }
}
