VibratorService.java revision 7b41467704f941b11af6aace3e40993afc7f6c6f
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";
58cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood
5918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private final LinkedList<Vibration> mVibrations;
6018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private Vibration mCurrentVibration;
617e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    private final WorkSource mTmpWorkSource = new WorkSource();
627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Handler mH = new Handler();
637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Context mContext;
657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final PowerManager.WakeLock mWakeLock;
66a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IAppOpsService mAppOpsService;
67a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IBatteryStats mBatteryStatsService;
68eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn    private PowerManagerInternal mPowerManagerInternal;
697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private InputManager mIm;
707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    volatile VibrateThread mThread;
727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    // mInputDeviceVibrators lock should be acquired after mVibrations lock, if both are
747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    // to be acquired
757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
79a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private int mCurVibUid = -1;
8013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private boolean mLowPowerMode;
8113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private SettingsObserver mSettingObserver;
82a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static boolean vibratorExists();
847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOn(long milliseconds);
857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOff();
8618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
8718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private class Vibration implements IBinder.DeathRecipient {
8818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final IBinder mToken;
8918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final long    mTimeout;
9018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final long    mStartTime;
9118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final long[]  mPattern;
9218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final int     mRepeat;
937b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock        private final int     mUsageHint;
947e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn        private final int     mUid;
958fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer        private final String  mOpPkg;
9618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
977b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock        Vibration(IBinder token, long millis, int usageHint, int uid, String opPkg) {
987b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            this(token, millis, null, 0, usageHint, uid, opPkg);
9918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
10018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1017b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock        Vibration(IBinder token, long[] pattern, int repeat, int usageHint, int uid,
1028fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer                String opPkg) {
1037b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            this(token, 0, pattern, repeat, usageHint, uid, opPkg);
10418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
10518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
10618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private Vibration(IBinder token, long millis, long[] pattern,
1077b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                int repeat, int usageHint, int uid, String opPkg) {
10818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mToken = token;
10918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mTimeout = millis;
11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mStartTime = SystemClock.uptimeMillis();
11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mPattern = pattern;
11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mRepeat = repeat;
1137b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            mUsageHint = usageHint;
1147e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mUid = uid;
1158fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer            mOpPkg = opPkg;
11618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void binderDied() {
11918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            synchronized (mVibrations) {
12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                mVibrations.remove(this);
12118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                if (this == mCurrentVibration) {
12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
12318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    startNextVibrationLocked();
12418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
12518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public boolean hasLongerTimeout(long millis) {
12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            if (mTimeout == 0) {
13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                // This is a pattern, return false to play the simple
13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                // vibration.
13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return false;
13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            if ((mStartTime + mTimeout)
13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    < (SystemClock.uptimeMillis() + millis)) {
13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                // If this vibration will end before the time passed in, let
13718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                // the new vibration play.
13818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return false;
13918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
14018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            return true;
14118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
142969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown
143969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        public boolean isSystemHapticFeedback() {
144969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown            return (mUid == Process.SYSTEM_UID || mUid == 0) && mRepeat < 0;
145969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        }
14618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
14718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1483a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    VibratorService(Context context) {
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Reset the hardware to a default state, in case this is a runtime
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // restart instead of a fresh boot.
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        vibratorOff();
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PowerManager pm = (PowerManager)context.getSystemService(
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Context.POWER_SERVICE);
1567e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock.setReferenceCounted(true);
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
159a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        mAppOpsService = IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
16091268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn        mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
16191268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn                BatteryStats.SERVICE_NAME));
162a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
16318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        mVibrations = new LinkedList<Vibration>();
16418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter filter = new IntentFilter();
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_SCREEN_OFF);
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        context.registerReceiver(mIntentReceiver, filter);
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void systemReady() {
1717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        mIm = (InputManager)mContext.getSystemService(Context.INPUT_SERVICE);
17213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        mSettingObserver = new SettingsObserver(mH);
173d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
174eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
175eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal.registerLowPowerModeObserver(
176eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn                new PowerManagerInternal.LowPowerModeListener() {
177eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn            @Override
178eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn            public void onLowPowerModeChanged(boolean enabled) {
179eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn                updateInputDeviceVibrators();
180eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn            }
181eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        });
182eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn
1837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        mContext.getContentResolver().registerContentObserver(
18413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
18513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                true, mSettingObserver, UserHandle.USER_ALL);
18613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
187d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
188d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            @Override
189d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            public void onReceive(Context context, Intent intent) {
190d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                updateInputDeviceVibrators();
191d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            }
192d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
193d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
1948206525b242ceb012d882849c4e355223ba81b9dJeff Brown        updateInputDeviceVibrators();
1957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
1967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
19713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private final class SettingsObserver extends ContentObserver {
19813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public SettingsObserver(Handler handler) {
19913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi            super(handler);
20013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
20113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
20213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        @Override
20313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public void onChange(boolean SelfChange) {
20413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi            updateInputDeviceVibrators();
20513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
20613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    }
20713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
208ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    public boolean hasVibrator() {
2097f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        return doVibratorExists();
210ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    }
2117f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
212f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
213f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (uid == Binder.getCallingUid()) {
214f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
215f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
216f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
217f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
218f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
219f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
220f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
221f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
222f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
2237b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock    public void vibrate(int uid, String opPkg, long milliseconds, int usageHint,
2241af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            IBinder token) {
225105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
226105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
227105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            throw new SecurityException("Requires VIBRATE permission");
228105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
229f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
23024f1076097588b7db1269044fb55af58bc420e58Patrick Scott        // We're running in the system server so we cannot crash. Check for a
23124f1076097588b7db1269044fb55af58bc420e58Patrick Scott        // timeout of 0 or negative. This will ensure that a vibration has
23224f1076097588b7db1269044fb55af58bc420e58Patrick Scott        // either a timeout of > 0 or a non-null pattern.
23324f1076097588b7db1269044fb55af58bc420e58Patrick Scott        if (milliseconds <= 0 || (mCurrentVibration != null
23424f1076097588b7db1269044fb55af58bc420e58Patrick Scott                && mCurrentVibration.hasLongerTimeout(milliseconds))) {
23518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // Ignore this vibration since the current vibration will play for
23618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // longer than milliseconds.
23718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            return;
23818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
2397f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
2407b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock        Vibration vib = new Vibration(token, milliseconds, usageHint, uid, opPkg);
241a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
242a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        final long ident = Binder.clearCallingIdentity();
243a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        try {
244a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            synchronized (mVibrations) {
245a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                removeVibrationLocked(token);
246a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                doCancelVibrateLocked();
247a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                mCurrentVibration = vib;
248a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                startVibrationLocked(vib);
249a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
250a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        } finally {
251a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            Binder.restoreCallingIdentity(ident);
25218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isAll0(long[] pattern) {
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int N = pattern.length;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < N; i++) {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pattern[i] != 0) {
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
265f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    public void vibratePattern(int uid, String packageName, long[] pattern, int repeat,
2667b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            int usageHint, IBinder token) {
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires VIBRATE permission");
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
271f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (false) {
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String s = "";
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int N = pattern.length;
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                for (int i=0; i<N; i++) {
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    s += " " + pattern[i];
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.i(TAG, "vibrating with pattern: " + s);
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we're running in the server so we can't fail
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (pattern == null || pattern.length == 0
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || isAll0(pattern)
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || repeat >= pattern.length || token == null) {
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2917b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            Vibration vib = new Vibration(token, pattern, repeat, usageHint, uid, packageName);
29218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            try {
29318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                token.linkToDeath(vib, 0);
29418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            } catch (RemoteException e) {
29518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return;
29618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            synchronized (mVibrations) {
29918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                removeVibrationLocked(token);
30018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                doCancelVibrateLocked();
30118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                if (repeat >= 0) {
30218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    mVibrations.addFirst(vib);
30318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    startNextVibrationLocked();
30418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                } else {
30518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    // A negative repeat means that this pattern is not meant
30618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    // to repeat. Treat it like a simple vibration.
30718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    mCurrentVibration = vib;
30818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    startVibrationLocked(vib);
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        finally {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
31718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    public void cancelVibrate(IBinder token) {
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.VIBRATE,
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "cancelVibrate");
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // so wakelock calls will succeed
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long identity = Binder.clearCallingIdentity();
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
32518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            synchronized (mVibrations) {
32618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                final Vibration vib = removeVibrationLocked(token);
32718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                if (vib == mCurrentVibration) {
32818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
32918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    startNextVibrationLocked();
33018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
33118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        finally {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(identity);
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
337f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
33818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private final Runnable mVibrationRunnable = new Runnable() {
33918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void run() {
34018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            synchronized (mVibrations) {
34118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                doCancelVibrateLocked();
34218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                startNextVibrationLocked();
34318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
34418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
34518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    };
34618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
34718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    // Lock held on mVibrations
34818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void doCancelVibrateLocked() {
34918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (mThread != null) {
35018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            synchronized (mThread) {
35118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                mThread.mDone = true;
35218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                mThread.notify();
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
35418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread = null;
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        doVibratorOff();
35718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        mH.removeCallbacks(mVibrationRunnable);
358a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        reportFinishVibrationLocked();
35918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
36018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
36118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    // Lock held on mVibrations
36218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void startNextVibrationLocked() {
36318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (mVibrations.size() <= 0) {
364a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            reportFinishVibrationLocked();
365b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            mCurrentVibration = null;
36618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            return;
36718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
36818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        mCurrentVibration = mVibrations.getFirst();
36918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        startVibrationLocked(mCurrentVibration);
37018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
37118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
37218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    // Lock held on mVibrations
37318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void startVibrationLocked(final Vibration vib) {
374a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        try {
3757b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            if (mLowPowerMode
3767b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                    && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_TELEPHONY_RINGTONE) {
377664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi                return;
378664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi            }
37913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
3801af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
3817b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                    vib.mUsageHint, vib.mUid, vib.mOpPkg);
3821af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            if (mode == AppOpsManager.MODE_ALLOWED) {
3831af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock                mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
3848fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
3851af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
386a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (mode != AppOpsManager.MODE_ALLOWED) {
387a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                if (mode == AppOpsManager.MODE_ERRORED) {
388a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);
389a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
390a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                mH.post(mVibrationRunnable);
391a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                return;
392a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
393a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        } catch (RemoteException e) {
394a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
39518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (vib.mTimeout != 0) {
3967b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            doVibratorOn(vib.mTimeout, vib.mUid, vib.mUsageHint);
39718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mH.postDelayed(mVibrationRunnable, vib.mTimeout);
39818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        } else {
39918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // mThread better be null here. doCancelVibrate should always be
40018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // called before startNextVibrationLocked or startVibrationLocked.
40118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread = new VibrateThread(vib);
40218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread.start();
40318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
40418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
40518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
406a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private void reportFinishVibrationLocked() {
407a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mCurrentVibration != null) {
408a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            try {
409e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
410e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
4118fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer                        mCurrentVibration.mOpPkg);
412a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            } catch (RemoteException e) {
413a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
414a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mCurrentVibration = null;
415a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
416a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
417a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
41818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    // Lock held on mVibrations
41918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private Vibration removeVibrationLocked(IBinder token) {
42018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        ListIterator<Vibration> iter = mVibrations.listIterator(0);
42118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        while (iter.hasNext()) {
42218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            Vibration vib = iter.next();
42318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            if (vib.mToken == token) {
42418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                iter.remove();
425b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson                unlinkVibration(vib);
42618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return vib;
42718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
42818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
42918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        // We might be looking for a simple vibration which is only stored in
43018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        // mCurrentVibration.
43118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (mCurrentVibration != null && mCurrentVibration.mToken == token) {
432b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            unlinkVibration(mCurrentVibration);
43318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            return mCurrentVibration;
43418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
43518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        return null;
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
438b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    private void unlinkVibration(Vibration vib) {
439b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson        if (vib.mPattern != null) {
440b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            // If Vibration object has a pattern,
441b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            // the Vibration object has also been linkedToDeath.
442b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            vib.mToken.unlinkToDeath(vib, 0);
443b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson        }
444b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    }
445b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson
4467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private void updateInputDeviceVibrators() {
4477f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mVibrations) {
4487f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            doCancelVibrateLocked();
4497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
4507f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            synchronized (mInputDeviceVibrators) {
4518206525b242ceb012d882849c4e355223ba81b9dJeff Brown                mVibrateInputDevicesSetting = false;
4528206525b242ceb012d882849c4e355223ba81b9dJeff Brown                try {
453d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                    mVibrateInputDevicesSetting = Settings.System.getIntForUser(
454d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                            mContext.getContentResolver(),
455d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown                            Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0;
4568206525b242ceb012d882849c4e355223ba81b9dJeff Brown                } catch (SettingNotFoundException snfe) {
4578206525b242ceb012d882849c4e355223ba81b9dJeff Brown                }
4588206525b242ceb012d882849c4e355223ba81b9dJeff Brown
459eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn                mLowPowerMode = mPowerManagerInternal.getLowPowerModeEnabled();
46013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
4618206525b242ceb012d882849c4e355223ba81b9dJeff Brown                if (mVibrateInputDevicesSetting) {
4628206525b242ceb012d882849c4e355223ba81b9dJeff Brown                    if (!mInputDeviceListenerRegistered) {
4638206525b242ceb012d882849c4e355223ba81b9dJeff Brown                        mInputDeviceListenerRegistered = true;
4648206525b242ceb012d882849c4e355223ba81b9dJeff Brown                        mIm.registerInputDeviceListener(this, mH);
4658206525b242ceb012d882849c4e355223ba81b9dJeff Brown                    }
4668206525b242ceb012d882849c4e355223ba81b9dJeff Brown                } else {
4678206525b242ceb012d882849c4e355223ba81b9dJeff Brown                    if (mInputDeviceListenerRegistered) {
4688206525b242ceb012d882849c4e355223ba81b9dJeff Brown                        mInputDeviceListenerRegistered = false;
4698206525b242ceb012d882849c4e355223ba81b9dJeff Brown                        mIm.unregisterInputDeviceListener(this);
4708206525b242ceb012d882849c4e355223ba81b9dJeff Brown                    }
4718206525b242ceb012d882849c4e355223ba81b9dJeff Brown                }
4728206525b242ceb012d882849c4e355223ba81b9dJeff Brown
4737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                mInputDeviceVibrators.clear();
4747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                if (mVibrateInputDevicesSetting) {
4757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    int[] ids = mIm.getInputDeviceIds();
4767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    for (int i = 0; i < ids.length; i++) {
4777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                        InputDevice device = mIm.getInputDevice(ids[i]);
4787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                        Vibrator vibrator = device.getVibrator();
4797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                        if (vibrator.hasVibrator()) {
4807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                            mInputDeviceVibrators.add(vibrator);
4817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                        }
4827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    }
4837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
4847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
4857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
4867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            startNextVibrationLocked();
4877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
4887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
4897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
4907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
4917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceAdded(int deviceId) {
4927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        updateInputDeviceVibrators();
4937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
4947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
4957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
4967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceChanged(int deviceId) {
4977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        updateInputDeviceVibrators();
4987f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
4997f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5007f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
5017f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
5027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        updateInputDeviceVibrators();
5037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
5047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean doVibratorExists() {
5061064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // For now, we choose to ignore the presence of input devices that have vibrators
5071064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // when reporting whether the device has a vibrator.  Applications often use this
5081064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // information to decide whether to enable certain features so they expect the
5091064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // result of hasVibrator() to be constant.  For now, just report whether
5101064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // the device has a built-in vibrator.
5111064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //synchronized (mInputDeviceVibrators) {
5121064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //    return !mInputDeviceVibrators.isEmpty() || vibratorExists();
5131064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //}
514c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        return vibratorExists();
5157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
5167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5177b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock    private void doVibratorOn(long millis, int uid, int usageHint) {
5187f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
519a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            try {
520a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                mBatteryStatsService.noteVibratorOn(uid, millis);
521a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                mCurVibUid = uid;
522a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            } catch (RemoteException e) {
523a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
5247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
5257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
5267b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                final AudioAttributes attributes = new AudioAttributes.Builder().setUsage(usageHint)
5277b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                        .build();
5287f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
5297b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                    mInputDeviceVibrators.get(i).vibrate(millis, attributes);
5307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
5317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
5327f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOn(millis);
5337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
5347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
5357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
5367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5377f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private void doVibratorOff() {
5387f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
539a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            if (mCurVibUid >= 0) {
540a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                try {
541a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                    mBatteryStatsService.noteVibratorOff(mCurVibUid);
542a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                } catch (RemoteException e) {
543a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                }
544a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                mCurVibUid = -1;
545a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
5467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
5477f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
5487f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
5497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    mInputDeviceVibrators.get(i).cancel();
5507f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
5517f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
5527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOff();
5537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
5547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
5557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
5567f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class VibrateThread extends Thread {
55818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        final Vibration mVibration;
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean mDone;
560f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
56118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        VibrateThread(Vibration vib) {
56218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mVibration = vib;
5637e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mTmpWorkSource.set(vib.mUid);
5647e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.setWorkSource(mTmpWorkSource);
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mWakeLock.acquire();
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        private void delay(long duration) {
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration > 0) {
570e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan                long bedtime = duration + SystemClock.uptimeMillis();
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        this.wait(duration);
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    catch (InterruptedException e) {
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mDone) {
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
580e4c56d9367ae89c705b92e44f327bd1d0132129cVairavan Srinivasan                    duration = bedtime - SystemClock.uptimeMillis();
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } while (duration > 0);
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
588a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                final long[] pattern = mVibration.mPattern;
589a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                final int len = pattern.length;
590a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                final int repeat = mVibration.mRepeat;
591a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn                final int uid = mVibration.mUid;
5927b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                final int usageHint = mVibration.mUsageHint;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int index = 0;
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                long duration = 0;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (!mDone) {
597f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen                    // add off-time duration to any accumulated on-time duration
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (index < len) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        duration += pattern[index++];
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // sleep until it is time to start the vibrator
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    delay(duration);
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (mDone) {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (index < len) {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // read on-time duration and start the vibrator
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // duration is saved for delay() at top of loop
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        duration = pattern[index++];
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (duration > 0) {
6137b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                            VibratorService.this.doVibratorOn(duration, uid, usageHint);
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
61618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                        if (repeat < 0) {
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            break;
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        } else {
61918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                            index = repeat;
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            duration = 0;
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mWakeLock.release();
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
62618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            synchronized (mVibrations) {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mThread == this) {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mThread = null;
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
63018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                if (!mDone) {
63118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    // If this vibration finished naturally, start the next
63218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    // vibration.
63318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    mVibrations.remove(mVibration);
634b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson                    unlinkVibration(mVibration);
63518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    startNextVibrationLocked();
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
639969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown    }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
642969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        @Override
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
64518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                synchronized (mVibrations) {
646969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // When the system is entering a non-interactive state, we want
647969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // to cancel vibrations in case a misbehaving app has abandoned
648969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // them.  However it may happen that the system is currently playing
649969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // haptic feedback as part of the transition.  So we don't cancel
650969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // system vibrations.
651969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    if (mCurrentVibration != null
652969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                            && !mCurrentVibration.isSystemHapticFeedback()) {
653969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        doCancelVibrateLocked();
6548a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan                    }
6558a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan
656969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // Clear all remaining vibrations.
657969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    Iterator<Vibration> it = mVibrations.iterator();
658969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    while (it.hasNext()) {
659969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        Vibration vibration = it.next();
660969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        if (vibration != mCurrentVibration) {
661969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                            unlinkVibration(vibration);
662969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                            it.remove();
663969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        }
664969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    }
66518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
670