VibratorService.java revision 017939e43ceb847333d1115258c3db1411dbc03a
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; 518a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 527f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice; 537b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes; 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 55a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 56a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats; 57fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils; 58455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport com.android.server.power.BatterySaverPolicy.ServiceType; 59a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 603a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor; 613a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter; 627f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList; 633a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.util.Arrays; 64969579bb9d208c91e081ff96d2fd788269d254bdJeff Brownimport java.util.Iterator; 6518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList; 6618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator; 6718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 687f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub 697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown implements InputManager.InputDeviceListener { 703a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood private static final String TAG = "VibratorService"; 7182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown private static final boolean DEBUG = false; 7218f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi private static final String SYSTEM_UI_PACKAGE = "com.android.systemui"; 73cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood 743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final LinkedList<VibrationInfo> mPreviousVibrations; 753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final int mPreviousVibrationsLimit; 767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final boolean mSupportsAmplitudeControl; 777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mDefaultVibrationAmplitude; 787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect[] mFallbackEffects; 797e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final WorkSource mTmpWorkSource = new WorkSource(); 807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Handler mH = new Handler(); 817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final Object mLock = new Object(); 827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Context mContext; 847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final PowerManager.WakeLock mWakeLock; 85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IAppOpsService mAppOpsService; 86a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IBatteryStats mBatteryStatsService; 87eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn private PowerManagerInternal mPowerManagerInternal; 887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private InputManager mIm; 897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private volatile VibrateThread mThread; 917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // mInputDeviceVibrators lock should be acquired after mLock, if both are 937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // to be acquired 947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private Vibration mCurrentVibration; 99a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int mCurVibUid = -1; 10013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private boolean mLowPowerMode; 10113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private SettingsObserver mSettingObserver; 102a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static boolean vibratorExists(); 104e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker native static void vibratorInit(); 1057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOn(long milliseconds); 1067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOff(); 1077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static boolean vibratorSupportsAmplitudeControl(); 1087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static void vibratorSetAmplitude(int amplitude); 1097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static long vibratorPerformEffect(long effect, long strength); 11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private class Vibration implements IBinder.DeathRecipient { 11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final IBinder mToken; 1137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect mEffect; 1147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final long mStartTime; 1157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 1167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 1177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final String mOpPkg; 11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private Vibration(IBinder token, VibrationEffect effect, 1207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int usageHint, int uid, String opPkg) { 12118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mToken = token; 1227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mEffect = effect; 12318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mStartTime = SystemClock.uptimeMillis(); 1247b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mUsageHint = usageHint; 1257e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mUid = uid; 1268fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mOpPkg = opPkg; 12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void binderDied() { 1307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (this == mCurrentVibration) { 13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 13718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public boolean hasLongerTimeout(long millis) { 1387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If the current effect is a one shot vibration that will end after the given timeout 1397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // for the new one shot vibration, then just let the current vibration finish. All 1407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // other effect types will get pre-empted. 1417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mEffect instanceof VibrationEffect.OneShot) { 1427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) mEffect; 1437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mStartTime + oneShot.getTiming() > SystemClock.uptimeMillis() + millis; 14418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 1457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 14618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 147969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown 148969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown public boolean isSystemHapticFeedback() { 1497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean repeating = false; 1507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mEffect instanceof VibrationEffect.Waveform) { 1517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) mEffect; 1527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright repeating = (waveform.getRepeatIndex() < 0); 1537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 15418f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg)) 1557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && !repeating; 156969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 15718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 15818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1593a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private static class VibrationInfo { 1607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final long mStartTime; 1617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect mEffect; 1627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 1637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 1647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final String mOpPkg; 1657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 1667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public VibrationInfo(long startTime, VibrationEffect effect, 1673a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int usageHint, int uid, String opPkg) { 1687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mStartTime = startTime; 1697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mEffect = effect; 1707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUsageHint = usageHint; 1717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUid = uid; 1727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mOpPkg = opPkg; 1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski public String toString() { 1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski return new StringBuilder() 1783a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", startTime: ") 1797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mStartTime) 1807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(", effect: ") 1817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mEffect) 1823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", usageHint: ") 1837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mUsageHint) 1843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", uid: ") 1857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mUid) 1863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", opPkg: ") 1877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mOpPkg) 1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .toString(); 1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1923a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood VibratorService(Context context) { 193e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker vibratorInit(); 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the hardware to a default state, in case this is a runtime 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restart instead of a fresh boot. 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vibratorOff(); 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl(); 1997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 2017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 2027e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(true); 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mAppOpsService = 2067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); 20791268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService( 20891268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn BatteryStats.SERVICE_NAME)); 209a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 2103a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrationsLimit = mContext.getResources().getInteger( 2113a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski com.android.internal.R.integer.config_previousVibrationsDumpLimit); 2123a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 2137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mDefaultVibrationAmplitude = mContext.getResources().getInteger( 2147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright com.android.internal.R.integer.config_defaultVibrationAmplitude); 2157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2163a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations = new LinkedList<>(); 21718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_SCREEN_OFF); 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.registerReceiver(mIntentReceiver, filter); 2217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] clickEffectTimings = getLongIntArray(context.getResources(), 2237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright com.android.internal.R.array.config_virtualKeyVibePattern); 224b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer VibrationEffect clickEffect; 225017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer if (clickEffectTimings.length == 0) { 226017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer clickEffect = null; 227017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer } else if (clickEffectTimings.length == 1) { 228b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer clickEffect = VibrationEffect.createOneShot( 229b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer clickEffectTimings[0], VibrationEffect.DEFAULT_AMPLITUDE); 230b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer } else { 231b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1); 232b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer } 2337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect doubleClickEffect = VibrationEffect.createWaveform( 2347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new long[] {0, 30, 100, 30} /*timings*/, -1); 2357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect }; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2397f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 2408ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa mIm = mContext.getSystemService(InputManager.class); 24113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi mSettingObserver = new SettingsObserver(mH); 242d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 243eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 244eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal.registerLowPowerModeObserver( 245eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn new PowerManagerInternal.LowPowerModeListener() { 246455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei @Override 247455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei public int getServiceType() { 248455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei return ServiceType.VIBRATION; 249455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei } 250455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei 251455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei @Override 252455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei public void onLowPowerModeChanged(PowerSaveState result) { 2537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 254455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei } 255eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn }); 256eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn 2577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 25813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), 25913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi true, mSettingObserver, UserHandle.USER_ALL); 26013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 261d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 262d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 263d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 2647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 265d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 266d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 267d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 2687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 2697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 2707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 27113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private final class SettingsObserver extends ContentObserver { 27213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public SettingsObserver(Handler handler) { 27313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi super(handler); 27413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 27513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 27613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi @Override 27713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public void onChange(boolean SelfChange) { 2787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 27913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 28013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 28113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 28282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 283ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 2847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 285ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 2867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 2877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright @Override // Binder call 2887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public boolean hasAmplitudeControl() { 2897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mInputDeviceVibrators) { 2907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Input device vibrators don't support amplitude controls yet, but are still used over 2917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // the system vibrator when connected. 2927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty(); 2937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 2947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 2957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 296f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 297f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (uid == Binder.getCallingUid()) { 298f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 299f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 300f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 301f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 302f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 303f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 304f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 305f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 306f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 3077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 3087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Validate the incoming VibrationEffect. 3097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 3107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * We can't throw exceptions here since we might be called from some system_server component, 3117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * which would bring the whole system down. 3127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 3137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * @return whether the VibrationEffect is valid 3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private static boolean verifyVibrationEffect(VibrationEffect effect) { 3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect == null) { 3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Effect must not be null. 3187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.wtf(TAG, "effect must not be null"); 3197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 320105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 321a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright effect.validate(); 3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (Exception e) { 3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e); 3257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 32618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private static long[] getLongIntArray(Resources r, int resid) { 3317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int[] ar = r.getIntArray(resid); 3327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (ar == null) { 3337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return null; 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] out = new long[ar.length]; 3367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright for (int i = 0; i < ar.length; i++) { 3377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright out[i] = ar[i]; 3387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return out; 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint, 3447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright IBinder token) { 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (token == null) { 3507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "token must not be null"); 3517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 3527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 353f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 3547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (!verifyVibrationEffect(effect)) { 3557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 3567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If our current vibration is longer than the new vibration and is the same amplitude, 3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // then just let the current one finish. 3607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect instanceof VibrationEffect.OneShot 3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && mCurrentVibration != null 3627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) { 3637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect; 3647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot currentOneShot = 3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright (VibrationEffect.OneShot) mCurrentVibration.mEffect; 3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming()) 3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) { 3687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration"); 3707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 3757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg); 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Only link against waveforms since they potentially don't have a finish if 3787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // they're repeating. Let other effects just play out until they're done. 3797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect instanceof VibrationEffect.Waveform) { 38018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 38118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 38218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 38318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 38418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 3887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long ident = Binder.clearCallingIdentity(); 3897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 3907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 39118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 3927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationLocked(vib); 3933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski addToPreviousVibrationsLocked(vib); 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 3967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Binder.restoreCallingIdentity(ident); 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4003a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private void addToPreviousVibrationsLocked(Vibration vib) { 4013a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mPreviousVibrations.size() > mPreviousVibrationsLimit) { 4023a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations.removeFirst(); 4033a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 4047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mPreviousVibrations.addLast(new VibrationInfo( 4057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg)); 4063a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 4073a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 40882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 40918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 4157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 4167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.d(TAG, "Canceling vibration."); 4187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long ident = Binder.clearCallingIdentity(); 4207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 42118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 4227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 4237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Binder.restoreCallingIdentity(ident); 42418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 42518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 428f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 4297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final Runnable mVibrationEndRunnable = new Runnable() { 43082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override 43118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 4327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onVibrationFinished(); 43318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 43418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 43518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 43618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 4377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.removeCallbacks(mVibrationEndRunnable); 43818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 4397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.cancel(); 44018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4427f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 443a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 44418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 4467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Callback for whenever the current vibration has finished played out 4477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void onVibrationFinished() { 4487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibration finished, cleaning up"); 4507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Make sure the vibration is really done. This also reports that the vibration is 4537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // finished. 4547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doCancelVibrateLocked(); 45518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 45618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 45718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 45818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 4597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) { 4607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibrate ignored, low power mode"); 462664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi } 4637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 4647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 46513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE && 4677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright !shouldVibrateForRingtone()) { 4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); 470d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds } 4717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 4727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 473d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds 4747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int mode = getAppOpMode(vib); 4757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode != AppOpsManager.MODE_ALLOWED) { 4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode == AppOpsManager.MODE_ERRORED) { 4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // We might be getting calls from within system_server, so we don't actually want 4787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // to throw a SecurityException here. 4797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 4801af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 4817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 482a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationInnerLocked(vib); 4847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 4867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void startVibrationInnerLocked(Vibration vib) { 4877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurrentVibration = vib; 4887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mEffect instanceof VibrationEffect.OneShot) { 4897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect; 4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint); 4917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming()); 4927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (vib.mEffect instanceof VibrationEffect.Waveform) { 49318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 49418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect; 4967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint); 49718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 4987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (vib.mEffect instanceof VibrationEffect.Prebaked) { 4997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timeout = doVibratorPrebakedEffectLocked(vib); 5007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (timeout > 0) { 5017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.postDelayed(mVibrationEndRunnable, timeout); 5027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 5047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Unknown vibration type, ignoring"); 50518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 50618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 50718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 5082d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger private boolean shouldVibrateForRingtone() { 5092d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 510dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger int ringerMode = audioManager.getRingerModeInternal(); 5112d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger // "Also vibrate for calls" Setting in Sound 5122d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger if (Settings.System.getInt( 5132d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) { 5142d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode != AudioManager.RINGER_MODE_SILENT; 5152d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } else { 5162d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode == AudioManager.RINGER_MODE_VIBRATE; 5172d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5182d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5192d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger 5207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private int getAppOpMode(Vibration vib) { 5217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int mode; 5227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 5237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE, 5247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vib.mUsageHint, vib.mUid, vib.mOpPkg); 5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode == AppOpsManager.MODE_ALLOWED) { 5267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), 5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg); 5287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { 5307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Failed to get appop mode for vibration!", e); 5317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = AppOpsManager.MODE_IGNORED; 5327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mode; 5347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 536a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 537a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 538a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 539e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), 540e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 5418fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mCurrentVibration.mOpPkg); 5427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { } 543a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 544a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 545a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 546a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 547b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 5487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mEffect instanceof VibrationEffect.Waveform) { 549b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 550b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 551b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 552b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 5537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void updateVibrators() { 5547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 5557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean devicesUpdated = updateInputDeviceVibratorsLocked(); 5567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean lowPowerModeUpdated = updateLowPowerModeLocked(); 5577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (devicesUpdated || lowPowerModeUpdated) { 5597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If the state changes out from under us then just reset. 5607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doCancelVibrateLocked(); 5617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5648206525b242ceb012d882849c4e355223ba81b9dJeff Brown 5657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean updateInputDeviceVibratorsLocked() { 5667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean changed = false; 5677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean vibrateInputDevices = false; 5687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 5697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibrateInputDevices = Settings.System.getIntForUser( 5707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mContext.getContentResolver(), 5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (SettingNotFoundException snfe) { 5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibrateInputDevices != mVibrateInputDevicesSetting) { 5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright changed = true; 5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mVibrateInputDevicesSetting = vibrateInputDevices; 5777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 57813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mVibrateInputDevicesSetting) { 5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (!mInputDeviceListenerRegistered) { 5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceListenerRegistered = true; 5827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mIm.registerInputDeviceListener(this, mH); 5837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 5857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mInputDeviceListenerRegistered) { 5867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceListenerRegistered = false; 5877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mIm.unregisterInputDeviceListener(this); 5887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5908206525b242ceb012d882849c4e355223ba81b9dJeff Brown 5917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceVibrators.clear(); 5927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mVibrateInputDevicesSetting) { 5937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int[] ids = mIm.getInputDeviceIds(); 5947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright for (int i = 0; i < ids.length; i++) { 5957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright InputDevice device = mIm.getInputDevice(ids[i]); 5967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibrator vibrator = device.getVibrator(); 5977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibrator.hasVibrator()) { 5987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceVibrators.add(vibrator); 5997f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6007f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return changed; 6047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean updateLowPowerModeLocked() { 6077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean lowPowerMode = mPowerManagerInternal 6087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled; 6097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (lowPowerMode != mLowPowerMode) { 6107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mLowPowerMode = lowPowerMode; 6117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 6127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 6147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 6187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6197f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6207f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6217f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6227f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 6237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6267f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6277f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 6287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 6321064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 6331064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 6341064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 6351064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 6361064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 6371064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 6381064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 6391064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 640c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn return vibratorExists(); 6417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6427f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) { 6447f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 6457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) { 6467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright amplitude = mDefaultVibrationAmplitude; 64782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 6487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 6497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.d(TAG, "Turning vibrator on for " + millis + " ms" + 6507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright " with amplitude " + amplitude + "."); 651a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 6527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOnLocked(uid, millis); 6537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final AudioAttributes attributes = 6567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new AudioAttributes.Builder().setUsage(usageHint).build(); 6577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6587b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mInputDeviceVibrators.get(i).vibrate(millis, attributes); 6597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Note: ordering is important here! Many haptic drivers will reset their amplitude 6627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // when enabled, so we always have to enable frst, then set the amplitude. 6637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 6647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorSetAmplitude(amplitude); 6657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void doVibratorSetAmplitude(int amplitude) { 6707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mSupportsAmplitudeControl) { 6717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibratorSetAmplitude(amplitude); 6727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 6757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 6767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 67782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 67882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator off."); 67982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 6807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOffLocked(); 6817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 6857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 6887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long doVibratorPrebakedEffectLocked(Vibration vib) { 6937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mInputDeviceVibrators) { 6947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect; 6957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Input devices don't support prebaked effect, so skip trying it with them. 6967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int vibratorCount = mInputDeviceVibrators.size(); 6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibratorCount == 0) { 6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM); 6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (timeout > 0) { 7007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOnLocked(vib.mUid, timeout); 7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return timeout; 7027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int id = prebaked.getId(); 705017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer if (id < 0 || id >= mFallbackEffects.length || mFallbackEffects[id] == null) { 7067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.w(TAG, "Failed to play prebaked effect, no fallback"); 7077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect effect = mFallbackEffects[id]; 7107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibration fallbackVib = 7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg); 7127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationInnerLocked(fallbackVib); 7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void noteVibratorOnLocked(int uid, long millis) { 7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mBatteryStatsService.noteVibratorOn(uid, millis); 7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurVibUid = uid; 7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { 7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void noteVibratorOffLocked() { 7267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurVibUid >= 0) { 7277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mBatteryStatsService.noteVibratorOff(mCurVibUid); 7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { } 7307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurVibUid = -1; 7317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 7357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect.Waveform mWaveform; 7367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 7377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 738f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 7397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean mForceStop; 7407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) { 7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWaveform = waveform; 7437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUid = uid; 7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUsageHint = usageHint; 7457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mTmpWorkSource.set(uid); 7467e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long delayLocked(long duration) { 7507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long durationRemaining = duration; 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 7527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long bedtime = duration + SystemClock.uptimeMillis(); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright this.wait(durationRemaining); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright catch (InterruptedException e) { } 7587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mForceStop) { 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright durationRemaining = bedtime - SystemClock.uptimeMillis(); 7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } while (durationRemaining > 0); 7637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return duration - durationRemaining; 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWakeLock.acquire(); 7717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean finished = playWaveform(); 7737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (finished) { 7747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onVibrationFinished(); 7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWakeLock.release(); 7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Play the waveform. 7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 7847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * @return true if it finished naturally, false otherwise (e.g. it was canceled). 7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 7867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public boolean playWaveform() { 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 7887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long[] timings = mWaveform.getTimings(); 7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int[] amplitudes = mWaveform.getAmplitudes(); 7907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int len = timings.length; 7917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int repeat = mWaveform.getRepeatIndex(); 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int index = 0; 7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long onDuration = 0; 7957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright while (!mForceStop) { 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 7977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int amplitude = amplitudes[index]; 7987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long duration = timings[index++]; 7997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (duration <= 0) { 8007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright continue; 8017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude != 0) { 8037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (onDuration <= 0) { 8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Telling the vibrator to start multiple times usually causes 8057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // effects to feel "choppy" because the motor resets at every on 8067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // command. Instead we figure out how long our next "on" period is 8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // going to be, tell the motor to stay on for the full duration, 8087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // and then wake up to change the amplitude at the appropriate 8097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // intervals. 8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onDuration = 8117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright getTotalOnDuration(timings, amplitudes, index - 1, repeat); 8127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorOn(onDuration, amplitude, mUid, mUsageHint); 8137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorSetAmplitude(amplitude); 8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long waitTime = delayLocked(duration); 8197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude != 0) { 8207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onDuration -= waitTime; 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (repeat < 0) { 8237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright break; 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright index = repeat; 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return !mForceStop; 8297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void cancel() { 8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (this) { 8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.mForceStop = true; 8357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.notify(); 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Get the duration the vibrator will be on starting at startIndex until the next time it's 8417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * off. 8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long getTotalOnDuration( 8447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] timings, int[] amplitudes, int startIndex, int repeatIndex) { 8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int i = startIndex; 8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timing = 0; 8477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright while(amplitudes[i] != 0) { 8487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright timing += timings[i++]; 8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (i >= timings.length) { 8507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (repeatIndex >= 0) { 8517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright i = repeatIndex; 8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 8537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright break; 8547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (i == startIndex) { 8577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 1000; 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return timing; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 862969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 865969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown @Override 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 8687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 869969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // When the system is entering a non-interactive state, we want 870969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // to cancel vibrations in case a misbehaving app has abandoned 871969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // them. However it may happen that the system is currently playing 872969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // haptic feedback as part of the transition. So we don't cancel 873969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // system vibrations. 874969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (mCurrentVibration != null 875969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown && !mCurrentVibration.isSystemHapticFeedback()) { 876969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown doCancelVibrateLocked(); 8778a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 87818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 8823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 8833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 8843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 885fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 8863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 8873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Previous vibrations:"); 8887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 8893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski for (VibrationInfo info : mPreviousVibrations) { 8903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.print(" "); 8913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println(info.toString()); 8923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 8933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 8943a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 895a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 896a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 897a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 898a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String[] args, ShellCallback callback, ResultReceiver resultReceiver) 899a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throws RemoteException { 900a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver); 901a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 902a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 903a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final class VibratorShellCommand extends ShellCommand { 904a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 905a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private static final long MAX_VIBRATION_MS = 200; 906a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 907a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final IBinder mToken; 908a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 909a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private VibratorShellCommand(IBinder token) { 910a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken = token; 911a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 912a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 913a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 914a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public int onCommand(String cmd) { 915a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if ("vibrate".equals(cmd)) { 916a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return runVibrate(); 917a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 918a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return handleDefaultCommands(cmd); 919a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 920a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 921a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private int runVibrate() { 922a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme final long duration = Long.parseLong(getNextArgRequired()); 923a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (duration > MAX_VIBRATION_MS) { 924a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS); 925a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 926a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String description = getNextArg(); 927a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (description == null) { 928a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme description = "Shell command"; 929a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 9307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 9317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect effect = 9327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE); 9337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN, 934a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken); 935a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return 0; 936a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 937a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 938a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 939a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onHelp() { 940a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme try (PrintWriter pw = getOutPrintWriter();) { 941a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println("Vibrator commands:"); 942a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" help"); 943a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Prints this help text."); 944a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 945a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" vibrate duration [description]"); 946a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Vibrates for duration milliseconds."); 947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 950a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 951a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 953