Merge "Add more vibrator traces" into main
diff --git a/core/java/android/os/SystemVibratorManager.java b/core/java/android/os/SystemVibratorManager.java
index 58ab5b6..cfbf528 100644
--- a/core/java/android/os/SystemVibratorManager.java
+++ b/core/java/android/os/SystemVibratorManager.java
@@ -138,11 +138,14 @@
Log.w(TAG, "Failed to vibrate; no vibrator manager service.");
return;
}
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason=" + reason);
try {
mService.vibrate(uid, mContext.getDeviceId(), opPkg, effect, attributes, reason,
mToken);
} catch (RemoteException e) {
Log.w(TAG, "Failed to vibrate.", e);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -152,11 +155,14 @@
Log.w(TAG, "Failed to perform haptic feedback; no vibrator manager service.");
return;
}
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "performHapticFeedback, reason=" + reason);
try {
mService.performHapticFeedback(mUid, mContext.getDeviceId(), mPackageName, constant,
reason, flags, privFlags);
} catch (RemoteException e) {
Log.w(TAG, "Failed to perform haptic feedback.", e);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -168,11 +174,15 @@
+ " no vibrator manager service.");
return;
}
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR,
+ "performHapticFeedbackForInputDevice, reason=" + reason);
try {
mService.performHapticFeedbackForInputDevice(mUid, mContext.getDeviceId(), mPackageName,
constant, inputDeviceId, inputSource, reason, flags, privFlags);
} catch (RemoteException e) {
Log.w(TAG, "Failed to perform haptic feedback for input device.", e);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
diff --git a/services/core/java/com/android/server/vibrator/VibrationThread.java b/services/core/java/com/android/server/vibrator/VibrationThread.java
index ab4a4d8..4c1e16c 100644
--- a/services/core/java/com/android/server/vibrator/VibrationThread.java
+++ b/services/core/java/com/android/server/vibrator/VibrationThread.java
@@ -128,15 +128,20 @@
* before the release callback.
*/
boolean runVibrationOnVibrationThread(VibrationStepConductor conductor) {
- synchronized (mLock) {
- if (mRequestedActiveConductor != null) {
- Slog.wtf(TAG, "Attempt to start vibration when one already running");
- return false;
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runVibrationOnVibrationThread");
+ try {
+ synchronized (mLock) {
+ if (mRequestedActiveConductor != null) {
+ Slog.wtf(TAG, "Attempt to start vibration when one already running");
+ return false;
+ }
+ mRequestedActiveConductor = conductor;
+ mLock.notifyAll();
}
- mRequestedActiveConductor = conductor;
- mLock.notifyAll();
+ return true;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
- return true;
}
@Override
diff --git a/services/core/java/com/android/server/vibrator/VibratorController.java b/services/core/java/com/android/server/vibrator/VibratorController.java
index 4fc0b74..3c47850 100644
--- a/services/core/java/com/android/server/vibrator/VibratorController.java
+++ b/services/core/java/com/android/server/vibrator/VibratorController.java
@@ -23,6 +23,7 @@
import android.os.Parcel;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
+import android.os.Trace;
import android.os.VibrationEffect;
import android.os.VibratorInfo;
import android.os.vibrator.PrebakedSegment;
@@ -123,21 +124,26 @@
/** Reruns the query to the vibrator to load the {@link VibratorInfo}, if not yet successful. */
public void reloadVibratorInfoIfNeeded() {
- // Early check outside lock, for quick return.
- if (mVibratorInfoLoadSuccessful) {
- return;
- }
- synchronized (mLock) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#reloadVibratorInfoIfNeeded");
+ try {
+ // Early check outside lock, for quick return.
if (mVibratorInfoLoadSuccessful) {
return;
}
- int vibratorId = mVibratorInfo.getId();
- VibratorInfo.Builder vibratorInfoBuilder = new VibratorInfo.Builder(vibratorId);
- mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(vibratorInfoBuilder);
- mVibratorInfo = vibratorInfoBuilder.build();
- if (!mVibratorInfoLoadSuccessful) {
- Slog.e(TAG, "Failed retry of HAL getInfo for vibrator " + vibratorId);
+ synchronized (mLock) {
+ if (mVibratorInfoLoadSuccessful) {
+ return;
+ }
+ int vibratorId = mVibratorInfo.getId();
+ VibratorInfo.Builder vibratorInfoBuilder = new VibratorInfo.Builder(vibratorId);
+ mVibratorInfoLoadSuccessful = mNativeWrapper.getInfo(vibratorInfoBuilder);
+ mVibratorInfo = vibratorInfoBuilder.build();
+ if (!mVibratorInfoLoadSuccessful) {
+ Slog.e(TAG, "Failed retry of HAL getInfo for vibrator " + vibratorId);
+ }
}
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -193,8 +199,13 @@
/** Return {@code true} if the underlying vibrator is currently available, false otherwise. */
public boolean isAvailable() {
- synchronized (mLock) {
- return mNativeWrapper.isAvailable();
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#isAvailable");
+ try {
+ synchronized (mLock) {
+ return mNativeWrapper.isAvailable();
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -204,12 +215,17 @@
* <p>This will affect the state of {@link #isUnderExternalControl()}.
*/
public void setExternalControl(boolean externalControl) {
- if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
- return;
- }
- synchronized (mLock) {
- mIsUnderExternalControl = externalControl;
- mNativeWrapper.setExternalControl(externalControl);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "setExternalControl(" + externalControl + ")");
+ try {
+ if (!mVibratorInfo.hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) {
+ return;
+ }
+ synchronized (mLock) {
+ mIsUnderExternalControl = externalControl;
+ mNativeWrapper.setExternalControl(externalControl);
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -218,28 +234,38 @@
* if given {@code effect} is {@code null}.
*/
public void updateAlwaysOn(int id, @Nullable PrebakedSegment prebaked) {
- if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
- return;
- }
- synchronized (mLock) {
- if (prebaked == null) {
- mNativeWrapper.alwaysOnDisable(id);
- } else {
- mNativeWrapper.alwaysOnEnable(id, prebaked.getEffectId(),
- prebaked.getEffectStrength());
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#updateAlwaysOn");
+ try {
+ if (!mVibratorInfo.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
+ return;
}
+ synchronized (mLock) {
+ if (prebaked == null) {
+ mNativeWrapper.alwaysOnDisable(id);
+ } else {
+ mNativeWrapper.alwaysOnEnable(id, prebaked.getEffectId(),
+ prebaked.getEffectStrength());
+ }
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
/** Set the vibration amplitude. This will NOT affect the state of {@link #isVibrating()}. */
public void setAmplitude(float amplitude) {
- synchronized (mLock) {
- if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
- mNativeWrapper.setAmplitude(amplitude);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#setAmplitude");
+ try {
+ synchronized (mLock) {
+ if (mVibratorInfo.hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) {
+ mNativeWrapper.setAmplitude(amplitude);
+ }
+ if (mIsVibrating) {
+ mCurrentAmplitude = amplitude;
+ }
}
- if (mIsVibrating) {
- mCurrentAmplitude = amplitude;
- }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -253,13 +279,18 @@
* do not support the input or a negative number if the operation failed.
*/
public long on(long milliseconds, long vibrationId) {
- synchronized (mLock) {
- long duration = mNativeWrapper.on(milliseconds, vibrationId);
- if (duration > 0) {
- mCurrentAmplitude = -1;
- notifyListenerOnVibrating(true);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#on");
+ try {
+ synchronized (mLock) {
+ long duration = mNativeWrapper.on(milliseconds, vibrationId);
+ if (duration > 0) {
+ mCurrentAmplitude = -1;
+ notifyListenerOnVibrating(true);
+ }
+ return duration;
}
- return duration;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -273,6 +304,7 @@
* do not support the input or a negative number if the operation failed.
*/
public long on(VibrationEffect.VendorEffect vendorEffect, long vibrationId) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#on (vendor)");
synchronized (mLock) {
Parcel vendorData = Parcel.obtain();
try {
@@ -288,6 +320,7 @@
return duration;
} finally {
vendorData.recycle();
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
}
@@ -302,14 +335,19 @@
* do not support the input or a negative number if the operation failed.
*/
public long on(PrebakedSegment prebaked, long vibrationId) {
- synchronized (mLock) {
- long duration = mNativeWrapper.perform(prebaked.getEffectId(),
- prebaked.getEffectStrength(), vibrationId);
- if (duration > 0) {
- mCurrentAmplitude = -1;
- notifyListenerOnVibrating(true);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#on (Prebaked)");
+ try {
+ synchronized (mLock) {
+ long duration = mNativeWrapper.perform(prebaked.getEffectId(),
+ prebaked.getEffectStrength(), vibrationId);
+ if (duration > 0) {
+ mCurrentAmplitude = -1;
+ notifyListenerOnVibrating(true);
+ }
+ return duration;
}
- return duration;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -323,16 +361,21 @@
* do not support the input or a negative number if the operation failed.
*/
public long on(PrimitiveSegment[] primitives, long vibrationId) {
- if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
- return 0;
- }
- synchronized (mLock) {
- long duration = mNativeWrapper.compose(primitives, vibrationId);
- if (duration > 0) {
- mCurrentAmplitude = -1;
- notifyListenerOnVibrating(true);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#on (Primitive)");
+ try {
+ if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) {
+ return 0;
}
- return duration;
+ synchronized (mLock) {
+ long duration = mNativeWrapper.compose(primitives, vibrationId);
+ if (duration > 0) {
+ mCurrentAmplitude = -1;
+ notifyListenerOnVibrating(true);
+ }
+ return duration;
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -345,17 +388,22 @@
* @return The duration of the effect playing, or 0 if unsupported.
*/
public long on(RampSegment[] primitives, long vibrationId) {
- if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
- return 0;
- }
- synchronized (mLock) {
- int braking = mVibratorInfo.getDefaultBraking();
- long duration = mNativeWrapper.composePwle(primitives, braking, vibrationId);
- if (duration > 0) {
- mCurrentAmplitude = -1;
- notifyListenerOnVibrating(true);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#on (PWLE)");
+ try {
+ if (!mVibratorInfo.hasCapability(IVibrator.CAP_COMPOSE_PWLE_EFFECTS)) {
+ return 0;
}
- return duration;
+ synchronized (mLock) {
+ int braking = mVibratorInfo.getDefaultBraking();
+ long duration = mNativeWrapper.composePwle(primitives, braking, vibrationId);
+ if (duration > 0) {
+ mCurrentAmplitude = -1;
+ notifyListenerOnVibrating(true);
+ }
+ return duration;
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -365,10 +413,15 @@
* <p>This will affect the state of {@link #isVibrating()}.
*/
public void off() {
- synchronized (mLock) {
- mNativeWrapper.off();
- mCurrentAmplitude = 0;
- notifyListenerOnVibrating(false);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorController#off");
+ try {
+ synchronized (mLock) {
+ mNativeWrapper.off();
+ mCurrentAmplitude = 0;
+ notifyListenerOnVibrating(false);
+ }
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 799934a..899f0b1 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -462,20 +462,31 @@
@Override // Binder call
public void performHapticFeedback(int uid, int deviceId, String opPkg, int constant,
String reason, int flags, int privFlags) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "performHapticFeedback");
// Note that the `performHapticFeedback` method does not take a token argument from the
// caller, and instead, uses this service as the token. This is to mitigate performance
// impact that would otherwise be caused due to marshal latency. Haptic feedback effects are
// short-lived, so we don't need to cancel when the process dies.
- performHapticFeedbackInternal(uid, deviceId, opPkg, constant, reason, /* token= */
- this, flags, privFlags);
+ try {
+ performHapticFeedbackInternal(uid, deviceId, opPkg, constant, reason, /* token= */
+ this, flags, privFlags);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
}
@Override // Binder call
public void performHapticFeedbackForInputDevice(int uid, int deviceId, String opPkg,
int constant, int inputDeviceId, int inputSource, String reason, int flags,
int privFlags) {
- performHapticFeedbackForInputDeviceInternal(uid, deviceId, opPkg, constant, inputDeviceId,
- inputSource, reason, /* token= */ this, flags, privFlags);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "performHapticFeedbackForInputDevice");
+ try {
+ performHapticFeedbackForInputDeviceInternal(uid, deviceId, opPkg, constant,
+ inputDeviceId,
+ inputSource, reason, /* token= */ this, flags, privFlags);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
}
/**
@@ -919,30 +930,25 @@
@GuardedBy("mLock")
@Nullable
private Vibration.EndInfo startVibrationOnThreadLocked(VibrationStepConductor conductor) {
- Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationThreadLocked");
- try {
- HalVibration vib = conductor.getVibration();
- int mode = startAppOpModeLocked(vib.callerInfo);
- switch (mode) {
- case AppOpsManager.MODE_ALLOWED:
- Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
- // Make sure mCurrentVibration is set while triggering the VibrationThread.
- mCurrentVibration = conductor;
- if (!mVibrationThread.runVibrationOnVibrationThread(mCurrentVibration)) {
- // Shouldn't happen. The method call already logs a wtf.
- mCurrentVibration = null; // Aborted.
- return new Vibration.EndInfo(Status.IGNORED_ERROR_SCHEDULING);
- }
- return null;
- case AppOpsManager.MODE_ERRORED:
- Slog.w(TAG, "Start AppOpsManager operation errored for uid "
- + vib.callerInfo.uid);
- return new Vibration.EndInfo(Status.IGNORED_ERROR_APP_OPS);
- default:
- return new Vibration.EndInfo(Status.IGNORED_APP_OPS);
- }
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ HalVibration vib = conductor.getVibration();
+ int mode = startAppOpModeLocked(vib.callerInfo);
+ switch (mode) {
+ case AppOpsManager.MODE_ALLOWED:
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
+ // Make sure mCurrentVibration is set while triggering the VibrationThread.
+ mCurrentVibration = conductor;
+ if (!mVibrationThread.runVibrationOnVibrationThread(mCurrentVibration)) {
+ // Shouldn't happen. The method call already logs a wtf.
+ mCurrentVibration = null; // Aborted.
+ return new Vibration.EndInfo(Status.IGNORED_ERROR_SCHEDULING);
+ }
+ return null;
+ case AppOpsManager.MODE_ERRORED:
+ Slog.w(TAG, "Start AppOpsManager operation errored for uid "
+ + vib.callerInfo.uid);
+ return new Vibration.EndInfo(Status.IGNORED_ERROR_APP_OPS);
+ default:
+ return new Vibration.EndInfo(Status.IGNORED_APP_OPS);
}
}
@@ -1050,21 +1056,16 @@
@GuardedBy("mLock")
private void reportFinishedVibrationLocked(Vibration.EndInfo vibrationEndInfo) {
- Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "reportFinishVibrationLocked");
Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0);
- try {
- HalVibration vib = mCurrentVibration.getVibration();
- if (DEBUG) {
- Slog.d(TAG, "Reporting vibration " + vib.id + " finished with "
- + vibrationEndInfo);
- }
- // DO NOT write metrics at this point, wait for the VibrationThread to report the
- // vibration was released, after all cleanup. The metrics will be reported then.
- endVibrationLocked(vib, vibrationEndInfo, /* shouldWriteStats= */ false);
- finishAppOpModeLocked(vib.callerInfo);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ HalVibration vib = mCurrentVibration.getVibration();
+ if (DEBUG) {
+ Slog.d(TAG, "Reporting vibration " + vib.id + " finished with "
+ + vibrationEndInfo);
}
+ // DO NOT write metrics at this point, wait for the VibrationThread to report the
+ // vibration was released, after all cleanup. The metrics will be reported then.
+ endVibrationLocked(vib, vibrationEndInfo, /* shouldWriteStats= */ false);
+ finishAppOpModeLocked(vib.callerInfo);
}
private void onSyncedVibrationComplete(long vibrationId) {
@@ -1418,40 +1419,34 @@
@GuardedBy("mLock")
@Nullable
- private SparseArray<PrebakedSegment> fixupAlwaysOnEffectsLocked(
- CombinedVibration effect) {
- Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "fixupAlwaysOnEffectsLocked");
- try {
- SparseArray<VibrationEffect> effects;
- if (effect instanceof CombinedVibration.Mono) {
- VibrationEffect syncedEffect = ((CombinedVibration.Mono) effect).getEffect();
- effects = transformAllVibratorsLocked(unused -> syncedEffect);
- } else if (effect instanceof CombinedVibration.Stereo) {
- effects = ((CombinedVibration.Stereo) effect).getEffects();
- } else {
- // Only synced combinations can be used for always-on effects.
- return null;
- }
- SparseArray<PrebakedSegment> result = new SparseArray<>();
- for (int i = 0; i < effects.size(); i++) {
- PrebakedSegment prebaked = extractPrebakedSegment(effects.valueAt(i));
- if (prebaked == null) {
- Slog.e(TAG, "Only prebaked effects supported for always-on.");
- return null;
- }
- int vibratorId = effects.keyAt(i);
- VibratorController vibrator = mVibrators.get(vibratorId);
- if (vibrator != null && vibrator.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
- result.put(vibratorId, prebaked);
- }
- }
- if (result.size() == 0) {
- return null;
- }
- return result;
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ private SparseArray<PrebakedSegment> fixupAlwaysOnEffectsLocked(CombinedVibration effect) {
+ SparseArray<VibrationEffect> effects;
+ if (effect instanceof CombinedVibration.Mono) {
+ VibrationEffect syncedEffect = ((CombinedVibration.Mono) effect).getEffect();
+ effects = transformAllVibratorsLocked(unused -> syncedEffect);
+ } else if (effect instanceof CombinedVibration.Stereo) {
+ effects = ((CombinedVibration.Stereo) effect).getEffects();
+ } else {
+ // Only synced combinations can be used for always-on effects.
+ return null;
}
+ SparseArray<PrebakedSegment> result = new SparseArray<>();
+ for (int i = 0; i < effects.size(); i++) {
+ PrebakedSegment prebaked = extractPrebakedSegment(effects.valueAt(i));
+ if (prebaked == null) {
+ Slog.e(TAG, "Only prebaked effects supported for always-on.");
+ return null;
+ }
+ int vibratorId = effects.keyAt(i);
+ VibratorController vibrator = mVibrators.get(vibratorId);
+ if (vibrator != null && vibrator.hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) {
+ result.put(vibratorId, prebaked);
+ }
+ }
+ if (result.size() == 0) {
+ return null;
+ }
+ return result;
}
@Nullable
@@ -1580,25 +1575,42 @@
@Override
public boolean prepareSyncedVibration(long requiredCapabilities, int[] vibratorIds) {
- if ((mCapabilities & requiredCapabilities) != requiredCapabilities) {
- // This sync step requires capabilities this device doesn't have, skipping sync...
- return false;
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "prepareSyncedVibration");
+ try {
+ if ((mCapabilities & requiredCapabilities) != requiredCapabilities) {
+ // This sync step requires capabilities this device doesn't have, skipping
+ // sync...
+ return false;
+ }
+ return mNativeWrapper.prepareSynced(vibratorIds);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
- return mNativeWrapper.prepareSynced(vibratorIds);
}
@Override
public boolean triggerSyncedVibration(long vibrationId) {
- return mNativeWrapper.triggerSynced(vibrationId);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "triggerSyncedVibration");
+ try {
+ return mNativeWrapper.triggerSynced(vibrationId);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
}
@Override
public void cancelSyncedVibration() {
- mNativeWrapper.cancelSynced();
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "cancelSyncedVibration");
+ try {
+ mNativeWrapper.cancelSynced();
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ }
}
@Override
public void noteVibratorOn(int uid, long duration) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "noteVibratorOn");
try {
if (duration <= 0) {
// Tried to turn vibrator ON and got:
@@ -1616,16 +1628,21 @@
mFrameworkStatsLogger.writeVibratorStateOnAsync(uid, duration);
} catch (RemoteException e) {
Slog.e(TAG, "Error logging VibratorStateChanged to ON", e);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@Override
public void noteVibratorOff(int uid) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "noteVibratorOff");
try {
mBatteryStatsService.noteVibratorOff(uid);
mFrameworkStatsLogger.writeVibratorStateOffAsync(uid);
} catch (RemoteException e) {
Slog.e(TAG, "Error logging VibratorStateChanged to OFF", e);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -1634,11 +1651,16 @@
if (DEBUG) {
Slog.d(TAG, "Vibration " + vibrationId + " finished with " + vibrationEndInfo);
}
- synchronized (mLock) {
- if (mCurrentVibration != null
- && mCurrentVibration.getVibration().id == vibrationId) {
- reportFinishedVibrationLocked(vibrationEndInfo);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "onVibrationCompleted");
+ try {
+ synchronized (mLock) {
+ if (mCurrentVibration != null
+ && mCurrentVibration.getVibration().id == vibrationId) {
+ reportFinishedVibrationLocked(vibrationEndInfo);
+ }
}
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@@ -1647,34 +1669,40 @@
if (DEBUG) {
Slog.d(TAG, "VibrationThread released after finished vibration");
}
- synchronized (mLock) {
- if (DEBUG) {
- Slog.d(TAG, "Processing VibrationThread released callback");
- }
- if (Build.IS_DEBUGGABLE && mCurrentVibration != null
- && mCurrentVibration.getVibration().id != vibrationId) {
- Slog.wtf(TAG, TextUtils.formatSimple(
- "VibrationId mismatch on release. expected=%d, released=%d",
- mCurrentVibration.getVibration().id, vibrationId));
- }
- if (mCurrentVibration != null) {
- // This is when we consider the current vibration complete, so report metrics.
- mFrameworkStatsLogger.writeVibrationReportedAsync(
- mCurrentVibration.getVibration().getStatsInfo(
- /* completionUptimeMillis= */ SystemClock.uptimeMillis()));
- mCurrentVibration = null;
- }
- if (mNextVibration != null) {
- VibrationStepConductor nextConductor = mNextVibration;
- mNextVibration = null;
- Vibration.EndInfo vibrationEndInfo = startVibrationOnThreadLocked(
- nextConductor);
- if (vibrationEndInfo != null) {
- // Failed to start the vibration, end it and report metrics right away.
- endVibrationLocked(nextConductor.getVibration(),
- vibrationEndInfo, /* shouldWriteStats= */ true);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "onVibrationThreadReleased: " + vibrationId);
+ try {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "Processing VibrationThread released callback");
+ }
+ if (Build.IS_DEBUGGABLE && mCurrentVibration != null
+ && mCurrentVibration.getVibration().id != vibrationId) {
+ Slog.wtf(TAG, TextUtils.formatSimple(
+ "VibrationId mismatch on release. expected=%d, released=%d",
+ mCurrentVibration.getVibration().id, vibrationId));
+ }
+ if (mCurrentVibration != null) {
+ // This is when we consider the current vibration complete, so report
+ // metrics.
+ mFrameworkStatsLogger.writeVibrationReportedAsync(
+ mCurrentVibration.getVibration().getStatsInfo(
+ /* completionUptimeMillis= */ SystemClock.uptimeMillis()));
+ mCurrentVibration = null;
+ }
+ if (mNextVibration != null) {
+ VibrationStepConductor nextConductor = mNextVibration;
+ mNextVibration = null;
+ Vibration.EndInfo vibrationEndInfo = startVibrationOnThreadLocked(
+ nextConductor);
+ if (vibrationEndInfo != null) {
+ // Failed to start the vibration, end it and report metrics right away.
+ endVibrationLocked(nextConductor.getVibration(),
+ vibrationEndInfo, /* shouldWriteStats= */ true);
+ }
}
}
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
}
@@ -1917,22 +1945,17 @@
@GuardedBy("mLock")
private void endExternalVibrateLocked(Vibration.EndInfo vibrationEndInfo,
boolean continueExternalControl) {
- Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "endExternalVibrateLocked");
- try {
- if (mCurrentExternalVibration == null) {
- return;
- }
- mCurrentExternalVibration.unlinkToDeath();
- if (!continueExternalControl) {
- setExternalControl(false, mCurrentExternalVibration.stats);
- }
- // The external control was turned off, end it and report metrics right away.
- endVibrationLocked(mCurrentExternalVibration, vibrationEndInfo,
- /* shouldWriteStats= */ true);
- mCurrentExternalVibration = null;
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
+ if (mCurrentExternalVibration == null) {
+ return;
}
+ mCurrentExternalVibration.unlinkToDeath();
+ if (!continueExternalControl) {
+ setExternalControl(false, mCurrentExternalVibration.stats);
+ }
+ // The external control was turned off, end it and report metrics right away.
+ endVibrationLocked(mCurrentExternalVibration, vibrationEndInfo,
+ /* shouldWriteStats= */ true);
+ mCurrentExternalVibration = null;
}
private HapticFeedbackVibrationProvider getHapticVibrationProvider() {
@@ -1987,143 +2010,160 @@
@Override
public ExternalVibrationScale onExternalVibrationStart(ExternalVibration vib) {
- // Create Vibration.Stats as close to the received request as possible, for tracking.
- ExternalVibrationSession externalVibration = new ExternalVibrationSession(vib);
- // Mute the request until we run all the checks and accept the vibration.
- externalVibration.muteScale();
- boolean alreadyUnderExternalControl = false;
- boolean waitForCompletion = false;
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "onExternalVibrationStart");
+ try {
+ // Create Vibration.Stats as close to the received request as possible, for
+ // tracking.
+ ExternalVibrationSession externalVibration = new ExternalVibrationSession(vib);
+ // Mute the request until we run all the checks and accept the vibration.
+ externalVibration.muteScale();
+ boolean alreadyUnderExternalControl = false;
+ boolean waitForCompletion = false;
- synchronized (mLock) {
- if (!hasExternalControlCapability()) {
- endVibrationLocked(externalVibration,
- new Vibration.EndInfo(Status.IGNORED_UNSUPPORTED),
- /* shouldWriteStats= */ true);
- return externalVibration.getScale();
- }
+ synchronized (mLock) {
+ if (!hasExternalControlCapability()) {
+ endVibrationLocked(externalVibration,
+ new Vibration.EndInfo(Status.IGNORED_UNSUPPORTED),
+ /* shouldWriteStats= */ true);
+ return externalVibration.getScale();
+ }
- if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE,
- vib.getUid(), -1 /*owningUid*/, true /*exported*/)
- != PackageManager.PERMISSION_GRANTED) {
- Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
- + " tried to play externally controlled vibration"
- + " without VIBRATE permission, ignoring.");
- endVibrationLocked(externalVibration,
- new Vibration.EndInfo(Status.IGNORED_MISSING_PERMISSION),
- /* shouldWriteStats= */ true);
- return externalVibration.getScale();
- }
+ if (ActivityManager.checkComponentPermission(
+ android.Manifest.permission.VIBRATE,
+ vib.getUid(), -1 /*owningUid*/, true /*exported*/)
+ != PackageManager.PERMISSION_GRANTED) {
+ Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid()
+ + " tried to play externally controlled vibration"
+ + " without VIBRATE permission, ignoring.");
+ endVibrationLocked(externalVibration,
+ new Vibration.EndInfo(Status.IGNORED_MISSING_PERMISSION),
+ /* shouldWriteStats= */ true);
+ return externalVibration.getScale();
+ }
- Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(
- externalVibration.callerInfo);
+ Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(
+ externalVibration.callerInfo);
- if (vibrationEndInfo == null
- && mCurrentExternalVibration != null
- && mCurrentExternalVibration.isHoldingSameVibration(vib)) {
- // We are already playing this external vibration, so we can return the same
- // scale calculated in the previous call to this method.
- return mCurrentExternalVibration.getScale();
- }
+ if (vibrationEndInfo == null
+ && mCurrentExternalVibration != null
+ && mCurrentExternalVibration.isHoldingSameVibration(vib)) {
+ // We are already playing this external vibration, so we can return the same
+ // scale calculated in the previous call to this method.
+ return mCurrentExternalVibration.getScale();
+ }
- if (vibrationEndInfo == null) {
- // Check if ongoing vibration is more important than this vibration.
- vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(externalVibration);
- }
+ if (vibrationEndInfo == null) {
+ // Check if ongoing vibration is more important than this vibration.
+ vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(externalVibration);
+ }
- if (vibrationEndInfo != null) {
- endVibrationLocked(externalVibration, vibrationEndInfo,
- /* shouldWriteStats= */ true);
- return externalVibration.getScale();
- }
+ if (vibrationEndInfo != null) {
+ endVibrationLocked(externalVibration, vibrationEndInfo,
+ /* shouldWriteStats= */ true);
+ return externalVibration.getScale();
+ }
- if (mCurrentExternalVibration == null) {
- // If we're not under external control right now, then cancel any normal
- // vibration that may be playing and ready the vibrator for external control.
- if (mCurrentVibration != null) {
+ if (mCurrentExternalVibration == null) {
+ // If we're not under external control right now, then cancel any normal
+ // vibration that may be playing and ready the vibrator for external
+ // control.
+ if (mCurrentVibration != null) {
+ externalVibration.stats.reportInterruptedAnotherVibration(
+ mCurrentVibration.getVibration().callerInfo);
+ clearNextVibrationLocked(
+ new Vibration.EndInfo(Status.IGNORED_FOR_EXTERNAL,
+ externalVibration.callerInfo));
+ mCurrentVibration.notifyCancelled(
+ new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED,
+ externalVibration.callerInfo),
+ /* immediate= */ true);
+ waitForCompletion = true;
+ }
+ } else {
+ // At this point we have an externally controlled vibration playing already.
+ // Since the interface defines that only one externally controlled
+ // vibration can
+ // play at a time, we need to first mute the ongoing vibration and then
+ // return
+ // a scale from this function for the new one, so we can be assured that the
+ // ongoing will be muted in favor of the new vibration.
+ //
+ // Note that this doesn't support multiple concurrent external controls,
+ // as we would need to mute the old one still if it came from a different
+ // controller.
+ alreadyUnderExternalControl = true;
+ mCurrentExternalVibration.notifyEnded();
externalVibration.stats.reportInterruptedAnotherVibration(
- mCurrentVibration.getVibration().callerInfo);
- clearNextVibrationLocked(
- new Vibration.EndInfo(Status.IGNORED_FOR_EXTERNAL,
- externalVibration.callerInfo));
- mCurrentVibration.notifyCancelled(
+ mCurrentExternalVibration.callerInfo);
+ endExternalVibrateLocked(
new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED,
externalVibration.callerInfo),
- /* immediate= */ true);
- waitForCompletion = true;
+ /* continueExternalControl= */ true);
}
- } else {
- // At this point we have an externally controlled vibration playing already.
- // Since the interface defines that only one externally controlled vibration can
- // play at a time, we need to first mute the ongoing vibration and then return
- // a scale from this function for the new one, so we can be assured that the
- // ongoing will be muted in favor of the new vibration.
- //
- // Note that this doesn't support multiple concurrent external controls, as we
- // would need to mute the old one still if it came from a different controller.
- alreadyUnderExternalControl = true;
- mCurrentExternalVibration.notifyEnded();
- externalVibration.stats.reportInterruptedAnotherVibration(
- mCurrentExternalVibration.callerInfo);
- endExternalVibrateLocked(
- new Vibration.EndInfo(Status.CANCELLED_SUPERSEDED,
- externalVibration.callerInfo),
- /* continueExternalControl= */ true);
- }
- VibrationAttributes attrs = fixupVibrationAttributes(vib.getVibrationAttributes(),
- /* effect= */ null);
- if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
- // Force update of user settings before checking if this vibration effect should
- // be ignored or scaled.
- mVibrationSettings.update();
- }
-
- mCurrentExternalVibration = externalVibration;
- externalVibration.linkToDeath(this::onExternalVibrationBinderDied);
- externalVibration.scale(mVibrationScaler, attrs.getUsage());
- }
-
- if (waitForCompletion) {
- if (!mVibrationThread.waitForThreadIdle(VIBRATION_CANCEL_WAIT_MILLIS)) {
- Slog.e(TAG, "Timed out waiting for vibration to cancel");
- synchronized (mLock) {
- // Trigger endExternalVibrateLocked to unlink to death recipient.
- endExternalVibrateLocked(
- new Vibration.EndInfo(Status.IGNORED_ERROR_CANCELLING),
- /* continueExternalControl= */ false);
- // Mute the request, vibration will be ignored.
- externalVibration.muteScale();
+ VibrationAttributes attrs = fixupVibrationAttributes(
+ vib.getVibrationAttributes(),
+ /* effect= */ null);
+ if (attrs.isFlagSet(VibrationAttributes.FLAG_INVALIDATE_SETTINGS_CACHE)) {
+ // Force update of user settings before checking if this vibration effect
+ // should be ignored or scaled.
+ mVibrationSettings.update();
}
- return externalVibration.getScale();
+
+ mCurrentExternalVibration = externalVibration;
+ externalVibration.linkToDeath(this::onExternalVibrationBinderDied);
+ externalVibration.scale(mVibrationScaler, attrs.getUsage());
}
- }
- if (!alreadyUnderExternalControl) {
+
+ if (waitForCompletion) {
+ if (!mVibrationThread.waitForThreadIdle(VIBRATION_CANCEL_WAIT_MILLIS)) {
+ Slog.e(TAG, "Timed out waiting for vibration to cancel");
+ synchronized (mLock) {
+ // Trigger endExternalVibrateLocked to unlink to death recipient.
+ endExternalVibrateLocked(
+ new Vibration.EndInfo(Status.IGNORED_ERROR_CANCELLING),
+ /* continueExternalControl= */ false);
+ // Mute the request, vibration will be ignored.
+ externalVibration.muteScale();
+ }
+ return externalVibration.getScale();
+ }
+ }
+ if (!alreadyUnderExternalControl) {
+ if (DEBUG) {
+ Slog.d(TAG, "Vibrator going under external control.");
+ }
+ setExternalControl(true, externalVibration.stats);
+ }
if (DEBUG) {
- Slog.d(TAG, "Vibrator going under external control.");
+ Slog.d(TAG, "Playing external vibration: " + vib);
}
- setExternalControl(true, externalVibration.stats);
+ // Vibrator will start receiving data from external channels after this point.
+ // Report current time as the vibration start time, for debugging.
+ externalVibration.stats.reportStarted();
+ return externalVibration.getScale();
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
- if (DEBUG) {
- Slog.d(TAG, "Playing external vibration: " + vib);
- }
- // Vibrator will start receiving data from external channels after this point.
- // Report current time as the vibration start time, for debugging.
- externalVibration.stats.reportStarted();
- return externalVibration.getScale();
}
@Override
public void onExternalVibrationStop(ExternalVibration vib) {
- synchronized (mLock) {
- if (mCurrentExternalVibration != null
- && mCurrentExternalVibration.isHoldingSameVibration(vib)) {
- if (DEBUG) {
- Slog.d(TAG, "Stopping external vibration: " + vib);
+ Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "onExternalVibrationStop");
+ try {
+ synchronized (mLock) {
+ if (mCurrentExternalVibration != null
+ && mCurrentExternalVibration.isHoldingSameVibration(vib)) {
+ if (DEBUG) {
+ Slog.d(TAG, "Stopping external vibration: " + vib);
+ }
+ endExternalVibrateLocked(
+ new Vibration.EndInfo(Status.FINISHED),
+ /* continueExternalControl= */ false);
}
- endExternalVibrateLocked(
- new Vibration.EndInfo(Status.FINISHED),
- /* continueExternalControl= */ false);
}
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}