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

Commit 0d07a8fa authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "active-unlock"

* changes:
  Implementing lockUser
  Adding logic for active unlock to grant trust
parents 79d91e3e 40436e55
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.os.UserHandle;
oneway interface ITrustAgentServiceCallback {
    void grantTrust(CharSequence message, long durationMs, int flags);
    void revokeTrust();
    void lockUser();
    void setManagingTrust(boolean managingTrust);
    void onConfigureCompleted(boolean result, IBinder token);
    void addEscrowToken(in byte[] token, int userId);
+7 −6
Original line number Diff line number Diff line
@@ -126,9 +126,6 @@ public class TrustAgentService extends Service {
     * <p>When the platform internally removes the agent's trust in this manner, an agent can
     * re-grant it (via a call to grantTrust) without the user having to unlock the device through
     * another method (e.g. PIN). This renewable state only persists for a limited time.
     *
     * TODO(b/213631675): Remove @hide
     * @hide
     */
    public static final int FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE = 1 << 2;

@@ -624,11 +621,15 @@ public class TrustAgentService extends Service {
     *
     * If the user has no auth method specified, then keyguard will still be shown but can be
     * dismissed normally.
     *
     * TODO(b/213631675): Implement & make public
     * @hide
     */
    public final void lockUser() {
        if (mCallback != null) {
            try {
                mCallback.lockUser();
            } catch (RemoteException e) {
                onError("calling lockUser");
            }
        }
    }

    /**
+48 −1
Original line number Diff line number Diff line
@@ -71,6 +71,7 @@ public class TrustAgentWrapper {
    private static final int MSG_ESCROW_TOKEN_STATE = 9;
    private static final int MSG_UNLOCK_USER = 10;
    private static final int MSG_SHOW_KEYGUARD_ERROR_MESSAGE = 11;
    private static final int MSG_LOCK_USER = 12;

    /**
     * Time in uptime millis that we wait for the service connection, both when starting
@@ -100,6 +101,8 @@ public class TrustAgentWrapper {

    // Trust state
    private boolean mTrusted;
    private boolean mWaitingForTrustableDowngrade = false;
    private boolean mTrustable;
    private CharSequence mMessage;
    private boolean mDisplayTrustGrantedMessage;
    private boolean mTrustDisabledByDpm;
@@ -108,6 +111,25 @@ public class TrustAgentWrapper {
    private AlarmManager mAlarmManager;
    private final Intent mAlarmIntent;
    private PendingIntent mAlarmPendingIntent;
    private final BroadcastReceiver mTrustableDowngradeReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (!TrustManagerService.ENABLE_ACTIVE_UNLOCK_FLAG) {
                return;
            }
            if (!mWaitingForTrustableDowngrade) {
                return;
            }
            // are these the broadcasts we want to listen to
            if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())
                    || Intent.ACTION_USER_PRESENT.equals(intent.getAction())) {
                mTrusted = false;
                mTrustable = true;
                mWaitingForTrustableDowngrade = false;
                mTrustManagerService.updateTrust(mUserId, 0);
            }
        }
    };

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
@@ -126,16 +148,21 @@ public class TrustAgentWrapper {
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_GRANT_TRUST:
                    // TODO(b/213631675): Respect FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE
                    if (!isConnected()) {
                        Log.w(TAG, "Agent is not connected, cannot grant trust: "
                                + mName.flattenToShortString());
                        return;
                    }
                    mTrusted = true;
                    mTrustable = false;
                    mMessage = (CharSequence) msg.obj;
                    int flags = msg.arg1;
                    mDisplayTrustGrantedMessage = (flags & FLAG_GRANT_TRUST_DISPLAY_MESSAGE) != 0;
                    if ((flags & TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0) {
                        mWaitingForTrustableDowngrade = true;
                    } else {
                        mWaitingForTrustableDowngrade = false;
                    }
                    long durationMs = msg.getData().getLong(DATA_DURATION);
                    if (durationMs > 0) {
                        final long duration;
@@ -270,6 +297,13 @@ public class TrustAgentWrapper {
                    mTrustManagerService.showKeyguardErrorMessage(message);
                    break;
                }
                case MSG_LOCK_USER: {
                    mTrusted = false;
                    mTrustable = false;
                    mTrustManagerService.updateTrust(mUserId, 0 /* flags */);
                    mTrustManagerService.lockUser(mUserId);
                    break;
                }
            }
        }
    };
