指纹加/解锁流程:
一.按power键加锁指纹监听流程分析
|----com.android.server.power.PowerManagerService.goToSleepNoUpdateLocked(PowerManagerService.java:1391)
01-02 07:16:26.436 939 1004 D PowerManagerService: |----com.android.server.power.PowerManagerService.goToSleepInternal(PowerManagerService.java:1380)
01-02 07:16:26.437 939 1004 D PowerManagerService: |----com.android.server.power.PowerManagerService.-wrap15(PowerManagerService.java)
01-02 07:16:26.437 939 1004 D PowerManagerService: |----com.android.server.power.PowerManagerService$BinderService.goToSleep(PowerManagerService.java:3644)
01-02 07:16:26.438 939 1004 D PowerManagerService: |----android.os.PowerManager.goToSleep(PowerManager.java:692)
01-02 07:16:26.438 939 1004 D PowerManagerService: |----com.android.server.policy.PhoneWindowManager.powerPress(PhoneWindowManager.java:1058)
01-02 07:16:26.439 939 1004 D PowerManagerService: |----com.android.server.policy.PhoneWindowManager.interceptPowerKeyUp(PhoneWindowManager.java:1016)
01-02 07:16:26.439 939 1004 D PowerManagerService: |----com.android.server.policy.PhoneWindowManager.interceptKeyBeforeQueueing(PhoneWindowManager.java:5264)
01-02 07:16:26.440 939 1004 D PowerManagerService: |----com.android.server.wm.InputMonitor.interceptKeyBeforeQueueing(InputMonitor.java:494)
01-02 07:16:26.440 939 1004 D PowerManagerService: |----com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:1536)
a. PhoneWindowManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\policy)
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
if (!mSystemBooted) {
// If we have not yet booted, don't let key events do anything.
return 0;
}
/// M: power-off alarm, disable power_key @{
if (KeyEvent.KEYCODE_POWER == event.getKeyCode() && mIsAlarmBoot) {
return 0;
}
/// @}
/// M: IPO migration
synchronized (mKeyDispatchLock) {
if (KEY_DISPATCH_MODE_ALL_DISABLE == mKeyDispatcMode) {
return 0;
}
}
final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
final int keyCode = event.getKeyCode();
final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
// If screen is off then we treat the case where the keyguard is open but hidden
// the same as if it were open and in front.
// This will prevent any keys other than the power button from waking the screen
// when the keyguard is hidden by another activity.
final boolean keyguardActive = (mKeyguardDelegate == null ? false :
(interactive ?
isKeyguardShowingAndNotOccluded() :
mKeyguardDelegate.isShowing()));
/// M: Remove this log.
if (false && DEBUG_INPUT) {
Log.d(TAG, "interceptKeyTq keycode=" + keyCode
+ " interactive=" + interactive + " keyguardActive=" + keyguardActive
+ " policyFlags=" + Integer.toHexString(policyFlags));
}
// Basic policy based on interactive state.
int result;
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
|| event.isWakeKey();
if (interactive || (isInjected && !isWakeKey)) {
// When the device is interactive or the key is injected pass the
// key to the application.
result = ACTION_PASS_TO_USER;
isWakeKey = false;
} else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
// If we're currently dozing with the screen on and the keyguard showing, pass the key
// to the application but preserve its wake key status to make sure we still move
// from dozing to fully interactive if we would normally go from off to fully
// interactive.
result = ACTION_PASS_TO_USER;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
result = 0;
if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
isWakeKey = false;
}
}
// If the key would be handled globally, just return the result, don't worry about special
// key processing.
if (isValidGlobalKey(keyCode)
&& mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
if (isWakeKey) {
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
}
boolean useHapticFeedback = down
/* && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0*/
&&(KeyEvent.KEYCODE_HOME == keyCode||KeyEvent.KEYCODE_MENU == keyCode || KeyEvent.KEYCODE_BACK == keyCode)
&& event.getRepeatCount() == 0;
/// M: Add log.
if (false == IS_USER_BUILD) {
Log.d(TAG, "interceptKeyTq keycode=" + keyCode
+ " interactive=" + interactive + " keyguardActive=" + keyguardActive
+ " policyFlags=" + Integer.toHexString(policyFlags)
+ " down =" + down + " canceled = " + canceled
+ " isWakeKey=" + isWakeKey
+ " mVolumeDownKeyTriggered =" + mScreenshotChordVolumeDownKeyTriggered
+ " mVolumeUpKeyTriggered =" + mScreenshotChordVolumeUpKeyTriggered
+ " result = " + result
+ " useHapticFeedback = " + useHapticFeedback
+ " isInjected = " + isInjected);
}
// Handle special keys.
switch (keyCode) {
/*[blestech] add begin */
case KeyEvent.KEYCODE_F10:
if(down) {
Log.v("btl_jni", "KEYCODE_F10");
mFingerPrintWakeLock.acquire(100);
final long now = SystemClock.uptimeMillis();
if (((now - mFingerprintDownKeyTime) >= FINGERPRINT_KEY_DEBOUNCE_DELAY_MILLIS)
|| mFingerprintDownKeyTime == 0){
Message msg = mHandler.obtainMessage(MSG_FINGERPRINT_KEY);
msg.setAsynchronous(true);
msg.sendToTarget();
mFingerprintDownKeyTime = now;
}
}
break;
/*[blestech] add end */
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
if (mUseTvRouting) {
// On TVs volume keys never go to the foreground app
result &= ~ACTION_PASS_TO_USER;
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
if (interactive && !mScreenshotChordVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordVolumeDownKeyTriggered = true;
mScreenshotChordVolumeDownKeyTime = event.getDownTime();
mScreenshotChordVolumeDownKeyConsumed = false;
cancelPendingPowerKeyAction();
interceptScreenshotChord();
}
} else {
mScreenshotChordVolumeDownKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
/// M: Key remapping
if ((false == IS_USER_BUILD)
&& SystemProperties.get("persist.sys.anr_sys_key").equals("1")) {
mHandler.postDelayed(mKeyRemappingVolumeDownLongPress_Test, 0);
}
if (down) {
if (interactive && !mScreenshotChordVolumeUpKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordVolumeUpKeyTriggered = true;
cancelPendingPowerKeyAction();
cancelPendingScreenshotChordAction();
}
} else {
mScreenshotChordVolumeUpKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
}
if (down) {
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null) {
if (telecomManager.isRinging()) {
// If an incoming call is ringing, either VOLUME key means
// "silence ringer". We handle these keys here, rather than
// in the InCallScreen, to make sure we'll respond to them
// even if the InCallScreen hasn't come to the foreground yet.
// Look for the DOWN event here, to agree with the "fallback"
// behavior in the InCallScreen.
Log.i(TAG, "interceptKeyBeforeQueueing:"
+ " VOLUME key-down while ringing: Silence ringer!");
// Silence the ringer. (It's safe to call this
// even if the ringer has already been silenced.)
telecomManager.silenceRinger();
// And *don't* pass this key thru to the current activity
// (which is probably the InCallScreen.)
result &= ~ACTION_PASS_TO_USER;
break;
}
if (telecomManager.isInCall()
&& (result & ACTION_PASS_TO_USER) == 0) {
// If we are in call but we decided not to pass the key to
// the application, just pass it to the session service.
MediaSessionLegacyHelper.getHelper(mContext)
.sendVolumeKeyEvent(event, false);
break;
}
}
if ((result & ACTION_PASS_TO_USER) == 0) {
if (mUseTvRouting) {
dispatchDirectAudioEvent(event);
} else {
// If we aren't passing to the user and no one else
// handled it send it to the session manager to
// figure out.
MediaSessionLegacyHelper.getHelper(mContext)
.sendVolumeKeyEvent(event, true);
}
break;
}
}
break;
}
case KeyEvent.KEYCODE_ENDCALL: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
TelecomManager telecomManager = getTelecommService();
boolean hungUp = false;
if (telecomManager != null) {
hungUp = telecomManager.endCall();
}
if (interactive && !hungUp) {
mEndCallKeyHandled = false;
mHandler.postDelayed(mEndCallLongPress,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
} else {
mEndCallKeyHandled = true;
}
} else {
if (!mEndCallKeyHandled) {
mHandler.removeCallbacks(mEndCallLongPress);
if (!canceled) {
if ((mEndcallBehavior
& Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
if (goHome()) {
break;
}
}
if ((mEndcallBehavior
& Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
mPowerManager.goToSleep(event.getEventTime(),
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
isWakeKey = false;
}
}
}
}
break;
}
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
case KeyEvent.KEYCODE_SLEEP: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false;
if (!mPowerManager.isInteractive()) {
useHapticFeedback = false; // suppress feedback if already non-interactive
}
if (down) {
sleepPress(event.getEventTime());
} else {
sleepRelease(event.getEventTime());
}
break;
}
case KeyEvent.KEYCODE_WAKEUP: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = true;
break;
}
case KeyEvent.KEYCODE_MEDIA_PLAY:
case KeyEvent.KEYCODE_MEDIA_PAUSE:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MUTE:
case KeyEvent.KEYCODE_MEDIA_STOP:
case KeyEvent.KEYCODE_MEDIA_NEXT:
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
case KeyEvent.KEYCODE_MEDIA_REWIND:
case KeyEvent.KEYCODE_MEDIA_RECORD:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
// If the global session is active pass all media keys to it
// instead of the active window.
result &= ~ACTION_PASS_TO_USER;
}
if ((result & ACTION_PASS_TO_USER) == 0) {
// Only do this if we would otherwise not pass it to the user. In that
// case, the PhoneWindow class will do the same thing, except it will
// only do it if the showing app doesn't process the key on its own.
// Note that we need to make a copy of the key event here because the
// original key event will be recycled when we return.
mBroadcastWakeLock.acquire();
Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
new KeyEvent(event));
msg.setAsynchronous(true);
msg.sendToTarget();
}
break;
}
case KeyEvent.KEYCODE_CALL: {
if (down) {
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null) {
if (telecomManager.isRinging()) {
Log.i(TAG, "interceptKeyBeforeQueueing:"
+ " CALL key-down while ringing: Answer the call!");
telecomManager.acceptRingingCall();
// And *don't* pass this key thru to the current activity
// (which is presumably the InCallScreen.)
result &= ~ACTION_PASS_TO_USER;
}
}
}
break;
}
case KeyEvent.KEYCODE_VOICE_ASSIST: {
// Only do this if we would otherwise not pass it to the user. In that case,
// interceptKeyBeforeDispatching would apply a similar but different policy in
// order to invoke voice assist actions. Note that we need to make a copy of the
// key event here because the original key event will be recycled when we return.
if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
mBroadcastWakeLock.acquire();
Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
keyguardActive ? 1 : 0, 0);
msg.setAsynchronous(true);
msg.sendToTarget();
}
}
}
if (useHapticFeedback) {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
}
if (isWakeKey) {
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
}
private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;
mScreenshotChordPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
cancelPendingPowerKeyAction();
if (!handled) {
// Figure out how to handle the key now that it has been released.
mPowerKeyPressCounter += 1;
final int maxCount = getMaxMultiPressPowerCount();
final long eventTime = event.getDownTime();
if (mPowerKeyPressCounter < maxCount) {
// This could be a multi-press. Wait a little bit longer to confirm.
// Continue holding the wake lock.
Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
return;
}
// No other actions. Handle it immediately.
powerPress(eventTime, interactive, mPowerKeyPressCounter);
}
// Done. Reset our state.
finishPowerKeyPress();
}
private void powerPress(long eventTime, boolean interactive, int count) {
if (mScreenOnEarly && !mScreenOnFully) {
Slog.i(TAG, "Suppressed redundant power key press while "
+ "already in the process of turning the screen on.");
return;
}
if (count == 2) {
powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
} else if (count == 3) {
powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
} else if (interactive && !mBeganFromNonInteractive) {
switch (mShortPressOnPowerBehavior) {
case SHORT_PRESS_POWER_NOTHING:
break;
case SHORT_PRESS_POWER_GO_TO_SLEEP:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
break;
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
break;
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
launchHomeFromHotKey();
break;
case SHORT_PRESS_POWER_GO_HOME:
launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
break;
}
}
}
b.PowerManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\core\java\android\os)
public void goToSleep(long time, int reason, int flags) {
try {
mService.goToSleep(time, reason, flags);
} catch (RemoteException e) {
}
}
c.PowerManagerService.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\power)
private final class BinderService extends IPowerManager.Stub {
@Override // Binder call
public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
String packageName, int uid) {
if (uid < 0) {
uid = Binder.getCallingUid();
}
acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null);
}
@Override // Binder call
public void powerHint(int hintId, int data) {
if (!mSystemReady) {
// Service not ready yet, so who the heck cares about power hints, bah.
return;
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
powerHintInternal(hintId, data);
}
@Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
if (packageName == null) {
throw new IllegalArgumentException("packageName must not be null");
}
PowerManager.validateWakeLockParameters(flags, tag);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
}
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void releaseWakeLock(IBinder lock, int flags) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
final long ident = Binder.clearCallingIdentity();
try {
releaseWakeLockInternal(lock, flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void updateWakeLockUids(IBinder lock, int[] uids) {
WorkSource ws = null;
if (uids != null) {
ws = new WorkSource();
// XXX should WorkSource have a way to set uids as an int[] instead of adding them
// one at a time?
for (int i = 0; i < uids.length; i++) {
ws.add(uids[i]);
}
}
updateWakeLockWorkSource(lock, ws, null);
}
@Override // Binder call
public void updateWakeLockWorkSource(IBinder lock, WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int callingUid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
updateWakeLockWorkSourceInternal(lock, ws, historyTag, callingUid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isWakeLockLevelSupported(int level) {
final long ident = Binder.clearCallingIdentity();
try {
return isWakeLockLevelSupportedInternal(level);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void userActivity(long eventTime, int event, int flags) {
final long now = SystemClock.uptimeMillis();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED
&& mContext.checkCallingOrSelfPermission(
android.Manifest.permission.USER_ACTIVITY)
!= PackageManager.PERMISSION_GRANTED) {
// Once upon a time applications could call userActivity().
// Now we require the DEVICE_POWER permission. Log a warning and ignore the
// request instead of throwing a SecurityException so we don't break old apps.
synchronized (mLock) {
if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
mLastWarningAboutUserActivityPermission = now;
Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
+ "caller does not have DEVICE_POWER or USER_ACTIVITY "
+ "permission. Please fix your app! "
+ " pid=" + Binder.getCallingPid()
+ " uid=" + Binder.getCallingUid());
}
}
return;
}
if (eventTime > now) {
throw new IllegalArgumentException("event time must not be in the future");
}
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
userActivityInternal(eventTime, event, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void wakeUp(long eventTime, String reason, String opPackageName) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void goToSleep(long eventTime, int reason, int flags) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
goToSleepInternal(eventTime, reason, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void nap(long eventTime) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
napInternal(eventTime, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isInteractive() {
final long ident = Binder.clearCallingIdentity();
try {
return isInteractiveInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isPowerSaveMode() {
final long ident = Binder.clearCallingIdentity();
try {
return isLowPowerModeInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean setPowerSaveMode(boolean mode) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
return setLowPowerModeInternal(mode);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isDeviceIdleMode() {
final long ident = Binder.clearCallingIdentity();
try {
return isDeviceIdleModeInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Reboots the device.
*
* @param confirm If true, shows a reboot confirmation dialog.
* @param reason The reason for the reboot, or null if none.
* @param wait If true, this call waits for the reboot to complete and does not return.
*/
@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
if (PowerManager.REBOOT_RECOVERY.equals(reason)) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
}
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(false, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Shuts down the device.
*
* @param confirm If true, shows a shutdown confirmation dialog.
* @param wait If true, this call waits for the shutdown to complete and does not return.
*/
@Override // Binder call
public void shutdown(boolean confirm, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(true, confirm, null, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Crash the runtime (causing a complete restart of the Android framework).
* Requires REBOOT permission. Mostly for testing. Should not return.
*/
@Override // Binder call
public void crash(String message) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
crashInternal(message);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Set the setting that determines whether the device stays on when plugged in.
* The argument is a bit string, with each bit specifying a power source that,
* when the device is connected to that source, causes the device to stay on.
* See {@link android.os.BatteryManager} for the list of power sources that
* can be specified. Current values include
* {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
* and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
*
* Used by "adb shell svc power stayon ..."
*
* @param val an {@code int} containing the bits that specify which power sources
* should cause the device to stay on.
*/
@Override // Binder call
public void setStayOnSetting(int val) {
int uid = Binder.getCallingUid();
// if uid is of root's, we permit this operation straight away
if (uid != Process.ROOT_UID) {
if (!Settings.checkAndNoteWriteSettingsOperation(mContext, uid,
Settings.getPackageNameForUid(mContext, uid), true)) {
return;
}
}
final long ident = Binder.clearCallingIdentity();
try {
setStayOnSettingInternal(val);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the settings application and brightness control widgets to
* temporarily override the current screen brightness setting so that the
* user can observe the effect of an intended settings change without applying
* it immediately.
*
* The override will be canceled when the setting value is next updated.
*
* @param brightness The overridden brightness.
*
* @see android.provider.Settings.System#SCREEN_BRIGHTNESS
*/
@Override // Binder call
public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the settings application and brightness control widgets to
* temporarily override the current screen auto-brightness adjustment setting so that the
* user can observe the effect of an intended settings change without applying
* it immediately.
*
* The override will be canceled when the setting value is next updated.
*
* @param adj The overridden brightness, or Float.NaN to disable the override.
*
* @see android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
*/
@Override // Binder call
public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the phone application to make the attention LED flash when ringing.
*/
@Override // Binder call
public void setAttentionLight(boolean on, int color) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setAttentionLightInternal(on, color);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void boostScreenBrightness(long eventTime) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
boostScreenBrightnessInternal(eventTime, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isScreenBrightnessBoosted() {
final long ident = Binder.clearCallingIdentity();
try {
return isScreenBrightnessBoostedInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump PowerManager from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
final long ident = Binder.clearCallingIdentity();
try {
dumpInternal(pw);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void wakeUpByReason(long eventTime, int reason) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
wakeUpByReasonInternal(eventTime, reason);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void startBacklight(int delay_msec) {
synchronized (mLock) {
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
Slog.d(TAG, "startBacklight");
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
mDisplayManagerInternal.setIPOScreenOnDelay(delay_msec);
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(),
"android.server.power:POWER",
Process.SYSTEM_UID,
mContext.getOpPackageName(),
Process.SYSTEM_UID);
updatePowerStateLocked();
} finally {
Binder.restoreCallingIdentity(ident);
}
} else {
Slog.d(TAG, "skip startBacklight because MTK_IPO_SUPPORT not enabled");
}
}
}
@Override // Binder call
public void stopBacklight() {
synchronized (mLock) {
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
Slog.d(TAG, "stopBacklight");
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
mDisplayManagerInternal.setIPOScreenOnDelay(0);
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
} finally {
Binder.restoreCallingIdentity(ident);
}
} else {
Slog.d(TAG, "skip stopBacklight because MTK_IPO_SUPPORT not enabled");
}
}
}
@Override
public void setBacklightOffForWfd(boolean enable) {
if(enable) {
Slog.d(TAG, "setBacklightOffForWfd true");
mBacklight.setBrightness(0);
} else {
if (mWfdShouldBypass != true) {
Slog.d(TAG, "setBacklightOffForWfd false");
mBacklight.setBrightness(mScreenBrightnessSetting);
} else {
Slog.d(TAG, "setBacklightOffForWfd false ignored due to screen is off by power key");
}
}
}
}
private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
synchronized (mLock) {
if (mProximityPositive && reason == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON) {
Slog.d(TAG, "Proximity positive sleep and force wakeup by power button");
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_ASLEEP;
updatePowerStateLocked();
return;
}
if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
updatePowerStateLocked();
}
}
}
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
if (DEBUG) {
StackTraceElement[] stack = new Throwable().getStackTrace();
for (StackTraceElement element : stack) {
Slog.d(TAG, " |----" + element.toString());
}
}
if (DEBUG_SPEW) {
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
+ ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
}
if (reason == PowerManager.GO_TO_SLEEP_REASON_SHUTDOWN) {
mDirty |= DIRTY_SETTINGS;
mShutdownFlag = true;
Slog.d(TAG, "mShutdownFlag = " + mShutdownFlag);
return true;
}
if (eventTime < mLastWakeTime
|| mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
try {
switch (reason) {
case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
Slog.i(TAG, "Going to sleep due to device administration policy "
+ "(uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_HDMI:
Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_PROXIMITY:
Slog.i(TAG, "Going to sleep due to proximity (uid " + uid +")...");
break;
default:
Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
break;
}
mLastSleepTime = eventTime;
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
// Report the number of wake locks that will be cleared by going to sleep.
int numWakeLocksCleared = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
numWakeLocksCleared += 1;
break;
}
}
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
// Wakelock debug
dumpWakeLockLocked();
// Skip dozing if requested.
if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
reallyGoToSleepNoUpdateLocked(eventTime, uid);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
private void setWakefulnessLocked(int wakefulness, int reason) {
if (mWakefulness != wakefulness) {
mWakefulness = wakefulness;
mWakefulnessChanging = true;
mDirty |= DIRTY_WAKEFULNESS;
mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
}
}
d. Notifier.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\power)
public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
if (DEBUG) {
Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
+ ", reason=" + reason + ", interactive=" + interactive);
}
// Tell the activity manager about changes in wakefulness, not just interactivity.
// It needs more granularity than other components.
mHandler.post(new Runnable() {
@Override
public void run() {
mActivityManagerInternal.onWakefulnessChanged(wakefulness);
}
});
// Handle any early interactive state changes.
// Finish pending incomplete ones from a previous cycle.
if (mInteractive != interactive) {
// Finish up late behaviors if needed.
if (mInteractiveChanging) {
handleLateInteractiveChange();
}
// Start input as soon as we start waking up or going to sleep.
mInputManagerInternal.setInteractive(interactive);
mInputMethodManagerInternal.setInteractive(interactive);
// Notify battery stats.
try {
mBatteryStats.noteInteractive(interactive);
} catch (RemoteException ex) { }
// Handle early behaviors.
mInteractive = interactive;
mInteractiveChangeReason = reason;
mInteractiveChanging = true;
handleEarlyInteractiveChange();
}
}
private void handleEarlyInteractiveChange() {
synchronized (mLock) {
if (mInteractive) {
// Waking up...
mHandler.post(new Runnable() {
@Override
public void run() {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
if (DEBUG) {
Slog.d(TAG, "handleEarlyInteractiveChange: mPolicy.startedWakingUp");
}
mPolicy.startedWakingUp();
}
});
// Send interactive broadcast.
mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
mPendingWakeUpBroadcast = true;
updatePendingBroadcastLocked();
} else {
// Going to sleep...
// Tell the policy that we started going to sleep.
final int why = translateOffReason(mInteractiveChangeReason);
mHandler.post(new Runnable() {
@Override
public void run() {
mPolicy.startedGoingToSleep(why);
}
});
}
}
}
e. PhoneWindowManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\policy)
// Called on the PowerManager's Notifier thread.
@Override
public void startedGoingToSleep(int why) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedGoingToSleep(why);
}
}
f. KeyguardServiceDelegate.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\policy\keyguard)
public void onStartedGoingToSleep(int why) {
if (mKeyguardService != null) {
Log.v(TAG, "onStartedGoingToSleep(),why:"+why);
mKeyguardService.onStartedGoingToSleep(why);
}
mKeyguardState.offReason = why;
}
g. KeyguardServiceWrapper.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\policy\keyguard)
@Override
public void onStartedGoingToSleep(int reason) {
try {
Slog.v(TAG , "reason :");
mService.onStartedGoingToSleep(reason);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
h. KeyguardService.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\systemui\src\com\android\systemui\keyguard)
public void onStartedGoingToSleep(int reason) {
checkPermission();
Log.w(TAG, "shizsun Binder interface onStartedGoingToSleep'");
mKeyguardViewMediator.onStartedGoingToSleep(reason);
}
i.KeyguardViewMediator.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\systemui\src\com\android\systemui\keyguard)
public void onStartedGoingToSleep(int why) {
if (DEBUG) Log.d(TAG, "onStartedGoingToSleep(" + why + ")");
synchronized (this) {
mDeviceInteractive = false;
mGoingToSleep = true;
// Lock immediately based on setting if secure (user has a pin/pattern/password).
// This also "locks" the device when not secure to provide easy access to the
// camera while preventing unwanted input.
int currentUser = KeyguardUpdateMonitor.getCurrentUser();
final boolean lockImmediately =
mLockPatternUtils.getPowerButtonInstantlyLocks(currentUser)
|| !mLockPatternUtils.isSecure(currentUser);
long timeout = getLockTimeout();
/// M: Add for supporting lock immediately when screen timeout. @{
final boolean lockWhenTimeout =
KeyguardPluginFactory.getKeyguardUtilExt(mContext)
.lockImmediatelyWhenScreenTimeout();
/// @}
if (DBG_WAKE) {
Log.d(TAG, "onStartedGoingToSleep(" + why +
") ---ScreenOff mScreenOn = false; After--boolean lockImmediately=" +
lockImmediately +
", mExitSecureCallback=" + mExitSecureCallback +
", mShowing=" + mShowing +
", mIsIPOShutDown = " + mIsIPOShutDown);
}
if (mExitSecureCallback != null) {
if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
try {
mExitSecureCallback.onKeyguardExitResult(false);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
}
mExitSecureCallback = null;
if (!mExternallyEnabled) {
hideLocked();
}
} else if (mShowing) {
mPendingReset = true;
} else if ((why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT && timeout > 0
&& !lockWhenTimeout)
|| (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)
&& !mIsIPOShutDown) {
doKeyguardLaterLocked(timeout);
} else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
// Do not enable the keyguard if the prox sensor forced the screen off.
Log.d(TAG, "Screen off because PROX_SENSOR, do not draw lock view.") ;
} else if (!mLockPatternUtils.isLockScreenDisabled(currentUser)) {
mPendingLock = true;
}
if (mPendingLock) {
playSounds(true);
}
}
KeyguardUpdateMonitor.getInstance(mContext).dispatchStartedGoingToSleep(why);
//notifyStartedGoingToSleep();
}
j.KeyguardUpdateMonitor.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\keyguard\src\com\android\keyguard)
protected void handleStartedGoingToSleep(int arg1) {
clearFingerprintRecognized();
final int count = mCallbacks.size();
for (int i = 0; i < count; i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onStartedGoingToSleep(arg1);
}
}
mGoingToSleep = true;
mFingerprintAlreadyAuthenticated = false;
updateFingerprintListeningState();
}
private void updateFingerprintListeningState() {
boolean shouldListenForFingerprint = shouldListenForFingerprint();
if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {
stopListeningForFingerprint();
} else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING
&& shouldListenForFingerprint) {
startListeningForFingerprint();
}
}
private void startListeningForFingerprint() {
if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {
setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);
return;
}
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = ActivityManager.getCurrentUser();
if (isUnlockWithFingerprintPossible(userId)) {
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
}
mFingerprintCancelSignal = new CancellationSignal();
mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
}
}
k.FingerprintManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\core\java\android\hardware\fingerprint)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
if (cancel != null) {
if (cancel.isCanceled()) {
Log.w(TAG, "authentication already canceled");
return;
} else {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
}
}
Log.w(TAG, "shizsun:authentication manager it");
if (mService != null) try {
useHandler(handler);
mAuthenticationCallback = callback;
mCryptoObject = crypto;
long sessionId = crypto != null ? crypto.getOpId() : 0;
mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
mContext.getOpPackageName());
} catch (RemoteException e) {
Log.w(TAG, "Remote exception while authenticating: ", e);
if (callback != null) {
// Though this may not be a hardware issue, it will cause apps to give up or try
// again later.
callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
}
}
}
l. FingerprintService.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\fingerprint)
public void authenticate(final IBinder token, final long opId, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags,
final String opPackageName) {
if (!canUseFingerprint(opPackageName, true /* foregroundOnly */)) {
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
return;
}
// Group ID is arbitrarily set to parent profile user ID. It just represents
// the default fingerprints for the user.
final int effectiveGroupId = getEffectiveUserId(groupId);
Slog.w(TAG, "shizsun:authenticate(): reject " + opPackageName+"effectiveGroupId="+effectiveGroupId);
final boolean restricted = isRestricted();
mHandler.post(new Runnable() {
@Override
public void run() {
MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
startAuthentication(token, opId, effectiveGroupId, receiver, flags, restricted,
opPackageName);
}
});
}
void startAuthentication(IBinder token, long opId, int groupId,
IFingerprintServiceReceiver receiver, int flags, boolean restricted,
String opPackageName) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startAuthentication: no fingeprintd!");
return;
}
stopPendingOperations(true);
mAuthClient = new ClientMonitor(token, receiver, groupId, restricted, opPackageName);
if (inLockoutMode()) {
Slog.v(TAG, "In lockout mode; disallowing authentication");
if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
Slog.w(TAG, "Cannot send timeout message to client");
}
mAuthClient = null;
return;
}
Slog.w(TAG, "shizsun:startAuthentication: go start!");
try {
final int result = daemon.authenticate(opId, groupId);
if (result != 0) {
Slog.w(TAG, "startAuthentication failed, result=" + result);
handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
}
} catch (RemoteException e) {
Slog.e(TAG, "startAuthentication failed", e);
}
}
m. FingerprintDaemonProxy.cpp (z:\home\shizsun\work\k506\k506\system\core\fingerprintd)
int32_t FingerprintDaemonProxy::authenticate(uint64_t sessionId, uint32_t groupId) {
ALOG(LOG_VERBOSE, LOG_TAG, "authenticate(sid=%" PRId64 ", gid=%d)\n", sessionId, groupId);
return mDevice->authenticate(mDevice, sessionId, groupId);
}
n. Fingerprint.c (z:\home\shizsun\work\k506\k506\hardware\libhardware\modules\fingerprint)
static int fingerprint_authenticate(struct fingerprint_device __unused *dev,
uint64_t __unused operation_id, __unused uint32_t gid)
{
if (Fp_Authenticate(dev,operation_id, gid) < 0) return -1;
return 0;
}
二.指纹解锁流程分析
a. fingerprint.c
memset(&msg, 0, sizeof(fingerprint_msg_t));
msg.type = FINGERPRINT_AUTHENTICATED;
msg.data.authenticated.finger.gid = gFingerprintVar.gid ;
msg.data.authenticated.finger.fid = fingerID;
msg.data.authenticated.hat.user_id = gFingerprintVar.gid;
msg.data.authenticated.hat.authenticator_id = gFingerprintVar.token;
uint32_t tmp = (uint32_t)HW_AUTH_FINGERPRINT;
msg.data.authenticated.hat.authenticator_type = my_hton(tmp);
msg.data.authenticated.hat.challenge = gFingerprintParam.operation_id;
msg.data.authenticated.hat.timestamp = my_htonl(btl_api_createToken());
dev->notify(&msg);
b.FingerprintDaemonProxy.cpp (z:\home\shizsun\work\k506\k506\system\core\fingerprintd)
void FingerprintDaemonProxy::hal_notify_callback(const fingerprint_msg_t *msg) {
FingerprintDaemonProxy* instance = FingerprintDaemonProxy::getInstance();
const sp<IFingerprintDaemonCallback> callback = instance->mCallback;
if (callback == NULL) {
ALOGE("Invalid callback object");
return;
}
const int64_t device = (int64_t) instance->mDevice;
switch (msg->type) {
case FINGERPRINT_ERROR:
ALOGD("onError(%d)", msg->data.error);
callback->onError(device, msg->data.error);
break;
case FINGERPRINT_ACQUIRED:
ALOGD("onAcquired(%d)", msg->data.acquired.acquired_info);
callback->onAcquired(device, msg->data.acquired.acquired_info);
break;
case FINGERPRINT_AUTHENTICATED:
ALOGD("onAuthenticated(fid=%d, gid=%d)",
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid);
if (msg->data.authenticated.finger.fid != 0) {
const uint8_t* hat = reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
instance->notifyKeystore(hat, sizeof(msg->data.authenticated.hat));
}
callback->onAuthenticated(device,
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid);
break;
case FINGERPRINT_TEMPLATE_ENROLLING:
ALOGD("onEnrollResult(fid=%d, gid=%d, rem=%d)",
msg->data.enroll.finger.fid,
msg->data.enroll.finger.gid,
msg->data.enroll.samples_remaining);
callback->onEnrollResult(device,
msg->data.enroll.finger.fid,
msg->data.enroll.finger.gid,
msg->data.enroll.samples_remaining);
break;
case FINGERPRINT_TEMPLATE_REMOVED:
ALOGD("onRemove(fid=%d, gid=%d)",
msg->data.removed.finger.fid,
msg->data.removed.finger.gid);
callback->onRemoved(device,
msg->data.removed.finger.fid,
msg->data.removed.finger.gid);
break;
default:
ALOGE("invalid msg type: %d", msg->type);
return;
}
}
c.FingerprintService.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\fingerprint)
private IFingerprintDaemonCallback mDaemonCallback = new IFingerprintDaemonCallback.Stub() {
@Override
public void onEnrollResult(final long deviceId, final int fingerId, final int groupId,
final int remaining) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleEnrollResult(deviceId, fingerId, groupId, remaining);
}
});
}
@Override
public void onAcquired(final long deviceId, final int acquiredInfo) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleAcquired(deviceId, acquiredInfo);
}
});
}
@Override
public void onAuthenticated(final long deviceId, final int fingerId, final int groupId) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleAuthenticated(deviceId, fingerId, groupId);
}
});
}
@Override
public void onError(final long deviceId, final int error) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleError(deviceId, error);
}
});
}
@Override
public void onRemoved(final long deviceId, final int fingerId, final int groupId) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleRemoved(deviceId, fingerId, groupId);
}
});
}
@Override
public void onEnumerate(final long deviceId, final int[] fingerIds, final int[] groupIds) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleEnumerate(deviceId, fingerIds, groupIds);
}
});
}
}
protected void handleAuthenticated(long deviceId, int fingerId, int groupId) {
if (mAuthClient != null) {
final IBinder token = mAuthClient.token;
if (mAuthClient.sendAuthenticated(fingerId, groupId)) {
stopAuthentication(token, false);
removeClient(mAuthClient);
}
}
}
private boolean sendAuthenticated(int fpId, int groupId) {
boolean result = false;
boolean authenticated = fpId != 0;
if (receiver != null) {
try {
MetricsLogger.action(mContext, MetricsLogger.ACTION_FINGERPRINT_AUTH,
authenticated);
if (!authenticated) {
receiver.onAuthenticationFailed(mHalDeviceId);
} else {
if (DEBUG) {
Slog.v(TAG, "onAuthenticated(owner=" + mAuthClient.owner
+ ", id=" + fpId + ", gp=" + groupId + ")");
}
Fingerprint fp = !restricted ?
new Fingerprint("" /* TODO */, groupId, fpId, mHalDeviceId) : null;
receiver.onAuthenticationSucceeded(mHalDeviceId, fp);
}
} catch (RemoteException e) {
Slog.w(TAG, "Failed to notify Authenticated:", e);
result = true; // client failed
}
} else {
result = true; // client not listening
}
if (fpId == 0) {
if (receiver != null) {
FingerprintUtils.vibrateFingerprintError(getContext());
}
result |= handleFailedAttempt(this);
} else {
if (receiver != null) {
FingerprintUtils.vibrateFingerprintSuccess(getContext());
}
result |= true; // we have a valid fingerprint
resetFailedAttempts();
}
return result;
}
d. FingerprintManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\core\java\android\hardware\fingerprint)
private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
@Override // binder call
public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
}
@Override // binder call
public void onAcquired(long deviceId, int acquireInfo) {
mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
}
@Override // binder call
public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
}
@Override // binder call
public void onAuthenticationFailed(long deviceId) {
mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
}
@Override // binder call
public void onError(long deviceId, int error) {
mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
}
@Override // binder call
public void onRemoved(long deviceId, int fingerId, int groupId) {
mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
}
}
private void sendAuthenticatedSucceeded(Fingerprint fp) {
if (mAuthenticationCallback != null) {
final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
mAuthenticationCallback.onAuthenticationSucceeded(result);
}
}
e. KeyguardUpdateMonitor.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\keyguard\src\com\android\keyguard)
private FingerprintManager.AuthenticationCallback mAuthenticationCallback
= new AuthenticationCallback() {
@Override
public void onAuthenticationFailed() {
handleFingerprintAuthFailed();
};
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
handleFingerprintAuthenticated();
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
handleFingerprintHelp(helpMsgId, helpString.toString());
}
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
handleFingerprintError(errMsgId, errString.toString());
}
@Override
public void onAuthenticationAcquired(int acquireInfo) {
handleFingerprintAcquired(acquireInfo);
}
}
private void handleFingerprintAuthenticated() {
try {
final int userId;
try {
userId = ActivityManagerNative.getDefault().getCurrentUser().id;
} catch (RemoteException e) {
Log.e(TAG, "Failed to get current user id: ", e);
return;
}
if (isFingerprintDisabled(userId)) {
Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
return;
}
onFingerprintAuthenticated(userId);
} finally {
setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
}
}
private void onFingerprintAuthenticated(int userId) {
mUserFingerprintAuthenticated.put(userId, true);
// If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a
// wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is
// fully gone.
mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onFingerprintAuthenticated(userId);
}
}
}
f. FingerprintUnlockController.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\systemui\src\com\android\systemui\statusbar\phone)
@Override
public void onFingerprintAuthenticated(int userId) {
if (mUpdateMonitor.isGoingToSleep()) {
mPendingAuthenticatedUserId = userId;
return;
}
boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
mMode = calculateMode();
if (!wasDeviceInteractive) {
if (DEBUG_FP_WAKELOCK) {
Log.i(TAG, "fp wakelock: Authenticated, waking up...");
}
mPowerManager.wakeUp(SystemClock.uptimeMillis());
}
releaseFingerprintWakeLock();
switch (mMode) {
case MODE_DISMISS_BOUNCER:
mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
false /* strongAuth */);
break;
case MODE_UNLOCK:
case MODE_SHOW_BOUNCER:
if (!wasDeviceInteractive) {
mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
}
mStatusBarKeyguardViewManager.animateCollapsePanels(
FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
break;
case MODE_WAKE_AND_UNLOCK_PULSING:
mPhoneStatusBar.updateMediaMetaData(false /* metaDataChanged */);
// Fall through.
case MODE_WAKE_AND_UNLOCK:
mStatusBarWindowManager.setStatusBarFocusable(false);
mDozeScrimController.abortPulsing();
mKeyguardViewMediator.onWakeAndUnlocking();
mScrimController.setWakeAndUnlocking();
if (mPhoneStatusBar.getNavigationBarView() != null) {
mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
}
break;
case MODE_ONLY_WAKE:
case MODE_NONE:
break;
}
if (mMode != MODE_WAKE_AND_UNLOCK_PULSING) {
mStatusBarWindowManager.setForceDozeBrightness(false);
}
mPhoneStatusBar.notifyFpAuthModeChanged();
}
g. KeyguardViewMediator.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\systemui\src\com\android\systemui\keyguard)
public void onWakeAndUnlocking() {
mWakeAndUnlocking = true;
keyguardDone(true /* authenticated */);
}
public void keyguardDone(boolean authenticated) {
if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated +")");
EventLog.writeEvent(70000, 2);
Message msg = mHandler.obtainMessage(KEYGUARD_DONE, authenticated ? 1 : 0);
mHandler.sendMessage(msg);
}
private void handleKeyguardDone(boolean authenticated) {
Log.d(TAG, "handleKeyguardDone, authenticated=" + authenticated);
synchronized (this) {
resetKeyguardDonePendingLocked();
}
///M: [ALPS01567248] Timing issue.
/// Voice Unlock View dismiss -> AntiTheft View shows
/// -> previous Voice Unlock dismiss flow calls handleKeyguardDone
/// -> remove AntiTheft View
/// So we avoid handleKeyguardDone if AntiTheft is the current view,
/// and not yet unlock correctly.
if (AntiTheftManager.isAntiTheftLocked()) {
Log.d(TAG, "handleKeyguardDone() - Skip keyguard done! antitheft = " +
AntiTheftManager.isAntiTheftLocked() +
" or sim = " + mUpdateMonitor.isSimPinSecure());
return ;
}
Log.d(TAG, "set mKeyguardDoneOnGoing = true") ;
mKeyguardDoneOnGoing = true ;
if (authenticated) {
mUpdateMonitor.clearFailedUnlockAttempts();
}
mUpdateMonitor.clearFingerprintRecognized();
if (mGoingToSleep) {
Log.i(TAG, "Device is going to sleep, aborting keyguardDone");
return;
}
if (mExitSecureCallback != null) {
try {
mExitSecureCallback.onKeyguardExitResult(authenticated);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(" + authenticated + ")", e);
}
mExitSecureCallback = null;
if (authenticated) {
// after succesfully exiting securely, no need to reshow
// the keyguard when they've released the lock
mExternallyEnabled = true;
mNeedToReshowWhenReenabled = false;
updateInputRestricted();
}
}
///M: [ALPS00827994] always to play sound for user to unlock keyguard
mSuppressNextLockSound = false;
handleHide();
}
一.按power键加锁指纹监听流程分析
|----com.android.server.power.PowerManagerService.goToSleepNoUpdateLocked(PowerManagerService.java:1391)
01-02 07:16:26.436 939 1004 D PowerManagerService: |----com.android.server.power.PowerManagerService.goToSleepInternal(PowerManagerService.java:1380)
01-02 07:16:26.437 939 1004 D PowerManagerService: |----com.android.server.power.PowerManagerService.-wrap15(PowerManagerService.java)
01-02 07:16:26.437 939 1004 D PowerManagerService: |----com.android.server.power.PowerManagerService$BinderService.goToSleep(PowerManagerService.java:3644)
01-02 07:16:26.438 939 1004 D PowerManagerService: |----android.os.PowerManager.goToSleep(PowerManager.java:692)
01-02 07:16:26.438 939 1004 D PowerManagerService: |----com.android.server.policy.PhoneWindowManager.powerPress(PhoneWindowManager.java:1058)
01-02 07:16:26.439 939 1004 D PowerManagerService: |----com.android.server.policy.PhoneWindowManager.interceptPowerKeyUp(PhoneWindowManager.java:1016)
01-02 07:16:26.439 939 1004 D PowerManagerService: |----com.android.server.policy.PhoneWindowManager.interceptKeyBeforeQueueing(PhoneWindowManager.java:5264)
01-02 07:16:26.440 939 1004 D PowerManagerService: |----com.android.server.wm.InputMonitor.interceptKeyBeforeQueueing(InputMonitor.java:494)
01-02 07:16:26.440 939 1004 D PowerManagerService: |----com.android.server.input.InputManagerService.interceptKeyBeforeQueueing(InputManagerService.java:1536)
a. PhoneWindowManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\policy)
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
if (!mSystemBooted) {
// If we have not yet booted, don't let key events do anything.
return 0;
}
/// M: power-off alarm, disable power_key @{
if (KeyEvent.KEYCODE_POWER == event.getKeyCode() && mIsAlarmBoot) {
return 0;
}
/// @}
/// M: IPO migration
synchronized (mKeyDispatchLock) {
if (KEY_DISPATCH_MODE_ALL_DISABLE == mKeyDispatcMode) {
return 0;
}
}
final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
final int keyCode = event.getKeyCode();
final boolean isInjected = (policyFlags & WindowManagerPolicy.FLAG_INJECTED) != 0;
// If screen is off then we treat the case where the keyguard is open but hidden
// the same as if it were open and in front.
// This will prevent any keys other than the power button from waking the screen
// when the keyguard is hidden by another activity.
final boolean keyguardActive = (mKeyguardDelegate == null ? false :
(interactive ?
isKeyguardShowingAndNotOccluded() :
mKeyguardDelegate.isShowing()));
/// M: Remove this log.
if (false && DEBUG_INPUT) {
Log.d(TAG, "interceptKeyTq keycode=" + keyCode
+ " interactive=" + interactive + " keyguardActive=" + keyguardActive
+ " policyFlags=" + Integer.toHexString(policyFlags));
}
// Basic policy based on interactive state.
int result;
boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
|| event.isWakeKey();
if (interactive || (isInjected && !isWakeKey)) {
// When the device is interactive or the key is injected pass the
// key to the application.
result = ACTION_PASS_TO_USER;
isWakeKey = false;
} else if (!interactive && shouldDispatchInputWhenNonInteractive()) {
// If we're currently dozing with the screen on and the keyguard showing, pass the key
// to the application but preserve its wake key status to make sure we still move
// from dozing to fully interactive if we would normally go from off to fully
// interactive.
result = ACTION_PASS_TO_USER;
} else {
// When the screen is off and the key is not injected, determine whether
// to wake the device but don't pass the key to the application.
result = 0;
if (isWakeKey && (!down || !isWakeKeyWhenScreenOff(keyCode))) {
isWakeKey = false;
}
}
// If the key would be handled globally, just return the result, don't worry about special
// key processing.
if (isValidGlobalKey(keyCode)
&& mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
if (isWakeKey) {
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
}
boolean useHapticFeedback = down
/* && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0*/
&&(KeyEvent.KEYCODE_HOME == keyCode||KeyEvent.KEYCODE_MENU == keyCode || KeyEvent.KEYCODE_BACK == keyCode)
&& event.getRepeatCount() == 0;
/// M: Add log.
if (false == IS_USER_BUILD) {
Log.d(TAG, "interceptKeyTq keycode=" + keyCode
+ " interactive=" + interactive + " keyguardActive=" + keyguardActive
+ " policyFlags=" + Integer.toHexString(policyFlags)
+ " down =" + down + " canceled = " + canceled
+ " isWakeKey=" + isWakeKey
+ " mVolumeDownKeyTriggered =" + mScreenshotChordVolumeDownKeyTriggered
+ " mVolumeUpKeyTriggered =" + mScreenshotChordVolumeUpKeyTriggered
+ " result = " + result
+ " useHapticFeedback = " + useHapticFeedback
+ " isInjected = " + isInjected);
}
// Handle special keys.
switch (keyCode) {
/*[blestech] add begin */
case KeyEvent.KEYCODE_F10:
if(down) {
Log.v("btl_jni", "KEYCODE_F10");
mFingerPrintWakeLock.acquire(100);
final long now = SystemClock.uptimeMillis();
if (((now - mFingerprintDownKeyTime) >= FINGERPRINT_KEY_DEBOUNCE_DELAY_MILLIS)
|| mFingerprintDownKeyTime == 0){
Message msg = mHandler.obtainMessage(MSG_FINGERPRINT_KEY);
msg.setAsynchronous(true);
msg.sendToTarget();
mFingerprintDownKeyTime = now;
}
}
break;
/*[blestech] add end */
case KeyEvent.KEYCODE_VOLUME_DOWN:
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_MUTE: {
if (mUseTvRouting) {
// On TVs volume keys never go to the foreground app
result &= ~ACTION_PASS_TO_USER;
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
if (interactive && !mScreenshotChordVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordVolumeDownKeyTriggered = true;
mScreenshotChordVolumeDownKeyTime = event.getDownTime();
mScreenshotChordVolumeDownKeyConsumed = false;
cancelPendingPowerKeyAction();
interceptScreenshotChord();
}
} else {
mScreenshotChordVolumeDownKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
/// M: Key remapping
if ((false == IS_USER_BUILD)
&& SystemProperties.get("persist.sys.anr_sys_key").equals("1")) {
mHandler.postDelayed(mKeyRemappingVolumeDownLongPress_Test, 0);
}
if (down) {
if (interactive && !mScreenshotChordVolumeUpKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
mScreenshotChordVolumeUpKeyTriggered = true;
cancelPendingPowerKeyAction();
cancelPendingScreenshotChordAction();
}
} else {
mScreenshotChordVolumeUpKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
}
if (down) {
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null) {
if (telecomManager.isRinging()) {
// If an incoming call is ringing, either VOLUME key means
// "silence ringer". We handle these keys here, rather than
// in the InCallScreen, to make sure we'll respond to them
// even if the InCallScreen hasn't come to the foreground yet.
// Look for the DOWN event here, to agree with the "fallback"
// behavior in the InCallScreen.
Log.i(TAG, "interceptKeyBeforeQueueing:"
+ " VOLUME key-down while ringing: Silence ringer!");
// Silence the ringer. (It's safe to call this
// even if the ringer has already been silenced.)
telecomManager.silenceRinger();
// And *don't* pass this key thru to the current activity
// (which is probably the InCallScreen.)
result &= ~ACTION_PASS_TO_USER;
break;
}
if (telecomManager.isInCall()
&& (result & ACTION_PASS_TO_USER) == 0) {
// If we are in call but we decided not to pass the key to
// the application, just pass it to the session service.
MediaSessionLegacyHelper.getHelper(mContext)
.sendVolumeKeyEvent(event, false);
break;
}
}
if ((result & ACTION_PASS_TO_USER) == 0) {
if (mUseTvRouting) {
dispatchDirectAudioEvent(event);
} else {
// If we aren't passing to the user and no one else
// handled it send it to the session manager to
// figure out.
MediaSessionLegacyHelper.getHelper(mContext)
.sendVolumeKeyEvent(event, true);
}
break;
}
}
break;
}
case KeyEvent.KEYCODE_ENDCALL: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
TelecomManager telecomManager = getTelecommService();
boolean hungUp = false;
if (telecomManager != null) {
hungUp = telecomManager.endCall();
}
if (interactive && !hungUp) {
mEndCallKeyHandled = false;
mHandler.postDelayed(mEndCallLongPress,
ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
} else {
mEndCallKeyHandled = true;
}
} else {
if (!mEndCallKeyHandled) {
mHandler.removeCallbacks(mEndCallLongPress);
if (!canceled) {
if ((mEndcallBehavior
& Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
if (goHome()) {
break;
}
}
if ((mEndcallBehavior
& Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
mPowerManager.goToSleep(event.getEventTime(),
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
isWakeKey = false;
}
}
}
}
break;
}
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false; // wake-up will be handled separately
if (down) {
interceptPowerKeyDown(event, interactive);
} else {
interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
case KeyEvent.KEYCODE_SLEEP: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = false;
if (!mPowerManager.isInteractive()) {
useHapticFeedback = false; // suppress feedback if already non-interactive
}
if (down) {
sleepPress(event.getEventTime());
} else {
sleepRelease(event.getEventTime());
}
break;
}
case KeyEvent.KEYCODE_WAKEUP: {
result &= ~ACTION_PASS_TO_USER;
isWakeKey = true;
break;
}
case KeyEvent.KEYCODE_MEDIA_PLAY:
case KeyEvent.KEYCODE_MEDIA_PAUSE:
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
case KeyEvent.KEYCODE_HEADSETHOOK:
case KeyEvent.KEYCODE_MUTE:
case KeyEvent.KEYCODE_MEDIA_STOP:
case KeyEvent.KEYCODE_MEDIA_NEXT:
case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
case KeyEvent.KEYCODE_MEDIA_REWIND:
case KeyEvent.KEYCODE_MEDIA_RECORD:
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK: {
if (MediaSessionLegacyHelper.getHelper(mContext).isGlobalPriorityActive()) {
// If the global session is active pass all media keys to it
// instead of the active window.
result &= ~ACTION_PASS_TO_USER;
}
if ((result & ACTION_PASS_TO_USER) == 0) {
// Only do this if we would otherwise not pass it to the user. In that
// case, the PhoneWindow class will do the same thing, except it will
// only do it if the showing app doesn't process the key on its own.
// Note that we need to make a copy of the key event here because the
// original key event will be recycled when we return.
mBroadcastWakeLock.acquire();
Message msg = mHandler.obtainMessage(MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK,
new KeyEvent(event));
msg.setAsynchronous(true);
msg.sendToTarget();
}
break;
}
case KeyEvent.KEYCODE_CALL: {
if (down) {
TelecomManager telecomManager = getTelecommService();
if (telecomManager != null) {
if (telecomManager.isRinging()) {
Log.i(TAG, "interceptKeyBeforeQueueing:"
+ " CALL key-down while ringing: Answer the call!");
telecomManager.acceptRingingCall();
// And *don't* pass this key thru to the current activity
// (which is presumably the InCallScreen.)
result &= ~ACTION_PASS_TO_USER;
}
}
}
break;
}
case KeyEvent.KEYCODE_VOICE_ASSIST: {
// Only do this if we would otherwise not pass it to the user. In that case,
// interceptKeyBeforeDispatching would apply a similar but different policy in
// order to invoke voice assist actions. Note that we need to make a copy of the
// key event here because the original key event will be recycled when we return.
if ((result & ACTION_PASS_TO_USER) == 0 && !down) {
mBroadcastWakeLock.acquire();
Message msg = mHandler.obtainMessage(MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK,
keyguardActive ? 1 : 0, 0);
msg.setAsynchronous(true);
msg.sendToTarget();
}
}
}
if (useHapticFeedback) {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
}
if (isWakeKey) {
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
}
return result;
}
private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
final boolean handled = canceled || mPowerKeyHandled;
mScreenshotChordPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
cancelPendingPowerKeyAction();
if (!handled) {
// Figure out how to handle the key now that it has been released.
mPowerKeyPressCounter += 1;
final int maxCount = getMaxMultiPressPowerCount();
final long eventTime = event.getDownTime();
if (mPowerKeyPressCounter < maxCount) {
// This could be a multi-press. Wait a little bit longer to confirm.
// Continue holding the wake lock.
Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
msg.setAsynchronous(true);
mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
return;
}
// No other actions. Handle it immediately.
powerPress(eventTime, interactive, mPowerKeyPressCounter);
}
// Done. Reset our state.
finishPowerKeyPress();
}
private void powerPress(long eventTime, boolean interactive, int count) {
if (mScreenOnEarly && !mScreenOnFully) {
Slog.i(TAG, "Suppressed redundant power key press while "
+ "already in the process of turning the screen on.");
return;
}
if (count == 2) {
powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
} else if (count == 3) {
powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
} else if (interactive && !mBeganFromNonInteractive) {
switch (mShortPressOnPowerBehavior) {
case SHORT_PRESS_POWER_NOTHING:
break;
case SHORT_PRESS_POWER_GO_TO_SLEEP:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
break;
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
break;
case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
mPowerManager.goToSleep(eventTime,
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
launchHomeFromHotKey();
break;
case SHORT_PRESS_POWER_GO_HOME:
launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
break;
}
}
}
b.PowerManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\core\java\android\os)
public void goToSleep(long time, int reason, int flags) {
try {
mService.goToSleep(time, reason, flags);
} catch (RemoteException e) {
}
}
c.PowerManagerService.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\power)
private final class BinderService extends IPowerManager.Stub {
@Override // Binder call
public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
String packageName, int uid) {
if (uid < 0) {
uid = Binder.getCallingUid();
}
acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null);
}
@Override // Binder call
public void powerHint(int hintId, int data) {
if (!mSystemReady) {
// Service not ready yet, so who the heck cares about power hints, bah.
return;
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
powerHintInternal(hintId, data);
}
@Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
if (packageName == null) {
throw new IllegalArgumentException("packageName must not be null");
}
PowerManager.validateWakeLockParameters(flags, tag);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if ((flags & PowerManager.DOZE_WAKE_LOCK) != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
}
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void releaseWakeLock(IBinder lock, int flags) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
final long ident = Binder.clearCallingIdentity();
try {
releaseWakeLockInternal(lock, flags);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void updateWakeLockUids(IBinder lock, int[] uids) {
WorkSource ws = null;
if (uids != null) {
ws = new WorkSource();
// XXX should WorkSource have a way to set uids as an int[] instead of adding them
// one at a time?
for (int i = 0; i < uids.length; i++) {
ws.add(uids[i]);
}
}
updateWakeLockWorkSource(lock, ws, null);
}
@Override // Binder call
public void updateWakeLockWorkSource(IBinder lock, WorkSource ws, String historyTag) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
if (ws != null && ws.size() != 0) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.UPDATE_DEVICE_STATS, null);
} else {
ws = null;
}
final int callingUid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
updateWakeLockWorkSourceInternal(lock, ws, historyTag, callingUid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isWakeLockLevelSupported(int level) {
final long ident = Binder.clearCallingIdentity();
try {
return isWakeLockLevelSupportedInternal(level);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void userActivity(long eventTime, int event, int flags) {
final long now = SystemClock.uptimeMillis();
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
!= PackageManager.PERMISSION_GRANTED
&& mContext.checkCallingOrSelfPermission(
android.Manifest.permission.USER_ACTIVITY)
!= PackageManager.PERMISSION_GRANTED) {
// Once upon a time applications could call userActivity().
// Now we require the DEVICE_POWER permission. Log a warning and ignore the
// request instead of throwing a SecurityException so we don't break old apps.
synchronized (mLock) {
if (now >= mLastWarningAboutUserActivityPermission + (5 * 60 * 1000)) {
mLastWarningAboutUserActivityPermission = now;
Slog.w(TAG, "Ignoring call to PowerManager.userActivity() because the "
+ "caller does not have DEVICE_POWER or USER_ACTIVITY "
+ "permission. Please fix your app! "
+ " pid=" + Binder.getCallingPid()
+ " uid=" + Binder.getCallingUid());
}
}
return;
}
if (eventTime > now) {
throw new IllegalArgumentException("event time must not be in the future");
}
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
userActivityInternal(eventTime, event, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void wakeUp(long eventTime, String reason, String opPackageName) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void goToSleep(long eventTime, int reason, int flags) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
goToSleepInternal(eventTime, reason, flags, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void nap(long eventTime) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
napInternal(eventTime, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isInteractive() {
final long ident = Binder.clearCallingIdentity();
try {
return isInteractiveInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isPowerSaveMode() {
final long ident = Binder.clearCallingIdentity();
try {
return isLowPowerModeInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean setPowerSaveMode(boolean mode) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
return setLowPowerModeInternal(mode);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isDeviceIdleMode() {
final long ident = Binder.clearCallingIdentity();
try {
return isDeviceIdleModeInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Reboots the device.
*
* @param confirm If true, shows a reboot confirmation dialog.
* @param reason The reason for the reboot, or null if none.
* @param wait If true, this call waits for the reboot to complete and does not return.
*/
@Override // Binder call
public void reboot(boolean confirm, String reason, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
if (PowerManager.REBOOT_RECOVERY.equals(reason)) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.RECOVERY, null);
}
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(false, confirm, reason, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Shuts down the device.
*
* @param confirm If true, shows a shutdown confirmation dialog.
* @param wait If true, this call waits for the shutdown to complete and does not return.
*/
@Override // Binder call
public void shutdown(boolean confirm, boolean wait) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
shutdownOrRebootInternal(true, confirm, null, wait);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Crash the runtime (causing a complete restart of the Android framework).
* Requires REBOOT permission. Mostly for testing. Should not return.
*/
@Override // Binder call
public void crash(String message) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
final long ident = Binder.clearCallingIdentity();
try {
crashInternal(message);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Set the setting that determines whether the device stays on when plugged in.
* The argument is a bit string, with each bit specifying a power source that,
* when the device is connected to that source, causes the device to stay on.
* See {@link android.os.BatteryManager} for the list of power sources that
* can be specified. Current values include
* {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
* and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
*
* Used by "adb shell svc power stayon ..."
*
* @param val an {@code int} containing the bits that specify which power sources
* should cause the device to stay on.
*/
@Override // Binder call
public void setStayOnSetting(int val) {
int uid = Binder.getCallingUid();
// if uid is of root's, we permit this operation straight away
if (uid != Process.ROOT_UID) {
if (!Settings.checkAndNoteWriteSettingsOperation(mContext, uid,
Settings.getPackageNameForUid(mContext, uid), true)) {
return;
}
}
final long ident = Binder.clearCallingIdentity();
try {
setStayOnSettingInternal(val);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the settings application and brightness control widgets to
* temporarily override the current screen brightness setting so that the
* user can observe the effect of an intended settings change without applying
* it immediately.
*
* The override will be canceled when the setting value is next updated.
*
* @param brightness The overridden brightness.
*
* @see android.provider.Settings.System#SCREEN_BRIGHTNESS
*/
@Override // Binder call
public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the settings application and brightness control widgets to
* temporarily override the current screen auto-brightness adjustment setting so that the
* user can observe the effect of an intended settings change without applying
* it immediately.
*
* The override will be canceled when the setting value is next updated.
*
* @param adj The overridden brightness, or Float.NaN to disable the override.
*
* @see android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
*/
@Override // Binder call
public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setTemporaryScreenAutoBrightnessAdjustmentSettingOverrideInternal(adj);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
/**
* Used by the phone application to make the attention LED flash when ringing.
*/
@Override // Binder call
public void setAttentionLight(boolean on, int color) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
setAttentionLightInternal(on, color);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void boostScreenBrightness(long eventTime) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.DEVICE_POWER, null);
final int uid = Binder.getCallingUid();
final long ident = Binder.clearCallingIdentity();
try {
boostScreenBrightnessInternal(eventTime, uid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public boolean isScreenBrightnessBoosted() {
final long ident = Binder.clearCallingIdentity();
try {
return isScreenBrightnessBoostedInternal();
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
pw.println("Permission Denial: can't dump PowerManager from from pid="
+ Binder.getCallingPid()
+ ", uid=" + Binder.getCallingUid());
return;
}
final long ident = Binder.clearCallingIdentity();
try {
dumpInternal(pw);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void wakeUpByReason(long eventTime, int reason) {
if (eventTime > SystemClock.uptimeMillis()) {
throw new IllegalArgumentException("event time must not be in the future");
}
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
wakeUpByReasonInternal(eventTime, reason);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@Override // Binder call
public void startBacklight(int delay_msec) {
synchronized (mLock) {
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
Slog.d(TAG, "startBacklight");
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
mDisplayManagerInternal.setIPOScreenOnDelay(delay_msec);
wakeUpNoUpdateLocked(SystemClock.uptimeMillis(),
"android.server.power:POWER",
Process.SYSTEM_UID,
mContext.getOpPackageName(),
Process.SYSTEM_UID);
updatePowerStateLocked();
} finally {
Binder.restoreCallingIdentity(ident);
}
} else {
Slog.d(TAG, "skip startBacklight because MTK_IPO_SUPPORT not enabled");
}
}
}
@Override // Binder call
public void stopBacklight() {
synchronized (mLock) {
if (SystemProperties.get("ro.mtk_ipo_support").equals("1")) {
Slog.d(TAG, "stopBacklight");
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
final long ident = Binder.clearCallingIdentity();
try {
mDisplayManagerInternal.setIPOScreenOnDelay(0);
goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, Process.SYSTEM_UID);
updatePowerStateLocked();
} finally {
Binder.restoreCallingIdentity(ident);
}
} else {
Slog.d(TAG, "skip stopBacklight because MTK_IPO_SUPPORT not enabled");
}
}
}
@Override
public void setBacklightOffForWfd(boolean enable) {
if(enable) {
Slog.d(TAG, "setBacklightOffForWfd true");
mBacklight.setBrightness(0);
} else {
if (mWfdShouldBypass != true) {
Slog.d(TAG, "setBacklightOffForWfd false");
mBacklight.setBrightness(mScreenBrightnessSetting);
} else {
Slog.d(TAG, "setBacklightOffForWfd false ignored due to screen is off by power key");
}
}
}
}
private void goToSleepInternal(long eventTime, int reason, int flags, int uid) {
synchronized (mLock) {
if (mProximityPositive && reason == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON) {
Slog.d(TAG, "Proximity positive sleep and force wakeup by power button");
mDirty |= DIRTY_WAKEFULNESS;
mWakefulness = WAKEFULNESS_ASLEEP;
updatePowerStateLocked();
return;
}
if (goToSleepNoUpdateLocked(eventTime, reason, flags, uid)) {
updatePowerStateLocked();
}
}
}
private boolean goToSleepNoUpdateLocked(long eventTime, int reason, int flags, int uid) {
if (DEBUG) {
StackTraceElement[] stack = new Throwable().getStackTrace();
for (StackTraceElement element : stack) {
Slog.d(TAG, " |----" + element.toString());
}
}
if (DEBUG_SPEW) {
Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime
+ ", reason=" + reason + ", flags=" + flags + ", uid=" + uid);
}
if (reason == PowerManager.GO_TO_SLEEP_REASON_SHUTDOWN) {
mDirty |= DIRTY_SETTINGS;
mShutdownFlag = true;
Slog.d(TAG, "mShutdownFlag = " + mShutdownFlag);
return true;
}
if (eventTime < mLastWakeTime
|| mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| !mBootCompleted || !mSystemReady) {
return false;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "goToSleep");
try {
switch (reason) {
case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
Slog.i(TAG, "Going to sleep due to device administration policy "
+ "(uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
Slog.i(TAG, "Going to sleep due to screen timeout (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH:
Slog.i(TAG, "Going to sleep due to lid switch (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON:
Slog.i(TAG, "Going to sleep due to power button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON:
Slog.i(TAG, "Going to sleep due to sleep button (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_HDMI:
Slog.i(TAG, "Going to sleep due to HDMI standby (uid " + uid +")...");
break;
case PowerManager.GO_TO_SLEEP_REASON_PROXIMITY:
Slog.i(TAG, "Going to sleep due to proximity (uid " + uid +")...");
break;
default:
Slog.i(TAG, "Going to sleep by application request (uid " + uid +")...");
reason = PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
break;
}
mLastSleepTime = eventTime;
mSandmanSummoned = true;
setWakefulnessLocked(WAKEFULNESS_DOZING, reason);
// Report the number of wake locks that will be cleared by going to sleep.
int numWakeLocksCleared = 0;
final int numWakeLocks = mWakeLocks.size();
for (int i = 0; i < numWakeLocks; i++) {
final WakeLock wakeLock = mWakeLocks.get(i);
switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
case PowerManager.FULL_WAKE_LOCK:
case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
case PowerManager.SCREEN_DIM_WAKE_LOCK:
numWakeLocksCleared += 1;
break;
}
}
EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
// Wakelock debug
dumpWakeLockLocked();
// Skip dozing if requested.
if ((flags & PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE) != 0) {
reallyGoToSleepNoUpdateLocked(eventTime, uid);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
return true;
}
private void setWakefulnessLocked(int wakefulness, int reason) {
if (mWakefulness != wakefulness) {
mWakefulness = wakefulness;
mWakefulnessChanging = true;
mDirty |= DIRTY_WAKEFULNESS;
mNotifier.onWakefulnessChangeStarted(wakefulness, reason);
}
}
d. Notifier.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\power)
public void onWakefulnessChangeStarted(final int wakefulness, int reason) {
final boolean interactive = PowerManagerInternal.isInteractive(wakefulness);
if (DEBUG) {
Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness
+ ", reason=" + reason + ", interactive=" + interactive);
}
// Tell the activity manager about changes in wakefulness, not just interactivity.
// It needs more granularity than other components.
mHandler.post(new Runnable() {
@Override
public void run() {
mActivityManagerInternal.onWakefulnessChanged(wakefulness);
}
});
// Handle any early interactive state changes.
// Finish pending incomplete ones from a previous cycle.
if (mInteractive != interactive) {
// Finish up late behaviors if needed.
if (mInteractiveChanging) {
handleLateInteractiveChange();
}
// Start input as soon as we start waking up or going to sleep.
mInputManagerInternal.setInteractive(interactive);
mInputMethodManagerInternal.setInteractive(interactive);
// Notify battery stats.
try {
mBatteryStats.noteInteractive(interactive);
} catch (RemoteException ex) { }
// Handle early behaviors.
mInteractive = interactive;
mInteractiveChangeReason = reason;
mInteractiveChanging = true;
handleEarlyInteractiveChange();
}
}
private void handleEarlyInteractiveChange() {
synchronized (mLock) {
if (mInteractive) {
// Waking up...
mHandler.post(new Runnable() {
@Override
public void run() {
EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
if (DEBUG) {
Slog.d(TAG, "handleEarlyInteractiveChange: mPolicy.startedWakingUp");
}
mPolicy.startedWakingUp();
}
});
// Send interactive broadcast.
mPendingInteractiveState = INTERACTIVE_STATE_AWAKE;
mPendingWakeUpBroadcast = true;
updatePendingBroadcastLocked();
} else {
// Going to sleep...
// Tell the policy that we started going to sleep.
final int why = translateOffReason(mInteractiveChangeReason);
mHandler.post(new Runnable() {
@Override
public void run() {
mPolicy.startedGoingToSleep(why);
}
});
}
}
}
e. PhoneWindowManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\policy)
// Called on the PowerManager's Notifier thread.
@Override
public void startedGoingToSleep(int why) {
if (DEBUG_WAKEUP) Slog.i(TAG, "Started going to sleep... (why=" + why + ")");
if (mKeyguardDelegate != null) {
mKeyguardDelegate.onStartedGoingToSleep(why);
}
}
f. KeyguardServiceDelegate.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\policy\keyguard)
public void onStartedGoingToSleep(int why) {
if (mKeyguardService != null) {
Log.v(TAG, "onStartedGoingToSleep(),why:"+why);
mKeyguardService.onStartedGoingToSleep(why);
}
mKeyguardState.offReason = why;
}
g. KeyguardServiceWrapper.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\policy\keyguard)
@Override
public void onStartedGoingToSleep(int reason) {
try {
Slog.v(TAG , "reason :");
mService.onStartedGoingToSleep(reason);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
h. KeyguardService.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\systemui\src\com\android\systemui\keyguard)
public void onStartedGoingToSleep(int reason) {
checkPermission();
Log.w(TAG, "shizsun Binder interface onStartedGoingToSleep'");
mKeyguardViewMediator.onStartedGoingToSleep(reason);
}
i.KeyguardViewMediator.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\systemui\src\com\android\systemui\keyguard)
public void onStartedGoingToSleep(int why) {
if (DEBUG) Log.d(TAG, "onStartedGoingToSleep(" + why + ")");
synchronized (this) {
mDeviceInteractive = false;
mGoingToSleep = true;
// Lock immediately based on setting if secure (user has a pin/pattern/password).
// This also "locks" the device when not secure to provide easy access to the
// camera while preventing unwanted input.
int currentUser = KeyguardUpdateMonitor.getCurrentUser();
final boolean lockImmediately =
mLockPatternUtils.getPowerButtonInstantlyLocks(currentUser)
|| !mLockPatternUtils.isSecure(currentUser);
long timeout = getLockTimeout();
/// M: Add for supporting lock immediately when screen timeout. @{
final boolean lockWhenTimeout =
KeyguardPluginFactory.getKeyguardUtilExt(mContext)
.lockImmediatelyWhenScreenTimeout();
/// @}
if (DBG_WAKE) {
Log.d(TAG, "onStartedGoingToSleep(" + why +
") ---ScreenOff mScreenOn = false; After--boolean lockImmediately=" +
lockImmediately +
", mExitSecureCallback=" + mExitSecureCallback +
", mShowing=" + mShowing +
", mIsIPOShutDown = " + mIsIPOShutDown);
}
if (mExitSecureCallback != null) {
if (DEBUG) Log.d(TAG, "pending exit secure callback cancelled");
try {
mExitSecureCallback.onKeyguardExitResult(false);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
}
mExitSecureCallback = null;
if (!mExternallyEnabled) {
hideLocked();
}
} else if (mShowing) {
mPendingReset = true;
} else if ((why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT && timeout > 0
&& !lockWhenTimeout)
|| (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)
&& !mIsIPOShutDown) {
doKeyguardLaterLocked(timeout);
} else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
// Do not enable the keyguard if the prox sensor forced the screen off.
Log.d(TAG, "Screen off because PROX_SENSOR, do not draw lock view.") ;
} else if (!mLockPatternUtils.isLockScreenDisabled(currentUser)) {
mPendingLock = true;
}
if (mPendingLock) {
playSounds(true);
}
}
KeyguardUpdateMonitor.getInstance(mContext).dispatchStartedGoingToSleep(why);
//notifyStartedGoingToSleep();
}
j.KeyguardUpdateMonitor.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\keyguard\src\com\android\keyguard)
protected void handleStartedGoingToSleep(int arg1) {
clearFingerprintRecognized();
final int count = mCallbacks.size();
for (int i = 0; i < count; i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onStartedGoingToSleep(arg1);
}
}
mGoingToSleep = true;
mFingerprintAlreadyAuthenticated = false;
updateFingerprintListeningState();
}
private void updateFingerprintListeningState() {
boolean shouldListenForFingerprint = shouldListenForFingerprint();
if (mFingerprintRunningState == FINGERPRINT_STATE_RUNNING && !shouldListenForFingerprint) {
stopListeningForFingerprint();
} else if (mFingerprintRunningState != FINGERPRINT_STATE_RUNNING
&& shouldListenForFingerprint) {
startListeningForFingerprint();
}
}
private void startListeningForFingerprint() {
if (mFingerprintRunningState == FINGERPRINT_STATE_CANCELLING) {
setFingerprintRunningState(FINGERPRINT_STATE_CANCELLING_RESTARTING);
return;
}
if (DEBUG) Log.v(TAG, "startListeningForFingerprint()");
int userId = ActivityManager.getCurrentUser();
if (isUnlockWithFingerprintPossible(userId)) {
if (mFingerprintCancelSignal != null) {
mFingerprintCancelSignal.cancel();
}
mFingerprintCancelSignal = new CancellationSignal();
mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId);
setFingerprintRunningState(FINGERPRINT_STATE_RUNNING);
}
}
k.FingerprintManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\core\java\android\hardware\fingerprint)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
if (cancel != null) {
if (cancel.isCanceled()) {
Log.w(TAG, "authentication already canceled");
return;
} else {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
}
}
Log.w(TAG, "shizsun:authentication manager it");
if (mService != null) try {
useHandler(handler);
mAuthenticationCallback = callback;
mCryptoObject = crypto;
long sessionId = crypto != null ? crypto.getOpId() : 0;
mService.authenticate(mToken, sessionId, userId, mServiceReceiver, flags,
mContext.getOpPackageName());
} catch (RemoteException e) {
Log.w(TAG, "Remote exception while authenticating: ", e);
if (callback != null) {
// Though this may not be a hardware issue, it will cause apps to give up or try
// again later.
callback.onAuthenticationError(FINGERPRINT_ERROR_HW_UNAVAILABLE,
getErrorString(FINGERPRINT_ERROR_HW_UNAVAILABLE));
}
}
}
l. FingerprintService.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\fingerprint)
public void authenticate(final IBinder token, final long opId, final int groupId,
final IFingerprintServiceReceiver receiver, final int flags,
final String opPackageName) {
if (!canUseFingerprint(opPackageName, true /* foregroundOnly */)) {
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
return;
}
// Group ID is arbitrarily set to parent profile user ID. It just represents
// the default fingerprints for the user.
final int effectiveGroupId = getEffectiveUserId(groupId);
Slog.w(TAG, "shizsun:authenticate(): reject " + opPackageName+"effectiveGroupId="+effectiveGroupId);
final boolean restricted = isRestricted();
mHandler.post(new Runnable() {
@Override
public void run() {
MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
startAuthentication(token, opId, effectiveGroupId, receiver, flags, restricted,
opPackageName);
}
});
}
void startAuthentication(IBinder token, long opId, int groupId,
IFingerprintServiceReceiver receiver, int flags, boolean restricted,
String opPackageName) {
IFingerprintDaemon daemon = getFingerprintDaemon();
if (daemon == null) {
Slog.w(TAG, "startAuthentication: no fingeprintd!");
return;
}
stopPendingOperations(true);
mAuthClient = new ClientMonitor(token, receiver, groupId, restricted, opPackageName);
if (inLockoutMode()) {
Slog.v(TAG, "In lockout mode; disallowing authentication");
if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) {
Slog.w(TAG, "Cannot send timeout message to client");
}
mAuthClient = null;
return;
}
Slog.w(TAG, "shizsun:startAuthentication: go start!");
try {
final int result = daemon.authenticate(opId, groupId);
if (result != 0) {
Slog.w(TAG, "startAuthentication failed, result=" + result);
handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
}
} catch (RemoteException e) {
Slog.e(TAG, "startAuthentication failed", e);
}
}
m. FingerprintDaemonProxy.cpp (z:\home\shizsun\work\k506\k506\system\core\fingerprintd)
int32_t FingerprintDaemonProxy::authenticate(uint64_t sessionId, uint32_t groupId) {
ALOG(LOG_VERBOSE, LOG_TAG, "authenticate(sid=%" PRId64 ", gid=%d)\n", sessionId, groupId);
return mDevice->authenticate(mDevice, sessionId, groupId);
}
n. Fingerprint.c (z:\home\shizsun\work\k506\k506\hardware\libhardware\modules\fingerprint)
static int fingerprint_authenticate(struct fingerprint_device __unused *dev,
uint64_t __unused operation_id, __unused uint32_t gid)
{
if (Fp_Authenticate(dev,operation_id, gid) < 0) return -1;
return 0;
}
二.指纹解锁流程分析
a. fingerprint.c
memset(&msg, 0, sizeof(fingerprint_msg_t));
msg.type = FINGERPRINT_AUTHENTICATED;
msg.data.authenticated.finger.gid = gFingerprintVar.gid ;
msg.data.authenticated.finger.fid = fingerID;
msg.data.authenticated.hat.user_id = gFingerprintVar.gid;
msg.data.authenticated.hat.authenticator_id = gFingerprintVar.token;
uint32_t tmp = (uint32_t)HW_AUTH_FINGERPRINT;
msg.data.authenticated.hat.authenticator_type = my_hton(tmp);
msg.data.authenticated.hat.challenge = gFingerprintParam.operation_id;
msg.data.authenticated.hat.timestamp = my_htonl(btl_api_createToken());
dev->notify(&msg);
b.FingerprintDaemonProxy.cpp (z:\home\shizsun\work\k506\k506\system\core\fingerprintd)
void FingerprintDaemonProxy::hal_notify_callback(const fingerprint_msg_t *msg) {
FingerprintDaemonProxy* instance = FingerprintDaemonProxy::getInstance();
const sp<IFingerprintDaemonCallback> callback = instance->mCallback;
if (callback == NULL) {
ALOGE("Invalid callback object");
return;
}
const int64_t device = (int64_t) instance->mDevice;
switch (msg->type) {
case FINGERPRINT_ERROR:
ALOGD("onError(%d)", msg->data.error);
callback->onError(device, msg->data.error);
break;
case FINGERPRINT_ACQUIRED:
ALOGD("onAcquired(%d)", msg->data.acquired.acquired_info);
callback->onAcquired(device, msg->data.acquired.acquired_info);
break;
case FINGERPRINT_AUTHENTICATED:
ALOGD("onAuthenticated(fid=%d, gid=%d)",
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid);
if (msg->data.authenticated.finger.fid != 0) {
const uint8_t* hat = reinterpret_cast<const uint8_t *>(&msg->data.authenticated.hat);
instance->notifyKeystore(hat, sizeof(msg->data.authenticated.hat));
}
callback->onAuthenticated(device,
msg->data.authenticated.finger.fid,
msg->data.authenticated.finger.gid);
break;
case FINGERPRINT_TEMPLATE_ENROLLING:
ALOGD("onEnrollResult(fid=%d, gid=%d, rem=%d)",
msg->data.enroll.finger.fid,
msg->data.enroll.finger.gid,
msg->data.enroll.samples_remaining);
callback->onEnrollResult(device,
msg->data.enroll.finger.fid,
msg->data.enroll.finger.gid,
msg->data.enroll.samples_remaining);
break;
case FINGERPRINT_TEMPLATE_REMOVED:
ALOGD("onRemove(fid=%d, gid=%d)",
msg->data.removed.finger.fid,
msg->data.removed.finger.gid);
callback->onRemoved(device,
msg->data.removed.finger.fid,
msg->data.removed.finger.gid);
break;
default:
ALOGE("invalid msg type: %d", msg->type);
return;
}
}
c.FingerprintService.java (z:\home\shizsun\work\k506\k506\frameworks\base\services\core\java\com\android\server\fingerprint)
private IFingerprintDaemonCallback mDaemonCallback = new IFingerprintDaemonCallback.Stub() {
@Override
public void onEnrollResult(final long deviceId, final int fingerId, final int groupId,
final int remaining) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleEnrollResult(deviceId, fingerId, groupId, remaining);
}
});
}
@Override
public void onAcquired(final long deviceId, final int acquiredInfo) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleAcquired(deviceId, acquiredInfo);
}
});
}
@Override
public void onAuthenticated(final long deviceId, final int fingerId, final int groupId) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleAuthenticated(deviceId, fingerId, groupId);
}
});
}
@Override
public void onError(final long deviceId, final int error) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleError(deviceId, error);
}
});
}
@Override
public void onRemoved(final long deviceId, final int fingerId, final int groupId) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleRemoved(deviceId, fingerId, groupId);
}
});
}
@Override
public void onEnumerate(final long deviceId, final int[] fingerIds, final int[] groupIds) {
mHandler.post(new Runnable() {
@Override
public void run() {
handleEnumerate(deviceId, fingerIds, groupIds);
}
});
}
}
protected void handleAuthenticated(long deviceId, int fingerId, int groupId) {
if (mAuthClient != null) {
final IBinder token = mAuthClient.token;
if (mAuthClient.sendAuthenticated(fingerId, groupId)) {
stopAuthentication(token, false);
removeClient(mAuthClient);
}
}
}
private boolean sendAuthenticated(int fpId, int groupId) {
boolean result = false;
boolean authenticated = fpId != 0;
if (receiver != null) {
try {
MetricsLogger.action(mContext, MetricsLogger.ACTION_FINGERPRINT_AUTH,
authenticated);
if (!authenticated) {
receiver.onAuthenticationFailed(mHalDeviceId);
} else {
if (DEBUG) {
Slog.v(TAG, "onAuthenticated(owner=" + mAuthClient.owner
+ ", id=" + fpId + ", gp=" + groupId + ")");
}
Fingerprint fp = !restricted ?
new Fingerprint("" /* TODO */, groupId, fpId, mHalDeviceId) : null;
receiver.onAuthenticationSucceeded(mHalDeviceId, fp);
}
} catch (RemoteException e) {
Slog.w(TAG, "Failed to notify Authenticated:", e);
result = true; // client failed
}
} else {
result = true; // client not listening
}
if (fpId == 0) {
if (receiver != null) {
FingerprintUtils.vibrateFingerprintError(getContext());
}
result |= handleFailedAttempt(this);
} else {
if (receiver != null) {
FingerprintUtils.vibrateFingerprintSuccess(getContext());
}
result |= true; // we have a valid fingerprint
resetFailedAttempts();
}
return result;
}
d. FingerprintManager.java (z:\home\shizsun\work\k506\k506\frameworks\base\core\java\android\hardware\fingerprint)
private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
@Override // binder call
public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
}
@Override // binder call
public void onAcquired(long deviceId, int acquireInfo) {
mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
}
@Override // binder call
public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
}
@Override // binder call
public void onAuthenticationFailed(long deviceId) {
mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
}
@Override // binder call
public void onError(long deviceId, int error) {
mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
}
@Override // binder call
public void onRemoved(long deviceId, int fingerId, int groupId) {
mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
}
}
private void sendAuthenticatedSucceeded(Fingerprint fp) {
if (mAuthenticationCallback != null) {
final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
mAuthenticationCallback.onAuthenticationSucceeded(result);
}
}
e. KeyguardUpdateMonitor.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\keyguard\src\com\android\keyguard)
private FingerprintManager.AuthenticationCallback mAuthenticationCallback
= new AuthenticationCallback() {
@Override
public void onAuthenticationFailed() {
handleFingerprintAuthFailed();
};
@Override
public void onAuthenticationSucceeded(AuthenticationResult result) {
handleFingerprintAuthenticated();
}
@Override
public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
handleFingerprintHelp(helpMsgId, helpString.toString());
}
@Override
public void onAuthenticationError(int errMsgId, CharSequence errString) {
handleFingerprintError(errMsgId, errString.toString());
}
@Override
public void onAuthenticationAcquired(int acquireInfo) {
handleFingerprintAcquired(acquireInfo);
}
}
private void handleFingerprintAuthenticated() {
try {
final int userId;
try {
userId = ActivityManagerNative.getDefault().getCurrentUser().id;
} catch (RemoteException e) {
Log.e(TAG, "Failed to get current user id: ", e);
return;
}
if (isFingerprintDisabled(userId)) {
Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
return;
}
onFingerprintAuthenticated(userId);
} finally {
setFingerprintRunningState(FINGERPRINT_STATE_STOPPED);
}
}
private void onFingerprintAuthenticated(int userId) {
mUserFingerprintAuthenticated.put(userId, true);
// If fingerprint unlocking is allowed, this event will lead to a Keyguard dismiss or to a
// wake-up (if Keyguard is not showing), so we don't need to listen until Keyguard is
// fully gone.
mFingerprintAlreadyAuthenticated = isUnlockingWithFingerprintAllowed();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onFingerprintAuthenticated(userId);
}
}
}
f. FingerprintUnlockController.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\systemui\src\com\android\systemui\statusbar\phone)
@Override
public void onFingerprintAuthenticated(int userId) {
if (mUpdateMonitor.isGoingToSleep()) {
mPendingAuthenticatedUserId = userId;
return;
}
boolean wasDeviceInteractive = mUpdateMonitor.isDeviceInteractive();
mMode = calculateMode();
if (!wasDeviceInteractive) {
if (DEBUG_FP_WAKELOCK) {
Log.i(TAG, "fp wakelock: Authenticated, waking up...");
}
mPowerManager.wakeUp(SystemClock.uptimeMillis());
}
releaseFingerprintWakeLock();
switch (mMode) {
case MODE_DISMISS_BOUNCER:
mStatusBarKeyguardViewManager.notifyKeyguardAuthenticated(
false /* strongAuth */);
break;
case MODE_UNLOCK:
case MODE_SHOW_BOUNCER:
if (!wasDeviceInteractive) {
mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
}
mStatusBarKeyguardViewManager.animateCollapsePanels(
FINGERPRINT_COLLAPSE_SPEEDUP_FACTOR);
break;
case MODE_WAKE_AND_UNLOCK_PULSING:
mPhoneStatusBar.updateMediaMetaData(false /* metaDataChanged */);
// Fall through.
case MODE_WAKE_AND_UNLOCK:
mStatusBarWindowManager.setStatusBarFocusable(false);
mDozeScrimController.abortPulsing();
mKeyguardViewMediator.onWakeAndUnlocking();
mScrimController.setWakeAndUnlocking();
if (mPhoneStatusBar.getNavigationBarView() != null) {
mPhoneStatusBar.getNavigationBarView().setWakeAndUnlocking(true);
}
break;
case MODE_ONLY_WAKE:
case MODE_NONE:
break;
}
if (mMode != MODE_WAKE_AND_UNLOCK_PULSING) {
mStatusBarWindowManager.setForceDozeBrightness(false);
}
mPhoneStatusBar.notifyFpAuthModeChanged();
}
g. KeyguardViewMediator.java (z:\home\shizsun\work\k506\k506\frameworks\base\packages\systemui\src\com\android\systemui\keyguard)
public void onWakeAndUnlocking() {
mWakeAndUnlocking = true;
keyguardDone(true /* authenticated */);
}
public void keyguardDone(boolean authenticated) {
if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated +")");
EventLog.writeEvent(70000, 2);
Message msg = mHandler.obtainMessage(KEYGUARD_DONE, authenticated ? 1 : 0);
mHandler.sendMessage(msg);
}
private void handleKeyguardDone(boolean authenticated) {
Log.d(TAG, "handleKeyguardDone, authenticated=" + authenticated);
synchronized (this) {
resetKeyguardDonePendingLocked();
}
///M: [ALPS01567248] Timing issue.
/// Voice Unlock View dismiss -> AntiTheft View shows
/// -> previous Voice Unlock dismiss flow calls handleKeyguardDone
/// -> remove AntiTheft View
/// So we avoid handleKeyguardDone if AntiTheft is the current view,
/// and not yet unlock correctly.
if (AntiTheftManager.isAntiTheftLocked()) {
Log.d(TAG, "handleKeyguardDone() - Skip keyguard done! antitheft = " +
AntiTheftManager.isAntiTheftLocked() +
" or sim = " + mUpdateMonitor.isSimPinSecure());
return ;
}
Log.d(TAG, "set mKeyguardDoneOnGoing = true") ;
mKeyguardDoneOnGoing = true ;
if (authenticated) {
mUpdateMonitor.clearFailedUnlockAttempts();
}
mUpdateMonitor.clearFingerprintRecognized();
if (mGoingToSleep) {
Log.i(TAG, "Device is going to sleep, aborting keyguardDone");
return;
}
if (mExitSecureCallback != null) {
try {
mExitSecureCallback.onKeyguardExitResult(authenticated);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to call onKeyguardExitResult(" + authenticated + ")", e);
}
mExitSecureCallback = null;
if (authenticated) {
// after succesfully exiting securely, no need to reshow
// the keyguard when they've released the lock
mExternallyEnabled = true;
mNeedToReshowWhenReenabled = false;
updateInputRestricted();
}
}
///M: [ALPS00827994] always to play sound for user to unlock keyguard
mSuppressNextLockSound = false;
handleHide();
}