summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java20
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java83
-rw-r--r--core/java/com/authentec/AuthentecHelper.java231
-rw-r--r--core/java/com/authentec/GfxEngineRelayService.java127
-rw-r--r--core/java/com/authentec/TrueSuiteMobile/RelayReceiverService.aidl7
5 files changed, 443 insertions, 25 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 570351d..802b3ef 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -190,7 +190,15 @@ public class DevicePolicyManager {
* are ordered so that higher values are more restrictive.
*/
public static final int PASSWORD_QUALITY_SOMETHING = 0x10000;
-
+
+ /**
+ * Constant for {@link #setPasswordQuality}: the user must swipe a finger
+ * to unlock the screen. Note that quality constants are
+ * ordered so that higher values are more restrictive.
+ * @hide
+ */
+ public static final int PASSWORD_QUALITY_FINGER = 0x1FFFF;
+
/**
* Constant for {@link #setPasswordQuality}: the user must have entered a
* password containing at least numeric characters. Note that quality
@@ -418,7 +426,15 @@ public class DevicePolicyManager {
* the password again until the user has entered it.
*/
public static final int RESET_PASSWORD_REQUIRE_ENTRY = 0x0001;
-
+
+ /**
+ * Flag for {@link #resetPassword}: Enable/Disable finger lock
+ */
+ /** @hide */
+ public static final int ENABLE_FINGER_LOCK = 0x1000;
+ /** @hide */
+ public static final int DISABLE_FINGER_LOCK = 0x1001;
+
/**
* Force a new device unlock password (the password needed to access the
* entire device, not for individual accounts) on the user. This takes
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 668b029..cbd1317 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -101,8 +101,9 @@ public class LockPatternUtils {
private final static String LOCKOUT_PERMANENT_KEY = "lockscreen.lockedoutpermanently";
private final static String LOCKOUT_ATTEMPT_DEADLINE = "lockscreen.lockoutattemptdeadline";
private final static String PATTERN_EVER_CHOSEN_KEY = "lockscreen.patterneverchosen";
- public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
private final static String LOCK_PASSWORD_SALT_KEY = "lockscreen.password_salt";
+ private final static String LOCK_FINGER_ENABLED = "lockscreen.lockfingerenabled";
+ public final static String PASSWORD_TYPE_KEY = "lockscreen.password_type";
private final Context mContext;
private final ContentResolver mContentResolver;
@@ -251,6 +252,14 @@ public class LockPatternUtils {
}
/**
+ * Check to see if the user has stored a finger.
+ * @return Whether a saved finger exists.
+ */
+ public boolean savedFingerExists() {
+ return true;
+ }
+
+ /**
* Return true if the user has ever chosen a pattern. This is true even if the pattern is
* currently cleared.
*
@@ -287,6 +296,11 @@ public class LockPatternUtils {
activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
}
break;
+ case DevicePolicyManager.PASSWORD_QUALITY_FINGER:
+ if (isLockFingerEnabled()) {
+ activePasswordQuality = DevicePolicyManager.PASSWORD_QUALITY_FINGER;
+ }
+ break;
}
return activePasswordQuality;
}
@@ -560,6 +574,15 @@ public class LockPatternUtils {
}
/**
+ * @return Whether the lock finger is enabled.
+ */
+ public boolean isLockFingerEnabled() {
+ return getBoolean(LOCK_FINGER_ENABLED)
+ && getLong(PASSWORD_TYPE_KEY, 0)
+ == DevicePolicyManager.PASSWORD_QUALITY_FINGER;
+ }
+
+ /**
* Set whether the lock pattern is enabled.
*/
public void setLockPatternEnabled(boolean enabled) {
@@ -567,6 +590,18 @@ public class LockPatternUtils {
}
/**
+ * Set whether the lock finger is enabled.
+ */
+ public void setLockFingerEnabled(boolean enabled) {
+ setBoolean(LOCK_FINGER_ENABLED, enabled);
+ if (enabled) {
+ setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_FINGER);
+ } else {
+ setLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+ }
+ }
+
+ /**
* @return Whether the visible pattern is enabled.
*/
public boolean isVisiblePatternEnabled() {
@@ -593,59 +628,59 @@ public class LockPatternUtils {
public void setTactileFeedbackEnabled(boolean enabled) {
setBoolean(Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, enabled);
}
-
+
public void setVisibleDotsEnabled(boolean enabled) {
- setBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, enabled);
+ setBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, enabled);
}
-
+
public boolean isVisibleDotsEnabled() {
return getBoolean(Settings.Secure.LOCK_DOTS_VISIBLE, true);
}
-
+
public void setShowErrorPath(boolean enabled) {
- setBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, enabled);
+ setBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, enabled);
}
-
+
public boolean isShowErrorPath() {
return getBoolean(Settings.Secure.LOCK_SHOW_ERROR_PATH, true);
}
-
+
public void setShowCustomMsg(boolean enabled) {
setBoolean(Settings.Secure.LOCK_SHOW_CUSTOM_MSG, enabled);
}
-
+
public boolean isShowCustomMsg() {
return getBoolean(Settings.Secure.LOCK_SHOW_CUSTOM_MSG, false);
}
-
+
public void setCustomMsg(String msg) {
setString(Settings.Secure.LOCK_CUSTOM_MSG, msg);
}
-
+
public String getCustomMsg() {
return getString(Settings.Secure.LOCK_CUSTOM_MSG);
}
-
+
public int getIncorrectDelay() {
return getInt(Settings.Secure.LOCK_INCORRECT_DELAY, 2000);
}
-
+
public void setIncorrectDelay(int delay) {
setInt(Settings.Secure.LOCK_INCORRECT_DELAY, delay);
}
-
+
public void setShowUnlockMsg(boolean enabled) {
setBoolean(Settings.Secure.SHOW_UNLOCK_TEXT, enabled);
}
-
+
public boolean isShowUnlockMsg() {
return getBoolean(Settings.Secure.SHOW_UNLOCK_TEXT, true);
}
-
+
public void setShowUnlockErrMsg(boolean enabled) {
setBoolean(Settings.Secure.SHOW_UNLOCK_ERR_TEXT, enabled);
}
-
+
public boolean isShowUnlockErrMsg() {
return getBoolean(Settings.Secure.SHOW_UNLOCK_ERR_TEXT, true);
}
@@ -852,7 +887,7 @@ public class LockPatternUtils {
return 1 ==
android.provider.Settings.Secure.getInt(mContentResolver, secureSettingKey, 0);
}
-
+
private boolean getBoolean(String systemSettingKey, boolean defaultValue) {
return 1 ==
android.provider.Settings.Secure.getInt(
@@ -872,7 +907,7 @@ public class LockPatternUtils {
private void setLong(String secureSettingKey, long value) {
android.provider.Settings.Secure.putLong(mContentResolver, secureSettingKey, value);
}
-
+
private int getInt(String systemSettingKey, int def) {
return android.provider.Settings.Secure.getInt(mContentResolver, systemSettingKey, def);
}
@@ -880,16 +915,16 @@ public class LockPatternUtils {
private void setInt(String systemSettingKey, int value) {
android.provider.Settings.Secure.putInt(mContentResolver, systemSettingKey, value);
}
-
+
private String getString(String systemSettingKey) {
String s = android.provider.Settings.Secure.getString(mContentResolver, systemSettingKey);
-
+
if (s == null)
return "";
-
+
return s;
}
-
+
private void setString(String systemSettingKey, String value) {
android.provider.Settings.Secure.putString(mContentResolver, systemSettingKey, value);
}
@@ -897,10 +932,12 @@ public class LockPatternUtils {
public boolean isSecure() {
long mode = getKeyguardStoredPasswordQuality();
final boolean isPattern = mode == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+ final boolean isFinger = mode == DevicePolicyManager.PASSWORD_QUALITY_FINGER;
final boolean isPassword = mode == DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
|| mode == DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
final boolean secure = isPattern && isLockPatternEnabled() && savedPatternExists()
+ || isFinger && isLockFingerEnabled() && savedFingerExists()
|| isPassword && savedPasswordExists();
return secure;
}
diff --git a/core/java/com/authentec/AuthentecHelper.java b/core/java/com/authentec/AuthentecHelper.java
new file mode 100644
index 0000000..7a5b17b
--- /dev/null
+++ b/core/java/com/authentec/AuthentecHelper.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2011 The CyanogenMOD 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.authentec;
+
+import dalvik.system.DexClassLoader;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+
+import android.os.SystemProperties;
+
+import java.lang.reflect.Constructor;
+
+public class AuthentecHelper
+{
+ private static DexClassLoader sAuthentecClassLoader = null;
+ private Class TSM = null;
+ private Class AuthentecMobile = null;
+ private Object am = null;
+
+ /* AM_STATUS codes */
+ public static final int eAM_STATUS_ACCESS_ERROR = 6;
+ public static final int eAM_STATUS_APPLICATION_IO_ERROR = 11;
+ public static final int eAM_STATUS_CAPTURE_FAILED = 15;
+ public static final int eAM_STATUS_CLIENT_CANCELED = 17;
+ public static final int eAM_STATUS_CLIENT_NOT_PERMITTED = 18;
+ public static final int eAM_STATUS_CREDENTIAL_LOCKED = 3;
+ public static final int eAM_STATUS_CREDENTIAL_TOO_LARGE = 5;
+ public static final int eAM_STATUS_DATABASE_FULL = 7;
+ public static final int eAM_STATUS_FINGERS_NOT_PROVISIONED = 19;
+ public static final int eAM_STATUS_FOREIGN_DATABASE = 8;
+ public static final int eAM_STATUS_GUI_IS_OFFLINE = 21;
+ public static final int eAM_STATUS_INVALID_APP_CONTEXT = 10;
+ public static final int eAM_STATUS_INVALID_PARAMETER = 4;
+ public static final int eAM_STATUS_INVALID_USER_ID = 22;
+ public static final int eAM_STATUS_LIBRARY_NOT_AVAILABLE = 14;
+ public static final int eAM_STATUS_NO_ACTIVE_USER = 20;
+ public static final int eAM_STATUS_NO_STORED_CREDENTIAL = 2;
+ public static final int eAM_STATUS_OK = 0;
+ public static final int eAM_STATUS_TIMEOUT = 12;
+ public static final int eAM_STATUS_UI_TIMEOUT = 16;
+ public static final int eAM_STATUS_UNKNOWN_COMMAND = 1;
+ public static final int eAM_STATUS_UNKNOWN_ERROR = 99;
+ public static final int eAM_STATUS_USER_CANCELED = 9;
+ public static final int eAM_STATUS_USURP_FAILURE = 13;
+
+ private AuthentecHelper(Context ctx)
+ {
+ try {
+ AuthentecMobile = sAuthentecClassLoader.loadClass("com.authentec.amjni.AuthentecMobile");
+ TSM = sAuthentecClassLoader.loadClass("com.authentec.amjni.TSM");
+ Constructor ctor = AuthentecMobile.getDeclaredConstructors()[0];
+ am = ctor.newInstance(ctx);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ return;
+ }
+ }
+
+ public int fingerprintUnlock(String sScreen, Context ctx) {
+ int iResult = 0;
+
+ try {
+ if (! (Boolean) AuthentecMobile.getMethod("AM2ClientLibraryLoaded").invoke(am)) {
+ return eAM_STATUS_LIBRARY_NOT_AVAILABLE;
+ }
+
+ if(null == ctx) {
+ return eAM_STATUS_INVALID_PARAMETER;
+ }
+
+ //int iResult = TSM.LAP(ctx).verify().viaGfxScreen(sScreen).exec();
+ Class partTypes[] = new Class[1];
+ Object argList[] = new Object[1];
+
+ partTypes[0] = Context.class;
+ argList[0] = ctx;
+ Object TSMi = TSM.getMethod("LAP", partTypes).invoke(null, argList);
+
+ TSM.getMethod("verify").invoke(TSMi);
+
+ partTypes[0] = String.class;
+ argList[0] = sScreen;
+ TSM.getMethod("viaGfxScreen", partTypes).invoke(TSMi, argList);
+
+ iResult = (Integer) TSM.getMethod("exec").invoke(TSMi);
+ TSMi = null;
+
+ try {
+ Thread.sleep(1500);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return iResult;
+ }
+
+ public int startEnrollmentWizard(Context choosefinger, String msTempPasscode)
+ {
+ int miResult = eAM_STATUS_LIBRARY_NOT_AVAILABLE;
+
+ try {
+ Class partTypes[] = new Class[1];
+ Object argList[] = new Object[1];
+
+ partTypes[0] = Context.class;
+ argList[0] = choosefinger;
+ Object TSMi = TSM.getMethod("LAP", partTypes).invoke(null, argList);
+
+ if (msTempPasscode != null) {
+ partTypes[0] = String.class;
+ argList[0] = msTempPasscode;
+ argList[0] = (String) TSM.getMethod("Hexify", partTypes).invoke(null, argList);
+
+ TSM.getMethod("usingPasscode", partTypes).invoke(TSMi, argList);
+
+ TSM.getMethod("enroll").invoke(TSMi);
+ //miResult = TSM.LAP(ChooseLockFinger.this).usingPasscode(TSM.Hexify(msTempPasscode)).enroll().exec();
+ } else {
+ partTypes[0] = String.class;
+ argList[0] = "_classicEnroll";
+ TSM.getMethod("addFunction", partTypes).invoke(TSMi, argList);
+ //miResult = TSM.LAP(ChooseLockFinger.this).addFunction("_classicEnroll").exec();
+ }
+
+ miResult = (Integer) TSM.getMethod("exec").invoke(TSMi);
+ TSMi = null;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return miResult;
+ }
+
+ public int startVerification(Context choosefinger)
+ {
+ int miResult = eAM_STATUS_LIBRARY_NOT_AVAILABLE;
+
+ try {
+ //miResult = TSM.LAP(ChooseLockFinger.this).verify().viaGfxScreen("lap-verify").exec();
+ Class partTypes[] = new Class[1];
+ Object argList[] = new Object[1];
+
+ partTypes[0] = Context.class;
+ argList[0] = choosefinger;
+ Object TSMi = TSM.getMethod("LAP", partTypes).invoke(null, argList);
+
+ TSM.getMethod("verify").invoke(TSMi);
+
+ partTypes[0] = String.class;
+ argList[0] = "lap-verify";
+ TSM.getMethod("viaGfxScreen", partTypes).invoke(TSMi, argList);
+
+ miResult = (Integer) TSM.getMethod("exec").invoke(TSMi);
+ TSMi = null;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return miResult;
+ }
+
+ public int verifyPolicy(Context ctx)
+ {
+ int iResult = eAM_STATUS_LIBRARY_NOT_AVAILABLE;
+
+ try {
+ //iResult = TSM.LAP(m_Context).waitForUI().verify().exec();
+ Class partTypes[] = new Class[1];
+ Object argList[] = new Object[1];
+
+ partTypes[0] = Context.class;
+ argList[0] = ctx;
+ Object TSMi = TSM.getMethod("LAP", partTypes).invoke(null, argList);
+
+ TSM.getMethod("waitForUI").invoke(TSMi, (Object[]) null);
+
+ TSM.getMethod("verify").invoke(TSMi, (Object[]) null);
+
+ iResult = (Integer) TSM.getMethod("exec").invoke(TSMi, (Object[]) null);
+ TSMi = null;
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return iResult;
+ }
+
+ public static AuthentecHelper getInstance(Context ctx)
+ {
+ ensureClassLoader(ctx);
+ return new AuthentecHelper(ctx);
+ }
+
+ public static void ensureClassLoader(Context ctx)
+ {
+ if (sAuthentecClassLoader != null) {
+ return;
+ }
+
+ String authentecJarLocation = SystemProperties.get("ro.authentec.fingerprint.jar","");
+ String authentecSoLocation = SystemProperties.get("ro.authentec.fingerprint.so","");
+
+ if ("".equals(authentecJarLocation) || "".equals(authentecSoLocation))
+ return;
+
+ sAuthentecClassLoader = new DexClassLoader(authentecJarLocation,
+ new ContextWrapper(ctx).getCacheDir().getAbsolutePath(),
+ authentecSoLocation,ClassLoader.getSystemClassLoader());
+ }
+}
diff --git a/core/java/com/authentec/GfxEngineRelayService.java b/core/java/com/authentec/GfxEngineRelayService.java
new file mode 100644
index 0000000..53a4d68
--- /dev/null
+++ b/core/java/com/authentec/GfxEngineRelayService.java
@@ -0,0 +1,127 @@
+package com.authentec;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.authentec.TrueSuiteMobile.RelayReceiverService;
+
+public class GfxEngineRelayService extends Service {
+
+ public interface Receiver
+ {
+ public void receiveCommand(String command, String args);
+ }
+
+ static Receiver mLocalReceiver = null;
+ public static void setLocalReceiver(Receiver localReceiver) {
+ // first send any queued commands to the activity
+ while (!mCommandBuffer.isEmpty()) {
+ Command storedCommand = mCommandBuffer.remove(0);
+ if (null == localReceiver) continue;
+
+ // send the command on to the receiver
+ localReceiver.receiveCommand(
+ storedCommand.mCommand, storedCommand.mArguments);
+
+ }
+
+ // finally record who the receiver is
+ mLocalReceiver = localReceiver;
+ }
+
+ static private ArrayList<Command> mCommandBuffer = new ArrayList<Command>();
+ static private List<String> mEventBuffer = new ArrayList<String>();
+ static private Semaphore mEventBufferSemaphore = null;
+
+ private class Command {
+ public String mCommand;
+ public String mArguments;
+ public Command(String command, String arguments) {
+ mCommand = command;
+ mArguments = arguments;
+ }
+ }
+
+ static public void queueEvent(String event) {
+ if (null == mEventBufferSemaphore) return;
+ mEventBuffer.add(event);
+ mEventBufferSemaphore.release();
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ /* when we're bound to, we want to have an empty event buffer */
+ mEventBuffer.clear();
+ mEventBufferSemaphore = new Semaphore(0);
+ return new RelayReceiverServiceImpl();
+ }
+
+ private class RelayReceiverServiceImpl extends RelayReceiverService.Stub
+ implements RelayReceiverService {
+
+ /* remote clients call sendCommand() when the GfxEngine has provided */
+ /* a new command to apply to the UI */
+ public void sendCommand(String command, String args) throws RemoteException {
+
+ /* if we've got a local receiver, pass the command to it */
+ if (null != mLocalReceiver) {
+ while (!mCommandBuffer.isEmpty()) {
+ // first pull items from the buffer. if anything is in here,
+ // it came in before the activity was ready to receive them.
+ Command storedCommand = mCommandBuffer.remove(0);
+ mLocalReceiver.receiveCommand(
+ storedCommand.mCommand, storedCommand.mArguments);
+ }
+ mLocalReceiver.receiveCommand(command, args);
+ }
+ else {
+ // append it to a buffer to be delivered later
+ mCommandBuffer.add(new Command(command, args));
+ }
+ }
+
+ /* remote clients call receiveEvent() to get the next event from the */
+ /* UI's event queue -- things like #cancel and #timeout */
+ public String receiveEvent() throws RemoteException {
+ /* block until there's something in the event queue */
+ try {
+ // mEventBufferSemaphore.acquire();
+
+ // This method runs in the service's main thread (and there's no way
+ // to move it to a child thread, since it needs to return an answer
+ // to the GfxEngine), and when the keyguard blocks here, Android has
+ // problems. So it's better to add a timeout to the block waiting.
+ if (!mEventBufferSemaphore.tryAcquire(10, TimeUnit.SECONDS)) {
+
+ // The GfxEngine is not currently expecting this exception and it will
+ // try to use the null pointer. We should probably fix this in the GfxEngine,
+ // but a short term solution is to return "" instead of null.
+ return "";
+ }
+ } catch (InterruptedException e) {
+ // return null;
+ return "";
+ }
+
+ /* remove the next event from the queue and return it */
+ if (mEventBuffer.isEmpty()) {
+ return "";
+ }
+ else{
+ return mEventBuffer.remove(0);
+ }
+ }
+
+ /* remote clients call receiveEvent() to release mEventBufferSemaphore */
+ public void quit() throws RemoteException {
+ mEventBufferSemaphore.release();
+ }
+ }
+}
diff --git a/core/java/com/authentec/TrueSuiteMobile/RelayReceiverService.aidl b/core/java/com/authentec/TrueSuiteMobile/RelayReceiverService.aidl
new file mode 100644
index 0000000..ac8c8af
--- /dev/null
+++ b/core/java/com/authentec/TrueSuiteMobile/RelayReceiverService.aidl
@@ -0,0 +1,7 @@
+package com.authentec.TrueSuiteMobile;
+interface RelayReceiverService
+{
+ void sendCommand(String command, String args);
+ String receiveEvent();
+ void quit();
+}