VibratorService.java revision b97ae357cad31913793f2695123c7f09cf5eaddf
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; 225b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer if (clickEffectTimings.length == 1) { 226b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer clickEffect = VibrationEffect.createOneShot( 227b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer clickEffectTimings[0], VibrationEffect.DEFAULT_AMPLITUDE); 228b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer } else { 229b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1); 230b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer } 2317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect doubleClickEffect = VibrationEffect.createWaveform( 2327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new long[] {0, 30, 100, 30} /*timings*/, -1); 2337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect }; 2357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 2398ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa mIm = mContext.getSystemService(InputManager.class); 24013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi mSettingObserver = new SettingsObserver(mH); 241d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 242eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 243eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal.registerLowPowerModeObserver( 244eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn new PowerManagerInternal.LowPowerModeListener() { 245455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei @Override 246455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei public int getServiceType() { 247455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei return ServiceType.VIBRATION; 248455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei } 249455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei 250455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei @Override 251455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei public void onLowPowerModeChanged(PowerSaveState result) { 2527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 253455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei } 254eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn }); 255eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn 2567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 25713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), 25813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi true, mSettingObserver, UserHandle.USER_ALL); 25913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 260d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 261d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 262d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 2637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 264d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 265d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 266d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 2677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 2687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 2697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 27013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private final class SettingsObserver extends ContentObserver { 27113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public SettingsObserver(Handler handler) { 27213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi super(handler); 27313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 27413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 27513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi @Override 27613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public void onChange(boolean SelfChange) { 2777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 27813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 27913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 28013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 28182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 282ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 2837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 284ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 2857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 2867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright @Override // Binder call 2877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public boolean hasAmplitudeControl() { 2887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mInputDeviceVibrators) { 2897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Input device vibrators don't support amplitude controls yet, but are still used over 2907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // the system vibrator when connected. 2917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty(); 2927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 2937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 2947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 295f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 296f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (uid == Binder.getCallingUid()) { 297f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 298f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 299f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 300f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 301f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 302f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 303f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 304f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 305f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 3067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 3077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Validate the incoming VibrationEffect. 3087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 3097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * We can't throw exceptions here since we might be called from some system_server component, 3107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * which would bring the whole system down. 3117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 3127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * @return whether the VibrationEffect is valid 3137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private static boolean verifyVibrationEffect(VibrationEffect effect) { 3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect == null) { 3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Effect must not be null. 3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.wtf(TAG, "effect must not be null"); 3187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 319105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 320a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 3217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright effect.validate(); 3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (Exception e) { 3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e); 3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 32518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private static long[] getLongIntArray(Resources r, int resid) { 3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int[] ar = r.getIntArray(resid); 3317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (ar == null) { 3327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return null; 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] out = new long[ar.length]; 3357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright for (int i = 0; i < ar.length; i++) { 3367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright out[i] = ar[i]; 3377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return out; 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 34182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 3427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint, 3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright IBinder token) { 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (token == null) { 3497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "token must not be null"); 3507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 3517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 352f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 3537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (!verifyVibrationEffect(effect)) { 3547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 3557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If our current vibration is longer than the new vibration and is the same amplitude, 3587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // then just let the current one finish. 3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect instanceof VibrationEffect.OneShot 3607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && mCurrentVibration != null 3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) { 3627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect; 3637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot currentOneShot = 3647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright (VibrationEffect.OneShot) mCurrentVibration.mEffect; 3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming()) 3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) { 3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 3687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration"); 3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 3747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg); 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Only link against waveforms since they potentially don't have a finish if 3777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // they're repeating. Let other effects just play out until they're done. 3787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect instanceof VibrationEffect.Waveform) { 37918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 38018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 38118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 38218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 38318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 3877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long ident = Binder.clearCallingIdentity(); 3887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 3897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 39018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 3917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationLocked(vib); 3923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski addToPreviousVibrationsLocked(vib); 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 3957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Binder.restoreCallingIdentity(ident); 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3993a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private void addToPreviousVibrationsLocked(Vibration vib) { 4003a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mPreviousVibrations.size() > mPreviousVibrationsLimit) { 4013a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations.removeFirst(); 4023a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 4037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mPreviousVibrations.addLast(new VibrationInfo( 4047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg)); 4053a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 4063a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 40782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 40818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 4147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 4157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.d(TAG, "Canceling vibration."); 4177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long ident = Binder.clearCallingIdentity(); 4197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 42018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 4217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 4227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Binder.restoreCallingIdentity(ident); 42318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 42418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 427f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 4287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final Runnable mVibrationEndRunnable = new Runnable() { 42982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override 43018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 4317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onVibrationFinished(); 43218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 43318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 43418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 43518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 4367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.removeCallbacks(mVibrationEndRunnable); 43718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 4387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.cancel(); 43918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 442a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 44318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 4457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Callback for whenever the current vibration has finished played out 4467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void onVibrationFinished() { 4477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibration finished, cleaning up"); 4497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Make sure the vibration is really done. This also reports that the vibration is 4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // finished. 4537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doCancelVibrateLocked(); 45418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 45518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 45618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 45718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 4587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) { 4597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibrate ignored, low power mode"); 461664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi } 4627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 4637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 46413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 4657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE && 4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright !shouldVibrateForRingtone()) { 4677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); 469d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds } 4707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 4717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 472d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds 4737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int mode = getAppOpMode(vib); 4747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode != AppOpsManager.MODE_ALLOWED) { 4757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode == AppOpsManager.MODE_ERRORED) { 4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // We might be getting calls from within system_server, so we don't actually want 4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // to throw a SecurityException here. 4787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 4791af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 4807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 481a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 4827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationInnerLocked(vib); 4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 4857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void startVibrationInnerLocked(Vibration vib) { 4867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurrentVibration = vib; 4877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mEffect instanceof VibrationEffect.OneShot) { 4887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect; 4897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint); 4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming()); 4917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (vib.mEffect instanceof VibrationEffect.Waveform) { 49218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 49318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 4947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect; 4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint); 49618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 4977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (vib.mEffect instanceof VibrationEffect.Prebaked) { 4987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timeout = doVibratorPrebakedEffectLocked(vib); 4997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (timeout > 0) { 5007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.postDelayed(mVibrationEndRunnable, timeout); 5017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 5037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Unknown vibration type, ignoring"); 50418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 50518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 50618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 5072d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger private boolean shouldVibrateForRingtone() { 5082d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 509dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger int ringerMode = audioManager.getRingerModeInternal(); 5102d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger // "Also vibrate for calls" Setting in Sound 5112d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger if (Settings.System.getInt( 5122d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) { 5132d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode != AudioManager.RINGER_MODE_SILENT; 5142d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } else { 5152d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode == AudioManager.RINGER_MODE_VIBRATE; 5162d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5172d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5182d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger 5197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private int getAppOpMode(Vibration vib) { 5207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int mode; 5217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 5227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE, 5237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vib.mUsageHint, vib.mUid, vib.mOpPkg); 5247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode == AppOpsManager.MODE_ALLOWED) { 5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), 5267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg); 5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { 5297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Failed to get appop mode for vibration!", e); 5307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = AppOpsManager.MODE_IGNORED; 5317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mode; 5337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 535a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 536a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 537a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 538e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), 539e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 5408fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mCurrentVibration.mOpPkg); 5417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { } 542a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 543a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 544a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 545a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 546b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 5477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mEffect instanceof VibrationEffect.Waveform) { 548b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 549b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 550b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 551b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 5527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void updateVibrators() { 5537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 5547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean devicesUpdated = updateInputDeviceVibratorsLocked(); 5557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean lowPowerModeUpdated = updateLowPowerModeLocked(); 5567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (devicesUpdated || lowPowerModeUpdated) { 5587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If the state changes out from under us then just reset. 5597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doCancelVibrateLocked(); 5607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5638206525b242ceb012d882849c4e355223ba81b9dJeff Brown 5647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean updateInputDeviceVibratorsLocked() { 5657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean changed = false; 5667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean vibrateInputDevices = false; 5677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 5687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibrateInputDevices = Settings.System.getIntForUser( 5697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mContext.getContentResolver(), 5707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (SettingNotFoundException snfe) { 5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibrateInputDevices != mVibrateInputDevicesSetting) { 5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright changed = true; 5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mVibrateInputDevicesSetting = vibrateInputDevices; 5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 57713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 5787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mVibrateInputDevicesSetting) { 5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (!mInputDeviceListenerRegistered) { 5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceListenerRegistered = true; 5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mIm.registerInputDeviceListener(this, mH); 5827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mInputDeviceListenerRegistered) { 5857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceListenerRegistered = false; 5867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mIm.unregisterInputDeviceListener(this); 5877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5898206525b242ceb012d882849c4e355223ba81b9dJeff Brown 5907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceVibrators.clear(); 5917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mVibrateInputDevicesSetting) { 5927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int[] ids = mIm.getInputDeviceIds(); 5937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright for (int i = 0; i < ids.length; i++) { 5947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright InputDevice device = mIm.getInputDevice(ids[i]); 5957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibrator vibrator = device.getVibrator(); 5967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibrator.hasVibrator()) { 5977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceVibrators.add(vibrator); 5987f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5997f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 6017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return changed; 6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean updateLowPowerModeLocked() { 6067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean lowPowerMode = mPowerManagerInternal 6077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled; 6087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (lowPowerMode != mLowPowerMode) { 6097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mLowPowerMode = lowPowerMode; 6107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 6117f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 6137f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 6177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6187f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6197f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6207f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6217f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 6227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6237f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6267f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 6277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6287f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 6311064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 6321064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 6331064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 6341064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 6351064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 6361064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 6371064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 6381064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 639c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn return vibratorExists(); 6407f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) { 6437f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 6447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) { 6457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright amplitude = mDefaultVibrationAmplitude; 64682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 6477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 6487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.d(TAG, "Turning vibrator on for " + millis + " ms" + 6497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright " with amplitude " + amplitude + "."); 650a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 6517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOnLocked(uid, millis); 6527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final AudioAttributes attributes = 6557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new AudioAttributes.Builder().setUsage(usageHint).build(); 6567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6577b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mInputDeviceVibrators.get(i).vibrate(millis, attributes); 6587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Note: ordering is important here! Many haptic drivers will reset their amplitude 6617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // when enabled, so we always have to enable frst, then set the amplitude. 6627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 6637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorSetAmplitude(amplitude); 6647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void doVibratorSetAmplitude(int amplitude) { 6697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mSupportsAmplitudeControl) { 6707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibratorSetAmplitude(amplitude); 6717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 6747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 6757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 67682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 67782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator off."); 67882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 6797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOffLocked(); 6807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 6847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 6877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long doVibratorPrebakedEffectLocked(Vibration vib) { 6927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mInputDeviceVibrators) { 6937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect; 6947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Input devices don't support prebaked effect, so skip trying it with them. 6957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int vibratorCount = mInputDeviceVibrators.size(); 6967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibratorCount == 0) { 6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM); 6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (timeout > 0) { 6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOnLocked(vib.mUid, timeout); 7007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return timeout; 7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int id = prebaked.getId(); 7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (id < 0 || id >= mFallbackEffects.length) { 7057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.w(TAG, "Failed to play prebaked effect, no fallback"); 7067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect effect = mFallbackEffects[id]; 7097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibration fallbackVib = 7107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg); 7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationInnerLocked(fallbackVib); 7127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void noteVibratorOnLocked(int uid, long millis) { 7177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mBatteryStatsService.noteVibratorOn(uid, millis); 7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurVibUid = uid; 7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { 7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void noteVibratorOffLocked() { 7257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurVibUid >= 0) { 7267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mBatteryStatsService.noteVibratorOff(mCurVibUid); 7287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { } 7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurVibUid = -1; 7307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 7347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect.Waveform mWaveform; 7357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 7367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 737f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 7387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean mForceStop; 7397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) { 7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWaveform = waveform; 7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUid = uid; 7437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUsageHint = usageHint; 7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mTmpWorkSource.set(uid); 7457e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long delayLocked(long duration) { 7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long durationRemaining = duration; 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 7517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long bedtime = duration + SystemClock.uptimeMillis(); 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright this.wait(durationRemaining); 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright catch (InterruptedException e) { } 7577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mForceStop) { 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright durationRemaining = bedtime - SystemClock.uptimeMillis(); 7617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } while (durationRemaining > 0); 7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return duration - durationRemaining; 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 7697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWakeLock.acquire(); 7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean finished = playWaveform(); 7727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (finished) { 7737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onVibrationFinished(); 7747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWakeLock.release(); 7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Play the waveform. 7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * @return true if it finished naturally, false otherwise (e.g. it was canceled). 7847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public boolean playWaveform() { 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 7877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long[] timings = mWaveform.getTimings(); 7887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int[] amplitudes = mWaveform.getAmplitudes(); 7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int len = timings.length; 7907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int repeat = mWaveform.getRepeatIndex(); 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int index = 0; 7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long onDuration = 0; 7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright while (!mForceStop) { 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 7967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int amplitude = amplitudes[index]; 7977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long duration = timings[index++]; 7987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (duration <= 0) { 7997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright continue; 8007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude != 0) { 8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (onDuration <= 0) { 8037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Telling the vibrator to start multiple times usually causes 8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // effects to feel "choppy" because the motor resets at every on 8057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // command. Instead we figure out how long our next "on" period is 8067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // going to be, tell the motor to stay on for the full duration, 8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // and then wake up to change the amplitude at the appropriate 8087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // intervals. 8097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onDuration = 8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright getTotalOnDuration(timings, amplitudes, index - 1, repeat); 8117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorOn(onDuration, amplitude, mUid, mUsageHint); 8127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 8137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorSetAmplitude(amplitude); 8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long waitTime = delayLocked(duration); 8187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude != 0) { 8197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onDuration -= waitTime; 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (repeat < 0) { 8227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright break; 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright index = repeat; 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return !mForceStop; 8287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void cancel() { 8327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (this) { 8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.mForceStop = true; 8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.notify(); 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 8397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Get the duration the vibrator will be on starting at startIndex until the next time it's 8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * off. 8417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long getTotalOnDuration( 8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] timings, int[] amplitudes, int startIndex, int repeatIndex) { 8447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int i = startIndex; 8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timing = 0; 8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright while(amplitudes[i] != 0) { 8477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright timing += timings[i++]; 8487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (i >= timings.length) { 8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (repeatIndex >= 0) { 8507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright i = repeatIndex; 8517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright break; 8537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (i == startIndex) { 8567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 1000; 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return timing; 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 861969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 864969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown @Override 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 8677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 868969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // When the system is entering a non-interactive state, we want 869969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // to cancel vibrations in case a misbehaving app has abandoned 870969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // them. However it may happen that the system is currently playing 871969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // haptic feedback as part of the transition. So we don't cancel 872969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // system vibrations. 873969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (mCurrentVibration != null 874969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown && !mCurrentVibration.isSystemHapticFeedback()) { 875969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown doCancelVibrateLocked(); 8768a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 87718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 8813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 8823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 8833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 884fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return; 8853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 8863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Previous vibrations:"); 8877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 8883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski for (VibrationInfo info : mPreviousVibrations) { 8893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.print(" "); 8903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println(info.toString()); 8913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 8923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 8933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 894a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 895a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 896a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 897a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String[] args, ShellCallback callback, ResultReceiver resultReceiver) 898a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throws RemoteException { 899a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver); 900a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 901a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 902a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final class VibratorShellCommand extends ShellCommand { 903a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 904a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private static final long MAX_VIBRATION_MS = 200; 905a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 906a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final IBinder mToken; 907a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 908a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private VibratorShellCommand(IBinder token) { 909a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken = token; 910a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 911a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 912a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 913a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public int onCommand(String cmd) { 914a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if ("vibrate".equals(cmd)) { 915a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return runVibrate(); 916a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 917a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return handleDefaultCommands(cmd); 918a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 919a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 920a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private int runVibrate() { 921a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme final long duration = Long.parseLong(getNextArgRequired()); 922a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (duration > MAX_VIBRATION_MS) { 923a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS); 924a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 925a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String description = getNextArg(); 926a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (description == null) { 927a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme description = "Shell command"; 928a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 9297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 9307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect effect = 9317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE); 9327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN, 933a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken); 934a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return 0; 935a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 936a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 937a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 938a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onHelp() { 939a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme try (PrintWriter pw = getOutPrintWriter();) { 940a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println("Vibrator commands:"); 941a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" help"); 942a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Prints this help text."); 943a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 944a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" vibrate duration [description]"); 945a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Vibrates for duration milliseconds."); 946a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 950a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 952