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; 2791268cf21eace600792d04db1ac62e9268f48002Dianne Hackbornimport android.os.BatteryStats; 2895e4f70624ae9695bdd9029eb22a9e271401fbd5Joe Onoratoimport android.os.Handler; 293a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.IVibratorService; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager; 31eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackbornimport android.os.PowerManagerInternal; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process; 339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException; 349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder; 36a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager; 379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock; 38d49359631bc2642be73dc162a8a73207df1e0bafJeff Brownimport android.os.UserHandle; 397f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.os.Vibrator; 407e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource; 417f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings; 427f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings.SettingNotFoundException; 438a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog; 447f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice; 457b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes; 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 47a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService; 48a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats; 49a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 507f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList; 51969579bb9d208c91e081ff96d2fd788269d254bdJeff Brownimport java.util.Iterator; 5218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList; 5318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator; 5418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 557f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub 567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown implements InputManager.InputDeviceListener { 573a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood private static final String TAG = "VibratorService"; 5882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown private static final boolean DEBUG = false; 59cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood 6018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final LinkedList<Vibration> mVibrations; 6118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration mCurrentVibration; 627e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final WorkSource mTmpWorkSource = new WorkSource(); 637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Handler mH = new Handler(); 647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final Context mContext; 667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final PowerManager.WakeLock mWakeLock; 67a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IAppOpsService mAppOpsService; 68a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private final IBatteryStats mBatteryStatsService; 69eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn private PowerManagerInternal mPowerManagerInternal; 707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private InputManager mIm; 717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown volatile VibrateThread mThread; 737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are 757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown // to be acquired 767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>(); 777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators 787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators 797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 80a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private int mCurVibUid = -1; 8113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private boolean mLowPowerMode; 8213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private SettingsObserver mSettingObserver; 83a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static boolean vibratorExists(); 857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOn(long milliseconds); 867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown native static void vibratorOff(); 8718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 8818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private class Vibration implements IBinder.DeathRecipient { 8918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final IBinder mToken; 9018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mTimeout; 9118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long mStartTime; 9218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final long[] mPattern; 9318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final int mRepeat; 947b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock private final int mUsageHint; 957e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn private final int mUid; 968fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer private final String mOpPkg; 9718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 987b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration(IBinder token, long millis, int usageHint, int uid, String opPkg) { 997b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock this(token, millis, null, 0, usageHint, uid, opPkg); 10018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 10118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1027b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration(IBinder token, long[] pattern, int repeat, int usageHint, int uid, 1038fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer String opPkg) { 1047b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock this(token, 0, pattern, repeat, usageHint, uid, opPkg); 10518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 10618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 10718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration(IBinder token, long millis, long[] pattern, 1087b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock int repeat, int usageHint, int uid, String opPkg) { 10918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mToken = token; 11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mTimeout = millis; 11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mStartTime = SystemClock.uptimeMillis(); 11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mPattern = pattern; 11318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mRepeat = repeat; 1147b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mUsageHint = usageHint; 1157e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mUid = uid; 1168fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mOpPkg = opPkg; 11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 11918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void binderDied() { 12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 12118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.remove(this); 12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (this == mCurrentVibration) { 12318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 12418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 12518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public boolean hasLongerTimeout(long millis) { 13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mTimeout == 0) { 13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // This is a pattern, return false to play the simple 13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if ((mStartTime + mTimeout) 13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott < (SystemClock.uptimeMillis() + millis)) { 13718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration will end before the time passed in, let 13818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // the new vibration play. 13918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return false; 14018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 14118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return true; 14218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 143969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown 144969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown public boolean isSystemHapticFeedback() { 145969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown return (mUid == Process.SYSTEM_UID || mUid == 0) && mRepeat < 0; 146969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 14718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 14818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1493a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood VibratorService(Context context) { 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Reset the hardware to a default state, in case this is a runtime 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // restart instead of a fresh boot. 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project vibratorOff(); 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext = context; 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PowerManager pm = (PowerManager)context.getSystemService( 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Context.POWER_SERVICE); 1577e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*"); 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.setReferenceCounted(true); 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 160a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE)); 16191268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService( 16291268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn BatteryStats.SERVICE_NAME)); 163a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 16418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations = new LinkedList<Vibration>(); 16518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project IntentFilter filter = new IntentFilter(); 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project filter.addAction(Intent.ACTION_SCREEN_OFF); 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.registerReceiver(mIntentReceiver, filter); 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void systemReady() { 1727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE); 17313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi mSettingObserver = new SettingsObserver(mH); 174d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 175eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); 176eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mPowerManagerInternal.registerLowPowerModeObserver( 177eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn new PowerManagerInternal.LowPowerModeListener() { 178eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn @Override 179eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn public void onLowPowerModeChanged(boolean enabled) { 180eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn updateInputDeviceVibrators(); 181eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn } 182eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn }); 183eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn 1847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mContext.getContentResolver().registerContentObserver( 18513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES), 18613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi true, mSettingObserver, UserHandle.USER_ALL); 18713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 188d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.registerReceiver(new BroadcastReceiver() { 189d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown @Override 190d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown public void onReceive(Context context, Intent intent) { 191d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown updateInputDeviceVibrators(); 192d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown } 193d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); 194d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown 1958206525b242ceb012d882849c4e355223ba81b9dJeff Brown updateInputDeviceVibrators(); 1967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 1977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 19813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi private final class SettingsObserver extends ContentObserver { 19913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public SettingsObserver(Handler handler) { 20013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi super(handler); 20113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 20213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 20313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi @Override 20413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi public void onChange(boolean SelfChange) { 20513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi updateInputDeviceVibrators(); 20613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 20713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi } 20813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 20982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 210ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn public boolean hasVibrator() { 2117f6c231a76f0bedaf9655a24707737d343244312Jeff Brown return doVibratorExists(); 212ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn } 2137f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 214f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn private void verifyIncomingUid(int uid) { 215f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (uid == Binder.getCallingUid()) { 216f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 217f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 218f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn if (Binder.getCallingPid() == Process.myPid()) { 219f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn return; 220f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 221f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS, 222f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn Binder.getCallingPid(), Binder.getCallingUid(), null); 223f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn } 224f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 22582379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 2267b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock public void vibrate(int uid, String opPkg, long milliseconds, int usageHint, 2271af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock IBinder token) { 228105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 229105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 230105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 231105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project } 232f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 23324f1076097588b7db1269044fb55af58bc420e58Patrick Scott // We're running in the system server so we cannot crash. Check for a 23424f1076097588b7db1269044fb55af58bc420e58Patrick Scott // timeout of 0 or negative. This will ensure that a vibration has 23524f1076097588b7db1269044fb55af58bc420e58Patrick Scott // either a timeout of > 0 or a non-null pattern. 23624f1076097588b7db1269044fb55af58bc420e58Patrick Scott if (milliseconds <= 0 || (mCurrentVibration != null 23724f1076097588b7db1269044fb55af58bc420e58Patrick Scott && mCurrentVibration.hasLongerTimeout(milliseconds))) { 23818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Ignore this vibration since the current vibration will play for 23918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // longer than milliseconds. 24018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 24118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2427f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 24382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 24482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Vibrating for " + milliseconds + " ms."); 24582379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 24682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown 2477b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration vib = new Vibration(token, milliseconds, usageHint, uid, opPkg); 248a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 249a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long ident = Binder.clearCallingIdentity(); 250a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 251a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn synchronized (mVibrations) { 252a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn removeVibrationLocked(token); 253a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn doCancelVibrateLocked(); 254a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = vib; 255a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn startVibrationLocked(vib); 256a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 257a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } finally { 258a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Binder.restoreCallingIdentity(ident); 25918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private boolean isAll0(long[] pattern) { 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0; i < N; i++) { 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern[i] != 0) { 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return false; 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 27282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 273f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn public void vibratePattern(int uid, String packageName, long[] pattern, int repeat, 2747b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock int usageHint, IBinder token) { 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE) 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project != PackageManager.PERMISSION_GRANTED) { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new SecurityException("Requires VIBRATE permission"); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 279f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn verifyIncomingUid(uid); 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 28382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project String s = ""; 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int N = pattern.length; 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i=0; i<N; i++) { 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project s += " " + pattern[i]; 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 28982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Vibrating with pattern:" + s); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we're running in the server so we can't fail 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pattern == null || pattern.length == 0 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || isAll0(pattern) 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project || repeat >= pattern.length || token == null) { 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2997b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock Vibration vib = new Vibration(token, pattern, repeat, usageHint, uid, packageName); 30018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott try { 30118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott token.linkToDeath(vib, 0); 30218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } catch (RemoteException e) { 30318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 30418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 30618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 30718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott removeVibrationLocked(token); 30818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 30918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat >= 0) { 31018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.addFirst(vib); 31118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 31218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 31318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // A negative repeat means that this pattern is not meant 31418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // to repeat. Treat it like a simple vibration. 31518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mCurrentVibration = vib; 31618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(vib); 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32582379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override // Binder call 32618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void cancelVibrate(IBinder token) { 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mContext.enforceCallingOrSelfPermission( 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project android.Manifest.permission.VIBRATE, 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "cancelVibrate"); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // so wakelock calls will succeed 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long identity = Binder.clearCallingIdentity(); 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 33418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 33518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration vib = removeVibrationLocked(token); 33618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib == mCurrentVibration) { 33782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 33882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Canceling vibration."); 33982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 34018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 34118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 34218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 34318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project finally { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Binder.restoreCallingIdentity(identity); 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 349f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 35018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private final Runnable mVibrationRunnable = new Runnable() { 35182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown @Override 35218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott public void run() { 35318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 35418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott doCancelVibrateLocked(); 35518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 35618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 35718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 35818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott }; 35918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 36018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 36118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void doCancelVibrateLocked() { 36218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mThread != null) { 36318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mThread) { 36418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.mDone = true; 36518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.notify(); 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 36718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = null; 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doVibratorOff(); 37018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.removeCallbacks(mVibrationRunnable); 371a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 37218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 37318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 37418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 37518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startNextVibrationLocked() { 37618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mVibrations.size() <= 0) { 377a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn reportFinishVibrationLocked(); 378b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson mCurrentVibration = null; 37918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return; 38018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 38118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mCurrentVibration = mVibrations.getFirst(); 38218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startVibrationLocked(mCurrentVibration); 38318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 38418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 38518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 38618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private void startVibrationLocked(final Vibration vib) { 387a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 3887b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock if (mLowPowerMode 38989c3b29a9bfa0ae9858b913bc1ab6604c4613a15Jean-Michel Trivi && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) { 390664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi return; 391664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi } 39213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 3931af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE, 3947b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock vib.mUsageHint, vib.mUid, vib.mOpPkg); 3951af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock if (mode == AppOpsManager.MODE_ALLOWED) { 3961af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService), 3978fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg); 3981af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock } 399a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode != AppOpsManager.MODE_ALLOWED) { 400a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mode == AppOpsManager.MODE_ERRORED) { 401a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid); 402a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 403a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mH.post(mVibrationRunnable); 404a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn return; 405a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 406a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 407a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 40818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mTimeout != 0) { 4097b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint); 41018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mH.postDelayed(mVibrationRunnable, vib.mTimeout); 41118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } else { 41218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mThread better be null here. doCancelVibrate should always be 41318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // called before startNextVibrationLocked or startVibrationLocked. 41418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread = new VibrateThread(vib); 41518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mThread.start(); 41618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 41718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 41818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott 419a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn private void reportFinishVibrationLocked() { 420a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurrentVibration != null) { 421a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 422e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService), 423e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid, 4248fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer mCurrentVibration.mOpPkg); 425a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 426a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 427a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurrentVibration = null; 428a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 429a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 430a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 43118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // Lock held on mVibrations 43218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott private Vibration removeVibrationLocked(IBinder token) { 43318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott ListIterator<Vibration> iter = mVibrations.listIterator(0); 43418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott while (iter.hasNext()) { 43518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott Vibration vib = iter.next(); 43618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (vib.mToken == token) { 43718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott iter.remove(); 438b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(vib); 43918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return vib; 44018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // We might be looking for a simple vibration which is only stored in 44318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // mCurrentVibration. 44418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (mCurrentVibration != null && mCurrentVibration.mToken == token) { 445b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mCurrentVibration); 44618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return mCurrentVibration; 44718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 44818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott return null; 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 451b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson private void unlinkVibration(Vibration vib) { 452b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson if (vib.mPattern != null) { 453b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // If Vibration object has a pattern, 454b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson // the Vibration object has also been linkedToDeath. 455b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson vib.mToken.unlinkToDeath(vib, 0); 456b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 457b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson } 458b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson 4597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void updateInputDeviceVibrators() { 4607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mVibrations) { 4617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown doCancelVibrateLocked(); 4627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 4648206525b242ceb012d882849c4e355223ba81b9dJeff Brown mVibrateInputDevicesSetting = false; 4658206525b242ceb012d882849c4e355223ba81b9dJeff Brown try { 466d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mVibrateInputDevicesSetting = Settings.System.getIntForUser( 467d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown mContext.getContentResolver(), 468d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0; 4698206525b242ceb012d882849c4e355223ba81b9dJeff Brown } catch (SettingNotFoundException snfe) { 4708206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4718206525b242ceb012d882849c4e355223ba81b9dJeff Brown 472eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled(); 47313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi 4748206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mVibrateInputDevicesSetting) { 4758206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (!mInputDeviceListenerRegistered) { 4768206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = true; 4778206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.registerInputDeviceListener(this, mH); 4788206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4798206525b242ceb012d882849c4e355223ba81b9dJeff Brown } else { 4808206525b242ceb012d882849c4e355223ba81b9dJeff Brown if (mInputDeviceListenerRegistered) { 4818206525b242ceb012d882849c4e355223ba81b9dJeff Brown mInputDeviceListenerRegistered = false; 4828206525b242ceb012d882849c4e355223ba81b9dJeff Brown mIm.unregisterInputDeviceListener(this); 4838206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4848206525b242ceb012d882849c4e355223ba81b9dJeff Brown } 4858206525b242ceb012d882849c4e355223ba81b9dJeff Brown 4867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.clear(); 4877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (mVibrateInputDevicesSetting) { 4887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown int[] ids = mIm.getInputDeviceIds(); 4897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < ids.length; i++) { 4907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown InputDevice device = mIm.getInputDevice(ids[i]); 4917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown Vibrator vibrator = device.getVibrator(); 4927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibrator.hasVibrator()) { 4937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.add(vibrator); 4947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 4987f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 4997f6c231a76f0bedaf9655a24707737d343244312Jeff Brown startNextVibrationLocked(); 5007f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5017f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceAdded(int deviceId) { 5057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 5067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5077f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5087f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5097f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceChanged(int deviceId) { 5107f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 5117f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5137f6c231a76f0bedaf9655a24707737d343244312Jeff Brown @Override 5147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown public void onInputDeviceRemoved(int deviceId) { 5157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown updateInputDeviceVibrators(); 5167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5187f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private boolean doVibratorExists() { 5191064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // For now, we choose to ignore the presence of input devices that have vibrators 5201064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // when reporting whether the device has a vibrator. Applications often use this 5211064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // information to decide whether to enable certain features so they expect the 5221064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // result of hasVibrator() to be constant. For now, just report whether 5231064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // the device has a built-in vibrator. 5241064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //synchronized (mInputDeviceVibrators) { 5251064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown // return !mInputDeviceVibrators.isEmpty() || vibratorExists(); 5261064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown //} 527c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn return vibratorExists(); 5287f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5307b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock private void doVibratorOn(long millis, int uid, int usageHint) { 5317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 53282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 53382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator on for " + millis + " ms."); 53482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 535a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 536a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOn(uid, millis); 537a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = uid; 538a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 539a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 5407f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 5417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 5427b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final AudioAttributes attributes = new AudioAttributes.Builder().setUsage(usageHint) 5437b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock .build(); 5447f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 5457b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mInputDeviceVibrators.get(i).vibrate(millis, attributes); 5467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5477f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 5487f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOn(millis); 5497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5507f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5517f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown private void doVibratorOff() { 5547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown synchronized (mInputDeviceVibrators) { 55582379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown if (DEBUG) { 55682379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown Slog.d(TAG, "Turning vibrator off."); 55782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown } 558a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn if (mCurVibUid >= 0) { 559a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn try { 560a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mBatteryStatsService.noteVibratorOff(mCurVibUid); 561a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } catch (RemoteException e) { 562a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 563a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn mCurVibUid = -1; 564a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn } 5657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown final int vibratorCount = mInputDeviceVibrators.size(); 5667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown if (vibratorCount != 0) { 5677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown for (int i = 0; i < vibratorCount; i++) { 5687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown mInputDeviceVibrators.get(i).cancel(); 5697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } else { 5717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown vibratorOff(); 5727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown } 5757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private class VibrateThread extends Thread { 57718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott final Vibration mVibration; 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean mDone; 579f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen 58018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott VibrateThread(Vibration vib) { 58118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibration = vib; 5827e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mTmpWorkSource.set(vib.mUid); 5837e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn mWakeLock.setWorkSource(mTmpWorkSource); 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.acquire(); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private void delay(long duration) { 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 589e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan long bedtime = duration + SystemClock.uptimeMillis(); 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project do { 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project try { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.wait(duration); 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project catch (InterruptedException e) { 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 599e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan duration = bedtime - SystemClock.uptimeMillis(); 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } while (duration > 0); 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void run() { 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY); 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project synchronized (this) { 607a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final long[] pattern = mVibration.mPattern; 608a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int len = pattern.length; 609a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int repeat = mVibration.mRepeat; 610a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn final int uid = mVibration.mUid; 6117b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock final int usageHint = mVibration.mUsageHint; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int index = 0; 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long duration = 0; 6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project while (!mDone) { 616f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen // add off-time duration to any accumulated on-time duration 6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration += pattern[index++]; 6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // sleep until it is time to start the vibrator 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project delay(duration); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mDone) { 6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (index < len) { 6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // read on-time duration and start the vibrator 6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // duration is saved for delay() at top of loop 6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = pattern[index++]; 6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (duration > 0) { 6327b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock VibratorService.this.doVibratorOn(duration, uid, usageHint); 6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 63518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (repeat < 0) { 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 63818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott index = repeat; 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project duration = 0; 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mWakeLock.release(); 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 64518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mThread == this) { 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mThread = null; 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 64918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott if (!mDone) { 65018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // If this vibration finished naturally, start the next 65118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott // vibration. 65218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott mVibrations.remove(mVibration); 653b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson unlinkVibration(mVibration); 65418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott startNextVibrationLocked(); 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 658969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 661969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown @Override 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onReceive(Context context, Intent intent) { 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { 66418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott synchronized (mVibrations) { 665969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // When the system is entering a non-interactive state, we want 666969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // to cancel vibrations in case a misbehaving app has abandoned 667969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // them. However it may happen that the system is currently playing 668969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // haptic feedback as part of the transition. So we don't cancel 669969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // system vibrations. 670969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (mCurrentVibration != null 671969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown && !mCurrentVibration.isSystemHapticFeedback()) { 672969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown doCancelVibrateLocked(); 6738a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan } 6748a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan 675969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown // Clear all remaining vibrations. 676969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown Iterator<Vibration> it = mVibrations.iterator(); 677969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown while (it.hasNext()) { 678969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown Vibration vibration = it.next(); 679969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown if (vibration != mCurrentVibration) { 680969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown unlinkVibration(vibration); 681969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown it.remove(); 682969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 683969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown } 68418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott } 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 689