diff options
Diffstat (limited to 'core/java')
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(); +} |