From 16e4a1aade2b73edfdaa42aa86a3893fd039fc62 Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Mon, 29 Sep 2014 18:16:20 -0700 Subject: [PATCH] Use default encryption password if an accessibility service is enabled. When device is encrypted the user has to authenticate in order to decrypt the data partition which is required for running accessibility services and Text-To-Speech. In order to address this issue we are falling back to use the default password if there is an enabled accessibility service and the user has secure lock. This will enable the user to authenticate when accessibility layer is completely functional. bug:17671790 Change-Id: Iafffe7bcd234008cf91ffb5011b21b803dca227a --- .../view/AccessibilityManagerInternal.java | 31 ++++++++++++++++++ .../internal/widget/LockPatternUtils.java | 24 ++++++++++++++ .../AccessibilityManagerService.java | 32 +++++++++++++++++++ .../java/com/android/server/MountService.java | 17 ++++++++-- 4 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 core/java/android/view/AccessibilityManagerInternal.java diff --git a/core/java/android/view/AccessibilityManagerInternal.java b/core/java/android/view/AccessibilityManagerInternal.java new file mode 100644 index 0000000000000..7bb2dc510222a --- /dev/null +++ b/core/java/android/view/AccessibilityManagerInternal.java @@ -0,0 +1,31 @@ +/* + * 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.view; + +/** + * Accessibility manager local system service interface. + * + * @hide Only for use within the system server. + */ +public abstract class AccessibilityManagerInternal { + + /** + * Queries if the accessibility manager service permits setting + * a non-default encryption password. + */ + public abstract boolean isNonDefaultEncryptionPasswordAllowed(); +} diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index 16fa88edddcd1..2b7af4b78e922 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -877,6 +877,30 @@ public class LockPatternUtils { } } + /** + * Gets whether the device is encrypted. + * + * @return Whether the device is encrypted. + */ + public static boolean isDeviceEncrypted() { + IMountService mountService = IMountService.Stub.asInterface( + ServiceManager.getService("mount")); + try { + return mountService.getEncryptionState() != IMountService.ENCRYPTION_STATE_NONE + && mountService.getPasswordType() != StorageManager.CRYPT_TYPE_DEFAULT; + } catch (RemoteException re) { + Log.e(TAG, "Error getting encryption state", re); + } + return true; + } + + /** + * Clears the encryption password. + */ + public void clearEncryptionPassword() { + updateEncryptionPassword(StorageManager.CRYPT_TYPE_DEFAULT, null); + } + /** * Retrieves the quality mode we're in. * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java index be3fc47ef07fd..1253bc7c74535 100644 --- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -67,6 +67,7 @@ import android.util.Pools.Pool; import android.util.Pools.SimplePool; import android.util.Slog; import android.util.SparseArray; +import android.view.AccessibilityManagerInternal; import android.view.Display; import android.view.IWindow; import android.view.InputDevice; @@ -91,6 +92,7 @@ import android.view.accessibility.IAccessibilityManagerClient; import com.android.internal.R; import com.android.internal.content.PackageMonitor; import com.android.internal.statusbar.IStatusBarService; +import com.android.internal.widget.LockPatternUtils; import com.android.server.LocalServices; import org.xmlpull.v1.XmlPullParserException; @@ -202,6 +204,8 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { private final UserManager mUserManager; + private final LockPatternUtils mLockPatternUtils; + private int mCurrentUserId = UserHandle.USER_OWNER; //TODO: Remove this hack @@ -225,9 +229,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); mSecurityPolicy = new SecurityPolicy(); mMainHandler = new MainHandler(mContext.getMainLooper()); + mLockPatternUtils = new LockPatternUtils(context); registerBroadcastReceivers(); new AccessibilityContentObserver(mMainHandler).register( context.getContentResolver()); + LocalServices.addService(AccessibilityManagerInternal.class, new LocalService()); } private UserState getUserStateLocked(int userId) { @@ -1294,6 +1300,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { updateTouchExplorationLocked(userState); updateEnhancedWebAccessibilityLocked(userState); updateDisplayColorAdjustmentSettingsLocked(userState); + updateEncryptionState(userState); scheduleUpdateInputFilter(userState); scheduleUpdateClientsIfNeededLocked(userState); } @@ -1570,6 +1577,21 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId); } + private void updateEncryptionState(UserState userState) { + if (userState.mUserId != UserHandle.USER_OWNER) { + return; + } + if (hasRunningServicesLocked(userState) && LockPatternUtils.isDeviceEncrypted()) { + // If there are running accessibility services we do not have encryption as + // the user needs the accessibility layer to be running to authenticate. + mLockPatternUtils.clearEncryptionPassword(); + } + } + + private boolean hasRunningServicesLocked(UserState userState) { + return !userState.mBoundServices.isEmpty() || !userState.mBindingServices.isEmpty(); + } + private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) { IBinder windowToken = mGlobalWindowTokens.get(windowId); if (windowToken == null) { @@ -3883,4 +3905,14 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub { } } } + + private final class LocalService extends AccessibilityManagerInternal { + @Override + public boolean isNonDefaultEncryptionPasswordAllowed() { + synchronized (mLock) { + UserState userState = getCurrentUserStateLocked(); + return !hasRunningServicesLocked(userState); + } + } + } } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 7f24d07debce7..b0535b3c2a4c2 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -63,6 +63,7 @@ import android.util.AttributeSet; import android.util.Slog; import android.util.Xml; +import android.view.AccessibilityManagerInternal; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IMediaContainerService; @@ -557,6 +558,8 @@ class MountService extends IMountService.Stub private final Handler mHandler; + private final AccessibilityManagerInternal mAccessibilityManagerInternal; + void waitForAsecScan() { waitForLatch(mAsecsScanned); } @@ -1454,6 +1457,9 @@ class MountService extends IMountService.Stub hthread.start(); mHandler = new MountServiceHandler(hthread.getLooper()); + mAccessibilityManagerInternal = LocalServices.getService( + AccessibilityManagerInternal.class); + // Watch for user changes final IntentFilter userFilter = new IntentFilter(); userFilter.addAction(Intent.ACTION_USER_ADDED); @@ -2254,8 +2260,15 @@ class MountService extends IMountService.Stub final NativeDaemonEvent event; try { + // The accessibility layer may veto having a non-default encryption + // password because if there are enabled accessibility services the + // user cannot authenticate as the latter need access to the data. + if (!TextUtils.isEmpty(password) + && !mAccessibilityManagerInternal.isNonDefaultEncryptionPasswordAllowed()) { + return getEncryptionState(); + } event = mConnector.execute("cryptfs", "changepw", CRYPTO_TYPES[type], - new SensitiveArg(toHex(password))); + new SensitiveArg(toHex(password))); return Integer.parseInt(event.getMessage()); } catch (NativeDaemonConnectorException e) { // Encryption failed @@ -2302,7 +2315,7 @@ class MountService extends IMountService.Stub * @return The type, one of the CRYPT_TYPE_XXX consts from StorageManager. */ @Override - public int getPasswordType() throws RemoteException { + public int getPasswordType() { waitForReady();