/* * Copyright (C) 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 android.app.trust; import android.Manifest; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SystemService; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.hardware.biometrics.BiometricSourceType; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.Message; import android.os.RemoteException; import android.util.ArrayMap; import java.util.ArrayList; import java.util.List; /** * See {@link com.android.server.trust.TrustManagerService} * @hide */ @SystemService(Context.TRUST_SERVICE) public class TrustManager { /** * Intent action used to identify services that can serve as significant providers. * * @hide */ @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION) public static final String ACTION_BIND_SIGNIFICANT_PLACE_PROVIDER = "com.android.trust.provider.SignificantPlaceProvider.BIND"; private static final int MSG_TRUST_CHANGED = 1; private static final int MSG_TRUST_MANAGED_CHANGED = 2; private static final int MSG_TRUST_ERROR = 3; private static final int MSG_ENABLED_TRUST_AGENTS_CHANGED = 4; private static final int MSG_IS_ACTIVE_UNLOCK_RUNNING = 5; private static final String TAG = "TrustManager"; private static final String DATA_FLAGS = "initiatedByUser"; private static final String DATA_NEWLY_UNLOCKED = "newlyUnlocked"; private static final String DATA_MESSAGE = "message"; private static final String DATA_GRANTED_MESSAGES = "grantedMessages"; private final ITrustManager mService; private final ArrayMap mTrustListeners; public TrustManager(IBinder b) { mService = ITrustManager.Stub.asInterface(b); mTrustListeners = new ArrayMap(); } /** * Changes the lock status for the given user. This is only applicable to Managed Profiles, * other users should be handled by Keyguard. * * @param userId The id for the user to be locked/unlocked. * @param locked The value for that user's locked state. */ @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE) public void setDeviceLockedForUser(int userId, boolean locked) { try { mService.setDeviceLockedForUser(userId, locked); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Reports that user {@param userId} has tried to unlock the device. * * @param successful if true, the unlock attempt was successful. * * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. */ @UnsupportedAppUsage public void reportUnlockAttempt(boolean successful, int userId) { try { mService.reportUnlockAttempt(successful, userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Reports that the user {@code userId} is likely interested in unlocking the device. * * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. * * @param dismissKeyguard whether the user wants to dismiss keyguard */ public void reportUserRequestedUnlock(int userId, boolean dismissKeyguard) { try { mService.reportUserRequestedUnlock(userId, dismissKeyguard); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Reports that the user {@code userId} may want to unlock the device soon. * * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. */ public void reportUserMayRequestUnlock(int userId) { try { mService.reportUserMayRequestUnlock(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Reports that user {@param userId} has entered a temporary device lockout. * * This generally occurs when the user has unsuccessfully tried to unlock the device too many * times. The user will then be unable to unlock the device until a set amount of time has * elapsed. * * @param timeout The amount of time that needs to elapse, in milliseconds, until the user may * attempt to unlock the device again. * * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. */ public void reportUnlockLockout(int timeoutMs, int userId) { try { mService.reportUnlockLockout(timeoutMs, userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Reports that the list of enabled trust agents changed for user {@param userId}. * * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. */ public void reportEnabledTrustAgentsChanged(int userId) { try { mService.reportEnabledTrustAgentsChanged(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Reports that the visibility of the keyguard has changed. * * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission. */ public void reportKeyguardShowingChanged() { try { mService.reportKeyguardShowingChanged(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns whether active unlock can be used to unlock the device for user {@code userId}. */ public boolean isActiveUnlockRunning(int userId) { try { return mService.isActiveUnlockRunning(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Registers a listener for trust events. * * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission. */ public void registerTrustListener(final TrustListener trustListener) { try { ITrustListener.Stub iTrustListener = new ITrustListener.Stub() { @Override public void onTrustChanged(boolean enabled, boolean newlyUnlocked, int userId, int flags, List trustGrantedMessages) { Message m = mHandler.obtainMessage(MSG_TRUST_CHANGED, (enabled ? 1 : 0), userId, trustListener); if (flags != 0) { m.getData().putInt(DATA_FLAGS, flags); } m.getData().putInt(DATA_NEWLY_UNLOCKED, newlyUnlocked ? 1 : 0); m.getData().putCharSequenceArrayList( DATA_GRANTED_MESSAGES, (ArrayList) trustGrantedMessages); m.sendToTarget(); } @Override public void onEnabledTrustAgentsChanged(int userId) { final Message m = mHandler.obtainMessage(MSG_ENABLED_TRUST_AGENTS_CHANGED, userId, 0, trustListener); m.sendToTarget(); } @Override public void onTrustManagedChanged(boolean managed, int userId) { mHandler.obtainMessage(MSG_TRUST_MANAGED_CHANGED, (managed ? 1 : 0), userId, trustListener).sendToTarget(); } @Override public void onTrustError(CharSequence message) { Message m = mHandler.obtainMessage(MSG_TRUST_ERROR, trustListener); m.getData().putCharSequence(DATA_MESSAGE, message); m.sendToTarget(); } @Override public void onIsActiveUnlockRunningChanged(boolean isRunning, int userId) { mHandler.obtainMessage(MSG_IS_ACTIVE_UNLOCK_RUNNING, (isRunning ? 1 : 0), userId, trustListener).sendToTarget(); } }; mService.registerTrustListener(iTrustListener); mTrustListeners.put(trustListener, iTrustListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Unregisters a listener for trust events. * * Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission. */ public void unregisterTrustListener(final TrustListener trustListener) { ITrustListener iTrustListener = mTrustListeners.remove(trustListener); if (iTrustListener != null) { try { mService.unregisterTrustListener(iTrustListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } /** * @return whether {@param userId} has enabled and configured trust agents. Ignores short-term * unavailability of trust due to {@link LockPatternUtils.StrongAuthTracker}. */ @RequiresPermission(android.Manifest.permission.TRUST_LISTENER) public boolean isTrustUsuallyManaged(int userId) { try { return mService.isTrustUsuallyManaged(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Updates the trust state for the user due to the user unlocking via a biometric sensor. * Should only be called if user authenticated via fingerprint, face, or iris and bouncer * can be skipped. * * @param userId */ @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE) public void unlockedByBiometricForUser(int userId, BiometricSourceType source) { try { mService.unlockedByBiometricForUser(userId, source); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Clears authentication by the specified biometric type for all users. */ @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE) public void clearAllBiometricRecognized(BiometricSourceType source, int unlockedUser) { try { mService.clearAllBiometricRecognized(source, unlockedUser); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } private final Handler mHandler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { switch(msg.what) { case MSG_TRUST_CHANGED: Bundle data = msg.peekData(); int flags = data != null ? data.getInt(DATA_FLAGS) : 0; boolean enabled = msg.arg1 != 0; int newlyUnlockedInt = data != null ? data.getInt(DATA_NEWLY_UNLOCKED) : 0; boolean newlyUnlocked = newlyUnlockedInt != 0; ((TrustListener) msg.obj).onTrustChanged(enabled, newlyUnlocked, msg.arg2, flags, msg.getData().getStringArrayList(DATA_GRANTED_MESSAGES)); break; case MSG_TRUST_MANAGED_CHANGED: ((TrustListener)msg.obj).onTrustManagedChanged(msg.arg1 != 0, msg.arg2); break; case MSG_TRUST_ERROR: final CharSequence message = msg.peekData().getCharSequence(DATA_MESSAGE); ((TrustListener) msg.obj).onTrustError(message); break; case MSG_ENABLED_TRUST_AGENTS_CHANGED: ((TrustListener) msg.obj).onEnabledTrustAgentsChanged(msg.arg1); break; case MSG_IS_ACTIVE_UNLOCK_RUNNING: ((TrustListener) msg.obj) .onIsActiveUnlockRunningChanged(msg.arg1 != 0, msg.arg2); break; } } }; public interface TrustListener { /** * Reports that the trust state has changed. * @param enabled If true, the system believes the environment to be trusted. * @param newlyUnlocked If true, the system believes the device is newly unlocked due * to the trust changing. * @param userId The user, for which the trust changed. * @param flags Flags specified by the trust agent when granting trust. See * {@link android.service.trust.TrustAgentService#grantTrust(CharSequence, long, int) * TrustAgentService.grantTrust(CharSequence, long, int)}. * @param trustGrantedMessages Messages to display to the user when trust has been granted * by one or more trust agents. */ void onTrustChanged(boolean enabled, boolean newlyUnlocked, int userId, int flags, List trustGrantedMessages); /** * Reports that whether trust is managed has changed * @param enabled If true, at least one trust agent is managing trust. * @param userId The user, for which the state changed. */ void onTrustManagedChanged(boolean enabled, int userId); /** * Reports that an error happened on a TrustAgentService. * @param message A message that should be displayed on the UI. */ void onTrustError(CharSequence message); /** * Reports that the enabled trust agents for the specified user has changed. */ void onEnabledTrustAgentsChanged(int userId); /** * Reports changes on if the device can be unlocked with active unlock. * @param isRunning If true, the device can be unlocked with active unlock. * @param userId The user, for which the state changed. */ void onIsActiveUnlockRunningChanged(boolean isRunning, int userId); } }