android按键震动,android 手机虚拟按键 震动过程的追溯(1)

本文详细解析了Android系统从按键输入到触发震动反馈的完整处理流程,涉及ADB推送服务.jar文件、OAT编译、InputDispatcher、Vibrator服务等多个关键环节,深入探讨了权限检查、事件拦截及震动效果的实现机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

matthew@matthew:/media/matt1/ze550kl-m/out/target/product/Z00L/system/framework$ adb push ./services.jar  /system/framework/

2 KB/s (205 bytes in 0.072s)

matthew@matthew:/media/matt1/ze550kl-m/out/target/product/Z00L/system/framework$ cd /oat/arm64/

bash: cd: /oat/arm64/: 没有那个文件或目录

matthew@matthew:/media/matt1/ze550kl-m/out/target/product/Z00L/system/framework$ cd oat/arm64/

matthew@matthew:/media/matt1/ze550kl-m/out/target/product/Z00L/system/framework/oat/arm64$ adb push ./services.odex  /system/framework/oat/arm64/

void TouchInputMapper::dispatchVirtualKey(nsecs_t when, uint32_t policyFlags,

int32_t keyEventAction, int32_t keyEventFlags) {

getListener()->notifyKey(&args);

}

到了

void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {

ALOGD("matt-interceptKeyBeforeQueueing5");

mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);

}

private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {

Slog.e(TAG, "matt-interceptKeyBeforeQueueing3");

return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);

}

到了

public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {

Slog.d(WindowManagerService.TAG, "matt-interceptKeyBeforeQueueing2 ");

return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);

}

到了

然后到了

public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {

if (useHapticFeedback) {

performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);

}

}

然后到了

public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always) {

owningUid = android.os.Process.myUid();

owningPackage = mContext.getOpPackageName();

if (pattern.length == 1) {

// One-shot vibration

mVibrator.vibrate(owningUid, owningPackage, pattern[0], VIBRATION_ATTRIBUTES);//调用震动器

} else {

// Pattern vibration

mVibrator.vibrate(owningUid, owningPackage, pattern, -1, VIBRATION_ATTRIBUTES);//调用震动器

}

}

到了SystemVibrator.java里

public void vibrate(int uid, String opPkg, long[] pattern, int repeat,

AudioAttributes attributes) {

Log.e(TAG, "matt-+1");

if (mService == null) {

Log.w(TAG, "Failed to vibrate; no vibrator service.");

return;

}

// catch this here because the server will do nothing.  pattern may

// not be null, let that be checked, because the server will drop it

// anyway

if (repeat < pattern.length) {

try {

mService.vibratePattern(uid, opPkg, pattern, repeat, usageForAttributes(attributes),//启动震动

mToken);

} catch (RemoteException e) {

Log.w(TAG, "Failed to vibrate.", e);

}

} else {

throw new ArrayIndexOutOfBoundsException();

}

}

到了

public void vibratePattern(int uid, String packageName, long[] pattern, int repeat,

int usageHint, IBinder token) {

if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)

!= PackageManager.PERMISSION_GRANTED) {

throw new SecurityException("Requires VIBRATE permission");

}

verifyIncomingUid(uid);

// so wakelock calls will succeed

long identity = Binder.clearCallingIdentity();

try {

if (DEBUG) {

String s = "";

int N = pattern.length;

for (int i=0; is += " " + pattern[i];

}

Slog.d(TAG, "Vibrating with pattern:" + s);

}

// we're running in the server so we can't fail

if (pattern == null || pattern.length == 0

|| isAll0(pattern)

|| repeat >= pattern.length || token == null) {

return;

}

Vibration vib = new Vibration(token, pattern, repeat, usageHint, uid, packageName);

try {

token.linkToDeath(vib, 0);

} catch (RemoteException e) {

return;

}

synchronized (mVibrations) {

removeVibrationLocked(token);

doCancelVibrateLocked();

if (repeat >= 0) {

mVibrations.addFirst(vib);

startNextVibrationLocked(); //启动震动

} else {

// A negative repeat means that this pattern is not meant

// to repeat. Treat it like a simple vibration.

mCurrentVibration = vib;

startVibrationLocked(vib);

}

addToPreviousVibrationsLocked(vib);

}

}

finally {

Binder.restoreCallingIdentity(identity);

}

}

到了

private void startVibrationLocked(final Vibration vib) {

try {

if (mLowPowerMode

&& vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {

return;

}

int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,

vib.mUsageHint, vib.mUid, vib.mOpPkg);

if (mode == AppOpsManager.MODE_ALLOWED) {

mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),

AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);

}

if (mode != AppOpsManager.MODE_ALLOWED) {

if (mode == AppOpsManager.MODE_ERRORED) {

Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);

}

mH.post(mVibrationRunnable);

return;

}

} catch (RemoteException e) {

}

if (vib.mTimeout != 0) {

doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint);

// switch (asus_PRJ_ID) {

case 1://ASUS600KL

mH.postDelayed(mVibrationRunnable, vib.mTimeout + VIB_CAL_MS);

break;

default:

mH.postDelayed(mVibrationRunnable, vib.mTimeout);

break;

}

// } else {

// mThread better be null here. doCancelVibrate should always be

// called before startNextVibrationLocked or startVibrationLocked.

mThread = new VibrateThread(vib);  //启动一个新的线程

mThread.start();

}

}

跑到了run函数

public void run() {

Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);

synchronized (this) {

final long[] pattern = mVibration.mPattern;

final int len = pattern.length;

final int repeat = mVibration.mRepeat;

final int uid = mVibration.mUid;

final int usageHint = mVibration.mUsageHint;

int index = 0;

long duration = 0;

while (!mDone) {

// add off-time duration to any accumulated on-time duration

if (index < len) {

duration += pattern[index++];

}

// sleep until it is time to start the vibrator

delay(duration);

if (mDone) {

break;

}

if (index < len) {

// read on-time duration and start the vibrator

// duration is saved for delay() at top of loop

duration = pattern[index++];

if (duration > 0) {

VibratorService.this.doVibratorOn(duration, uid, usageHint);//最后是这边震动

}

} else {

if (repeat < 0) {

break;

} else {

index = repeat;

duration = 0;

}

}

}

mWakeLock.release();

}

synchronized (mVibrations) {

if (mThread == this) {

mThread = null;

}

if (!mDone) {

// If this vibration finished naturally, start the next

// vibration.

unlinkVibration(mVibration);

startNextVibrationLocked();

}

}

}

}

跑到

private void doVibratorOn(long millis, int uid, int usageHint) {

synchronized (mInputDeviceVibrators) {

if (DEBUG) {

Slog.d(TAG, "Turning vibrator on for " + millis + " ms.");

}

try {

mBatteryStatsService.noteVibratorOn(uid, millis);

mCurVibUid = uid;

} catch (RemoteException e) {

}

final int vibratorCount = mInputDeviceVibrators.size();

if (vibratorCount != 0) {

final AudioAttributes attributes = new AudioAttributes.Builder().setUsage(usageHint)

.build();

for (int i = 0; i < vibratorCount; i++) {

mInputDeviceVibrators.get(i).vibrate(millis, attributes);

}

} else {

// switch (asus_PRJ_ID) {

case 1://ASUS600KL

vibratorOn(millis + VIB_CAL_MS);

break;

default:

vibratorOn(millis);

break;

}

// }

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值