VibratorService.java revision 7121697a5e2d4458f6f63e9eb3b5deec62ee6202
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; 57455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport com.android.server.power.BatterySaverPolicy.ServiceType; 58a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 593a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor; 603a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter; 617f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList; 623a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.util.Arrays; 63969579bb9d208c91e081ff96d2fd788269d254bdJeff Brownimport java.util.Iterator; 6418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList; 6518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator; 6618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 677f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub 687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown implements InputManager.InputDeviceListener { 693a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood private static final String TAG = "VibratorService"; 7082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown private static final boolean DEBUG = false; 7118f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi private static final String SYSTEM_UI_PACKAGE = "com.android.systemui"; 72cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood 733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final LinkedList<VibrationInfo> mPreviousVibrations; 743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private final int mPreviousVibrationsLimit; 757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final boolean mSupportsAmplitudeControl; 767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mDefaultVibrationAmplitude; 777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect[] mFallbackEffects; 787e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final WorkSource mTmpWorkSource = new WorkSource(); 797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Handler mH = new Handler(); 807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final Object mLock = new Object(); 817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Context mContext; 837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final PowerManager.WakeLock mWakeLock; 84a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IAppOpsService mAppOpsService; 85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IBatteryStats mBatteryStatsService; 86eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn private PowerManagerInternal mPowerManagerInternal; 877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private InputManager mIm; 887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private volatile VibrateThread mThread; 907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // mInputDeviceVibrators lock should be acquired after mLock, if both are 927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // to be acquired 937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private Vibration mCurrentVibration; 98a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int mCurVibUid = -1; 9913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private boolean mLowPowerMode; 10013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private SettingsObserver mSettingObserver; 101a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 1027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static boolean vibratorExists(); 103e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker native static void vibratorInit(); 1047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOn(long milliseconds); 1057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOff(); 1067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static boolean vibratorSupportsAmplitudeControl(); 1077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static void vibratorSetAmplitude(int amplitude); 1087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright native static long vibratorPerformEffect(long effect, long strength); 10918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private class Vibration implements IBinder.DeathRecipient { 11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final IBinder mToken; 1127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect mEffect; 1137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final long mStartTime; 1147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 1157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 1167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final String mOpPkg; 11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private Vibration(IBinder token, VibrationEffect effect, 1197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int usageHint, int uid, String opPkg) { 12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mToken = token; 1217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mEffect = effect; 12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mStartTime = SystemClock.uptimeMillis(); 1237b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mUsageHint = usageHint; 1247e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mUid = uid; 1258fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mOpPkg = opPkg; 12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void binderDied() { 1297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (this == mCurrentVibration) { 13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public boolean hasLongerTimeout(long millis) { 1377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If the current effect is a one shot vibration that will end after the given timeout 1387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // for the new one shot vibration, then just let the current vibration finish. All 1397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // other effect types will get pre-empted. 1407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mEffect instanceof VibrationEffect.OneShot) { 1417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) mEffect; 1427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mStartTime + oneShot.getTiming() > SystemClock.uptimeMillis() + millis; 14318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 1447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 14518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 146969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown 147969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown public boolean isSystemHapticFeedback() { 1487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean repeating = false; 1497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mEffect instanceof VibrationEffect.Waveform) { 1507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) mEffect; 1517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright repeating = (waveform.getRepeatIndex() < 0); 1527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 15318f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg)) 1547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && !repeating; 155969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 15618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 15718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1583a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private static class VibrationInfo { 1597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final long mStartTime; 1607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect mEffect; 1617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 1627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 1637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final String mOpPkg; 1647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 1657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public VibrationInfo(long startTime, VibrationEffect effect, 1663a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski int usageHint, int uid, String opPkg) { 1677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mStartTime = startTime; 1687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mEffect = effect; 1697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUsageHint = usageHint; 1707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUid = uid; 1717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mOpPkg = opPkg; 1723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski public String toString() { 1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski return new StringBuilder() 1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", startTime: ") 1787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mStartTime) 1797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(", effect: ") 1807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mEffect) 1813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", usageHint: ") 1827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mUsageHint) 1833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", uid: ") 1847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mUid) 1853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .append(", opPkg: ") 1867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .append(mOpPkg) 1873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski .toString(); 1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 1913a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood VibratorService(Context context) { 192e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker vibratorInit(); 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the hardware to a default state, in case this is a runtime 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restart instead of a fresh boot. 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vibratorOff(); 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl(); 1987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 2007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); 2017e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(true); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mAppOpsService = 2057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); 20691268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService( 20791268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn BatteryStats.SERVICE_NAME)); 208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 2093a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrationsLimit = mContext.getResources().getInteger( 2103a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski com.android.internal.R.integer.config_previousVibrationsDumpLimit); 2113a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 2127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mDefaultVibrationAmplitude = mContext.getResources().getInteger( 2137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright com.android.internal.R.integer.config_defaultVibrationAmplitude); 2147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2153a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations = new LinkedList<>(); 21618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_SCREEN_OFF); 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.registerReceiver(mIntentReceiver, filter); 2207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] clickEffectTimings = getLongIntArray(context.getResources(), 2227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright com.android.internal.R.array.config_virtualKeyVibePattern); 2237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1); 2247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect doubleClickEffect = VibrationEffect.createWaveform( 2257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new long[] {0, 30, 100, 30} /*timings*/, -1); 2267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect }; 2287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 2328ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa mIm = mContext.getSystemService(InputManager.class); 23313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi mSettingObserver = new SettingsObserver(mH); 234d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 235eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 236eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal.registerLowPowerModeObserver( 237eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn new PowerManagerInternal.LowPowerModeListener() { 238455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei @Override 239455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei public int getServiceType() { 240455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei return ServiceType.VIBRATION; 241455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei } 242455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei 243455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei @Override 244455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei public void onLowPowerModeChanged(PowerSaveState result) { 2457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 246455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei } 247eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn }); 248eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn 2497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 25013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), 25113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi true, mSettingObserver, UserHandle.USER_ALL); 25213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 253d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 254d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 255d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 2567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 257d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 258d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 259d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 2607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 2617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 2627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 26313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private final class SettingsObserver extends ContentObserver { 26413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public SettingsObserver(Handler handler) { 26513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi super(handler); 26613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 26713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 26813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi @Override 26913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public void onChange(boolean SelfChange) { 2707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 27113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 27213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 27313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 27482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 275ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 2767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 277ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 2787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 2797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright @Override // Binder call 2807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public boolean hasAmplitudeControl() { 2817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mInputDeviceVibrators) { 2827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Input device vibrators don't support amplitude controls yet, but are still used over 2837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // the system vibrator when connected. 2847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty(); 2857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 2867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 2877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 288f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 289f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (uid == Binder.getCallingUid()) { 290f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 291f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 292f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 293f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 294f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 295f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 296f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 297f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 298f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 2997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 3007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Validate the incoming VibrationEffect. 3017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 3027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * We can't throw exceptions here since we might be called from some system_server component, 3037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * which would bring the whole system down. 3047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 3057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * @return whether the VibrationEffect is valid 3067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 3077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private static boolean verifyVibrationEffect(VibrationEffect effect) { 3087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect == null) { 3097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Effect must not be null. 3107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.wtf(TAG, "effect must not be null"); 3117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 312105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 313a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright effect.validate(); 3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (Exception e) { 3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e); 3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 31818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private static long[] getLongIntArray(Resources r, int resid) { 3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int[] ar = r.getIntArray(resid); 3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (ar == null) { 3257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return null; 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] out = new long[ar.length]; 3287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright for (int i = 0; i < ar.length; i++) { 3297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright out[i] = ar[i]; 3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return out; 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 33482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 3357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint, 3367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright IBinder token) { 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (token == null) { 3427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "token must not be null"); 3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 3447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 345f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 3467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (!verifyVibrationEffect(effect)) { 3477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 3487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If our current vibration is longer than the new vibration and is the same amplitude, 3517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // then just let the current one finish. 3527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect instanceof VibrationEffect.OneShot 3537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && mCurrentVibration != null 3547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) { 3557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect; 3567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot currentOneShot = 3577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright (VibrationEffect.OneShot) mCurrentVibration.mEffect; 3587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming()) 3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) { 3607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration"); 3627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg); 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Only link against waveforms since they potentially don't have a finish if 3707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // they're repeating. Let other effects just play out until they're done. 3717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (effect instanceof VibrationEffect.Waveform) { 37218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 37318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 37418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 37518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 37618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 3807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long ident = Binder.clearCallingIdentity(); 3817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 3827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 38318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 3847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationLocked(vib); 3853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski addToPreviousVibrationsLocked(vib); 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 3887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Binder.restoreCallingIdentity(ident); 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski private void addToPreviousVibrationsLocked(Vibration vib) { 3933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mPreviousVibrations.size() > mPreviousVibrationsLimit) { 3943a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski mPreviousVibrations.removeFirst(); 3953a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 3967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mPreviousVibrations.addLast(new VibrationInfo( 3977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg)); 3983a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 3993a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 40082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 40118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 4077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 4087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.d(TAG, "Canceling vibration."); 4107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long ident = Binder.clearCallingIdentity(); 4127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 41318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 4147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 4157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Binder.restoreCallingIdentity(ident); 41618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 41718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 420f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 4217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final Runnable mVibrationEndRunnable = new Runnable() { 42282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override 42318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 4247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onVibrationFinished(); 42518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 42618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 42718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 42818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 4297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.removeCallbacks(mVibrationEndRunnable); 43018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 4317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.cancel(); 43218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 435a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 43618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 43718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 4387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Callback for whenever the current vibration has finished played out 4397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void onVibrationFinished() { 4407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibration finished, cleaning up"); 4427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 4447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Make sure the vibration is really done. This also reports that the vibration is 4457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // finished. 4467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doCancelVibrateLocked(); 44718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 45018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) { 4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibrate ignored, low power mode"); 454664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi } 4557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 4567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 45713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 4587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE && 4597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright !shouldVibrateForRingtone()) { 4607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 4617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones"); 462d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds } 4637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 4647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 465d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds 4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int mode = getAppOpMode(vib); 4677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode != AppOpsManager.MODE_ALLOWED) { 4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode == AppOpsManager.MODE_ERRORED) { 4697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // We might be getting calls from within system_server, so we don't actually want 4707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // to throw a SecurityException here. 4717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 4721af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 4737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return; 474a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 4757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationInnerLocked(vib); 4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 4787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void startVibrationInnerLocked(Vibration vib) { 4797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurrentVibration = vib; 4807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mEffect instanceof VibrationEffect.OneShot) { 4817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect; 4827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint); 4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming()); 4847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (vib.mEffect instanceof VibrationEffect.Waveform) { 48518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 48618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 4877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect; 4887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint); 48918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (vib.mEffect instanceof VibrationEffect.Prebaked) { 4917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timeout = doVibratorPrebakedEffectLocked(vib); 4927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (timeout > 0) { 4937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mH.postDelayed(mVibrationEndRunnable, timeout); 4947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 4967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Unknown vibration type, ignoring"); 49718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 49818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 49918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 5002d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger private boolean shouldVibrateForRingtone() { 5012d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); 502dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger int ringerMode = audioManager.getRingerModeInternal(); 5032d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger // "Also vibrate for calls" Setting in Sound 5042d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger if (Settings.System.getInt( 5052d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) { 5062d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode != AudioManager.RINGER_MODE_SILENT; 5072d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } else { 5082d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger return ringerMode == AudioManager.RINGER_MODE_VIBRATE; 5092d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5102d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger } 5112d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger 5127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private int getAppOpMode(Vibration vib) { 5137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int mode; 5147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 5157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE, 5167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vib.mUsageHint, vib.mUid, vib.mOpPkg); 5177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mode == AppOpsManager.MODE_ALLOWED) { 5187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), 5197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg); 5207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { 5227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.e(TAG, "Failed to get appop mode for vibration!", e); 5237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mode = AppOpsManager.MODE_IGNORED; 5247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return mode; 5267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 528a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 529a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 530a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 531e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), 532e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 5338fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mCurrentVibration.mOpPkg); 5347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { } 535a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 536a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 537a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 538a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 539b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 5407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vib.mEffect instanceof VibrationEffect.Waveform) { 541b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 542b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 543b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 544b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 5457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void updateVibrators() { 5467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 5477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean devicesUpdated = updateInputDeviceVibratorsLocked(); 5487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean lowPowerModeUpdated = updateLowPowerModeLocked(); 5497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (devicesUpdated || lowPowerModeUpdated) { 5517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // If the state changes out from under us then just reset. 5527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doCancelVibrateLocked(); 5537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5568206525b242ceb012d882849c4e355223ba81b9dJeff Brown 5577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean updateInputDeviceVibratorsLocked() { 5587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean changed = false; 5597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean vibrateInputDevices = false; 5607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 5617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibrateInputDevices = Settings.System.getIntForUser( 5627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mContext.getContentResolver(), 5637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 5647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (SettingNotFoundException snfe) { 5657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibrateInputDevices != mVibrateInputDevicesSetting) { 5677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright changed = true; 5687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mVibrateInputDevicesSetting = vibrateInputDevices; 5697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 57013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mVibrateInputDevicesSetting) { 5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (!mInputDeviceListenerRegistered) { 5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceListenerRegistered = true; 5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mIm.registerInputDeviceListener(this, mH); 5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 5777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mInputDeviceListenerRegistered) { 5787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceListenerRegistered = false; 5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mIm.unregisterInputDeviceListener(this); 5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5828206525b242ceb012d882849c4e355223ba81b9dJeff Brown 5837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceVibrators.clear(); 5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mVibrateInputDevicesSetting) { 5857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int[] ids = mIm.getInputDeviceIds(); 5867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright for (int i = 0; i < ids.length; i++) { 5877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright InputDevice device = mIm.getInputDevice(ids[i]); 5887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibrator vibrator = device.getVibrator(); 5897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibrator.hasVibrator()) { 5907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mInputDeviceVibrators.add(vibrator); 5917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 5947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return changed; 5967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 5977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean updateLowPowerModeLocked() { 5997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean lowPowerMode = mPowerManagerInternal 6007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled; 6017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (lowPowerMode != mLowPowerMode) { 6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mLowPowerMode = lowPowerMode; 6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return true; 6047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return false; 6067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6077f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6087f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6097f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 6107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6117f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6137f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 6157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6187f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 6197f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 6207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright updateVibrators(); 6217f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6227f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6237f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 6241064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 6251064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 6261064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 6271064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 6281064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 6291064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 6301064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 6311064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 632c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn return vibratorExists(); 6337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) { 6367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 6377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) { 6387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright amplitude = mDefaultVibrationAmplitude; 63982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 6407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (DEBUG) { 6417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.d(TAG, "Turning vibrator on for " + millis + " ms" + 6427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright " with amplitude " + amplitude + "."); 643a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 6447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOnLocked(uid, millis); 6457f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final AudioAttributes attributes = 6487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new AudioAttributes.Builder().setUsage(usageHint).build(); 6497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6507b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mInputDeviceVibrators.get(i).vibrate(millis, attributes); 6517f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Note: ordering is important here! Many haptic drivers will reset their amplitude 6547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // when enabled, so we always have to enable frst, then set the amplitude. 6557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 6567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorSetAmplitude(amplitude); 6577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void doVibratorSetAmplitude(int amplitude) { 6627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mSupportsAmplitudeControl) { 6637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibratorSetAmplitude(amplitude); 6647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 6677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 6687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 66982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 67082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator off."); 67182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 6727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOffLocked(); 6737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 6747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 6757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 6767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 6777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 6797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 6807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 6837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 6847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long doVibratorPrebakedEffectLocked(Vibration vib) { 6857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mInputDeviceVibrators) { 6867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect; 6877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Input devices don't support prebaked effect, so skip trying it with them. 6887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int vibratorCount = mInputDeviceVibrators.size(); 6897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (vibratorCount == 0) { 6907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM); 6917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (timeout > 0) { 6927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright noteVibratorOnLocked(vib.mUid, timeout); 6937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return timeout; 6947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 6967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int id = prebaked.getId(); 6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (id < 0 || id >= mFallbackEffects.length) { 6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Slog.w(TAG, "Failed to play prebaked effect, no fallback"); 6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect effect = mFallbackEffects[id]; 7027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright Vibration fallbackVib = 7037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg); 7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright startVibrationInnerLocked(fallbackVib); 7057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void noteVibratorOnLocked(int uid, long millis) { 7107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mBatteryStatsService.noteVibratorOn(uid, millis); 7127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurVibUid = uid; 7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { 7147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private void noteVibratorOffLocked() { 7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mCurVibUid >= 0) { 7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mBatteryStatsService.noteVibratorOff(mCurVibUid); 7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } catch (RemoteException e) { } 7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mCurVibUid = -1; 7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 7277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final VibrationEffect.Waveform mWaveform; 7287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUid; 7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private final int mUsageHint; 730f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 7317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private boolean mForceStop; 7327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) { 7347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWaveform = waveform; 7357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUid = uid; 7367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mUsageHint = usageHint; 7377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mTmpWorkSource.set(uid); 7387e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long delayLocked(long duration) { 7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long durationRemaining = duration; 7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long bedtime = duration + SystemClock.uptimeMillis(); 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 7477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright this.wait(durationRemaining); 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright catch (InterruptedException e) { } 7507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (mForceStop) { 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright durationRemaining = bedtime - SystemClock.uptimeMillis(); 7547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } while (durationRemaining > 0); 7557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return duration - durationRemaining; 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 0; 7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWakeLock.acquire(); 7637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright try { 7647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright boolean finished = playWaveform(); 7657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (finished) { 7667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onVibrationFinished(); 7677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } finally { 7697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mWakeLock.release(); 7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 7737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 7747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Play the waveform. 7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * 7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * @return true if it finished naturally, false otherwise (e.g. it was canceled). 7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public boolean playWaveform() { 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long[] timings = mWaveform.getTimings(); 7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int[] amplitudes = mWaveform.getAmplitudes(); 7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int len = timings.length; 7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int repeat = mWaveform.getRepeatIndex(); 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int index = 0; 7867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long onDuration = 0; 7877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright while (!mForceStop) { 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final int amplitude = amplitudes[index]; 7907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright final long duration = timings[index++]; 7917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (duration <= 0) { 7927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright continue; 7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude != 0) { 7957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (onDuration <= 0) { 7967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // Telling the vibrator to start multiple times usually causes 7977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // effects to feel "choppy" because the motor resets at every on 7987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // command. Instead we figure out how long our next "on" period is 7997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // going to be, tell the motor to stay on for the full duration, 8007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // and then wake up to change the amplitude at the appropriate 8017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright // intervals. 8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onDuration = 8037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright getTotalOnDuration(timings, amplitudes, index - 1, repeat); 8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorOn(onDuration, amplitude, mUid, mUsageHint); 8057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 8067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright doVibratorSetAmplitude(amplitude); 8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long waitTime = delayLocked(duration); 8117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (amplitude != 0) { 8127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright onDuration -= waitTime; 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else if (repeat < 0) { 8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright break; 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright index = repeat; 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return !mForceStop; 8217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright public void cancel() { 8257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (this) { 8267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.mForceStop = true; 8277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright mThread.notify(); 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 8317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright /** 8327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * Get the duration the vibrator will be on starting at startIndex until the next time it's 8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright * off. 8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright */ 8357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright private long getTotalOnDuration( 8367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long[] timings, int[] amplitudes, int startIndex, int repeatIndex) { 8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright int i = startIndex; 8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright long timing = 0; 8397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright while(amplitudes[i] != 0) { 8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright timing += timings[i++]; 8417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (i >= timings.length) { 8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (repeatIndex >= 0) { 8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright i = repeatIndex; 8447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } else { 8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright break; 8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright if (i == startIndex) { 8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return 1000; 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright return timing; 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 854969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 857969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown @Override 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 8607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 861969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // When the system is entering a non-interactive state, we want 862969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // to cancel vibrations in case a misbehaving app has abandoned 863969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // them. However it may happen that the system is currently playing 864969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // haptic feedback as part of the transition. So we don't cancel 865969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // system vibrations. 866969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (mCurrentVibration != null 867969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown && !mCurrentVibration.isSystemHapticFeedback()) { 868969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown doCancelVibrateLocked(); 8698a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 87018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 8743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 8753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski @Override 8763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 8773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) 8783a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski != PackageManager.PERMISSION_GRANTED) { 8793a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski 8803a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Permission Denial: can't dump vibrator service from from pid=" 8813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski + Binder.getCallingPid() 8823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski + ", uid=" + Binder.getCallingUid()); 8833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski return; 8843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 8853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println("Previous vibrations:"); 8867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright synchronized (mLock) { 8873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski for (VibrationInfo info : mPreviousVibrations) { 8883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.print(" "); 8893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski pw.println(info.toString()); 8903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 8913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 8923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski } 893a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 894a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 895a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err, 896a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String[] args, ShellCallback callback, ResultReceiver resultReceiver) 897a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throws RemoteException { 898a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver); 899a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 900a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 901a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final class VibratorShellCommand extends ShellCommand { 902a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 903a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private static final long MAX_VIBRATION_MS = 200; 904a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 905a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private final IBinder mToken; 906a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 907a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private VibratorShellCommand(IBinder token) { 908a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken = token; 909a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 910a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 911a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 912a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public int onCommand(String cmd) { 913a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if ("vibrate".equals(cmd)) { 914a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return runVibrate(); 915a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 916a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return handleDefaultCommands(cmd); 917a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 918a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 919a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme private int runVibrate() { 920a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme final long duration = Long.parseLong(getNextArgRequired()); 921a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (duration > MAX_VIBRATION_MS) { 922a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS); 923a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 924a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme String description = getNextArg(); 925a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme if (description == null) { 926a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme description = "Shell command"; 927a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 9287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright 9297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect effect = 9307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE); 9317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN, 932a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme mToken); 933a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme return 0; 934a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 935a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 936a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme @Override 937a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme public void onHelp() { 938a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme try (PrintWriter pw = getOutPrintWriter();) { 939a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println("Vibrator commands:"); 940a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" help"); 941a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Prints this help text."); 942a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 943a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" vibrate duration [description]"); 944a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(" Vibrates for duration milliseconds."); 945a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme pw.println(""); 946a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme } 949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 951