19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 19a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver; 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager; 257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.content.res.Resources; 267f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.database.ContentObserver; 277f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.hardware.input.InputManager; 287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.hardware.vibrator.V1_0.Constants.EffectStrength; 292d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebingerimport android.media.AudioManager; 30455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport android.os.PowerSaveState; 3191268cf21eace600792d04db1ac62e9268f48002Dianne Hackbornimport android.os.BatteryStats; 3295e4f70624ae9695bdd9029eb22a9e271401fbd5Joe Onoratoimport android.os.Handler; 333a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.IVibratorService; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 35eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackbornimport android.os.PowerManagerInternal; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 38a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ResultReceiver; 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 41a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager; 42a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ShellCallback; 43a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ShellCommand; 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 45d49359631bc2642be73dc162a8a73207df1e0bafJeff Brownimport android.os.UserHandle; 467f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.os.Vibrator; 477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.os.VibrationEffect; 487e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource; 497f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings; 507f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings.SettingNotFoundException; 515e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Lemeimport android.util.DebugUtils; 528a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 537f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice; 547b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes; 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 56a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 57a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats; 58fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils; 59455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport com.android.server.power.BatterySaverPolicy.ServiceType; 60a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 613a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor; 623a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter; 637f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList; 6418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList; 6518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 667f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub 677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown implements InputManager.InputDeviceListener { 683a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood private static final String TAG = "VibratorService"; 6982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown private static final boolean DEBUG = false; 7018f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi private static final String SYSTEM_UI_PACKAGE = "com.android.systemui"; 71cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood 723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final LinkedList<VibrationInfo> mPreviousVibrations; 733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final int mPreviousVibrationsLimit; 74319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman private final boolean mAllowPriorityVibrationsInLowPowerMode; 757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final boolean mSupportsAmplitudeControl; 767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mDefaultVibrationAmplitude; 777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect[] mFallbackEffects; 787e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final WorkSource mTmpWorkSource = new WorkSource(); 797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Handler mH = new Handler(); 807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final Object mLock = new Object(); 817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Context mContext; 837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final PowerManager.WakeLock mWakeLock; 84a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IAppOpsService mAppOpsService; 85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IBatteryStats mBatteryStatsService; 86eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn private PowerManagerInternal mPowerManagerInternal; 877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private InputManager mIm; 887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private volatile VibrateThread mThread; 907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // mInputDeviceVibrators lock should be acquired after mLock, if both are 927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // to be acquired 937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private Vibration mCurrentVibration; 98a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int mCurVibUid = -1; 9913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private boolean mLowPowerMode; 10013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private SettingsObserver mSettingObserver; 101a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static boolean vibratorExists(); 103e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker native static void vibratorInit(); 1047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOn(long milliseconds); 1057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOff(); 1067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static boolean vibratorSupportsAmplitudeControl(); 1077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static void vibratorSetAmplitude(int amplitude); 1087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static long vibratorPerformEffect(long effect, long strength); 10918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private class Vibration implements IBinder.DeathRecipient { 11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final IBinder mToken; 1127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect mEffect; 1137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final long mStartTime; 1147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 1157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 1167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final String mOpPkg; 11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private Vibration(IBinder token, VibrationEffect effect, 1197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int usageHint, int uid, String opPkg) { 12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mToken = token; 1217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mEffect = effect; 12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mStartTime = SystemClock.uptimeMillis(); 1237b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mUsageHint = usageHint; 1247e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mUid = uid; 1258fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mOpPkg = opPkg; 12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void binderDied() { 1297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (this == mCurrentVibration) { 13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public boolean hasLongerTimeout(long millis) { 1377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If the current effect is a one shot vibration that will end after the given timeout 1387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // for the new one shot vibration, then just let the current vibration finish. All 1397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // other effect types will get pre-empted. 1407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mEffect instanceof VibrationEffect.OneShot) { 1417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) mEffect; 1427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mStartTime + oneShot.getTiming() > SystemClock.uptimeMillis() + millis; 14318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 1447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 14518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 146969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown 147969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown public boolean isSystemHapticFeedback() { 1487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean repeating = false; 1497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mEffect instanceof VibrationEffect.Waveform) { 1507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) mEffect; 1517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright repeating = (waveform.getRepeatIndex() < 0); 1527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 15318f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg)) 1547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && !repeating; 155969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 15618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 15718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1583a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private static class VibrationInfo { 1597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final long mStartTime; 1607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect mEffect; 1617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 1627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 1637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final String mOpPkg; 1647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 1657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public VibrationInfo(long startTime, VibrationEffect effect, 1663a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int usageHint, int uid, String opPkg) { 1677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mStartTime = startTime; 1687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mEffect = effect; 1697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUsageHint = usageHint; 1707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUid = uid; 1717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mOpPkg = opPkg; 1723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski public String toString() { 1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski return new StringBuilder() 1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", startTime: ") 1787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mStartTime) 1797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(", effect: ") 1807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mEffect) 1813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", usageHint: ") 1827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mUsageHint) 1833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", uid: ") 1847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mUid) 1853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", opPkg: ") 1867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mOpPkg) 1873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .toString(); 1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1913a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood VibratorService(Context context) { 192e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker vibratorInit(); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the hardware to a default state, in case this is a runtime 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restart instead of a fresh boot. 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vibratorOff(); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl(); 1987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 2007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 2017e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(true); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mAppOpsService = 2057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); 20691268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService( 20791268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn BatteryStats.SERVICE_NAME)); 208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 2093a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrationsLimit = mContext.getResources().getInteger( 2103a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski com.android.internal.R.integer.config_previousVibrationsDumpLimit); 2113a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 2127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mDefaultVibrationAmplitude = mContext.getResources().getInteger( 2137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright com.android.internal.R.integer.config_defaultVibrationAmplitude); 2147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 215319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean( 216319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode); 217319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman 2183a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations = new LinkedList<>(); 21918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_SCREEN_OFF); 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.registerReceiver(mIntentReceiver, filter); 2237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] clickEffectTimings = getLongIntArray(context.getResources(), 2257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright com.android.internal.R.array.config_virtualKeyVibePattern); 22657d94d9fb1e55345307e579977138aaf6177e388Michael Wright VibrationEffect clickEffect = createEffect(clickEffectTimings); 2277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect doubleClickEffect = VibrationEffect.createWaveform( 2287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new long[] {0, 30, 100, 30} /*timings*/, -1); 22957d94d9fb1e55345307e579977138aaf6177e388Michael Wright long[] tickEffectTimings = getLongIntArray(context.getResources(), 23057d94d9fb1e55345307e579977138aaf6177e388Michael Wright com.android.internal.R.array.config_clockTickVibePattern); 23157d94d9fb1e55345307e579977138aaf6177e388Michael Wright VibrationEffect tickEffect = createEffect(tickEffectTimings); 23257d94d9fb1e55345307e579977138aaf6177e388Michael Wright 23357d94d9fb1e55345307e579977138aaf6177e388Michael Wright mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect, tickEffect }; 23457d94d9fb1e55345307e579977138aaf6177e388Michael Wright } 2357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 23657d94d9fb1e55345307e579977138aaf6177e388Michael Wright private static VibrationEffect createEffect(long[] timings) { 23757d94d9fb1e55345307e579977138aaf6177e388Michael Wright if (timings == null || timings.length == 0) { 23857d94d9fb1e55345307e579977138aaf6177e388Michael Wright return null; 23957d94d9fb1e55345307e579977138aaf6177e388Michael Wright } else if (timings.length == 1) { 24057d94d9fb1e55345307e579977138aaf6177e388Michael Wright return VibrationEffect.createOneShot(timings[0], VibrationEffect.DEFAULT_AMPLITUDE); 24157d94d9fb1e55345307e579977138aaf6177e388Michael Wright } else { 24257d94d9fb1e55345307e579977138aaf6177e388Michael Wright return VibrationEffect.createWaveform(timings, -1); 24357d94d9fb1e55345307e579977138aaf6177e388Michael Wright } 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 2478ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa mIm = mContext.getSystemService(InputManager.class); 24813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi mSettingObserver = new SettingsObserver(mH); 249d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 250eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 251eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal.registerLowPowerModeObserver( 252eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn new PowerManagerInternal.LowPowerModeListener() { 253455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei @Override 254455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei public int getServiceType() { 255455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei return ServiceType.VIBRATION; 256455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei } 257455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei 258455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei @Override 259455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei public void onLowPowerModeChanged(PowerSaveState result) { 2607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 261455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei } 262eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn }); 263eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn 2647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 26513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), 26613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi true, mSettingObserver, UserHandle.USER_ALL); 26713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 268d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 269d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 270d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 2717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 272d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 273d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 274d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 2757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 2767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 2777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 27813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private final class SettingsObserver extends ContentObserver { 27913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public SettingsObserver(Handler handler) { 28013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi super(handler); 28113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 28213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 28313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi @Override 28413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public void onChange(boolean SelfChange) { 2857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 28613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 28713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 28813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 28982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 290ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 2917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 292ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 2937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 2947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright @Override // Binder call 2957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public boolean hasAmplitudeControl() { 2967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mInputDeviceVibrators) { 2977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Input device vibrators don't support amplitude controls yet, but are still used over 2987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // the system vibrator when connected. 2997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty(); 3007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 303f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 304f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (uid == Binder.getCallingUid()) { 305f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 306f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 307f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 308f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 309f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 310f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 311f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 312f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 313f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Validate the incoming VibrationEffect. 3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * We can't throw exceptions here since we might be called from some system_server component, 3187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * which would bring the whole system down. 3197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 3207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * @return whether the VibrationEffect is valid 3217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private static boolean verifyVibrationEffect(VibrationEffect effect) { 3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect == null) { 3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Effect must not be null. 3257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.wtf(TAG, "effect must not be null"); 3267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 327105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 328a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 3297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright effect.validate(); 3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (Exception e) { 3317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e); 3327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 33318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private static long[] getLongIntArray(Resources r, int resid) { 3387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int[] ar = r.getIntArray(resid); 3397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (ar == null) { 3407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return null; 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] out = new long[ar.length]; 3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright for (int i = 0; i < ar.length; i++) { 3447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright out[i] = ar[i]; 3457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return out; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 3507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint, 3517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright IBinder token) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (token == null) { 3577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "token must not be null"); 3587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 360f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (!verifyVibrationEffect(effect)) { 3627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 3637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If our current vibration is longer than the new vibration and is the same amplitude, 3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // then just let the current one finish. 3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect instanceof VibrationEffect.OneShot 3687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && mCurrentVibration != null 3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) { 3707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect; 3717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot currentOneShot = 3727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright (VibrationEffect.OneShot) mCurrentVibration.mEffect; 3737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming()) 3747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) { 3757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 37658c4631c29b4f36737f261d1a2888e66592eda32Michael Wright Slog.d(TAG, "Ignoring incoming vibration in favor of current vibration"); 3777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 38258c4631c29b4f36737f261d1a2888e66592eda32Michael Wright // If the current vibration is repeating and the incoming one is non-repeating, then ignore 38358c4631c29b4f36737f261d1a2888e66592eda32Michael Wright // the non-repeating vibration. This is so that we don't cancel vibrations that are meant 38458c4631c29b4f36737f261d1a2888e66592eda32Michael Wright // to grab the attention of the user, like ringtones and alarms, in favor of one-shot 38558c4631c29b4f36737f261d1a2888e66592eda32Michael Wright // vibrations that are likely quite short. 38658c4631c29b4f36737f261d1a2888e66592eda32Michael Wright if (!isRepeatingVibration(effect) 38758c4631c29b4f36737f261d1a2888e66592eda32Michael Wright && mCurrentVibration != null && isRepeatingVibration(mCurrentVibration.mEffect)) { 38858c4631c29b4f36737f261d1a2888e66592eda32Michael Wright if (DEBUG) { 38958c4631c29b4f36737f261d1a2888e66592eda32Michael Wright Slog.d(TAG, "Ignoring incoming vibration in favor of alarm vibration"); 39058c4631c29b4f36737f261d1a2888e66592eda32Michael Wright } 39158c4631c29b4f36737f261d1a2888e66592eda32Michael Wright return; 39258c4631c29b4f36737f261d1a2888e66592eda32Michael Wright } 39358c4631c29b4f36737f261d1a2888e66592eda32Michael Wright 3947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg); 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Only link against waveforms since they potentially don't have a finish if 3977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // they're repeating. Let other effects just play out until they're done. 3987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect instanceof VibrationEffect.Waveform) { 39918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 40018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 40118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 40218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 40318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 4047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 4077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long ident = Binder.clearCallingIdentity(); 4087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 4097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 41018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 4117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationLocked(vib); 4123a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski addToPreviousVibrationsLocked(vib); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 4157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Binder.restoreCallingIdentity(ident); 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 41958c4631c29b4f36737f261d1a2888e66592eda32Michael Wright private static boolean isRepeatingVibration(VibrationEffect effect) { 42058c4631c29b4f36737f261d1a2888e66592eda32Michael Wright if (effect instanceof VibrationEffect.Waveform) { 42158c4631c29b4f36737f261d1a2888e66592eda32Michael Wright final VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) effect; 42258c4631c29b4f36737f261d1a2888e66592eda32Michael Wright if (waveform.getRepeatIndex() >= 0) { 42358c4631c29b4f36737f261d1a2888e66592eda32Michael Wright return true; 42458c4631c29b4f36737f261d1a2888e66592eda32Michael Wright } 42558c4631c29b4f36737f261d1a2888e66592eda32Michael Wright } 42658c4631c29b4f36737f261d1a2888e66592eda32Michael Wright return false; 42758c4631c29b4f36737f261d1a2888e66592eda32Michael Wright } 42858c4631c29b4f36737f261d1a2888e66592eda32Michael Wright 4293a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private void addToPreviousVibrationsLocked(Vibration vib) { 4303a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mPreviousVibrations.size() > mPreviousVibrationsLimit) { 4313a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations.removeFirst(); 4323a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 4337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mPreviousVibrations.addLast(new VibrationInfo( 4347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg)); 4353a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 4363a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 43782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 43818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 4447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 4457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.d(TAG, "Canceling vibration."); 4477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long ident = Binder.clearCallingIdentity(); 4497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 45018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Binder.restoreCallingIdentity(ident); 45318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 45418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 457f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 4587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final Runnable mVibrationEndRunnable = new Runnable() { 45982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override 46018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 4617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onVibrationFinished(); 46218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 46318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 46418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 46518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.removeCallbacks(mVibrationEndRunnable); 46718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.cancel(); 46918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 472a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 47318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 47418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 4757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Callback for whenever the current vibration has finished played out 4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void onVibrationFinished() { 4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibration finished, cleaning up"); 4797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 4817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Make sure the vibration is really done. This also reports that the vibration is 4827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // finished. 4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doCancelVibrateLocked(); 48418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 48518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 48618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 48718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 488319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman if (!isAllowedToVibrate(vib)) { 4897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibrate ignored, low power mode"); 491664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi } 4927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 4937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 49413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE && 4967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright !shouldVibrateForRingtone()) { 4977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); 499d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds } 5007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 5017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 502d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds 5037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int mode = getAppOpMode(vib); 5047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode != AppOpsManager.MODE_ALLOWED) { 5057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode == AppOpsManager.MODE_ERRORED) { 5067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // We might be getting calls from within system_server, so we don't actually want 5077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // to throw a SecurityException here. 5087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 5091af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 5107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 511a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 5127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationInnerLocked(vib); 5137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 5157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void startVibrationInnerLocked(Vibration vib) { 5167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurrentVibration = vib; 5177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mEffect instanceof VibrationEffect.OneShot) { 5187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect; 5197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint); 5207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming()); 5217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (vib.mEffect instanceof VibrationEffect.Waveform) { 52218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 52318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 5247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect; 5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint); 52618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (vib.mEffect instanceof VibrationEffect.Prebaked) { 5287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timeout = doVibratorPrebakedEffectLocked(vib); 5297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (timeout > 0) { 5307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.postDelayed(mVibrationEndRunnable, timeout); 5317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 5337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Unknown vibration type, ignoring"); 53418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 53518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 53618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 537319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman private boolean isAllowedToVibrate(Vibration vib) { 538319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman if (!mLowPowerMode) { 539319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman return true; 540319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman } 541319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) { 542319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman return true; 543319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman } 544319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman if (!mAllowPriorityVibrationsInLowPowerMode) { 545319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman return false; 546319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman } 547319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman if (vib.mUsageHint == AudioAttributes.USAGE_ALARM || 548319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman vib.mUsageHint == AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY || 549319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST) { 550319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman 551319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman return true; 552319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman } 553319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman 554319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman return false; 555319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman } 556319a34ae87def49d503c19b24d3e00a8f7442809Tyler Freeman 5572d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger private boolean shouldVibrateForRingtone() { 5582d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 559dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger int ringerMode = audioManager.getRingerModeInternal(); 5602d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger // "Also vibrate for calls" Setting in Sound 5612d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger if (Settings.System.getInt( 5622d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) { 5632d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode != AudioManager.RINGER_MODE_SILENT; 5642d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } else { 5652d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode == AudioManager.RINGER_MODE_VIBRATE; 5662d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5672d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5682d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger 5697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private int getAppOpMode(Vibration vib) { 5707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int mode; 5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE, 5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vib.mUsageHint, vib.mUid, vib.mOpPkg); 5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode == AppOpsManager.MODE_ALLOWED) { 5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), 5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg); 5777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { 5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Failed to get appop mode for vibration!", e); 5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = AppOpsManager.MODE_IGNORED; 5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mode; 5837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 585a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 586a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 587a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 588e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), 589e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 5908fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mCurrentVibration.mOpPkg); 5917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { } 592a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 593a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 594a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 595a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 596b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 5977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mEffect instanceof VibrationEffect.Waveform) { 598b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 599b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 600b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 601b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void updateVibrators() { 6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 6047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean devicesUpdated = updateInputDeviceVibratorsLocked(); 6057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean lowPowerModeUpdated = updateLowPowerModeLocked(); 6067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (devicesUpdated || lowPowerModeUpdated) { 6087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If the state changes out from under us then just reset. 6097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doCancelVibrateLocked(); 6107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6138206525b242ceb012d882849c4e355223ba81b9dJeff Brown 6147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean updateInputDeviceVibratorsLocked() { 6157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean changed = false; 6167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean vibrateInputDevices = false; 6177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 6187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibrateInputDevices = Settings.System.getIntForUser( 6197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mContext.getContentResolver(), 6207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 6217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (SettingNotFoundException snfe) { 6227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibrateInputDevices != mVibrateInputDevicesSetting) { 6247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright changed = true; 6257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mVibrateInputDevicesSetting = vibrateInputDevices; 6267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 62713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 6287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mVibrateInputDevicesSetting) { 6297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (!mInputDeviceListenerRegistered) { 6307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceListenerRegistered = true; 6317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mIm.registerInputDeviceListener(this, mH); 6327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 6347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mInputDeviceListenerRegistered) { 6357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceListenerRegistered = false; 6367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mIm.unregisterInputDeviceListener(this); 6377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6398206525b242ceb012d882849c4e355223ba81b9dJeff Brown 6407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceVibrators.clear(); 6417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mVibrateInputDevicesSetting) { 6427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int[] ids = mIm.getInputDeviceIds(); 6437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright for (int i = 0; i < ids.length; i++) { 6447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright InputDevice device = mIm.getInputDevice(ids[i]); 6457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibrator vibrator = device.getVibrator(); 6467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibrator.hasVibrator()) { 6477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceVibrators.add(vibrator); 6487f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 6517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return changed; 6537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean updateLowPowerModeLocked() { 6567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean lowPowerMode = mPowerManagerInternal 6577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled; 6587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (lowPowerMode != mLowPowerMode) { 6597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mLowPowerMode = lowPowerMode; 6607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 6617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 6637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 6677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 6727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 6777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 6811064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 6821064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 6831064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 6841064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 6851064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 6861064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 6871064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 6881064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 689c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn return vibratorExists(); 6907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) { 6937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 6947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) { 6957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright amplitude = mDefaultVibrationAmplitude; 69682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.d(TAG, "Turning vibrator on for " + millis + " ms" + 6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright " with amplitude " + amplitude + "."); 700a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOnLocked(uid, millis); 7027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 7037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final AudioAttributes attributes = 7057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new AudioAttributes.Builder().setUsage(usageHint).build(); 7067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 7077b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mInputDeviceVibrators.get(i).vibrate(millis, attributes); 7087f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 7097f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 7107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Note: ordering is important here! Many haptic drivers will reset their amplitude 7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // when enabled, so we always have to enable frst, then set the amplitude. 7127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorSetAmplitude(amplitude); 7147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 7157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 7167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 7177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void doVibratorSetAmplitude(int amplitude) { 7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mSupportsAmplitudeControl) { 7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibratorSetAmplitude(amplitude); 7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 7257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 72682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 72782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator off."); 72882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOffLocked(); 7307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 7317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 7327f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 7337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 7347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 7357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 7367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 7377f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 7387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 7397f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 7407f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long doVibratorPrebakedEffectLocked(Vibration vib) { 7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mInputDeviceVibrators) { 7437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect; 7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Input devices don't support prebaked effect, so skip trying it with them. 7457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int vibratorCount = mInputDeviceVibrators.size(); 7467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibratorCount == 0) { 7477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM); 7487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (timeout > 0) { 7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOnLocked(vib.mUid, timeout); 7507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return timeout; 7517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 753dc2b3be240705b53fa1749cbdaedd0a63931378dMichael Wright if (!prebaked.shouldFallback()) { 754dc2b3be240705b53fa1749cbdaedd0a63931378dMichael Wright return 0; 755dc2b3be240705b53fa1749cbdaedd0a63931378dMichael Wright } 7567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int id = prebaked.getId(); 757017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer if (id < 0 || id >= mFallbackEffects.length || mFallbackEffects[id] == null) { 7587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.w(TAG, "Failed to play prebaked effect, no fallback"); 7597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect effect = mFallbackEffects[id]; 7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibration fallbackVib = 7637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg); 7647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationInnerLocked(fallbackVib); 7657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void noteVibratorOnLocked(int uid, long millis) { 7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mBatteryStatsService.noteVibratorOn(uid, millis); 7727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurVibUid = uid; 7737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { 7747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void noteVibratorOffLocked() { 7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurVibUid >= 0) { 7797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mBatteryStatsService.noteVibratorOff(mCurVibUid); 7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { } 7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurVibUid = -1; 7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 7877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect.Waveform mWaveform; 7887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 790f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 7917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean mForceStop; 7927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) { 7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWaveform = waveform; 7957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUid = uid; 7967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUsageHint = usageHint; 7977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mTmpWorkSource.set(uid); 7987e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long delayLocked(long duration) { 8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long durationRemaining = duration; 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long bedtime = duration + SystemClock.uptimeMillis(); 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright this.wait(durationRemaining); 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright catch (InterruptedException e) { } 8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mForceStop) { 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright durationRemaining = bedtime - SystemClock.uptimeMillis(); 8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } while (durationRemaining > 0); 8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return duration - durationRemaining; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 8227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWakeLock.acquire(); 8237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 8247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean finished = playWaveform(); 8257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (finished) { 8267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onVibrationFinished(); 8277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 8297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWakeLock.release(); 8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Play the waveform. 8357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 8367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * @return true if it finished naturally, false otherwise (e.g. it was canceled). 8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public boolean playWaveform() { 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long[] timings = mWaveform.getTimings(); 8417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int[] amplitudes = mWaveform.getAmplitudes(); 8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int len = timings.length; 8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int repeat = mWaveform.getRepeatIndex(); 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int index = 0; 8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long onDuration = 0; 8477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright while (!mForceStop) { 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int amplitude = amplitudes[index]; 8507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long duration = timings[index++]; 8517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (duration <= 0) { 8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright continue; 8537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude != 0) { 8557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (onDuration <= 0) { 8567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Telling the vibrator to start multiple times usually causes 8577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // effects to feel "choppy" because the motor resets at every on 8587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // command. Instead we figure out how long our next "on" period is 8597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // going to be, tell the motor to stay on for the full duration, 8607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // and then wake up to change the amplitude at the appropriate 8617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // intervals. 8627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onDuration = 8637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright getTotalOnDuration(timings, amplitudes, index - 1, repeat); 8647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorOn(onDuration, amplitude, mUid, mUsageHint); 8657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 8667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorSetAmplitude(amplitude); 8677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long waitTime = delayLocked(duration); 8717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude != 0) { 8727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onDuration -= waitTime; 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (repeat < 0) { 8757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright break; 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright index = repeat; 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return !mForceStop; 8817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void cancel() { 8857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (this) { 8867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.mForceStop = true; 8877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.notify(); 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 8927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Get the duration the vibrator will be on starting at startIndex until the next time it's 8937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * off. 8947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 8957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long getTotalOnDuration( 8967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] timings, int[] amplitudes, int startIndex, int repeatIndex) { 8977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int i = startIndex; 8987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timing = 0; 8997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright while(amplitudes[i] != 0) { 9007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright timing += timings[i++]; 9017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (i >= timings.length) { 9027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (repeatIndex >= 0) { 9037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright i = repeatIndex; 9047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 9057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright break; 9067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (i == startIndex) { 9097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 1000; 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return timing; 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 914969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 917969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown @Override 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 9207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 921969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // When the system is entering a non-interactive state, we want 922969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // to cancel vibrations in case a misbehaving app has abandoned 923969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // them. However it may happen that the system is currently playing 924969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // haptic feedback as part of the transition. So we don't cancel 925969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // system vibrations. 926969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (mCurrentVibration != null 927969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown && !mCurrentVibration.isSystemHapticFeedback()) { 928969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown doCancelVibrateLocked(); 9298a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 93018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 9343a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 9353a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 9363a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 937fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 9383a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 9393a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Previous vibrations:"); 9407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 9413a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski for (VibrationInfo info : mPreviousVibrations) { 9423a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.print(" "); 9433a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println(info.toString()); 9443a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 9453a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 9463a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 950a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String[] args, ShellCallback callback, ResultReceiver resultReceiver) 951a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throws RemoteException { 952a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver); 953a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 954a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 955a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final class VibratorShellCommand extends ShellCommand { 956a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 957a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private static final long MAX_VIBRATION_MS = 200; 958a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 959a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final IBinder mToken; 960a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 961a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private VibratorShellCommand(IBinder token) { 962a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken = token; 963a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 964a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 965a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 966a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public int onCommand(String cmd) { 967a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if ("vibrate".equals(cmd)) { 968a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return runVibrate(); 969a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 970a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return handleDefaultCommands(cmd); 971a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 972a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 973a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private int runVibrate() { 9745e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme try { 9755e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme final int zenMode = Settings.Global.getInt(mContext.getContentResolver(), 9765e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme Settings.Global.ZEN_MODE); 9775e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme if (zenMode != Settings.Global.ZEN_MODE_OFF) { 9785e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme try (PrintWriter pw = getOutPrintWriter();) { 9795e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme pw.print("Ignoring because device is on DND mode "); 9805e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme pw.println(DebugUtils.flagsToString(Settings.Global.class, "ZEN_MODE_", 9815e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme zenMode)); 9825e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme return 0; 9835e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme } 9845e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme } 9855e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme } catch (SettingNotFoundException e) { 9865e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme // ignore 9875e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme } 9885e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme 989a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme final long duration = Long.parseLong(getNextArgRequired()); 990a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (duration > MAX_VIBRATION_MS) { 991a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS); 992a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 993a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String description = getNextArg(); 994a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (description == null) { 995a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme description = "Shell command"; 996a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 9977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 9987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect effect = 9997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE); 10007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN, 1001a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken); 1002a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return 0; 1003a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 1004a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 1005a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 1006a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onHelp() { 1007a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme try (PrintWriter pw = getOutPrintWriter();) { 1008a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println("Vibrator commands:"); 1009a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" help"); 1010a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Prints this help text."); 1011a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 1012a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" vibrate duration [description]"); 10135e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme pw.println(" Vibrates for duration milliseconds; ignored when device is on DND "); 10145e2e632085f44e289dfcf3d6c32e952244e894fcFelipe Leme pw.println(" (Do Not Disturb) mode."); 1015a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 1016a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 1017a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 1018a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 1019a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1021