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; 257f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.database.ContentObserver; 267f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.hardware.input.InputManager; 2795e4f70624ae9695bdd9029eb22a9e271401fbd5Joe Onoratoimport android.os.Handler; 283a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.IVibratorService; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 34a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 36d49359631bc2642be73dc162a8a73207df1e0bafJeff Brownimport android.os.UserHandle; 377f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.os.Vibrator; 387e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource; 397f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings; 407f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings.SettingNotFoundException; 418a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 427f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice; 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 44a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 45a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats; 46a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 477f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList; 4818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList; 4918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator; 5018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 517f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub 527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown implements InputManager.InputDeviceListener { 533a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood private static final String TAG = "VibratorService"; 54cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood 5518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final LinkedList<Vibration> mVibrations; 5618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration mCurrentVibration; 577e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final WorkSource mTmpWorkSource = new WorkSource(); 587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Handler mH = new Handler(); 597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Context mContext; 617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final PowerManager.WakeLock mWakeLock; 62a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IAppOpsService mAppOpsService; 63a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IBatteryStats mBatteryStatsService; 647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private InputManager mIm; 657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown volatile VibrateThread mThread; 677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are 697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // to be acquired 707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 74a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int mCurVibUid = -1; 75a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static boolean vibratorExists(); 777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOn(long milliseconds); 787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOff(); 7918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 8018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private class Vibration implements IBinder.DeathRecipient { 8118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final IBinder mToken; 8218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mTimeout; 8318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mStartTime; 8418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long[] mPattern; 8518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final int mRepeat; 867e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final int mUid; 87a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final String mPackageName; 8818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 89a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Vibration(IBinder token, long millis, int uid, String packageName) { 90a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn this(token, millis, null, 0, uid, packageName); 9118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 9218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 93a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Vibration(IBinder token, long[] pattern, int repeat, int uid, String packageName) { 94a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn this(token, 0, pattern, repeat, uid, packageName); 9518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 9618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 9718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration(IBinder token, long millis, long[] pattern, 98a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn int repeat, int uid, String packageName) { 9918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mToken = token; 10018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mTimeout = millis; 10118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mStartTime = SystemClock.uptimeMillis(); 10218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mPattern = pattern; 10318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mRepeat = repeat; 1047e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mUid = uid; 105a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mPackageName = packageName; 10618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 10718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 10818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void binderDied() { 10918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.remove(this); 11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (this == mCurrentVibration) { 11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 11318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 11418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public boolean hasLongerTimeout(long millis) { 11918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mTimeout == 0) { 12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // This is a pattern, return false to play the simple 12118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 12318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if ((mStartTime + mTimeout) 12518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott < (SystemClock.uptimeMillis() + millis)) { 12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration will end before the time passed in, let 12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // the new vibration play. 12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return true; 13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1343a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood VibratorService(Context context) { 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the hardware to a default state, in case this is a runtime 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restart instead of a fresh boot. 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vibratorOff(); 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PowerManager pm = (PowerManager)context.getSystemService( 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context.POWER_SERVICE); 1427e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(true); 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 145a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); 146a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo")); 147a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 14818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations = new LinkedList<Vibration>(); 14918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_SCREEN_OFF); 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.registerReceiver(mIntentReceiver, filter); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 1567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE); 157d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 1587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 1597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), true, 1607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown new ContentObserver(mH) { 1617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 1627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onChange(boolean selfChange) { 1638206525b242ceb012d882849c4e355223ba81b9dJeff Brown updateInputDeviceVibrators(); 1647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 165d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, UserHandle.USER_ALL); 166d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 167d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 168d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 169d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 170d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown updateInputDeviceVibrators(); 171d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 172d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 173d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 1748206525b242ceb012d882849c4e355223ba81b9dJeff Brown updateInputDeviceVibrators(); 1757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 1767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 177ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 1787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 179ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 1807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 181f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 182f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (uid == Binder.getCallingUid()) { 183f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 184f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 185f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 186f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 187f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 188f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 189f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 190f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 191f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 192f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn public void vibrate(int uid, String packageName, long milliseconds, IBinder token) { 193105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 194105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 195105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 196105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 197f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 19824f1076097588b7db1269044fb55af58bc420e58Patrick Scott // We're running in the system server so we cannot crash. Check for a 19924f1076097588b7db1269044fb55af58bc420e58Patrick Scott // timeout of 0 or negative. This will ensure that a vibration has 20024f1076097588b7db1269044fb55af58bc420e58Patrick Scott // either a timeout of > 0 or a non-null pattern. 20124f1076097588b7db1269044fb55af58bc420e58Patrick Scott if (milliseconds <= 0 || (mCurrentVibration != null 20224f1076097588b7db1269044fb55af58bc420e58Patrick Scott && mCurrentVibration.hasLongerTimeout(milliseconds))) { 20318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Ignore this vibration since the current vibration will play for 20418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // longer than milliseconds. 20518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 20618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2077f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Vibration vib = new Vibration(token, milliseconds, uid, packageName); 209a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 210a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 211a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 212a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (mVibrations) { 213a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn removeVibrationLocked(token); 214a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn doCancelVibrateLocked(); 215a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = vib; 216a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn startVibrationLocked(vib); 217a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 218a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } finally { 219a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Binder.restoreCallingIdentity(ident); 22018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isAll0(long[] pattern) { 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern[i] != 0) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 233f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn public void vibratePattern(int uid, String packageName, long[] pattern, int repeat, 234f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn IBinder token) { 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 239f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (false) { 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = ""; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project s += " " + pattern[i]; 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2498a9b22056b13477f59df934928c00c58b5871c95Joe Onorato Slog.i(TAG, "vibrating with pattern: " + s); 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we're running in the server so we can't fail 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern == null || pattern.length == 0 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || isAll0(pattern) 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || repeat >= pattern.length || token == null) { 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Vibration vib = new Vibration(token, pattern, repeat, uid, packageName); 26018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 26118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 26218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 26318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 26418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 26618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 26718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott removeVibrationLocked(token); 26818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 26918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat >= 0) { 27018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.addFirst(vib); 27118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 27218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 27318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // A negative repeat means that this pattern is not meant 27418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // to repeat. Treat it like a simple vibration. 27518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mCurrentVibration = vib; 27618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(vib); 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 28518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 29318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 29418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration vib = removeVibrationLocked(token); 29518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib == mCurrentVibration) { 29618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 29718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 29818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 29918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 305f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 30618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final Runnable mVibrationRunnable = new Runnable() { 30718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 30818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 30918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 31018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 31118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 31218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 31318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 31418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 31518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 31618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 31718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 31818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mThread) { 31918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.mDone = true; 32018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.notify(); 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 32218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 32518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.removeCallbacks(mVibrationRunnable); 326a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 32718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 32818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 32918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 33018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startNextVibrationLocked() { 33118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mVibrations.size() <= 0) { 332a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 333b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson mCurrentVibration = null; 33418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 33518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 33618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mCurrentVibration = mVibrations.getFirst(); 33718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(mCurrentVibration); 33818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 33918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 34018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 34118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 342a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 343a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn int mode = mAppOpsService.startOperation(AppOpsManager.OP_VIBRATE, vib.mUid, vib.mPackageName); 344a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode != AppOpsManager.MODE_ALLOWED) { 345a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode == AppOpsManager.MODE_ERRORED) { 346a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 347a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 348a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mH.post(mVibrationRunnable); 349a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 350a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 351a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 352a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 35318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mTimeout != 0) { 354a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn doVibratorOn(vib.mTimeout, vib.mUid); 35518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.postDelayed(mVibrationRunnable, vib.mTimeout); 35618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 35718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 35818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 35918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = new VibrateThread(vib); 36018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 36118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 36218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 36318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 364a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 365a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 366a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 367a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mAppOpsService.finishOperation(AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 368a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration.mPackageName); 369a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 370a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 371a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 372a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 373a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 374a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 37518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 37618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration removeVibrationLocked(IBinder token) { 37718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott ListIterator<Vibration> iter = mVibrations.listIterator(0); 37818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott while (iter.hasNext()) { 37918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott Vibration vib = iter.next(); 38018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mToken == token) { 38118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott iter.remove(); 382b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(vib); 38318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return vib; 38418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 38518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 38618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // We might be looking for a simple vibration which is only stored in 38718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mCurrentVibration. 38818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 389b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mCurrentVibration); 39018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return mCurrentVibration; 39118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 39218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return null; 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 395b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 396b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson if (vib.mPattern != null) { 397b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // If Vibration object has a pattern, 398b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // the Vibration object has also been linkedToDeath. 399b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 400b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 401b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 402b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 4037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void updateInputDeviceVibrators() { 4047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mVibrations) { 4057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doCancelVibrateLocked(); 4067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4077f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 4088206525b242ceb012d882849c4e355223ba81b9dJeff Brown mVibrateInputDevicesSetting = false; 4098206525b242ceb012d882849c4e355223ba81b9dJeff Brown try { 410d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mVibrateInputDevicesSetting = Settings.System.getIntForUser( 411d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.getContentResolver(), 412d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 4138206525b242ceb012d882849c4e355223ba81b9dJeff Brown } catch (SettingNotFoundException snfe) { 4148206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4158206525b242ceb012d882849c4e355223ba81b9dJeff Brown 4168206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mVibrateInputDevicesSetting) { 4178206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (!mInputDeviceListenerRegistered) { 4188206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = true; 4198206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.registerInputDeviceListener(this, mH); 4208206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4218206525b242ceb012d882849c4e355223ba81b9dJeff Brown } else { 4228206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mInputDeviceListenerRegistered) { 4238206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = false; 4248206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.unregisterInputDeviceListener(this); 4258206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4268206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4278206525b242ceb012d882849c4e355223ba81b9dJeff Brown 4287f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.clear(); 4297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (mVibrateInputDevicesSetting) { 4307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown int[] ids = mIm.getInputDeviceIds(); 4317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < ids.length; i++) { 4327f6c231a76f0bedaf9655a24707737d343244312Jeff Brown InputDevice device = mIm.getInputDevice(ids[i]); 4337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown Vibrator vibrator = device.getVibrator(); 4347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibrator.hasVibrator()) { 4357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.add(vibrator); 4367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4377f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4397f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4407f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown startNextVibrationLocked(); 4427f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4437f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4447f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4457f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 4467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 4477f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 4487f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4507f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 4517f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 4527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 4537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 4567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 4577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 4587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 4611064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 4621064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 4631064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 4641064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 4651064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 4661064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 4671064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 4681064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 469c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn return vibratorExists(); 4707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 472a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void doVibratorOn(long millis, int uid) { 4737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 474a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 475a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOn(uid, millis); 476a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = uid; 477a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 478a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 4797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 4807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 4817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 4827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).vibrate(millis); 4837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 4857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 4867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 4917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 492a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurVibUid >= 0) { 493a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 494a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOff(mCurVibUid); 495a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 496a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 497a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = -1; 498a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 4997f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 5007f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 5017f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 5027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 5037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 5057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 5067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5077f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5087f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5097f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 51118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration mVibration; 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mDone; 513f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 51418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott VibrateThread(Vibration vib) { 51518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibration = vib; 5167e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mTmpWorkSource.set(vib.mUid); 5177e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void delay(long duration) { 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 523e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan long bedtime = duration + SystemClock.uptimeMillis(); 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.wait(duration); 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (InterruptedException e) { 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 533e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan duration = bedtime - SystemClock.uptimeMillis(); 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (duration > 0); 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 541a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long[] pattern = mVibration.mPattern; 542a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int len = pattern.length; 543a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int repeat = mVibration.mRepeat; 544a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int uid = mVibration.mUid; 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = 0; 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long duration = 0; 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!mDone) { 549f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen // add off-time duration to any accumulated on-time duration 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration += pattern[index++]; 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sleep until it is time to start the vibrator 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delay(duration); 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read on-time duration and start the vibrator 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // duration is saved for delay() at top of loop 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = pattern[index++]; 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 565a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn VibratorService.this.doVibratorOn(duration, uid); 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 56818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat < 0) { 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 57118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott index = repeat; 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = 0; 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 57818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mThread == this) { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThread = null; 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 58218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (!mDone) { 58318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration finished naturally, start the next 58418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 58518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.remove(mVibration); 586b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mVibration); 58718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 59118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 59618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 59718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 5988a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan 5998a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan int size = mVibrations.size(); 6008a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan for(int i = 0; i < size; i++) { 6018a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan unlinkVibration(mVibrations.get(i)); 6028a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 6038a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan 60418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.clear(); 60518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 610