@@ -294,6 +328,11 @@ public class TrustAgentWrapper {
            mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
        }

        @Override
        public void lockUser() {
            mHandler.sendEmptyMessage(MSG_LOCK_USER);
        }

        @Override
        public void setManagingTrust(boolean managingTrust) {
            if (DEBUG) Slog.d(TAG, "managingTrust()");
@@ -427,6 +466,9 @@ public class TrustAgentWrapper {
        final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME);
        alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL);

        IntentFilter trustableFilter = new IntentFilter(Intent.ACTION_USER_PRESENT);
        trustableFilter.addAction(Intent.ACTION_SCREEN_OFF);

        // Schedules a restart for when connecting times out. If the connection succeeds,
        // the restart is canceled in mCallback's onConnected.
        scheduleRestart();
@@ -435,6 +477,7 @@ public class TrustAgentWrapper {
        if (mBound) {
            mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null,
                    Context.RECEIVER_EXPORTED);
            mContext.registerReceiver(mTrustableDowngradeReceiver, trustableFilter);
        } else {
            Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString());
        }
@@ -591,6 +634,10 @@ public class TrustAgentWrapper {
        return mTrusted && mManagingTrust && !mTrustDisabledByDpm;
    }

    public boolean isTrustable() {
        return mTrustable && mManagingTrust && !mTrustDisabledByDpm;
    }

    public boolean isManagingTrust() {
        return mManagingTrust && !mTrustDisabledByDpm;
    }
