Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86f682fd authored by Erin Yan's avatar Erin Yan Committed by Android (Google) Code Review
Browse files

Merge "Add weak escrow token APIs"

parents 90c3c76b 459f6115
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -179,6 +179,7 @@ package android {
    field public static final String MANAGE_USB = "android.permission.MANAGE_USB";
    field public static final String MANAGE_USERS = "android.permission.MANAGE_USERS";
    field public static final String MANAGE_USER_OEM_UNLOCK_STATE = "android.permission.MANAGE_USER_OEM_UNLOCK_STATE";
    field public static final String MANAGE_WEAK_ESCROW_TOKEN = "android.permission.MANAGE_WEAK_ESCROW_TOKEN";
    field public static final String MANAGE_WIFI_AUTO_JOIN = "android.permission.MANAGE_WIFI_AUTO_JOIN";
    field public static final String MANAGE_WIFI_COUNTRY_CODE = "android.permission.MANAGE_WIFI_COUNTRY_CODE";
    field public static final String MARK_DEVICE_ORGANIZATION_OWNED = "android.permission.MARK_DEVICE_ORGANIZATION_OWNED";
@@ -771,18 +772,32 @@ package android.app {
  }
  public class KeyguardManager {
    method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public long addWeakEscrowToken(@NonNull byte[], @NonNull android.os.UserHandle, @NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.WeakEscrowTokenActivatedListener);
    method public android.content.Intent createConfirmFactoryResetCredentialIntent(CharSequence, CharSequence, CharSequence);
    method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public int getMinLockLength(boolean, int);
    method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public boolean getPrivateNotificationsAllowed();
    method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public boolean isValidLockPasswordComplexity(int, @NonNull byte[], int);
    method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public boolean isWeakEscrowTokenActive(long, @NonNull android.os.UserHandle);
    method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public boolean isWeakEscrowTokenValid(long, @NonNull byte[], @NonNull android.os.UserHandle);
    method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public boolean registerWeakEscrowTokenRemovedListener(@NonNull java.util.concurrent.Executor, @NonNull android.app.KeyguardManager.WeakEscrowTokenRemovedListener);
    method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public boolean removeWeakEscrowToken(long, @NonNull android.os.UserHandle);
    method @RequiresPermission(android.Manifest.permission.SHOW_KEYGUARD_MESSAGE) public void requestDismissKeyguard(@NonNull android.app.Activity, @Nullable CharSequence, @Nullable android.app.KeyguardManager.KeyguardDismissCallback);
    method @RequiresPermission("android.permission.SET_INITIAL_LOCK") public boolean setLock(int, @NonNull byte[], int);
    method @RequiresPermission(android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS) public void setPrivateNotificationsAllowed(boolean);
    method @RequiresPermission(android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN) public boolean unregisterWeakEscrowTokenRemovedListener(@NonNull android.app.KeyguardManager.WeakEscrowTokenRemovedListener);
    field public static final int PASSWORD = 0; // 0x0
    field public static final int PATTERN = 2; // 0x2
    field public static final int PIN = 1; // 0x1
  }
  public static interface KeyguardManager.WeakEscrowTokenActivatedListener {
    method public void onWeakEscrowTokenActivated(long, @NonNull android.os.UserHandle);
  }
  public static interface KeyguardManager.WeakEscrowTokenRemovedListener {
    method public void onWeakEscrowTokenRemoved(long, @NonNull android.os.UserHandle);
  }
  public class LocaleManager {
    method @NonNull @RequiresPermission(android.Manifest.permission.READ_APP_SPECIFIC_LOCALES) public android.os.LocaleList getApplicationLocales(@NonNull String);
    method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void setApplicationLocales(@NonNull String, @NonNull android.os.LocaleList);
+192 −6
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.app;

import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -40,8 +41,10 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.persistentdata.IPersistentDataBlockService;
import android.util.ArrayMap;
import android.util.Log;
import android.view.IOnKeyguardExitResult;
import android.view.IWindowManager;
@@ -49,6 +52,9 @@ import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerGlobal;

import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.IWeakEscrowTokenActivatedListener;
import com.android.internal.widget.IWeakEscrowTokenRemovedListener;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternView;
import com.android.internal.widget.LockscreenCredential;
@@ -57,6 +63,8 @@ import com.android.internal.widget.VerifyCredentialResponse;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;

/**
 * Class that can be used to lock and unlock the keyguard. The
@@ -69,10 +77,13 @@ public class KeyguardManager {
    private static final String TAG = "KeyguardManager";

    private final Context mContext;
    private final LockPatternUtils mLockPatternUtils;
    private final IWindowManager mWM;
    private final IActivityManager mAm;
    private final ITrustManager mTrustManager;
    private final INotificationManager mNotificationManager;
    private final ArrayMap<WeakEscrowTokenRemovedListener, IWeakEscrowTokenRemovedListener>
            mListeners = new ArrayMap<>();

    /**
     * Intent used to prompt user for device credentials.
@@ -455,8 +466,42 @@ public class KeyguardManager {
        public void onDismissCancelled() { }
    }

    /**
     * Callback passed to
     * {@link KeyguardManager#addWeakEscrowToken}
     * to notify caller of state change.
     * @hide
     */
    @SystemApi
    public interface WeakEscrowTokenActivatedListener {
        /**
         * The method to be called when the token is activated.
         * @param handle 64 bit handle corresponding to the escrow token
         * @param user user for whom the weak escrow token has been added
         */
        void onWeakEscrowTokenActivated(long handle, @NonNull UserHandle user);
    }

    /**
     * Listener passed to
     * {@link KeyguardManager#registerWeakEscrowTokenRemovedListener} and
     * {@link KeyguardManager#unregisterWeakEscrowTokenRemovedListener}
     * to notify caller of an weak escrow token has been removed.
     * @hide
     */
    @SystemApi
    public interface WeakEscrowTokenRemovedListener {
        /**
         * The method to be called when the token is removed.
         * @param handle 64 bit handle corresponding to the escrow token
         * @param user user for whom the escrow token has been added
         */
        void onWeakEscrowTokenRemoved(long handle, @NonNull UserHandle user);
    }

    KeyguardManager(Context context) throws ServiceNotFoundException {
        mContext = context;
        mLockPatternUtils = new LockPatternUtils(context);
        mWM = WindowManagerGlobal.getWindowManagerService();
        mAm = ActivityManager.getService();
        mTrustManager = ITrustManager.Stub.asInterface(
@@ -785,7 +830,6 @@ public class KeyguardManager {
            return false;
        }

        LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
        int userId = mContext.getUserId();
        if (isDeviceSecure(userId)) {
            Log.e(TAG, "Password already set, rejecting call to setLock");
@@ -799,7 +843,7 @@ public class KeyguardManager {
        try {
            LockscreenCredential credential = createLockscreenCredential(
                    lockType, password);
            success = lockPatternUtils.setLockCredential(
            success = mLockPatternUtils.setLockCredential(
                    credential,
                    /* savedPassword= */ LockscreenCredential.createNone(),
                    userId);
@@ -812,6 +856,150 @@ public class KeyguardManager {
        return success;
    }

    /**
     * Create a weak escrow token for the current user, which can later be used to unlock FBE
     * or change user password.
     *
     * After adding, if the user currently  has a secure lockscreen, they will need to perform a
     * confirm credential operation in order to activate the token for future use. If the user
     * has no secure lockscreen, then the token is activated immediately.
     *
     * If the user changes or removes the lockscreen password, any activated weak escrow token will
     * be removed.
     *
     * @return a unique 64-bit token handle which is needed to refer to this token later.
     * @hide
     */
    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
    @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN)
    @SystemApi
    public long addWeakEscrowToken(@NonNull byte[] token, @NonNull UserHandle user,
            @NonNull @CallbackExecutor Executor executor,
            @NonNull WeakEscrowTokenActivatedListener listener) {
        Objects.requireNonNull(token, "Token cannot be null.");
        Objects.requireNonNull(user, "User cannot be null.");
        Objects.requireNonNull(executor, "Executor cannot be null.");
        Objects.requireNonNull(listener, "Listener cannot be null.");
        int userId = user.getIdentifier();
        IWeakEscrowTokenActivatedListener internalListener =
                new IWeakEscrowTokenActivatedListener.Stub() {
            @Override
            public void onWeakEscrowTokenActivated(long handle, int userId) {
                UserHandle user = UserHandle.of(userId);
                final long restoreToken = Binder.clearCallingIdentity();
                try {
                    executor.execute(() -> listener.onWeakEscrowTokenActivated(handle, user));
                } finally {
                    Binder.restoreCallingIdentity(restoreToken);
                }
                Log.i(TAG, "Weak escrow token activated.");
            }
        };
        return mLockPatternUtils.addWeakEscrowToken(token, userId, internalListener);
    }

    /**
     * Remove a weak escrow token.
     *
     * @return true if the given handle refers to a valid weak token previously returned from
     * {@link #addWeakEscrowToken}, whether it's active or not. return false otherwise.
     * @hide
     */
    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
    @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN)
    @SystemApi
    public boolean removeWeakEscrowToken(long handle, @NonNull UserHandle user) {
        Objects.requireNonNull(user, "User cannot be null.");
        return mLockPatternUtils.removeWeakEscrowToken(handle, user.getIdentifier());
    }

    /**
     * Check if the given weak escrow token is active or not.
     * @hide
     */
    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
    @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN)
    @SystemApi
    public boolean isWeakEscrowTokenActive(long handle, @NonNull UserHandle user) {
        Objects.requireNonNull(user, "User cannot be null.");
        return mLockPatternUtils.isWeakEscrowTokenActive(handle, user.getIdentifier());
    }

    /**
     * Check if the given weak escrow token is validate.
     * @hide
     */
    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
    @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN)
    @SystemApi
    public boolean isWeakEscrowTokenValid(long handle, @NonNull byte[] token,
            @NonNull UserHandle user) {
        Objects.requireNonNull(token, "Token cannot be null.");
        Objects.requireNonNull(user, "User cannot be null.");
        return mLockPatternUtils.isWeakEscrowTokenValid(handle, token, user.getIdentifier());
    }

    /**
     * Register the given WeakEscrowTokenRemovedListener.
     *
     * @return true if the listener is registered successfully, return false otherwise.
     * @hide
     */
    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
    @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN)
    @SystemApi
    public boolean registerWeakEscrowTokenRemovedListener(
            @NonNull @CallbackExecutor Executor executor,
            @NonNull WeakEscrowTokenRemovedListener listener) {
        Objects.requireNonNull(listener, "Listener cannot be null.");
        Objects.requireNonNull(executor, "Executor cannot be null.");
        Preconditions.checkArgument(!mListeners.containsKey(listener),
                "Listener already registered: %s", listener);
        IWeakEscrowTokenRemovedListener internalListener =
                new IWeakEscrowTokenRemovedListener.Stub() {
            @Override
            public void onWeakEscrowTokenRemoved(long handle, int userId) {
                UserHandle user = UserHandle.of(userId);
                final long token = Binder.clearCallingIdentity();
                try {
                    executor.execute(() -> listener.onWeakEscrowTokenRemoved(handle, user));
                } finally {
                    Binder.restoreCallingIdentity(token);
                }
            }
        };
        if (mLockPatternUtils.registerWeakEscrowTokenRemovedListener(internalListener)) {
            mListeners.put(listener, internalListener);
            return true;
        } else {
            Log.e(TAG, "Listener failed to register");
            return false;
        }
    }

    /**
     * Unregister the given WeakEscrowTokenRemovedListener.
     *
     * @return true if the listener is unregistered successfully, return false otherwise.
     * @hide
     */
    @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
    @RequiresPermission(Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN)
    @SystemApi
    public boolean unregisterWeakEscrowTokenRemovedListener(
            @NonNull WeakEscrowTokenRemovedListener listener) {
        Objects.requireNonNull(listener, "Listener cannot be null.");
        IWeakEscrowTokenRemovedListener internalListener = mListeners.get(listener);
        Preconditions.checkArgument(internalListener != null, "Listener was not registered");
        if (mLockPatternUtils.unregisterWeakEscrowTokenRemovedListener(internalListener)) {
            mListeners.remove(listener);
            return true;
        } else {
            Log.e(TAG, "Listener failed to unregister.");
            return false;
        }
    }

    /**
     * Set the lockscreen password to {@code newPassword} after validating the current password
     * against {@code currentPassword}.
@@ -832,13 +1020,12 @@ public class KeyguardManager {
    })
    public boolean setLock(@LockTypes int newLockType, @Nullable byte[] newPassword,
            @LockTypes int currentLockType, @Nullable byte[] currentPassword) {
        final LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
        final int userId = mContext.getUserId();
        LockscreenCredential currentCredential = createLockscreenCredential(
                currentLockType, currentPassword);
        LockscreenCredential newCredential = createLockscreenCredential(
                newLockType, newPassword);
        return lockPatternUtils.setLockCredential(newCredential, currentCredential, userId);
        return mLockPatternUtils.setLockCredential(newCredential, currentCredential, userId);
    }

    /**
@@ -857,10 +1044,9 @@ public class KeyguardManager {
            Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE
    })
    public boolean checkLock(@LockTypes int lockType, @Nullable byte[] password) {
        final LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
        final LockscreenCredential credential = createLockscreenCredential(
                lockType, password);
        final VerifyCredentialResponse response = lockPatternUtils.verifyCredential(
        final VerifyCredentialResponse response = mLockPatternUtils.verifyCredential(
                credential, mContext.getUserId(), /* flags= */ 0);
        if (response == null) {
            return false;
+8 −0
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@ import android.security.keystore.recovery.KeyChainSnapshot;
import android.security.keystore.recovery.KeyChainProtectionParams;
import android.security.keystore.recovery.RecoveryCertPath;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.IWeakEscrowTokenActivatedListener;
import com.android.internal.widget.IWeakEscrowTokenRemovedListener;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.VerifyCredentialResponse;

@@ -96,4 +98,10 @@ interface ILockSettings {
    boolean tryUnlockWithCachedUnifiedChallenge(int userId);
    void removeCachedUnifiedChallenge(int userId);
    void updateEncryptionPassword(int type, in byte[] password);
    boolean registerWeakEscrowTokenRemovedListener(in IWeakEscrowTokenRemovedListener listener);
    boolean unregisterWeakEscrowTokenRemovedListener(in IWeakEscrowTokenRemovedListener listener);
    long addWeakEscrowToken(in byte[] token, int userId, in IWeakEscrowTokenActivatedListener callback);
    boolean removeWeakEscrowToken(long handle, int userId);
    boolean isWeakEscrowTokenActive(long handle, int userId);
    boolean isWeakEscrowTokenValid(long handle, in byte[] token, int userId);
}
+22 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.internal.widget;

/** @hide */
oneway interface IWeakEscrowTokenActivatedListener {
    void onWeakEscrowTokenActivated(long handle, int userId);
}
+22 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.internal.widget;

/** @hide */
oneway interface IWeakEscrowTokenRemovedListener {
    void onWeakEscrowTokenRemoved(long handle, int userId);
}
Loading