1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server; 18 19 import static android.os.VibrationEffect.Composition.PrimitiveEffect; 20 21 import android.annotation.Nullable; 22 import android.app.ActivityManager; 23 import android.app.AppOpsManager; 24 import android.app.IUidObserver; 25 import android.content.BroadcastReceiver; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.content.pm.PackageManager; 30 import android.content.pm.PackageManagerInternal; 31 import android.content.res.Resources; 32 import android.database.ContentObserver; 33 import android.hardware.input.InputManager; 34 import android.hardware.vibrator.IVibrator; 35 import android.hardware.vibrator.V1_0.EffectStrength; 36 import android.icu.text.DateFormat; 37 import android.media.AudioManager; 38 import android.os.BatteryStats; 39 import android.os.Binder; 40 import android.os.ExternalVibration; 41 import android.os.Handler; 42 import android.os.IBinder; 43 import android.os.IExternalVibratorService; 44 import android.os.IVibratorService; 45 import android.os.IVibratorStateListener; 46 import android.os.PowerManager; 47 import android.os.PowerManager.ServiceType; 48 import android.os.PowerManagerInternal; 49 import android.os.PowerSaveState; 50 import android.os.Process; 51 import android.os.RemoteCallbackList; 52 import android.os.RemoteException; 53 import android.os.ResultReceiver; 54 import android.os.ServiceManager; 55 import android.os.ShellCallback; 56 import android.os.ShellCommand; 57 import android.os.SystemClock; 58 import android.os.Trace; 59 import android.os.UserHandle; 60 import android.os.VibrationAttributes; 61 import android.os.VibrationEffect; 62 import android.os.Vibrator; 63 import android.os.WorkSource; 64 import android.provider.Settings; 65 import android.provider.Settings.SettingNotFoundException; 66 import android.util.DebugUtils; 67 import android.util.Slog; 68 import android.util.SparseArray; 69 import android.util.proto.ProtoOutputStream; 70 import android.view.InputDevice; 71 72 import com.android.internal.annotations.GuardedBy; 73 import com.android.internal.app.IBatteryStats; 74 import com.android.internal.util.DumpUtils; 75 import com.android.internal.util.FrameworkStatsLog; 76 77 import java.io.FileDescriptor; 78 import java.io.PrintWriter; 79 import java.util.ArrayList; 80 import java.util.Arrays; 81 import java.util.Date; 82 import java.util.LinkedList; 83 import java.util.List; 84 85 public class VibratorService extends IVibratorService.Stub 86 implements InputManager.InputDeviceListener { 87 private static final String TAG = "VibratorService"; 88 private static final boolean DEBUG = false; 89 private static final String EXTERNAL_VIBRATOR_SERVICE = "external_vibrator_service"; 90 91 private static final long[] DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS = { 0, 30, 100, 30 }; 92 93 // Scale levels. Each level, except MUTE, is defined as the delta between the current setting 94 // and the default intensity for that type of vibration (i.e. current - default). 95 private static final int SCALE_MUTE = IExternalVibratorService.SCALE_MUTE; // -100 96 private static final int SCALE_VERY_LOW = IExternalVibratorService.SCALE_VERY_LOW; // -2 97 private static final int SCALE_LOW = IExternalVibratorService.SCALE_LOW; // -1 98 private static final int SCALE_NONE = IExternalVibratorService.SCALE_NONE; // 0 99 private static final int SCALE_HIGH = IExternalVibratorService.SCALE_HIGH; // 1 100 private static final int SCALE_VERY_HIGH = IExternalVibratorService.SCALE_VERY_HIGH; // 2 101 102 // Gamma adjustments for scale levels. 103 private static final float SCALE_VERY_LOW_GAMMA = 2.0f; 104 private static final float SCALE_LOW_GAMMA = 1.5f; 105 private static final float SCALE_NONE_GAMMA = 1.0f; 106 private static final float SCALE_HIGH_GAMMA = 0.5f; 107 private static final float SCALE_VERY_HIGH_GAMMA = 0.25f; 108 109 // Max amplitudes for scale levels. If one is not listed, then the max amplitude is the default 110 // max amplitude. 111 private static final int SCALE_VERY_LOW_MAX_AMPLITUDE = 168; // 2/3 * 255 112 private static final int SCALE_LOW_MAX_AMPLITUDE = 192; // 3/4 * 255 113 114 // Default vibration attributes. Used when vibration is requested without attributes 115 private static final VibrationAttributes DEFAULT_ATTRIBUTES = 116 new VibrationAttributes.Builder().build(); 117 118 // If HAL supports callbacks set the timeout to ASYNC_TIMEOUT_MULTIPLIER * duration. 119 private static final long ASYNC_TIMEOUT_MULTIPLIER = 2; 120 121 122 // A mapping from the intensity adjustment to the scaling to apply, where the intensity 123 // adjustment is defined as the delta between the default intensity level and the user selected 124 // intensity level. It's important that we apply the scaling on the delta between the two so 125 // that the default intensity level applies no scaling to application provided effects. 126 private final SparseArray<ScaleLevel> mScaleLevels; 127 private final LinkedList<VibrationInfo> mPreviousRingVibrations; 128 private final LinkedList<VibrationInfo> mPreviousNotificationVibrations; 129 private final LinkedList<VibrationInfo> mPreviousAlarmVibrations; 130 private final LinkedList<ExternalVibration> mPreviousExternalVibrations; 131 private final LinkedList<VibrationInfo> mPreviousVibrations; 132 private final int mPreviousVibrationsLimit; 133 private final boolean mAllowPriorityVibrationsInLowPowerMode; 134 private final boolean mSupportsAmplitudeControl; 135 private final boolean mSupportsExternalControl; 136 private final List<Integer> mSupportedEffects; 137 private final long mCapabilities; 138 private final int mDefaultVibrationAmplitude; 139 private final SparseArray<VibrationEffect> mFallbackEffects; 140 private final SparseArray<Integer> mProcStatesCache = new SparseArray<>(); 141 private final WorkSource mTmpWorkSource = new WorkSource(); 142 private final Handler mH = new Handler(); 143 private final Object mLock = new Object(); 144 145 private final Context mContext; 146 private final PowerManager.WakeLock mWakeLock; 147 private final AppOpsManager mAppOps; 148 private final IBatteryStats mBatteryStatsService; 149 private final String mSystemUiPackage; 150 private PowerManagerInternal mPowerManagerInternal; 151 private InputManager mIm; 152 private Vibrator mVibrator; 153 private SettingsObserver mSettingObserver; 154 155 private volatile VibrateThread mThread; 156 157 // mInputDeviceVibrators lock should be acquired after mLock, if both are 158 // to be acquired 159 private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<>(); 160 private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 161 private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 162 163 @GuardedBy("mLock") 164 private Vibration mCurrentVibration; 165 private int mCurVibUid = -1; 166 private ExternalVibration mCurrentExternalVibration; 167 private boolean mVibratorUnderExternalControl; 168 private boolean mLowPowerMode; 169 @GuardedBy("mLock") 170 private boolean mIsVibrating; 171 @GuardedBy("mLock") 172 private final RemoteCallbackList<IVibratorStateListener> mVibratorStateListeners = 173 new RemoteCallbackList<>(); 174 private int mHapticFeedbackIntensity; 175 private int mNotificationIntensity; 176 private int mRingIntensity; 177 private SparseArray<Vibration> mAlwaysOnEffects = new SparseArray<>(); 178 vibratorExists()179 static native boolean vibratorExists(); vibratorInit()180 static native void vibratorInit(); vibratorOn(long milliseconds)181 static native void vibratorOn(long milliseconds); vibratorOff()182 static native void vibratorOff(); vibratorSupportsAmplitudeControl()183 static native boolean vibratorSupportsAmplitudeControl(); vibratorSetAmplitude(int amplitude)184 static native void vibratorSetAmplitude(int amplitude); vibratorGetSupportedEffects()185 static native int[] vibratorGetSupportedEffects(); vibratorPerformEffect(long effect, long strength, Vibration vibration, boolean withCallback)186 static native long vibratorPerformEffect(long effect, long strength, Vibration vibration, 187 boolean withCallback); vibratorPerformComposedEffect( VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration)188 static native void vibratorPerformComposedEffect( 189 VibrationEffect.Composition.PrimitiveEffect[] effect, Vibration vibration); vibratorSupportsExternalControl()190 static native boolean vibratorSupportsExternalControl(); vibratorSetExternalControl(boolean enabled)191 static native void vibratorSetExternalControl(boolean enabled); vibratorGetCapabilities()192 static native long vibratorGetCapabilities(); vibratorAlwaysOnEnable(long id, long effect, long strength)193 static native void vibratorAlwaysOnEnable(long id, long effect, long strength); vibratorAlwaysOnDisable(long id)194 static native void vibratorAlwaysOnDisable(long id); 195 196 private final IUidObserver mUidObserver = new IUidObserver.Stub() { 197 @Override public void onUidStateChanged(int uid, int procState, long procStateSeq, 198 int capability) { 199 mProcStatesCache.put(uid, procState); 200 } 201 202 @Override public void onUidGone(int uid, boolean disabled) { 203 mProcStatesCache.delete(uid); 204 } 205 206 @Override public void onUidActive(int uid) { 207 } 208 209 @Override public void onUidIdle(int uid, boolean disabled) { 210 } 211 212 @Override public void onUidCachedChanged(int uid, boolean cached) { 213 } 214 }; 215 216 private class Vibration implements IBinder.DeathRecipient { 217 public final IBinder token; 218 // Start time in CLOCK_BOOTTIME base. 219 public final long startTime; 220 // Start time in unix epoch time. Only to be used for debugging purposes and to correlate 221 // with other system events, any duration calculations should be done use startTime so as 222 // not to be affected by discontinuities created by RTC adjustments. 223 public final long startTimeDebug; 224 public final VibrationAttributes attrs; 225 public final int uid; 226 public final String opPkg; 227 public final String reason; 228 229 // The actual effect to be played. 230 public VibrationEffect effect; 231 // The original effect that was requested. This is non-null only when the original effect 232 // differs from the effect that's being played. Typically these two things differ because 233 // the effect was scaled based on the users vibration intensity settings. 234 public VibrationEffect originalEffect; 235 Vibration(IBinder token, VibrationEffect effect, VibrationAttributes attrs, int uid, String opPkg, String reason)236 private Vibration(IBinder token, VibrationEffect effect, 237 VibrationAttributes attrs, int uid, String opPkg, String reason) { 238 this.token = token; 239 this.effect = effect; 240 this.startTime = SystemClock.elapsedRealtime(); 241 this.startTimeDebug = System.currentTimeMillis(); 242 this.attrs = attrs; 243 this.uid = uid; 244 this.opPkg = opPkg; 245 this.reason = reason; 246 } 247 binderDied()248 public void binderDied() { 249 synchronized (mLock) { 250 if (this == mCurrentVibration) { 251 doCancelVibrateLocked(); 252 } 253 } 254 } 255 256 // Called by native 257 @SuppressWarnings("unused") onComplete()258 private void onComplete() { 259 synchronized (mLock) { 260 if (this == mCurrentVibration) { 261 doCancelVibrateLocked(); 262 } 263 } 264 } 265 hasTimeoutLongerThan(long millis)266 public boolean hasTimeoutLongerThan(long millis) { 267 final long duration = effect.getDuration(); 268 return duration >= 0 && duration > millis; 269 } 270 isHapticFeedback()271 public boolean isHapticFeedback() { 272 return VibratorService.this.isHapticFeedback(attrs.getUsage()); 273 } 274 isNotification()275 public boolean isNotification() { 276 return VibratorService.this.isNotification(attrs.getUsage()); 277 } 278 isRingtone()279 public boolean isRingtone() { 280 return VibratorService.this.isRingtone(attrs.getUsage()); 281 } 282 isAlarm()283 public boolean isAlarm() { 284 return VibratorService.this.isAlarm(attrs.getUsage()); 285 } 286 isFromSystem()287 public boolean isFromSystem() { 288 return uid == Process.SYSTEM_UID || uid == 0 || mSystemUiPackage.equals(opPkg); 289 } 290 toInfo()291 public VibrationInfo toInfo() { 292 return new VibrationInfo( 293 startTimeDebug, effect, originalEffect, attrs, uid, opPkg, reason); 294 } 295 } 296 297 private static class VibrationInfo { 298 private final long mStartTimeDebug; 299 private final VibrationEffect mEffect; 300 private final VibrationEffect mOriginalEffect; 301 private final VibrationAttributes mAttrs; 302 private final int mUid; 303 private final String mOpPkg; 304 private final String mReason; 305 VibrationInfo(long startTimeDebug, VibrationEffect effect, VibrationEffect originalEffect, VibrationAttributes attrs, int uid, String opPkg, String reason)306 VibrationInfo(long startTimeDebug, VibrationEffect effect, 307 VibrationEffect originalEffect, VibrationAttributes attrs, int uid, 308 String opPkg, String reason) { 309 mStartTimeDebug = startTimeDebug; 310 mEffect = effect; 311 mOriginalEffect = originalEffect; 312 mAttrs = attrs; 313 mUid = uid; 314 mOpPkg = opPkg; 315 mReason = reason; 316 } 317 318 @Override toString()319 public String toString() { 320 return new StringBuilder() 321 .append("startTime: ") 322 .append(DateFormat.getDateTimeInstance().format(new Date(mStartTimeDebug))) 323 .append(", effect: ") 324 .append(mEffect) 325 .append(", originalEffect: ") 326 .append(mOriginalEffect) 327 .append(", attrs: ") 328 .append(mAttrs) 329 .append(", uid: ") 330 .append(mUid) 331 .append(", opPkg: ") 332 .append(mOpPkg) 333 .append(", reason: ") 334 .append(mReason) 335 .toString(); 336 } 337 dumpProto(ProtoOutputStream proto, long fieldId)338 void dumpProto(ProtoOutputStream proto, long fieldId) { 339 synchronized (this) { 340 final long token = proto.start(fieldId); 341 proto.write(VibrationProto.START_TIME, mStartTimeDebug); 342 proto.end(token); 343 } 344 } 345 } 346 347 private static final class ScaleLevel { 348 public final float gamma; 349 public final int maxAmplitude; 350 ScaleLevel(float gamma)351 public ScaleLevel(float gamma) { 352 this(gamma, VibrationEffect.MAX_AMPLITUDE); 353 } 354 ScaleLevel(float gamma, int maxAmplitude)355 public ScaleLevel(float gamma, int maxAmplitude) { 356 this.gamma = gamma; 357 this.maxAmplitude = maxAmplitude; 358 } 359 360 @Override toString()361 public String toString() { 362 return "ScaleLevel{gamma=" + gamma + ", maxAmplitude=" + maxAmplitude + "}"; 363 } 364 } 365 VibratorService(Context context)366 VibratorService(Context context) { 367 vibratorInit(); 368 // Reset the hardware to a default state, in case this is a runtime 369 // restart instead of a fresh boot. 370 vibratorOff(); 371 372 mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl(); 373 mSupportsExternalControl = vibratorSupportsExternalControl(); 374 mSupportedEffects = asList(vibratorGetSupportedEffects()); 375 mCapabilities = vibratorGetCapabilities(); 376 377 mContext = context; 378 PowerManager pm = context.getSystemService(PowerManager.class); 379 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 380 mWakeLock.setReferenceCounted(true); 381 382 mAppOps = mContext.getSystemService(AppOpsManager.class); 383 mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService( 384 BatteryStats.SERVICE_NAME)); 385 mSystemUiPackage = LocalServices.getService(PackageManagerInternal.class) 386 .getSystemUiServiceComponent().getPackageName(); 387 388 mPreviousVibrationsLimit = mContext.getResources().getInteger( 389 com.android.internal.R.integer.config_previousVibrationsDumpLimit); 390 391 mDefaultVibrationAmplitude = mContext.getResources().getInteger( 392 com.android.internal.R.integer.config_defaultVibrationAmplitude); 393 394 mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean( 395 com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode); 396 397 mPreviousRingVibrations = new LinkedList<>(); 398 mPreviousNotificationVibrations = new LinkedList<>(); 399 mPreviousAlarmVibrations = new LinkedList<>(); 400 mPreviousVibrations = new LinkedList<>(); 401 mPreviousExternalVibrations = new LinkedList<>(); 402 403 IntentFilter filter = new IntentFilter(); 404 filter.addAction(Intent.ACTION_SCREEN_OFF); 405 context.registerReceiver(mIntentReceiver, filter); 406 407 VibrationEffect clickEffect = createEffectFromResource( 408 com.android.internal.R.array.config_virtualKeyVibePattern); 409 VibrationEffect doubleClickEffect = VibrationEffect.createWaveform( 410 DOUBLE_CLICK_EFFECT_FALLBACK_TIMINGS, -1 /*repeatIndex*/); 411 VibrationEffect heavyClickEffect = createEffectFromResource( 412 com.android.internal.R.array.config_longPressVibePattern); 413 VibrationEffect tickEffect = createEffectFromResource( 414 com.android.internal.R.array.config_clockTickVibePattern); 415 416 mFallbackEffects = new SparseArray<>(); 417 mFallbackEffects.put(VibrationEffect.EFFECT_CLICK, clickEffect); 418 mFallbackEffects.put(VibrationEffect.EFFECT_DOUBLE_CLICK, doubleClickEffect); 419 mFallbackEffects.put(VibrationEffect.EFFECT_TICK, tickEffect); 420 mFallbackEffects.put(VibrationEffect.EFFECT_HEAVY_CLICK, heavyClickEffect); 421 422 mFallbackEffects.put(VibrationEffect.EFFECT_TEXTURE_TICK, 423 VibrationEffect.get(VibrationEffect.EFFECT_TICK, false)); 424 425 mScaleLevels = new SparseArray<>(); 426 mScaleLevels.put(SCALE_VERY_LOW, 427 new ScaleLevel(SCALE_VERY_LOW_GAMMA, SCALE_VERY_LOW_MAX_AMPLITUDE)); 428 mScaleLevels.put(SCALE_LOW, new ScaleLevel(SCALE_LOW_GAMMA, SCALE_LOW_MAX_AMPLITUDE)); 429 mScaleLevels.put(SCALE_NONE, new ScaleLevel(SCALE_NONE_GAMMA)); 430 mScaleLevels.put(SCALE_HIGH, new ScaleLevel(SCALE_HIGH_GAMMA)); 431 mScaleLevels.put(SCALE_VERY_HIGH, new ScaleLevel(SCALE_VERY_HIGH_GAMMA)); 432 433 ServiceManager.addService(EXTERNAL_VIBRATOR_SERVICE, new ExternalVibratorService()); 434 } 435 createEffectFromResource(int resId)436 private VibrationEffect createEffectFromResource(int resId) { 437 long[] timings = getLongIntArray(mContext.getResources(), resId); 438 return createEffectFromTimings(timings); 439 } 440 createEffectFromTimings(long[] timings)441 private static VibrationEffect createEffectFromTimings(long[] timings) { 442 if (timings == null || timings.length == 0) { 443 return null; 444 } else if (timings.length == 1) { 445 return VibrationEffect.createOneShot(timings[0], VibrationEffect.DEFAULT_AMPLITUDE); 446 } else { 447 return VibrationEffect.createWaveform(timings, -1); 448 } 449 } 450 systemReady()451 public void systemReady() { 452 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "VibratorService#systemReady"); 453 try { 454 mIm = mContext.getSystemService(InputManager.class); 455 mVibrator = mContext.getSystemService(Vibrator.class); 456 mSettingObserver = new SettingsObserver(mH); 457 458 mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 459 mPowerManagerInternal.registerLowPowerModeObserver( 460 new PowerManagerInternal.LowPowerModeListener() { 461 @Override 462 public int getServiceType() { 463 return ServiceType.VIBRATION; 464 } 465 466 @Override 467 public void onLowPowerModeChanged(PowerSaveState result) { 468 updateVibrators(); 469 } 470 }); 471 472 mContext.getContentResolver().registerContentObserver( 473 Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), 474 true, mSettingObserver, UserHandle.USER_ALL); 475 476 mContext.getContentResolver().registerContentObserver( 477 Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_INTENSITY), 478 true, mSettingObserver, UserHandle.USER_ALL); 479 480 mContext.getContentResolver().registerContentObserver( 481 Settings.System.getUriFor(Settings.System.NOTIFICATION_VIBRATION_INTENSITY), 482 true, mSettingObserver, UserHandle.USER_ALL); 483 484 mContext.getContentResolver().registerContentObserver( 485 Settings.System.getUriFor(Settings.System.RING_VIBRATION_INTENSITY), 486 true, mSettingObserver, UserHandle.USER_ALL); 487 488 mContext.getContentResolver().registerContentObserver( 489 Settings.Global.getUriFor(Settings.Global.ZEN_MODE), 490 true, mSettingObserver, UserHandle.USER_ALL); 491 492 mContext.registerReceiver(new BroadcastReceiver() { 493 @Override 494 public void onReceive(Context context, Intent intent) { 495 updateVibrators(); 496 } 497 }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 498 499 try { 500 ActivityManager.getService().registerUidObserver(mUidObserver, 501 ActivityManager.UID_OBSERVER_PROCSTATE | ActivityManager.UID_OBSERVER_GONE, 502 ActivityManager.PROCESS_STATE_UNKNOWN, null); 503 } catch (RemoteException e) { 504 // ignored; both services live in system_server 505 } 506 507 updateVibrators(); 508 } finally { 509 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 510 } 511 } 512 513 private final class SettingsObserver extends ContentObserver { SettingsObserver(Handler handler)514 public SettingsObserver(Handler handler) { 515 super(handler); 516 } 517 518 @Override onChange(boolean SelfChange)519 public void onChange(boolean SelfChange) { 520 updateVibrators(); 521 } 522 } 523 524 @Override // Binder call hasVibrator()525 public boolean hasVibrator() { 526 return doVibratorExists(); 527 } 528 529 @Override // Binder call isVibrating()530 public boolean isVibrating() { 531 if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) { 532 throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission"); 533 } 534 synchronized (mLock) { 535 return mIsVibrating; 536 } 537 } 538 539 @GuardedBy("mLock") notifyStateListenerLocked(IVibratorStateListener listener)540 private void notifyStateListenerLocked(IVibratorStateListener listener) { 541 try { 542 listener.onVibrating(mIsVibrating); 543 } catch (RemoteException | RuntimeException e) { 544 Slog.e(TAG, "Vibrator callback failed to call", e); 545 } 546 } 547 548 @GuardedBy("mLock") notifyStateListenersLocked()549 private void notifyStateListenersLocked() { 550 final int length = mVibratorStateListeners.beginBroadcast(); 551 try { 552 for (int i = 0; i < length; i++) { 553 final IVibratorStateListener listener = 554 mVibratorStateListeners.getBroadcastItem(i); 555 notifyStateListenerLocked(listener); 556 } 557 } finally { 558 mVibratorStateListeners.finishBroadcast(); 559 } 560 } 561 562 @Override // Binder call registerVibratorStateListener(IVibratorStateListener listener)563 public boolean registerVibratorStateListener(IVibratorStateListener listener) { 564 if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) { 565 throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission"); 566 } 567 synchronized (mLock) { 568 final long token = Binder.clearCallingIdentity(); 569 try { 570 if (!mVibratorStateListeners.register(listener)) { 571 return false; 572 } 573 // Notify its callback after new client registered. 574 notifyStateListenerLocked(listener); 575 return true; 576 } finally { 577 Binder.restoreCallingIdentity(token); 578 } 579 } 580 } 581 582 @Override // Binder call 583 @GuardedBy("mLock") unregisterVibratorStateListener(IVibratorStateListener listener)584 public boolean unregisterVibratorStateListener(IVibratorStateListener listener) { 585 if (!hasPermission(android.Manifest.permission.ACCESS_VIBRATOR_STATE)) { 586 throw new SecurityException("Requires ACCESS_VIBRATOR_STATE permission"); 587 } 588 synchronized (mLock) { 589 final long token = Binder.clearCallingIdentity(); 590 try { 591 return mVibratorStateListeners.unregister(listener); 592 } finally { 593 Binder.restoreCallingIdentity(token); 594 } 595 } 596 } 597 598 @Override // Binder call hasAmplitudeControl()599 public boolean hasAmplitudeControl() { 600 synchronized (mInputDeviceVibrators) { 601 // Input device vibrators don't support amplitude controls yet, but are still used over 602 // the system vibrator when connected. 603 return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty(); 604 } 605 } 606 607 @Override // Binder call areEffectsSupported(int[] effectIds)608 public int[] areEffectsSupported(int[] effectIds) { 609 int[] supported = new int[effectIds.length]; 610 if (mSupportedEffects == null) { 611 Arrays.fill(supported, Vibrator.VIBRATION_EFFECT_SUPPORT_UNKNOWN); 612 } else { 613 for (int i = 0; i < effectIds.length; i++) { 614 supported[i] = mSupportedEffects.contains(effectIds[i]) 615 ? Vibrator.VIBRATION_EFFECT_SUPPORT_YES 616 : Vibrator.VIBRATION_EFFECT_SUPPORT_NO; 617 } 618 } 619 return supported; 620 } 621 622 @Override // Binder call arePrimitivesSupported(int[] primitiveIds)623 public boolean[] arePrimitivesSupported(int[] primitiveIds) { 624 boolean[] supported = new boolean[primitiveIds.length]; 625 if (hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { 626 Arrays.fill(supported, true); 627 } 628 return supported; 629 } 630 631 asList(int... vals)632 private static List<Integer> asList(int... vals) { 633 if (vals == null) { 634 return null; 635 } 636 List<Integer> l = new ArrayList<>(vals.length); 637 for (int val : vals) { 638 l.add(val); 639 } 640 return l; 641 } 642 643 @Override // Binder call setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect, VibrationAttributes attrs)644 public boolean setAlwaysOnEffect(int uid, String opPkg, int alwaysOnId, VibrationEffect effect, 645 VibrationAttributes attrs) { 646 if (!hasPermission(android.Manifest.permission.VIBRATE_ALWAYS_ON)) { 647 throw new SecurityException("Requires VIBRATE_ALWAYS_ON permission"); 648 } 649 if (!hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { 650 Slog.e(TAG, "Always-on effects not supported."); 651 return false; 652 } 653 if (effect == null) { 654 synchronized (mLock) { 655 mAlwaysOnEffects.delete(alwaysOnId); 656 vibratorAlwaysOnDisable(alwaysOnId); 657 } 658 } else { 659 if (!verifyVibrationEffect(effect)) { 660 return false; 661 } 662 if (!(effect instanceof VibrationEffect.Prebaked)) { 663 Slog.e(TAG, "Only prebaked effects supported for always-on."); 664 return false; 665 } 666 attrs = fixupVibrationAttributes(attrs); 667 synchronized (mLock) { 668 Vibration vib = new Vibration(null, effect, attrs, uid, opPkg, null); 669 mAlwaysOnEffects.put(alwaysOnId, vib); 670 updateAlwaysOnLocked(alwaysOnId, vib); 671 } 672 } 673 return true; 674 } 675 verifyIncomingUid(int uid)676 private void verifyIncomingUid(int uid) { 677 if (uid == Binder.getCallingUid()) { 678 return; 679 } 680 if (Binder.getCallingPid() == Process.myPid()) { 681 return; 682 } 683 mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 684 Binder.getCallingPid(), Binder.getCallingUid(), null); 685 } 686 687 /** 688 * Validate the incoming VibrationEffect. 689 * 690 * We can't throw exceptions here since we might be called from some system_server component, 691 * which would bring the whole system down. 692 * 693 * @return whether the VibrationEffect is valid 694 */ verifyVibrationEffect(VibrationEffect effect)695 private static boolean verifyVibrationEffect(VibrationEffect effect) { 696 if (effect == null) { 697 // Effect must not be null. 698 Slog.wtf(TAG, "effect must not be null"); 699 return false; 700 } 701 try { 702 effect.validate(); 703 } catch (Exception e) { 704 Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e); 705 return false; 706 } 707 return true; 708 } 709 fixupVibrationAttributes(VibrationAttributes attrs)710 private VibrationAttributes fixupVibrationAttributes(VibrationAttributes attrs) { 711 if (attrs == null) { 712 attrs = DEFAULT_ATTRIBUTES; 713 } 714 if (shouldBypassDnd(attrs)) { 715 if (!(hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) 716 || hasPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 717 || hasPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING))) { 718 final int flags = attrs.getFlags() 719 & ~VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY; 720 attrs = new VibrationAttributes.Builder(attrs).replaceFlags(flags).build(); 721 } 722 } 723 724 return attrs; 725 } 726 getLongIntArray(Resources r, int resid)727 private static long[] getLongIntArray(Resources r, int resid) { 728 int[] ar = r.getIntArray(resid); 729 if (ar == null) { 730 return null; 731 } 732 long[] out = new long[ar.length]; 733 for (int i = 0; i < ar.length; i++) { 734 out[i] = ar[i]; 735 } 736 return out; 737 } 738 739 @Override // Binder call vibrate(int uid, String opPkg, VibrationEffect effect, @Nullable VibrationAttributes attrs, String reason, IBinder token)740 public void vibrate(int uid, String opPkg, VibrationEffect effect, 741 @Nullable VibrationAttributes attrs, String reason, IBinder token) { 742 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "vibrate, reason = " + reason); 743 try { 744 if (!hasPermission(android.Manifest.permission.VIBRATE)) { 745 throw new SecurityException("Requires VIBRATE permission"); 746 } 747 if (token == null) { 748 Slog.e(TAG, "token must not be null"); 749 return; 750 } 751 verifyIncomingUid(uid); 752 if (!verifyVibrationEffect(effect)) { 753 return; 754 } 755 756 attrs = fixupVibrationAttributes(attrs); 757 758 // If our current vibration is longer than the new vibration and is the same amplitude, 759 // then just let the current one finish. 760 synchronized (mLock) { 761 if (effect instanceof VibrationEffect.OneShot 762 && mCurrentVibration != null 763 && mCurrentVibration.effect instanceof VibrationEffect.OneShot) { 764 VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect; 765 VibrationEffect.OneShot currentOneShot = 766 (VibrationEffect.OneShot) mCurrentVibration.effect; 767 if (mCurrentVibration.hasTimeoutLongerThan(newOneShot.getDuration()) 768 && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) { 769 if (DEBUG) { 770 Slog.d(TAG, 771 "Ignoring incoming vibration in favor of current vibration"); 772 } 773 return; 774 } 775 } 776 777 778 // If something has external control of the vibrator, assume that it's more 779 // important for now. 780 if (mCurrentExternalVibration != null) { 781 if (DEBUG) { 782 Slog.d(TAG, "Ignoring incoming vibration for current external vibration"); 783 } 784 return; 785 } 786 787 // If the current vibration is repeating and the incoming one is non-repeating, 788 // then ignore the non-repeating vibration. This is so that we don't cancel 789 // vibrations that are meant to grab the attention of the user, like ringtones and 790 // alarms, in favor of one-shot vibrations that are likely quite short. 791 if (!isRepeatingVibration(effect) 792 && mCurrentVibration != null 793 && isRepeatingVibration(mCurrentVibration.effect)) { 794 if (DEBUG) { 795 Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration"); 796 } 797 return; 798 } 799 800 Vibration vib = new Vibration(token, effect, attrs, uid, opPkg, reason); 801 if (mProcStatesCache.get(uid, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) 802 > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND 803 && !vib.isNotification() && !vib.isRingtone() && !vib.isAlarm()) { 804 Slog.e(TAG, "Ignoring incoming vibration as process with" 805 + " uid= " + uid + " is background," 806 + " attrs= " + vib.attrs); 807 return; 808 } 809 linkVibration(vib); 810 long ident = Binder.clearCallingIdentity(); 811 try { 812 doCancelVibrateLocked(); 813 startVibrationLocked(vib); 814 addToPreviousVibrationsLocked(vib); 815 } finally { 816 Binder.restoreCallingIdentity(ident); 817 } 818 } 819 } finally { 820 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 821 } 822 } 823 hasPermission(String permission)824 private boolean hasPermission(String permission) { 825 return mContext.checkCallingOrSelfPermission(permission) 826 == PackageManager.PERMISSION_GRANTED; 827 } 828 isRepeatingVibration(VibrationEffect effect)829 private static boolean isRepeatingVibration(VibrationEffect effect) { 830 return effect.getDuration() == Long.MAX_VALUE; 831 } 832 addToPreviousVibrationsLocked(Vibration vib)833 private void addToPreviousVibrationsLocked(Vibration vib) { 834 final LinkedList<VibrationInfo> previousVibrations; 835 if (vib.isRingtone()) { 836 previousVibrations = mPreviousRingVibrations; 837 } else if (vib.isNotification()) { 838 previousVibrations = mPreviousNotificationVibrations; 839 } else if (vib.isAlarm()) { 840 previousVibrations = mPreviousAlarmVibrations; 841 } else { 842 previousVibrations = mPreviousVibrations; 843 } 844 845 if (previousVibrations.size() > mPreviousVibrationsLimit) { 846 previousVibrations.removeFirst(); 847 } 848 previousVibrations.addLast(vib.toInfo()); 849 } 850 851 @Override // Binder call cancelVibrate(IBinder token)852 public void cancelVibrate(IBinder token) { 853 mContext.enforceCallingOrSelfPermission( 854 android.Manifest.permission.VIBRATE, 855 "cancelVibrate"); 856 857 synchronized (mLock) { 858 if (mCurrentVibration != null && mCurrentVibration.token == token) { 859 if (DEBUG) { 860 Slog.d(TAG, "Canceling vibration."); 861 } 862 long ident = Binder.clearCallingIdentity(); 863 try { 864 doCancelVibrateLocked(); 865 } finally { 866 Binder.restoreCallingIdentity(ident); 867 } 868 } 869 } 870 } 871 872 private final Runnable mVibrationEndRunnable = new Runnable() { 873 @Override 874 public void run() { 875 onVibrationFinished(); 876 } 877 }; 878 879 @GuardedBy("mLock") doCancelVibrateLocked()880 private void doCancelVibrateLocked() { 881 Trace.asyncTraceEnd(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); 882 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doCancelVibrateLocked"); 883 try { 884 mH.removeCallbacks(mVibrationEndRunnable); 885 if (mThread != null) { 886 mThread.cancel(); 887 mThread = null; 888 } 889 if (mCurrentExternalVibration != null) { 890 mCurrentExternalVibration.mute(); 891 mCurrentExternalVibration = null; 892 setVibratorUnderExternalControl(false); 893 } 894 doVibratorOff(); 895 reportFinishVibrationLocked(); 896 } finally { 897 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 898 } 899 } 900 901 // Callback for whenever the current vibration has finished played out onVibrationFinished()902 public void onVibrationFinished() { 903 if (DEBUG) { 904 Slog.e(TAG, "Vibration finished, cleaning up"); 905 } 906 synchronized (mLock) { 907 // Make sure the vibration is really done. This also reports that the vibration is 908 // finished. 909 doCancelVibrateLocked(); 910 } 911 } 912 913 @GuardedBy("mLock") startVibrationLocked(final Vibration vib)914 private void startVibrationLocked(final Vibration vib) { 915 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationLocked"); 916 try { 917 final int intensity = getCurrentIntensityLocked(vib); 918 if (!shouldVibrate(vib, intensity)) { 919 return; 920 } 921 applyVibrationIntensityScalingLocked(vib, intensity); 922 startVibrationInnerLocked(vib); 923 } finally { 924 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 925 } 926 } 927 928 @GuardedBy("mLock") startVibrationInnerLocked(Vibration vib)929 private void startVibrationInnerLocked(Vibration vib) { 930 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationInnerLocked"); 931 try { 932 mCurrentVibration = vib; 933 if (vib.effect instanceof VibrationEffect.OneShot) { 934 Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); 935 VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.effect; 936 doVibratorOn(oneShot.getDuration(), oneShot.getAmplitude(), vib.uid, vib.attrs); 937 mH.postDelayed(mVibrationEndRunnable, oneShot.getDuration()); 938 } else if (vib.effect instanceof VibrationEffect.Waveform) { 939 // mThread better be null here. doCancelVibrate should always be 940 // called before startNextVibrationLocked or startVibrationLocked. 941 Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); 942 VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.effect; 943 mThread = new VibrateThread(waveform, vib.uid, vib.attrs); 944 mThread.start(); 945 } else if (vib.effect instanceof VibrationEffect.Prebaked) { 946 Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); 947 long timeout = doVibratorPrebakedEffectLocked(vib); 948 if (timeout > 0) { 949 mH.postDelayed(mVibrationEndRunnable, timeout); 950 } 951 } else if (vib.effect instanceof VibrationEffect.Composed) { 952 Trace.asyncTraceBegin(Trace.TRACE_TAG_VIBRATOR, "vibration", 0); 953 doVibratorComposedEffectLocked(vib); 954 // FIXME: We rely on the completion callback here, but I don't think we require that 955 // devices which support composition also support the completion callback. If we 956 // ever get a device that supports the former but not the latter, then we have no 957 // real way of knowing how long a given effect should last. 958 mH.postDelayed(mVibrationEndRunnable, 10000); 959 } else { 960 Slog.e(TAG, "Unknown vibration type, ignoring"); 961 } 962 } finally { 963 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 964 } 965 } 966 isAllowedToVibrateLocked(Vibration vib)967 private boolean isAllowedToVibrateLocked(Vibration vib) { 968 if (!mLowPowerMode) { 969 return true; 970 } 971 972 int usage = vib.attrs.getUsage(); 973 return usage == VibrationAttributes.USAGE_RINGTONE 974 || usage == VibrationAttributes.USAGE_ALARM 975 || usage == VibrationAttributes.USAGE_COMMUNICATION_REQUEST; 976 } 977 getCurrentIntensityLocked(Vibration vib)978 private int getCurrentIntensityLocked(Vibration vib) { 979 if (vib.isRingtone()) { 980 return mRingIntensity; 981 } else if (vib.isNotification()) { 982 return mNotificationIntensity; 983 } else if (vib.isHapticFeedback()) { 984 return mHapticFeedbackIntensity; 985 } else if (vib.isAlarm()) { 986 return Vibrator.VIBRATION_INTENSITY_HIGH; 987 } else { 988 return Vibrator.VIBRATION_INTENSITY_MEDIUM; 989 } 990 } 991 992 /** 993 * Scale the vibration effect by the intensity as appropriate based its intent. 994 */ applyVibrationIntensityScalingLocked(Vibration vib, int intensity)995 private void applyVibrationIntensityScalingLocked(Vibration vib, int intensity) { 996 if (vib.effect instanceof VibrationEffect.Prebaked) { 997 // Prebaked effects are always just a direct translation from intensity to 998 // EffectStrength. 999 VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked)vib.effect; 1000 prebaked.setEffectStrength(intensityToEffectStrength(intensity)); 1001 return; 1002 } 1003 1004 final int defaultIntensity; 1005 if (vib.isRingtone()) { 1006 defaultIntensity = mVibrator.getDefaultRingVibrationIntensity(); 1007 } else if (vib.isNotification()) { 1008 defaultIntensity = mVibrator.getDefaultNotificationVibrationIntensity(); 1009 } else if (vib.isHapticFeedback()) { 1010 defaultIntensity = mVibrator.getDefaultHapticFeedbackIntensity(); 1011 } else if (vib.isAlarm()) { 1012 defaultIntensity = Vibrator.VIBRATION_INTENSITY_HIGH; 1013 } else { 1014 // If we don't know what kind of vibration we're playing then just skip scaling for 1015 // now. 1016 return; 1017 } 1018 1019 final ScaleLevel scale = mScaleLevels.get(intensity - defaultIntensity); 1020 if (scale == null) { 1021 // We should have scaling levels for all cases, so not being able to scale because of a 1022 // missing level is unexpected. 1023 Slog.e(TAG, "No configured scaling level!" 1024 + " (current=" + intensity + ", default= " + defaultIntensity + ")"); 1025 return; 1026 } 1027 1028 VibrationEffect scaledEffect = null; 1029 if (vib.effect instanceof VibrationEffect.OneShot) { 1030 VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.effect; 1031 oneShot = oneShot.resolve(mDefaultVibrationAmplitude); 1032 scaledEffect = oneShot.scale(scale.gamma, scale.maxAmplitude); 1033 } else if (vib.effect instanceof VibrationEffect.Waveform) { 1034 VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.effect; 1035 waveform = waveform.resolve(mDefaultVibrationAmplitude); 1036 scaledEffect = waveform.scale(scale.gamma, scale.maxAmplitude); 1037 } else if (vib.effect instanceof VibrationEffect.Composed) { 1038 VibrationEffect.Composed composed = (VibrationEffect.Composed) vib.effect; 1039 scaledEffect = composed.scale(scale.gamma, scale.maxAmplitude); 1040 } else { 1041 Slog.w(TAG, "Unable to apply intensity scaling, unknown VibrationEffect type"); 1042 } 1043 1044 if (scaledEffect != null) { 1045 vib.originalEffect = vib.effect; 1046 vib.effect = scaledEffect; 1047 } 1048 } 1049 shouldVibrateForRingtone()1050 private boolean shouldVibrateForRingtone() { 1051 AudioManager audioManager = mContext.getSystemService(AudioManager.class); 1052 int ringerMode = audioManager.getRingerModeInternal(); 1053 // "Also vibrate for calls" Setting in Sound 1054 if (Settings.System.getInt( 1055 mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) { 1056 return ringerMode != AudioManager.RINGER_MODE_SILENT; 1057 } else if (Settings.Global.getInt( 1058 mContext.getContentResolver(), Settings.Global.APPLY_RAMPING_RINGER, 0) != 0) { 1059 return ringerMode != AudioManager.RINGER_MODE_SILENT; 1060 } else { 1061 return ringerMode == AudioManager.RINGER_MODE_VIBRATE; 1062 } 1063 } 1064 shouldBypassDnd(VibrationAttributes attrs)1065 private static boolean shouldBypassDnd(VibrationAttributes attrs) { 1066 return attrs.isFlagSet(VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY); 1067 } 1068 getAppOpMode(int uid, String packageName, VibrationAttributes attrs)1069 private int getAppOpMode(int uid, String packageName, VibrationAttributes attrs) { 1070 int mode = mAppOps.checkAudioOpNoThrow(AppOpsManager.OP_VIBRATE, 1071 attrs.getAudioAttributes().getUsage(), uid, packageName); 1072 if (mode == AppOpsManager.MODE_ALLOWED) { 1073 mode = mAppOps.startOpNoThrow(AppOpsManager.OP_VIBRATE, uid, packageName); 1074 } 1075 1076 if (mode == AppOpsManager.MODE_IGNORED && shouldBypassDnd(attrs)) { 1077 // If we're just ignoring the vibration op then this is set by DND and we should ignore 1078 // if we're asked to bypass. AppOps won't be able to record this operation, so make 1079 // sure we at least note it in the logs for debugging. 1080 Slog.d(TAG, "Bypassing DND for vibrate from uid " + uid); 1081 mode = AppOpsManager.MODE_ALLOWED; 1082 } 1083 return mode; 1084 } 1085 shouldVibrate(Vibration vib, int intensity)1086 private boolean shouldVibrate(Vibration vib, int intensity) { 1087 if (!isAllowedToVibrateLocked(vib)) { 1088 return false; 1089 } 1090 1091 if (intensity == Vibrator.VIBRATION_INTENSITY_OFF) { 1092 return false; 1093 } 1094 1095 if (vib.isRingtone() && !shouldVibrateForRingtone()) { 1096 if (DEBUG) { 1097 Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); 1098 } 1099 return false; 1100 } 1101 1102 final int mode = getAppOpMode(vib.uid, vib.opPkg, vib.attrs); 1103 if (mode != AppOpsManager.MODE_ALLOWED) { 1104 if (mode == AppOpsManager.MODE_ERRORED) { 1105 // We might be getting calls from within system_server, so we don't actually 1106 // want to throw a SecurityException here. 1107 Slog.w(TAG, "Would be an error: vibrate from uid " + vib.uid); 1108 } 1109 return false; 1110 } 1111 1112 return true; 1113 } 1114 1115 @GuardedBy("mLock") reportFinishVibrationLocked()1116 private void reportFinishVibrationLocked() { 1117 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "reportFinishVibrationLocked"); 1118 try { 1119 if (mCurrentVibration != null) { 1120 mAppOps.finishOp(AppOpsManager.OP_VIBRATE, mCurrentVibration.uid, 1121 mCurrentVibration.opPkg); 1122 unlinkVibration(mCurrentVibration); 1123 mCurrentVibration = null; 1124 } 1125 } finally { 1126 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 1127 } 1128 } 1129 linkVibration(Vibration vib)1130 private void linkVibration(Vibration vib) { 1131 // Only link against waveforms since they potentially don't have a finish if 1132 // they're repeating. Let other effects just play out until they're done. 1133 if (vib.effect instanceof VibrationEffect.Waveform) { 1134 try { 1135 vib.token.linkToDeath(vib, 0); 1136 } catch (RemoteException e) { 1137 return; 1138 } 1139 } 1140 } 1141 unlinkVibration(Vibration vib)1142 private void unlinkVibration(Vibration vib) { 1143 if (vib.effect instanceof VibrationEffect.Waveform) { 1144 vib.token.unlinkToDeath(vib, 0); 1145 } 1146 } 1147 updateVibrators()1148 private void updateVibrators() { 1149 synchronized (mLock) { 1150 boolean devicesUpdated = updateInputDeviceVibratorsLocked(); 1151 boolean lowPowerModeUpdated = updateLowPowerModeLocked(); 1152 updateVibrationIntensityLocked(); 1153 1154 if (devicesUpdated || lowPowerModeUpdated) { 1155 // If the state changes out from under us then just reset. 1156 doCancelVibrateLocked(); 1157 } 1158 1159 updateAlwaysOnLocked(); 1160 } 1161 } 1162 updateInputDeviceVibratorsLocked()1163 private boolean updateInputDeviceVibratorsLocked() { 1164 boolean changed = false; 1165 boolean vibrateInputDevices = false; 1166 try { 1167 vibrateInputDevices = Settings.System.getIntForUser( 1168 mContext.getContentResolver(), 1169 Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 1170 } catch (SettingNotFoundException snfe) { 1171 } 1172 if (vibrateInputDevices != mVibrateInputDevicesSetting) { 1173 changed = true; 1174 mVibrateInputDevicesSetting = vibrateInputDevices; 1175 } 1176 1177 if (mVibrateInputDevicesSetting) { 1178 if (!mInputDeviceListenerRegistered) { 1179 mInputDeviceListenerRegistered = true; 1180 mIm.registerInputDeviceListener(this, mH); 1181 } 1182 } else { 1183 if (mInputDeviceListenerRegistered) { 1184 mInputDeviceListenerRegistered = false; 1185 mIm.unregisterInputDeviceListener(this); 1186 } 1187 } 1188 1189 mInputDeviceVibrators.clear(); 1190 if (mVibrateInputDevicesSetting) { 1191 int[] ids = mIm.getInputDeviceIds(); 1192 for (int i = 0; i < ids.length; i++) { 1193 InputDevice device = mIm.getInputDevice(ids[i]); 1194 Vibrator vibrator = device.getVibrator(); 1195 if (vibrator.hasVibrator()) { 1196 mInputDeviceVibrators.add(vibrator); 1197 } 1198 } 1199 return true; 1200 } 1201 return changed; 1202 } 1203 updateLowPowerModeLocked()1204 private boolean updateLowPowerModeLocked() { 1205 boolean lowPowerMode = mPowerManagerInternal 1206 .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled; 1207 if (lowPowerMode != mLowPowerMode) { 1208 mLowPowerMode = lowPowerMode; 1209 return true; 1210 } 1211 return false; 1212 } 1213 updateVibrationIntensityLocked()1214 private void updateVibrationIntensityLocked() { 1215 mHapticFeedbackIntensity = Settings.System.getIntForUser(mContext.getContentResolver(), 1216 Settings.System.HAPTIC_FEEDBACK_INTENSITY, 1217 mVibrator.getDefaultHapticFeedbackIntensity(), UserHandle.USER_CURRENT); 1218 mNotificationIntensity = Settings.System.getIntForUser(mContext.getContentResolver(), 1219 Settings.System.NOTIFICATION_VIBRATION_INTENSITY, 1220 mVibrator.getDefaultNotificationVibrationIntensity(), UserHandle.USER_CURRENT); 1221 mRingIntensity = Settings.System.getIntForUser(mContext.getContentResolver(), 1222 Settings.System.RING_VIBRATION_INTENSITY, 1223 mVibrator.getDefaultRingVibrationIntensity(), UserHandle.USER_CURRENT); 1224 } 1225 updateAlwaysOnLocked(int id, Vibration vib)1226 private void updateAlwaysOnLocked(int id, Vibration vib) { 1227 final int intensity = getCurrentIntensityLocked(vib); 1228 if (!shouldVibrate(vib, intensity)) { 1229 vibratorAlwaysOnDisable(id); 1230 } else { 1231 final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.effect; 1232 final int strength = intensityToEffectStrength(intensity); 1233 vibratorAlwaysOnEnable(id, prebaked.getId(), strength); 1234 } 1235 } 1236 updateAlwaysOnLocked()1237 private void updateAlwaysOnLocked() { 1238 for (int i = 0; i < mAlwaysOnEffects.size(); i++) { 1239 int id = mAlwaysOnEffects.keyAt(i); 1240 Vibration vib = mAlwaysOnEffects.valueAt(i); 1241 updateAlwaysOnLocked(id, vib); 1242 } 1243 } 1244 1245 @Override onInputDeviceAdded(int deviceId)1246 public void onInputDeviceAdded(int deviceId) { 1247 updateVibrators(); 1248 } 1249 1250 @Override onInputDeviceChanged(int deviceId)1251 public void onInputDeviceChanged(int deviceId) { 1252 updateVibrators(); 1253 } 1254 1255 @Override onInputDeviceRemoved(int deviceId)1256 public void onInputDeviceRemoved(int deviceId) { 1257 updateVibrators(); 1258 } 1259 doVibratorExists()1260 private boolean doVibratorExists() { 1261 // For now, we choose to ignore the presence of input devices that have vibrators 1262 // when reporting whether the device has a vibrator. Applications often use this 1263 // information to decide whether to enable certain features so they expect the 1264 // result of hasVibrator() to be constant. For now, just report whether 1265 // the device has a built-in vibrator. 1266 //synchronized (mInputDeviceVibrators) { 1267 // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 1268 //} 1269 return vibratorExists(); 1270 } 1271 doVibratorOn(long millis, int amplitude, int uid, VibrationAttributes attrs)1272 private void doVibratorOn(long millis, int amplitude, int uid, VibrationAttributes attrs) { 1273 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOn"); 1274 try { 1275 synchronized (mInputDeviceVibrators) { 1276 if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) { 1277 amplitude = mDefaultVibrationAmplitude; 1278 } 1279 if (DEBUG) { 1280 Slog.d(TAG, "Turning vibrator on for " + millis + " ms" + 1281 " with amplitude " + amplitude + "."); 1282 } 1283 noteVibratorOnLocked(uid, millis); 1284 final int vibratorCount = mInputDeviceVibrators.size(); 1285 if (vibratorCount != 0) { 1286 for (int i = 0; i < vibratorCount; i++) { 1287 mInputDeviceVibrators.get(i).vibrate(millis, attrs.getAudioAttributes()); 1288 } 1289 } else { 1290 // Note: ordering is important here! Many haptic drivers will reset their 1291 // amplitude when enabled, so we always have to enable first, then set the 1292 // amplitude. 1293 vibratorOn(millis); 1294 doVibratorSetAmplitude(amplitude); 1295 } 1296 } 1297 } finally { 1298 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 1299 } 1300 } 1301 doVibratorSetAmplitude(int amplitude)1302 private void doVibratorSetAmplitude(int amplitude) { 1303 if (mSupportsAmplitudeControl) { 1304 vibratorSetAmplitude(amplitude); 1305 } 1306 } 1307 doVibratorOff()1308 private void doVibratorOff() { 1309 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorOff"); 1310 try { 1311 synchronized (mInputDeviceVibrators) { 1312 if (DEBUG) { 1313 Slog.d(TAG, "Turning vibrator off."); 1314 } 1315 noteVibratorOffLocked(); 1316 final int vibratorCount = mInputDeviceVibrators.size(); 1317 if (vibratorCount != 0) { 1318 for (int i = 0; i < vibratorCount; i++) { 1319 mInputDeviceVibrators.get(i).cancel(); 1320 } 1321 } else { 1322 vibratorOff(); 1323 } 1324 } 1325 } finally { 1326 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 1327 } 1328 } 1329 1330 @GuardedBy("mLock") doVibratorPrebakedEffectLocked(Vibration vib)1331 private long doVibratorPrebakedEffectLocked(Vibration vib) { 1332 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorPrebakedEffectLocked"); 1333 try { 1334 final VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.effect; 1335 final boolean usingInputDeviceVibrators; 1336 synchronized (mInputDeviceVibrators) { 1337 usingInputDeviceVibrators = !mInputDeviceVibrators.isEmpty(); 1338 } 1339 // Input devices don't support prebaked effect, so skip trying it with them. 1340 if (!usingInputDeviceVibrators) { 1341 long duration = vibratorPerformEffect(prebaked.getId(), 1342 prebaked.getEffectStrength(), vib, 1343 hasCapability(IVibrator.CAP_PERFORM_CALLBACK)); 1344 long timeout = duration; 1345 if (hasCapability(IVibrator.CAP_PERFORM_CALLBACK)) { 1346 timeout *= ASYNC_TIMEOUT_MULTIPLIER; 1347 } 1348 if (timeout > 0) { 1349 noteVibratorOnLocked(vib.uid, duration); 1350 return timeout; 1351 } 1352 } 1353 if (!prebaked.shouldFallback()) { 1354 return 0; 1355 } 1356 VibrationEffect effect = getFallbackEffect(prebaked.getId()); 1357 if (effect == null) { 1358 Slog.w(TAG, "Failed to play prebaked effect, no fallback"); 1359 return 0; 1360 } 1361 Vibration fallbackVib = new Vibration(vib.token, effect, vib.attrs, vib.uid, 1362 vib.opPkg, vib.reason + " (fallback)"); 1363 final int intensity = getCurrentIntensityLocked(fallbackVib); 1364 linkVibration(fallbackVib); 1365 applyVibrationIntensityScalingLocked(fallbackVib, intensity); 1366 startVibrationInnerLocked(fallbackVib); 1367 return 0; 1368 } finally { 1369 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 1370 } 1371 } 1372 1373 @GuardedBy("mLock") doVibratorComposedEffectLocked(Vibration vib)1374 private void doVibratorComposedEffectLocked(Vibration vib) { 1375 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "doVibratorComposedEffectLocked"); 1376 1377 try { 1378 final VibrationEffect.Composed composed = (VibrationEffect.Composed) vib.effect; 1379 final boolean usingInputDeviceVibrators; 1380 synchronized (mInputDeviceVibrators) { 1381 usingInputDeviceVibrators = !mInputDeviceVibrators.isEmpty(); 1382 } 1383 // Input devices don't support composed effect, so skip trying it with them. 1384 if (usingInputDeviceVibrators) { 1385 return; 1386 } 1387 1388 if (!hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { 1389 return; 1390 } 1391 1392 PrimitiveEffect[] primitiveEffects = 1393 composed.getPrimitiveEffects().toArray(new PrimitiveEffect[0]); 1394 vibratorPerformComposedEffect(primitiveEffects, vib); 1395 1396 // Composed effects don't actually give us an estimated duration, so we just guess here. 1397 noteVibratorOnLocked(vib.uid, 10 * primitiveEffects.length); 1398 } finally { 1399 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 1400 } 1401 1402 } 1403 hasCapability(long capability)1404 private boolean hasCapability(long capability) { 1405 return (mCapabilities & capability) == capability; 1406 } 1407 getFallbackEffect(int effectId)1408 private VibrationEffect getFallbackEffect(int effectId) { 1409 return mFallbackEffects.get(effectId); 1410 } 1411 1412 /** 1413 * Return the current desired effect strength. 1414 * 1415 * If the returned value is < 0 then the vibration shouldn't be played at all. 1416 */ intensityToEffectStrength(int intensity)1417 private static int intensityToEffectStrength(int intensity) { 1418 switch (intensity) { 1419 case Vibrator.VIBRATION_INTENSITY_LOW: 1420 return EffectStrength.LIGHT; 1421 case Vibrator.VIBRATION_INTENSITY_MEDIUM: 1422 return EffectStrength.MEDIUM; 1423 case Vibrator.VIBRATION_INTENSITY_HIGH: 1424 return EffectStrength.STRONG; 1425 default: 1426 Slog.w(TAG, "Got unexpected vibration intensity: " + intensity); 1427 return EffectStrength.STRONG; 1428 } 1429 } 1430 isNotification(int usageHint)1431 private static boolean isNotification(int usageHint) { 1432 return usageHint == VibrationAttributes.USAGE_NOTIFICATION; 1433 } 1434 isRingtone(int usageHint)1435 private static boolean isRingtone(int usageHint) { 1436 return usageHint == VibrationAttributes.USAGE_RINGTONE; 1437 } 1438 isHapticFeedback(int usageHint)1439 private static boolean isHapticFeedback(int usageHint) { 1440 return usageHint == VibrationAttributes.USAGE_TOUCH; 1441 } 1442 isAlarm(int usageHint)1443 private static boolean isAlarm(int usageHint) { 1444 return usageHint == VibrationAttributes.USAGE_ALARM; 1445 } 1446 noteVibratorOnLocked(int uid, long millis)1447 private void noteVibratorOnLocked(int uid, long millis) { 1448 try { 1449 mBatteryStatsService.noteVibratorOn(uid, millis); 1450 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.VIBRATOR_STATE_CHANGED, uid, null, 1451 FrameworkStatsLog.VIBRATOR_STATE_CHANGED__STATE__ON, millis); 1452 mCurVibUid = uid; 1453 if (!mIsVibrating) { 1454 mIsVibrating = true; 1455 notifyStateListenersLocked(); 1456 } 1457 } catch (RemoteException e) { 1458 } 1459 } 1460 noteVibratorOffLocked()1461 private void noteVibratorOffLocked() { 1462 if (mCurVibUid >= 0) { 1463 try { 1464 mBatteryStatsService.noteVibratorOff(mCurVibUid); 1465 FrameworkStatsLog.write_non_chained(FrameworkStatsLog.VIBRATOR_STATE_CHANGED, 1466 mCurVibUid, null, FrameworkStatsLog.VIBRATOR_STATE_CHANGED__STATE__OFF, 0); 1467 } catch (RemoteException e) { } 1468 mCurVibUid = -1; 1469 } 1470 if (mIsVibrating) { 1471 mIsVibrating = false; 1472 notifyStateListenersLocked(); 1473 } 1474 } 1475 setVibratorUnderExternalControl(boolean externalControl)1476 private void setVibratorUnderExternalControl(boolean externalControl) { 1477 if (DEBUG) { 1478 if (externalControl) { 1479 Slog.d(TAG, "Vibrator going under external control."); 1480 } else { 1481 Slog.d(TAG, "Taking back control of vibrator."); 1482 } 1483 } 1484 mVibratorUnderExternalControl = externalControl; 1485 vibratorSetExternalControl(externalControl); 1486 } 1487 dumpInternal(PrintWriter pw)1488 private void dumpInternal(PrintWriter pw) { 1489 pw.println("Vibrator Service:"); 1490 synchronized (mLock) { 1491 pw.print(" mCurrentVibration="); 1492 if (mCurrentVibration != null) { 1493 pw.println(mCurrentVibration.toInfo().toString()); 1494 } else { 1495 pw.println("null"); 1496 } 1497 pw.print(" mCurrentExternalVibration=" + mCurrentExternalVibration); 1498 pw.println(" mVibratorUnderExternalControl=" + mVibratorUnderExternalControl); 1499 pw.println(" mIsVibrating=" + mIsVibrating); 1500 pw.println(" mVibratorStateListeners Count=" + 1501 mVibratorStateListeners.getRegisteredCallbackCount()); 1502 pw.println(" mLowPowerMode=" + mLowPowerMode); 1503 pw.println(" mHapticFeedbackIntensity=" + mHapticFeedbackIntensity); 1504 pw.println(" mNotificationIntensity=" + mNotificationIntensity); 1505 pw.println(" mRingIntensity=" + mRingIntensity); 1506 pw.println(" mSupportedEffects=" + mSupportedEffects); 1507 pw.println(); 1508 pw.println(" Previous ring vibrations:"); 1509 for (VibrationInfo info : mPreviousRingVibrations) { 1510 pw.print(" "); 1511 pw.println(info.toString()); 1512 } 1513 1514 pw.println(" Previous notification vibrations:"); 1515 for (VibrationInfo info : mPreviousNotificationVibrations) { 1516 pw.println(" " + info); 1517 } 1518 1519 pw.println(" Previous alarm vibrations:"); 1520 for (VibrationInfo info : mPreviousAlarmVibrations) { 1521 pw.println(" " + info); 1522 } 1523 1524 pw.println(" Previous vibrations:"); 1525 for (VibrationInfo info : mPreviousVibrations) { 1526 pw.println(" " + info); 1527 } 1528 1529 pw.println(" Previous external vibrations:"); 1530 for (ExternalVibration vib : mPreviousExternalVibrations) { 1531 pw.println(" " + vib); 1532 } 1533 } 1534 } 1535 dumpProto(FileDescriptor fd)1536 private void dumpProto(FileDescriptor fd) { 1537 final ProtoOutputStream proto = new ProtoOutputStream(fd); 1538 1539 synchronized (mLock) { 1540 if (mCurrentVibration != null) { 1541 mCurrentVibration.toInfo().dumpProto(proto, 1542 VibratorServiceDumpProto.CURRENT_VIBRATION); 1543 } 1544 proto.write(VibratorServiceDumpProto.IS_VIBRATING, mIsVibrating); 1545 proto.write(VibratorServiceDumpProto.VIBRATOR_UNDER_EXTERNAL_CONTROL, 1546 mVibratorUnderExternalControl); 1547 proto.write(VibratorServiceDumpProto.LOW_POWER_MODE, mLowPowerMode); 1548 proto.write(VibratorServiceDumpProto.HAPTIC_FEEDBACK_INTENSITY, 1549 mHapticFeedbackIntensity); 1550 proto.write(VibratorServiceDumpProto.NOTIFICATION_INTENSITY, 1551 mNotificationIntensity); 1552 proto.write(VibratorServiceDumpProto.RING_INTENSITY, mRingIntensity); 1553 1554 for (VibrationInfo info : mPreviousRingVibrations) { 1555 info.dumpProto(proto, 1556 VibratorServiceDumpProto.PREVIOUS_RING_VIBRATIONS); 1557 } 1558 1559 for (VibrationInfo info : mPreviousNotificationVibrations) { 1560 info.dumpProto(proto, 1561 VibratorServiceDumpProto.PREVIOUS_NOTIFICATION_VIBRATIONS); 1562 } 1563 1564 for (VibrationInfo info : mPreviousAlarmVibrations) { 1565 info.dumpProto(proto, 1566 VibratorServiceDumpProto.PREVIOUS_ALARM_VIBRATIONS); 1567 } 1568 1569 for (VibrationInfo info : mPreviousVibrations) { 1570 info.dumpProto(proto, 1571 VibratorServiceDumpProto.PREVIOUS_VIBRATIONS); 1572 } 1573 } 1574 proto.flush(); 1575 } 1576 1577 private class VibrateThread extends Thread { 1578 private final VibrationEffect.Waveform mWaveform; 1579 private final int mUid; 1580 private final VibrationAttributes mAttrs; 1581 1582 private boolean mForceStop; 1583 VibrateThread(VibrationEffect.Waveform waveform, int uid, VibrationAttributes attrs)1584 VibrateThread(VibrationEffect.Waveform waveform, int uid, VibrationAttributes attrs) { 1585 mWaveform = waveform; 1586 mUid = uid; 1587 mAttrs = attrs; 1588 mTmpWorkSource.set(uid); 1589 mWakeLock.setWorkSource(mTmpWorkSource); 1590 } 1591 delayLocked(long duration)1592 private long delayLocked(long duration) { 1593 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "delayLocked"); 1594 try { 1595 long durationRemaining = duration; 1596 if (duration > 0) { 1597 final long bedtime = duration + SystemClock.uptimeMillis(); 1598 do { 1599 try { 1600 this.wait(durationRemaining); 1601 } 1602 catch (InterruptedException e) { } 1603 if (mForceStop) { 1604 break; 1605 } 1606 durationRemaining = bedtime - SystemClock.uptimeMillis(); 1607 } while (durationRemaining > 0); 1608 return duration - durationRemaining; 1609 } 1610 return 0; 1611 } finally { 1612 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 1613 } 1614 } 1615 run()1616 public void run() { 1617 Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 1618 mWakeLock.acquire(); 1619 try { 1620 boolean finished = playWaveform(); 1621 if (finished) { 1622 onVibrationFinished(); 1623 } 1624 } finally { 1625 mWakeLock.release(); 1626 } 1627 } 1628 1629 /** 1630 * Play the waveform. 1631 * 1632 * @return true if it finished naturally, false otherwise (e.g. it was canceled). 1633 */ playWaveform()1634 public boolean playWaveform() { 1635 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "playWaveform"); 1636 try { 1637 synchronized (this) { 1638 final long[] timings = mWaveform.getTimings(); 1639 final int[] amplitudes = mWaveform.getAmplitudes(); 1640 final int len = timings.length; 1641 final int repeat = mWaveform.getRepeatIndex(); 1642 1643 int index = 0; 1644 long onDuration = 0; 1645 while (!mForceStop) { 1646 if (index < len) { 1647 final int amplitude = amplitudes[index]; 1648 final long duration = timings[index++]; 1649 if (duration <= 0) { 1650 continue; 1651 } 1652 if (amplitude != 0) { 1653 if (onDuration <= 0) { 1654 // Telling the vibrator to start multiple times usually causes 1655 // effects to feel "choppy" because the motor resets at every on 1656 // command. Instead we figure out how long our next "on" period 1657 // is going to be, tell the motor to stay on for the full 1658 // duration, and then wake up to change the amplitude at the 1659 // appropriate intervals. 1660 onDuration = getTotalOnDuration(timings, amplitudes, index - 1, 1661 repeat); 1662 doVibratorOn(onDuration, amplitude, mUid, mAttrs); 1663 } else { 1664 doVibratorSetAmplitude(amplitude); 1665 } 1666 } 1667 1668 long waitTime = delayLocked(duration); 1669 if (amplitude != 0) { 1670 onDuration -= waitTime; 1671 } 1672 } else if (repeat < 0) { 1673 break; 1674 } else { 1675 index = repeat; 1676 } 1677 } 1678 return !mForceStop; 1679 } 1680 } finally { 1681 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 1682 } 1683 } 1684 cancel()1685 public void cancel() { 1686 synchronized (this) { 1687 mThread.mForceStop = true; 1688 mThread.notify(); 1689 } 1690 } 1691 1692 /** 1693 * Get the duration the vibrator will be on starting at startIndex until the next time it's 1694 * off. 1695 */ getTotalOnDuration( long[] timings, int[] amplitudes, int startIndex, int repeatIndex)1696 private long getTotalOnDuration( 1697 long[] timings, int[] amplitudes, int startIndex, int repeatIndex) { 1698 int i = startIndex; 1699 long timing = 0; 1700 while (amplitudes[i] != 0) { 1701 timing += timings[i++]; 1702 if (i >= timings.length) { 1703 if (repeatIndex >= 0) { 1704 i = repeatIndex; 1705 // prevent infinite loop 1706 repeatIndex = -1; 1707 } else { 1708 break; 1709 } 1710 } 1711 if (i == startIndex) { 1712 return 1000; 1713 } 1714 } 1715 return timing; 1716 } 1717 } 1718 1719 BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 1720 @Override 1721 public void onReceive(Context context, Intent intent) { 1722 if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 1723 synchronized (mLock) { 1724 // When the system is entering a non-interactive state, we want 1725 // to cancel vibrations in case a misbehaving app has abandoned 1726 // them. However it may happen that the system is currently playing 1727 // haptic feedback as part of the transition. So we don't cancel 1728 // system vibrations. 1729 if (mCurrentVibration != null 1730 && !(mCurrentVibration.isHapticFeedback() 1731 && mCurrentVibration.isFromSystem())) { 1732 doCancelVibrateLocked(); 1733 } 1734 } 1735 } 1736 } 1737 }; 1738 1739 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1740 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1741 if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 1742 1743 final long ident = Binder.clearCallingIdentity(); 1744 1745 boolean isDumpProto = false; 1746 for (String arg : args) { 1747 if (arg.equals("--proto")) { 1748 isDumpProto = true; 1749 } 1750 } 1751 try { 1752 if (isDumpProto) { 1753 dumpProto(fd); 1754 } else { 1755 dumpInternal(pw); 1756 } 1757 } finally { 1758 Binder.restoreCallingIdentity(ident); 1759 } 1760 } 1761 1762 @Override onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, String[] args, ShellCallback callback, ResultReceiver resultReceiver)1763 public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 1764 String[] args, ShellCallback callback, ResultReceiver resultReceiver) { 1765 new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver); 1766 } 1767 1768 final class ExternalVibratorService extends IExternalVibratorService.Stub { 1769 ExternalVibrationDeathRecipient mCurrentExternalDeathRecipient; 1770 1771 @Override onExternalVibrationStart(ExternalVibration vib)1772 public int onExternalVibrationStart(ExternalVibration vib) { 1773 if (!mSupportsExternalControl) { 1774 return SCALE_MUTE; 1775 } 1776 if (ActivityManager.checkComponentPermission(android.Manifest.permission.VIBRATE, 1777 vib.getUid(), -1 /*owningUid*/, true /*exported*/) 1778 != PackageManager.PERMISSION_GRANTED) { 1779 Slog.w(TAG, "pkg=" + vib.getPackage() + ", uid=" + vib.getUid() 1780 + " tried to play externally controlled vibration" 1781 + " without VIBRATE permission, ignoring."); 1782 return SCALE_MUTE; 1783 } 1784 1785 int mode = getAppOpMode(vib.getUid(), vib.getPackage(), vib.getVibrationAttributes()); 1786 if (mode != AppOpsManager.MODE_ALLOWED) { 1787 if (mode == AppOpsManager.MODE_ERRORED) { 1788 Slog.w(TAG, "Would be an error: external vibrate from uid " + vib.getUid()); 1789 } 1790 return SCALE_MUTE; 1791 } 1792 1793 final int scaleLevel; 1794 synchronized (mLock) { 1795 if (!vib.equals(mCurrentExternalVibration)) { 1796 if (mCurrentExternalVibration == null) { 1797 // If we're not under external control right now, then cancel any normal 1798 // vibration that may be playing and ready the vibrator for external 1799 // control. 1800 doCancelVibrateLocked(); 1801 setVibratorUnderExternalControl(true); 1802 } 1803 // At this point we either have an externally controlled vibration playing, or 1804 // no vibration playing. Since the interface defines that only one externally 1805 // controlled vibration can play at a time, by returning something other than 1806 // SCALE_MUTE from this function we can be assured that if we are currently 1807 // playing vibration, it will be muted in favor of the new vibration. 1808 // 1809 // Note that this doesn't support multiple concurrent external controls, as we 1810 // would need to mute the old one still if it came from a different controller. 1811 mCurrentExternalVibration = vib; 1812 mCurrentExternalDeathRecipient = new ExternalVibrationDeathRecipient(); 1813 mCurrentExternalVibration.linkToDeath(mCurrentExternalDeathRecipient); 1814 if (mPreviousExternalVibrations.size() > mPreviousVibrationsLimit) { 1815 mPreviousExternalVibrations.removeFirst(); 1816 } 1817 mPreviousExternalVibrations.addLast(vib); 1818 if (DEBUG) { 1819 Slog.e(TAG, "Playing external vibration: " + vib); 1820 } 1821 } 1822 final int usage = vib.getVibrationAttributes().getUsage(); 1823 final int defaultIntensity; 1824 final int currentIntensity; 1825 if (isRingtone(usage)) { 1826 defaultIntensity = mVibrator.getDefaultRingVibrationIntensity(); 1827 currentIntensity = mRingIntensity; 1828 } else if (isNotification(usage)) { 1829 defaultIntensity = mVibrator.getDefaultNotificationVibrationIntensity(); 1830 currentIntensity = mNotificationIntensity; 1831 } else if (isHapticFeedback(usage)) { 1832 defaultIntensity = mVibrator.getDefaultHapticFeedbackIntensity(); 1833 currentIntensity = mHapticFeedbackIntensity; 1834 } else if (isAlarm(usage)) { 1835 defaultIntensity = Vibrator.VIBRATION_INTENSITY_HIGH; 1836 currentIntensity = Vibrator.VIBRATION_INTENSITY_HIGH; 1837 } else { 1838 defaultIntensity = 0; 1839 currentIntensity = 0; 1840 } 1841 scaleLevel = currentIntensity - defaultIntensity; 1842 } 1843 if (scaleLevel >= SCALE_VERY_LOW && scaleLevel <= SCALE_VERY_HIGH) { 1844 return scaleLevel; 1845 } else { 1846 // Presumably we want to play this but something about our scaling has gone 1847 // wrong, so just play with no scaling. 1848 Slog.w(TAG, "Error in scaling calculations, ended up with invalid scale level " 1849 + scaleLevel + " for vibration " + vib); 1850 return SCALE_NONE; 1851 } 1852 } 1853 1854 @Override onExternalVibrationStop(ExternalVibration vib)1855 public void onExternalVibrationStop(ExternalVibration vib) { 1856 synchronized (mLock) { 1857 if (vib.equals(mCurrentExternalVibration)) { 1858 mCurrentExternalVibration.unlinkToDeath(mCurrentExternalDeathRecipient); 1859 mCurrentExternalDeathRecipient = null; 1860 mCurrentExternalVibration = null; 1861 setVibratorUnderExternalControl(false); 1862 if (DEBUG) { 1863 Slog.e(TAG, "Stopping external vibration" + vib); 1864 } 1865 } 1866 } 1867 } 1868 1869 private class ExternalVibrationDeathRecipient implements IBinder.DeathRecipient { binderDied()1870 public void binderDied() { 1871 synchronized (mLock) { 1872 onExternalVibrationStop(mCurrentExternalVibration); 1873 } 1874 } 1875 } 1876 } 1877 1878 private final class VibratorShellCommand extends ShellCommand { 1879 1880 private final IBinder mToken; 1881 1882 private final class CommonOptions { 1883 public boolean force = false; check(String opt)1884 public void check(String opt) { 1885 switch (opt) { 1886 case "-f": 1887 force = true; 1888 break; 1889 } 1890 } 1891 } 1892 VibratorShellCommand(IBinder token)1893 private VibratorShellCommand(IBinder token) { 1894 mToken = token; 1895 } 1896 1897 @Override onCommand(String cmd)1898 public int onCommand(String cmd) { 1899 if ("vibrate".equals(cmd)) { 1900 return runVibrate(); 1901 } else if ("waveform".equals(cmd)) { 1902 return runWaveform(); 1903 } else if ("prebaked".equals(cmd)) { 1904 return runPrebaked(); 1905 } else if ("capabilities".equals(cmd)) { 1906 return runCapabilities(); 1907 } else if ("cancel".equals(cmd)) { 1908 cancelVibrate(mToken); 1909 return 0; 1910 } 1911 return handleDefaultCommands(cmd); 1912 } 1913 checkDoNotDisturb(CommonOptions opts)1914 private boolean checkDoNotDisturb(CommonOptions opts) { 1915 try { 1916 final int zenMode = Settings.Global.getInt(mContext.getContentResolver(), 1917 Settings.Global.ZEN_MODE); 1918 if (zenMode != Settings.Global.ZEN_MODE_OFF && !opts.force) { 1919 try (PrintWriter pw = getOutPrintWriter();) { 1920 pw.print("Ignoring because device is on DND mode "); 1921 pw.println(DebugUtils.flagsToString(Settings.Global.class, "ZEN_MODE_", 1922 zenMode)); 1923 return true; 1924 } 1925 } 1926 } catch (SettingNotFoundException e) { 1927 // ignore 1928 } 1929 1930 return false; 1931 } 1932 runVibrate()1933 private int runVibrate() { 1934 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runVibrate"); 1935 try { 1936 CommonOptions commonOptions = new CommonOptions(); 1937 1938 String opt; 1939 while ((opt = getNextOption()) != null) { 1940 commonOptions.check(opt); 1941 } 1942 1943 if (checkDoNotDisturb(commonOptions)) { 1944 return 0; 1945 } 1946 1947 final long duration = Long.parseLong(getNextArgRequired()); 1948 String description = getNextArg(); 1949 if (description == null) { 1950 description = "Shell command"; 1951 } 1952 1953 VibrationEffect effect = 1954 VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE); 1955 VibrationAttributes attrs = createVibrationAttributes(commonOptions); 1956 vibrate(Binder.getCallingUid(), description, effect, attrs, "Shell Command", 1957 mToken); 1958 return 0; 1959 } finally { 1960 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 1961 } 1962 } 1963 runWaveform()1964 private int runWaveform() { 1965 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runWaveform"); 1966 try { 1967 String description = "Shell command"; 1968 int repeat = -1; 1969 ArrayList<Integer> amplitudesList = null; 1970 CommonOptions commonOptions = new CommonOptions(); 1971 1972 String opt; 1973 while ((opt = getNextOption()) != null) { 1974 switch (opt) { 1975 case "-d": 1976 description = getNextArgRequired(); 1977 break; 1978 case "-r": 1979 repeat = Integer.parseInt(getNextArgRequired()); 1980 break; 1981 case "-a": 1982 if (amplitudesList == null) { 1983 amplitudesList = new ArrayList<Integer>(); 1984 } 1985 break; 1986 default: 1987 commonOptions.check(opt); 1988 break; 1989 } 1990 } 1991 1992 if (checkDoNotDisturb(commonOptions)) { 1993 return 0; 1994 } 1995 1996 ArrayList<Long> timingsList = new ArrayList<Long>(); 1997 1998 String arg; 1999 while ((arg = getNextArg()) != null) { 2000 if (amplitudesList != null && amplitudesList.size() < timingsList.size()) { 2001 amplitudesList.add(Integer.parseInt(arg)); 2002 } else { 2003 timingsList.add(Long.parseLong(arg)); 2004 } 2005 } 2006 2007 VibrationEffect effect; 2008 long[] timings = timingsList.stream().mapToLong(Long::longValue).toArray(); 2009 if (amplitudesList == null) { 2010 effect = VibrationEffect.createWaveform(timings, repeat); 2011 } else { 2012 int[] amplitudes = 2013 amplitudesList.stream().mapToInt(Integer::intValue).toArray(); 2014 effect = VibrationEffect.createWaveform(timings, amplitudes, repeat); 2015 } 2016 VibrationAttributes attrs = createVibrationAttributes(commonOptions); 2017 vibrate(Binder.getCallingUid(), description, effect, attrs, "Shell Command", 2018 mToken); 2019 return 0; 2020 } finally { 2021 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 2022 } 2023 } 2024 runPrebaked()2025 private int runPrebaked() { 2026 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runPrebaked"); 2027 try { 2028 CommonOptions commonOptions = new CommonOptions(); 2029 boolean shouldFallback = false; 2030 2031 String opt; 2032 while ((opt = getNextOption()) != null) { 2033 if ("-b".equals(opt)) { 2034 shouldFallback = true; 2035 } else { 2036 commonOptions.check(opt); 2037 } 2038 } 2039 2040 if (checkDoNotDisturb(commonOptions)) { 2041 return 0; 2042 } 2043 2044 final int id = Integer.parseInt(getNextArgRequired()); 2045 2046 String description = getNextArg(); 2047 if (description == null) { 2048 description = "Shell command"; 2049 } 2050 2051 VibrationEffect effect = VibrationEffect.get(id, shouldFallback); 2052 VibrationAttributes attrs = createVibrationAttributes(commonOptions); 2053 vibrate(Binder.getCallingUid(), description, effect, attrs, "Shell Command", 2054 mToken); 2055 return 0; 2056 } finally { 2057 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 2058 } 2059 } 2060 runCapabilities()2061 private int runCapabilities() { 2062 Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "runCapabilities"); 2063 try (PrintWriter pw = getOutPrintWriter();) { 2064 pw.println("Vibrator capabilities:"); 2065 if (hasCapability(IVibrator.CAP_ALWAYS_ON_CONTROL)) { 2066 pw.println(" Always on effects"); 2067 } 2068 if (hasCapability(IVibrator.CAP_COMPOSE_EFFECTS)) { 2069 pw.println(" Compose effects"); 2070 } 2071 if (mSupportsAmplitudeControl || hasCapability(IVibrator.CAP_AMPLITUDE_CONTROL)) { 2072 pw.println(" Amplitude control"); 2073 } 2074 if (mSupportsExternalControl || hasCapability(IVibrator.CAP_EXTERNAL_CONTROL)) { 2075 pw.println(" External control"); 2076 } 2077 if (hasCapability(IVibrator.CAP_EXTERNAL_AMPLITUDE_CONTROL)) { 2078 pw.println(" External amplitude control"); 2079 } 2080 pw.println(""); 2081 return 0; 2082 } finally { 2083 Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR); 2084 } 2085 } 2086 createVibrationAttributes(CommonOptions commonOptions)2087 private VibrationAttributes createVibrationAttributes(CommonOptions commonOptions) { 2088 final int flags = commonOptions.force 2089 ? VibrationAttributes.FLAG_BYPASS_INTERRUPTION_POLICY 2090 : 0; 2091 return new VibrationAttributes.Builder() 2092 // Used to apply Settings.System.HAPTIC_FEEDBACK_INTENSITY to scale effects. 2093 .setUsage(VibrationAttributes.USAGE_TOUCH) 2094 .replaceFlags(flags) 2095 .build(); 2096 } 2097 2098 @Override onHelp()2099 public void onHelp() { 2100 try (PrintWriter pw = getOutPrintWriter();) { 2101 pw.println("Vibrator commands:"); 2102 pw.println(" help"); 2103 pw.println(" Prints this help text."); 2104 pw.println(""); 2105 pw.println(" vibrate duration [description]"); 2106 pw.println(" Vibrates for duration milliseconds; ignored when device is on "); 2107 pw.println(" DND (Do Not Disturb) mode; touch feedback strength user setting "); 2108 pw.println(" will be used to scale amplitude."); 2109 pw.println(" waveform [-d description] [-r index] [-a] duration [amplitude] ..."); 2110 pw.println(" Vibrates for durations and amplitudes in list; ignored when "); 2111 pw.println(" device is on DND (Do Not Disturb) mode; touch feedback strength "); 2112 pw.println(" user setting will be used to scale amplitude."); 2113 pw.println(" If -r is provided, the waveform loops back to the specified"); 2114 pw.println(" index (e.g. 0 loops from the beginning)"); 2115 pw.println(" If -a is provided, the command accepts duration-amplitude pairs;"); 2116 pw.println(" otherwise, it accepts durations only and alternates off/on"); 2117 pw.println(" Duration is in milliseconds; amplitude is a scale of 1-255."); 2118 pw.println(" prebaked [-b] effect-id [description]"); 2119 pw.println(" Vibrates with prebaked effect; ignored when device is on DND "); 2120 pw.println(" (Do Not Disturb) mode; touch feedback strength user setting "); 2121 pw.println(" will be used to scale amplitude."); 2122 pw.println(" If -b is provided, the prebaked fallback effect will be played if"); 2123 pw.println(" the device doesn't support the given effect-id."); 2124 pw.println(" capabilities"); 2125 pw.println(" Prints capabilities of this device."); 2126 pw.println(" cancel"); 2127 pw.println(" Cancels any active vibration"); 2128 pw.println("Common Options:"); 2129 pw.println(" -f - Force. Ignore Do Not Disturb setting."); 2130 pw.println(""); 2131 } 2132 } 2133 } 2134 2135 } 2136