+113 −1
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.os.Message;
import android.os.PersistableBundle;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
@@ -65,6 +66,7 @@ import android.util.ArraySet;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.Xml;
import android.view.IWindowManager;
@@ -145,6 +147,21 @@ public class TrustManagerService extends SystemService {
    @GuardedBy("mUserIsTrusted")
    private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();

    //TODO(b/215724686): remove flag
    public static final boolean ENABLE_ACTIVE_UNLOCK_FLAG = SystemProperties.getBoolean(
            "fw.enable_active_unlock_flag", true);

    private enum TrustState {
        UNTRUSTED, // the phone is not unlocked by any trustagents
        TRUSTABLE, // the phone is in a semi-locked state that can be unlocked if
        // FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE is passed and a trustagent is trusted
        TRUSTED // the phone is unlocked
    };

    @GuardedBy("mUserTrustState")
    private final SparseArray<TrustManagerService.TrustState> mUserTrustState =
            new SparseArray<>();

    /**
     * Stores the locked state for users on the device. There are three different type of users
     * which are handled slightly differently:
@@ -228,7 +245,6 @@ public class TrustManagerService extends SystemService {
    }

    // Extend unlock config and logic

    private final class SettingsObserver extends ContentObserver {
        private final Uri TRUST_AGENTS_EXTEND_UNLOCK =
                Settings.Secure.getUriFor(Settings.Secure.TRUST_AGENTS_EXTEND_UNLOCK);
@@ -396,6 +412,14 @@ public class TrustManagerService extends SystemService {
    }

    private void updateTrust(int userId, int flags, boolean isFromUnlock) {
        if (ENABLE_ACTIVE_UNLOCK_FLAG) {
            updateTrustWithRenewableUnlock(userId, flags, isFromUnlock);
        } else {
            updateTrustWithExtendUnlock(userId, flags, isFromUnlock);
        }
    }

    private void updateTrustWithExtendUnlock(int userId, int flags, boolean isFromUnlock) {
        boolean managed = aggregateIsTrustManaged(userId);
        dispatchOnTrustManagedChanged(managed, userId);
        if (mStrongAuthTracker.isTrustAllowedForUser(userId)
@@ -441,6 +465,65 @@ public class TrustManagerService extends SystemService {
        }
    }

    private void updateTrustWithRenewableUnlock(int userId, int flags, boolean isFromUnlock) {
        boolean managed = aggregateIsTrustManaged(userId);
        dispatchOnTrustManagedChanged(managed, userId);
        if (mStrongAuthTracker.isTrustAllowedForUser(userId)
                && isTrustUsuallyManagedInternal(userId) != managed) {
            updateTrustUsuallyManaged(userId, managed);
        }

        boolean trustedByAtLeastOneAgent = aggregateIsTrusted(userId);
        boolean trustableByAtLeastOneAgent = aggregateIsTrustable(userId);
        boolean wasTrusted;
        boolean wasTrustable;
        TrustState pendingTrustState;

        IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
        boolean alreadyUnlocked = false;
        try {
            alreadyUnlocked = !wm.isKeyguardLocked();
        } catch (RemoteException e) {
        }

        synchronized (mUserTrustState) {
            wasTrusted = (mUserTrustState.get(userId) == TrustState.TRUSTED);
            wasTrustable = (mUserTrustState.get(userId) == TrustState.TRUSTABLE);
            boolean renewingTrust = wasTrustable && (
                    (flags & TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE) != 0);
            boolean canMoveToTrusted = alreadyUnlocked || isFromUnlock || renewingTrust;
            boolean upgradingTrustForCurrentUser = (userId == mCurrentUser);

            if (trustedByAtLeastOneAgent && wasTrusted) {
                // no change
                return;
            } else if (trustedByAtLeastOneAgent && canMoveToTrusted
                    && upgradingTrustForCurrentUser) {
                pendingTrustState = TrustState.TRUSTED;
            } else if (trustableByAtLeastOneAgent && (wasTrusted || wasTrustable)
                    && upgradingTrustForCurrentUser) {
                pendingTrustState = TrustState.TRUSTABLE;
            } else {
                pendingTrustState = TrustState.UNTRUSTED;
            }

            mUserTrustState.put(userId, pendingTrustState);
        }
        if (DEBUG) Slog.d(TAG, "pendingTrustState: " + pendingTrustState);

        boolean isNowTrusted = pendingTrustState == TrustState.TRUSTED;
        dispatchOnTrustChanged(isNowTrusted, userId, flags, getTrustGrantedMessages(userId));
        if (isNowTrusted != wasTrusted) {
            refreshDeviceLockedForUser(userId);
            if (!isNowTrusted) {
                maybeLockScreen(userId);
            } else {
                scheduleTrustTimeout(userId, false /* override */);
            }
        }
    }


    private void updateTrustUsuallyManaged(int userId, boolean managed) {
        synchronized (mTrustUsuallyManagedForUser) {
            mTrustUsuallyManagedForUser.put(userId, managed);
@@ -472,6 +555,20 @@ public class TrustManagerService extends SystemService {
        mLockPatternUtils.unlockUserWithToken(handle, token, userId);
    }

    /**
     * Locks the phone and requires some auth (not trust) like a biometric or passcode before
     * unlocking.
     */
    public void lockUser(int userId) {
        mLockPatternUtils.requireStrongAuth(
                StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
        try {
            WindowManagerGlobal.getWindowManagerService().lockNow(null);
        } catch (RemoteException e) {
            Slog.e(TAG, "Error locking screen when called from trust agent");
        }
    }

    void showKeyguardErrorMessage(CharSequence message) {
        dispatchOnTrustError(message);
    }
@@ -950,6 +1047,21 @@ public class TrustManagerService extends SystemService {
        return false;
    }

    private boolean aggregateIsTrustable(int userId) {
        if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
            return false;
        }
        for (int i = 0; i < mActiveAgents.size(); i++) {
            AgentInfo info = mActiveAgents.valueAt(i);
            if (info.userId == userId) {
                if (info.agent.isTrustable()) {
                    return true;
                }
            }
        }
        return false;
    }

    private List<String> getTrustGrantedMessages(int userId) {
        if (!mStrongAuthTracker.isTrustAllowedForUser(userId)) {
            return new ArrayList<>();