VibratorService.java revision 017939e43ceb847333d1115258c3db1411dbc03a
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.app.AppOpsManager;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.BroadcastReceiver;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.IntentFilter;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.content.res.Resources;
267f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.database.ContentObserver;
277f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.hardware.input.InputManager;
287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.hardware.vibrator.V1_0.Constants.EffectStrength;
292d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebingerimport android.media.AudioManager;
30455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport android.os.PowerSaveState;
3191268cf21eace600792d04db1ac62e9268f48002Dianne Hackbornimport android.os.BatteryStats;
3295e4f70624ae9695bdd9029eb22a9e271401fbd5Joe Onoratoimport android.os.Handler;
333a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwoodimport android.os.IVibratorService;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.PowerManager;
35eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackbornimport android.os.PowerManagerInternal;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Process;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
38a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ResultReceiver;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
41a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport android.os.ServiceManager;
42a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ShellCallback;
43a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Lemeimport android.os.ShellCommand;
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
45d49359631bc2642be73dc162a8a73207df1e0bafJeff Brownimport android.os.UserHandle;
467f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.os.Vibrator;
477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wrightimport android.os.VibrationEffect;
487e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackbornimport android.os.WorkSource;
497f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings;
507f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.provider.Settings.SettingNotFoundException;
518a9b22056b13477f59df934928c00c58b5871c95Joe Onoratoimport android.util.Slog;
527f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport android.view.InputDevice;
537b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockimport android.media.AudioAttributes;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
55a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IAppOpsService;
56a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackbornimport com.android.internal.app.IBatteryStats;
57fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkeyimport com.android.internal.util.DumpUtils;
58455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport com.android.server.power.BatterySaverPolicy.ServiceType;
59a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
603a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor;
613a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter;
627f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList;
633a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.util.Arrays;
64969579bb9d208c91e081ff96d2fd788269d254bdJeff Brownimport java.util.Iterator;
6518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList;
6618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator;
6718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
687f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub
697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        implements InputManager.InputDeviceListener {
703a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private static final String TAG = "VibratorService";
7182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    private static final boolean DEBUG = false;
7218f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi    private static final String SYSTEM_UI_PACKAGE = "com.android.systemui";
73cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood
743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private final LinkedList<VibrationInfo> mPreviousVibrations;
753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private final int mPreviousVibrationsLimit;
767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final boolean mSupportsAmplitudeControl;
777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final int mDefaultVibrationAmplitude;
787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final VibrationEffect[] mFallbackEffects;
797e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    private final WorkSource mTmpWorkSource = new WorkSource();
807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Handler mH = new Handler();
817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Object mLock = new Object();
827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Context mContext;
847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final PowerManager.WakeLock mWakeLock;
85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IAppOpsService mAppOpsService;
86a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IBatteryStats mBatteryStatsService;
87eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn    private PowerManagerInternal mPowerManagerInternal;
887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private InputManager mIm;
897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private volatile VibrateThread mThread;
917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // mInputDeviceVibrators lock should be acquired after mLock, if both are
937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    // to be acquired
947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private Vibration mCurrentVibration;
99a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private int mCurVibUid = -1;
10013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private boolean mLowPowerMode;
10113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private SettingsObserver mSettingObserver;
102a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
1037f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static boolean vibratorExists();
104e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker    native static void vibratorInit();
1057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOn(long milliseconds);
1067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOff();
1077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static boolean vibratorSupportsAmplitudeControl();
1087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static void vibratorSetAmplitude(int amplitude);
1097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static long vibratorPerformEffect(long effect, long strength);
11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private class Vibration implements IBinder.DeathRecipient {
11218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final IBinder mToken;
1137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect mEffect;
1147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final long mStartTime;
1157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
1167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
1177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final String mOpPkg;
11818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private Vibration(IBinder token, VibrationEffect effect,
1207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int usageHint, int uid, String opPkg) {
12118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mToken = token;
1227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mEffect = effect;
12318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mStartTime = SystemClock.uptimeMillis();
1247b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            mUsageHint = usageHint;
1257e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mUid = uid;
1268fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer            mOpPkg = opPkg;
12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
12918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void binderDied() {
1307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                if (this == mCurrentVibration) {
13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
13718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public boolean hasLongerTimeout(long millis) {
1387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // If the current effect is a one shot vibration that will end after the given timeout
1397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // for the new one shot vibration, then just let the current vibration finish. All
1407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // other effect types will get pre-empted.
1417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mEffect instanceof VibrationEffect.OneShot) {
1427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) mEffect;
1437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return mStartTime + oneShot.getTiming() > SystemClock.uptimeMillis() + millis;
14418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
1457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
14618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
147969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown
148969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        public boolean isSystemHapticFeedback() {
1497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean repeating = false;
1507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mEffect instanceof VibrationEffect.Waveform) {
1517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) mEffect;
1527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                repeating = (waveform.getRepeatIndex() < 0);
1537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
15418f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi            return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg))
1557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && !repeating;
156969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        }
15718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
15818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1593a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private static class VibrationInfo {
1607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final long mStartTime;
1617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect mEffect;
1627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
1637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
1647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final String mOpPkg;
1657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
1667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public VibrationInfo(long startTime, VibrationEffect effect,
1673a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                int usageHint, int uid, String opPkg) {
1687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mStartTime = startTime;
1697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mEffect = effect;
1707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
1717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
1727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mOpPkg = opPkg;
1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        @Override
1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        public String toString() {
1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            return new StringBuilder()
1783a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", startTime: ")
1797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mStartTime)
1807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(", effect: ")
1817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mEffect)
1823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", usageHint: ")
1837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mUsageHint)
1843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", uid: ")
1857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mUid)
1863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", opPkg: ")
1877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mOpPkg)
1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .toString();
1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
1913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
1923a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    VibratorService(Context context) {
193e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker        vibratorInit();
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Reset the hardware to a default state, in case this is a runtime
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // restart instead of a fresh boot.
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        vibratorOff();
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl();
1997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
2027e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock.setReferenceCounted(true);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mAppOpsService =
2067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
20791268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn        mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
20891268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn                BatteryStats.SERVICE_NAME));
209a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
2103a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        mPreviousVibrationsLimit = mContext.getResources().getInteger(
2113a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                com.android.internal.R.integer.config_previousVibrationsDumpLimit);
2123a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
2137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mDefaultVibrationAmplitude = mContext.getResources().getInteger(
2147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                com.android.internal.R.integer.config_defaultVibrationAmplitude);
2157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2163a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        mPreviousVibrations = new LinkedList<>();
21718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter filter = new IntentFilter();
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_SCREEN_OFF);
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        context.registerReceiver(mIntentReceiver, filter);
2217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] clickEffectTimings = getLongIntArray(context.getResources(),
2237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                com.android.internal.R.array.config_virtualKeyVibePattern);
224b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer        VibrationEffect clickEffect;
225017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer        if (clickEffectTimings.length == 0) {
226017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer            clickEffect = null;
227017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer        } else if (clickEffectTimings.length == 1) {
228b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer            clickEffect = VibrationEffect.createOneShot(
229b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer                    clickEffectTimings[0], VibrationEffect.DEFAULT_AMPLITUDE);
230b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer        } else {
231b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer            clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1);
232b97ae357cad31913793f2695123c7f09cf5eaddfErik Wolsheimer        }
2337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
2347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                new long[] {0, 30, 100, 30} /*timings*/, -1);
2357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect };
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2397f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void systemReady() {
2408ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa        mIm = mContext.getSystemService(InputManager.class);
24113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        mSettingObserver = new SettingsObserver(mH);
242d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
243eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
244eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal.registerLowPowerModeObserver(
245eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn                new PowerManagerInternal.LowPowerModeListener() {
246455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
247455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public int getServiceType() {
248455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                        return ServiceType.VIBRATION;
249455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
250455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei
251455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
252455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public void onLowPowerModeChanged(PowerSaveState result) {
2537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        updateVibrators();
254455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
255eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        });
256eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn
2577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        mContext.getContentResolver().registerContentObserver(
25813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
25913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                true, mSettingObserver, UserHandle.USER_ALL);
26013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
261d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
262d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            @Override
263d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            public void onReceive(Context context, Intent intent) {
2647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                updateVibrators();
265d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            }
266d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
267d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
2687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
2697f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
2707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
27113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private final class SettingsObserver extends ContentObserver {
27213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public SettingsObserver(Handler handler) {
27313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi            super(handler);
27413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
27513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
27613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        @Override
27713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public void onChange(boolean SelfChange) {
2787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            updateVibrators();
27913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
28013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    }
28113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
28282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
283ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    public boolean hasVibrator() {
2847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        return doVibratorExists();
285ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    }
2867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
2877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    @Override // Binder call
2887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public boolean hasAmplitudeControl() {
2897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
2907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input device vibrators don't support amplitude controls yet, but are still used over
2917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // the system vibrator when connected.
2927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty();
2937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
2947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
2957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
296f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
297f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (uid == Binder.getCallingUid()) {
298f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
299f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
300f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
301f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
302f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
303f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
304f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
305f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
306f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
3077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    /**
3087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * Validate the incoming VibrationEffect.
3097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * We can't throw exceptions here since we might be called from some system_server component,
3117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * which would bring the whole system down.
3127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * @return whether the VibrationEffect is valid
3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     */
3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static boolean verifyVibrationEffect(VibrationEffect effect) {
3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect == null) {
3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Effect must not be null.
3187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "effect must not be null");
3197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
320105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
321a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        try {
3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            effect.validate();
3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (Exception e) {
3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e);
3257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
32618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
3277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return true;
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static long[] getLongIntArray(Resources r, int resid) {
3317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int[] ar = r.getIntArray(resid);
3327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (ar == null) {
3337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return null;
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] out = new long[ar.length];
3367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        for (int i = 0; i < ar.length; i++) {
3377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            out[i] = ar[i];
3387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return out;
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint,
3447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IBinder token) {
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires VIBRATE permission");
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (token == null) {
3507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "token must not be null");
3517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
353f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
3547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (!verifyVibrationEffect(effect)) {
3557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // If our current vibration is longer than the new vibration and is the same amplitude,
3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // then just let the current one finish.
3607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.OneShot
3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration != null
3627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) {
3637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect;
3647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot currentOneShot =
3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    (VibrationEffect.OneShot) mCurrentVibration.mEffect;
3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming())
3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
3687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration");
3707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
3757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // Only link against waveforms since they potentially don't have a finish if
3787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // they're repeating. Let other effects just play out until they're done.
3797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.Waveform) {
38018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            try {
38118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                token.linkToDeath(vib, 0);
38218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            } catch (RemoteException e) {
38318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return;
38418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
3857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
3887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long ident = Binder.clearCallingIdentity();
3897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
3907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
39118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                doCancelVibrateLocked();
3927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                startVibrationLocked(vib);
3933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                addToPreviousVibrationsLocked(vib);
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } finally {
3967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Binder.restoreCallingIdentity(ident);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4003a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private void addToPreviousVibrationsLocked(Vibration vib) {
4013a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
4023a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            mPreviousVibrations.removeFirst();
4033a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
4047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mPreviousVibrations.addLast(new VibrationInfo(
4057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg));
4063a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
4073a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
40882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
40918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    public void cancelVibrate(IBinder token) {
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.VIBRATE,
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "cancelVibrate");
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration != null && mCurrentVibration.mToken == token) {
4167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
4177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.d(TAG, "Canceling vibration.");
4187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
4197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long ident = Binder.clearCallingIdentity();
4207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                try {
42118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
4227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } finally {
4237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Binder.restoreCallingIdentity(ident);
42418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
42518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
428f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
4297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Runnable mVibrationEndRunnable = new Runnable() {
43082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown        @Override
43118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void run() {
4327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            onVibrationFinished();
43318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
43418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    };
43518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
43618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void doCancelVibrateLocked() {
4377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mH.removeCallbacks(mVibrationEndRunnable);
43818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (mThread != null) {
4397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread.cancel();
44018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread = null;
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4427f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        doVibratorOff();
443a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        reportFinishVibrationLocked();
44418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
44518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
4467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // Callback for whenever the current vibration has finished played out
4477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void onVibrationFinished() {
4487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (DEBUG) {
4497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Vibration finished, cleaning up");
4507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Make sure the vibration is really done. This also reports that the vibration is
4537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // finished.
4547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doCancelVibrateLocked();
45518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
45618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
45718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
45818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void startVibrationLocked(final Vibration vib) {
4597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
4607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, low power mode");
462664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi            }
4637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
46513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE &&
4677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                !shouldVibrateForRingtone()) {
4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
470d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds            }
4717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
473d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds
4747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        final int mode = getAppOpMode(vib);
4757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mode != AppOpsManager.MODE_ALLOWED) {
4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ERRORED) {
4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // We might be getting calls from within system_server, so we don't actually want
4787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // to throw a SecurityException here.
4797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);
4801af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
4817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
482a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        startVibrationInnerLocked(vib);
4847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
4857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
4867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void startVibrationInnerLocked(Vibration vib) {
4877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mCurrentVibration = vib;
4887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.OneShot) {
4897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect;
4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint);
4917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming());
4927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Waveform) {
49318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // mThread better be null here. doCancelVibrate should always be
49418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // called before startNextVibrationLocked or startVibrationLocked.
4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect;
4967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint);
49718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread.start();
4987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Prebaked) {
4997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timeout = doVibratorPrebakedEffectLocked(vib);
5007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (timeout > 0) {
5017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mH.postDelayed(mVibrationEndRunnable, timeout);
5027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
5047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Unknown vibration type, ignoring");
50518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
50618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
50718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
5082d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    private boolean shouldVibrateForRingtone() {
5092d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
510dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger        int ringerMode = audioManager.getRingerModeInternal();
5112d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        // "Also vibrate for calls" Setting in Sound
5122d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        if (Settings.System.getInt(
5132d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger                mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) {
5142d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode != AudioManager.RINGER_MODE_SILENT;
5152d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        } else {
5162d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
5172d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        }
5182d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    }
5192d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger
5207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private int getAppOpMode(Vibration vib) {
5217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int mode;
5227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
5247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mUsageHint, vib.mUid, vib.mOpPkg);
5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ALLOWED) {
5267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
5287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
5307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Failed to get appop mode for vibration!", e);
5317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = AppOpsManager.MODE_IGNORED;
5327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return mode;
5347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
536a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private void reportFinishVibrationLocked() {
537a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mCurrentVibration != null) {
538a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            try {
539e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
540e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
5418fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer                        mCurrentVibration.mOpPkg);
5427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
543a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mCurrentVibration = null;
544a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
545a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
546a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
547b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    private void unlinkVibration(Vibration vib) {
5487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.Waveform) {
549b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            vib.mToken.unlinkToDeath(vib, 0);
550b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson        }
551b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    }
552b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson
5537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void updateVibrators() {
5547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
5557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean devicesUpdated = updateInputDeviceVibratorsLocked();
5567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean lowPowerModeUpdated = updateLowPowerModeLocked();
5577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (devicesUpdated || lowPowerModeUpdated) {
5597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // If the state changes out from under us then just reset.
5607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doCancelVibrateLocked();
5617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5648206525b242ceb012d882849c4e355223ba81b9dJeff Brown
5657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateInputDeviceVibratorsLocked() {
5667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean changed = false;
5677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean vibrateInputDevices = false;
5687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrateInputDevices = Settings.System.getIntForUser(
5707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mContext.getContentResolver(),
5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0;
5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (SettingNotFoundException snfe) {
5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vibrateInputDevices != mVibrateInputDevicesSetting) {
5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            changed = true;
5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mVibrateInputDevicesSetting = vibrateInputDevices;
5777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
57813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (!mInputDeviceListenerRegistered) {
5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = true;
5827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.registerInputDeviceListener(this, mH);
5837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
5857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mInputDeviceListenerRegistered) {
5867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = false;
5877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.unregisterInputDeviceListener(this);
5887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5908206525b242ceb012d882849c4e355223ba81b9dJeff Brown
5917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mInputDeviceVibrators.clear();
5927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
5937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int[] ids = mIm.getInputDeviceIds();
5947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            for (int i = 0; i < ids.length; i++) {
5957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                InputDevice device = mIm.getInputDevice(ids[i]);
5967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Vibrator vibrator = device.getVibrator();
5977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (vibrator.hasVibrator()) {
5987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mInputDeviceVibrators.add(vibrator);
5997f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6007f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return changed;
6047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateLowPowerModeLocked() {
6077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean lowPowerMode = mPowerManagerInternal
6087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
6097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (lowPowerMode != mLowPowerMode) {
6107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mLowPowerMode = lowPowerMode;
6117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return false;
6147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6157f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceAdded(int deviceId) {
6187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6197f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6207f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6217f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6227f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceChanged(int deviceId) {
6237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6267f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6277f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
6287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean doVibratorExists() {
6321064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // For now, we choose to ignore the presence of input devices that have vibrators
6331064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // when reporting whether the device has a vibrator.  Applications often use this
6341064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // information to decide whether to enable certain features so they expect the
6351064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // result of hasVibrator() to be constant.  For now, just report whether
6361064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // the device has a built-in vibrator.
6371064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //synchronized (mInputDeviceVibrators) {
6381064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //    return !mInputDeviceVibrators.isEmpty() || vibratorExists();
6391064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //}
640c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        return vibratorExists();
6417f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6427f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) {
6447f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
6457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
6467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                amplitude = mDefaultVibrationAmplitude;
64782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
6497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.d(TAG, "Turning vibrator on for " + millis + " ms" +
6507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        " with amplitude " + amplitude + ".");
651a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
6527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOnLocked(uid, millis);
6537f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
6547f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
6557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final AudioAttributes attributes =
6567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        new AudioAttributes.Builder().setUsage(usageHint).build();
6577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
6587b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                    mInputDeviceVibrators.get(i).vibrate(millis, attributes);
6597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
6617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // Note: ordering is important here! Many haptic drivers will reset their amplitude
6627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // when enabled, so we always have to enable frst, then set the amplitude.
6637f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOn(millis);
6647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doVibratorSetAmplitude(amplitude);
6657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6667f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorSetAmplitude(int amplitude) {
6707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mSupportsAmplitudeControl) {
6717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibratorSetAmplitude(amplitude);
6727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
6757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private void doVibratorOff() {
6767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
67782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            if (DEBUG) {
67882379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown                Slog.d(TAG, "Turning vibrator off.");
67982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOffLocked();
6817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
6827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
6837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
6847f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    mInputDeviceVibrators.get(i).cancel();
6857f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
6877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOff();
6887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private long doVibratorPrebakedEffectLocked(Vibration vib) {
6937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
6947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect;
6957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input devices don't support prebaked effect, so skip trying it with them.
6967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int vibratorCount = mInputDeviceVibrators.size();
6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (vibratorCount == 0) {
6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM);
6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (timeout > 0) {
7007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    noteVibratorOnLocked(vib.mUid, timeout);
7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return timeout;
7027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
7037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int id = prebaked.getId();
705017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer            if (id < 0 || id >= mFallbackEffects.length || mFallbackEffects[id] == null) {
7067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Failed to play prebaked effect, no fallback");
7077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return 0;
7087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect = mFallbackEffects[id];
7107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Vibration fallbackVib =
7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg);
7127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            startVibrationInnerLocked(fallbackVib);
7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return 0;
7157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOnLocked(int uid, long millis) {
7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mBatteryStatsService.noteVibratorOn(uid, millis);
7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = uid;
7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOffLocked() {
7267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mCurVibUid >= 0) {
7277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mBatteryStatsService.noteVibratorOff(mCurVibUid);
7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
7307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = -1;
7317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class VibrateThread extends Thread {
7357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect.Waveform mWaveform;
7367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
7377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
738f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
7397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private boolean mForceStop;
7407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) {
7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWaveform = waveform;
7437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
7457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mTmpWorkSource.set(uid);
7467e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.setWorkSource(mTmpWorkSource);
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long delayLocked(long duration) {
7507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long durationRemaining = duration;
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration > 0) {
7527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long bedtime = duration + SystemClock.uptimeMillis();
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
7557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        this.wait(durationRemaining);
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    catch (InterruptedException e) { }
7587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (mForceStop) {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    durationRemaining = bedtime - SystemClock.uptimeMillis();
7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } while (durationRemaining > 0);
7637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return duration - durationRemaining;
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return 0;
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWakeLock.acquire();
7717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                boolean finished = playWaveform();
7737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (finished) {
7747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    onVibrationFinished();
7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } finally {
7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mWakeLock.release();
7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Play the waveform.
7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         *
7847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * @return true if it finished naturally, false otherwise (e.g. it was canceled).
7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
7867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public boolean playWaveform() {
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
7887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long[] timings = mWaveform.getTimings();
7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int[] amplitudes = mWaveform.getAmplitudes();
7907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int len = timings.length;
7917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int repeat = mWaveform.getRepeatIndex();
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int index = 0;
7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long onDuration = 0;
7957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                while (!mForceStop) {
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (index < len) {
7977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final int amplitude = amplitudes[index];
7987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final long duration = timings[index++];
7997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (duration <= 0) {
8007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            continue;
8017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            if (onDuration <= 0) {
8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // Telling the vibrator to start multiple times usually causes
8057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // effects to feel "choppy" because the motor resets at every on
8067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // command.  Instead we figure out how long our next "on" period is
8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // going to be, tell the motor to stay on for the full duration,
8087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // and then wake up to change the amplitude at the appropriate
8097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // intervals.
8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                onDuration =
8117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                        getTotalOnDuration(timings, amplitudes, index - 1, repeat);
8127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorOn(onDuration, amplitude, mUid, mUsageHint);
8137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            } else {
8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorSetAmplitude(amplitude);
8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            }
8167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        long waitTime = delayLocked(duration);
8197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            onDuration -= waitTime;
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else if (repeat < 0) {
8237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
8257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        index = repeat;
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return !mForceStop;
8297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public void cancel() {
8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (this) {
8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.mForceStop = true;
8357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.notify();
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Get the duration the vibrator will be on starting at startIndex until the next time it's
8417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * off.
8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long getTotalOnDuration(
8447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long[] timings, int[] amplitudes, int startIndex, int repeatIndex) {
8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int i = startIndex;
8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timing = 0;
8477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            while(amplitudes[i] != 0) {
8487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                timing += timings[i++];
8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i >= timings.length) {
8507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (repeatIndex >= 0) {
8517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        i = repeatIndex;
8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else {
8537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    }
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i == startIndex) {
8577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return 1000;
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return timing;
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
862969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown    }
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
865969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        @Override
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
8687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                synchronized (mLock) {
869969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // When the system is entering a non-interactive state, we want
870969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // to cancel vibrations in case a misbehaving app has abandoned
871969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // them.  However it may happen that the system is currently playing
872969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // haptic feedback as part of the transition.  So we don't cancel
873969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // system vibrations.
874969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    if (mCurrentVibration != null
875969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                            && !mCurrentVibration.isSystemHapticFeedback()) {
876969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        doCancelVibrateLocked();
8778a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan                    }
87818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
8823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
8833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    @Override
8843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
885fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
8863a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
8873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        pw.println("Previous vibrations:");
8887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
8893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            for (VibrationInfo info : mPreviousVibrations) {
8903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.print("  ");
8913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.println(info.toString());
8923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            }
8933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
8943a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
895a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
896a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    @Override
897a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
898a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
899a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            throws RemoteException {
900a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
901a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
902a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
903a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    private final class VibratorShellCommand extends ShellCommand {
904a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
905a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private static final long MAX_VIBRATION_MS = 200;
906a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
907a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private final IBinder mToken;
908a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
909a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private VibratorShellCommand(IBinder token) {
910a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            mToken = token;
911a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
912a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
913a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
914a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public int onCommand(String cmd) {
915a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if ("vibrate".equals(cmd)) {
916a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                return runVibrate();
917a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
918a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return handleDefaultCommands(cmd);
919a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
920a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
921a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private int runVibrate() {
922a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            final long duration = Long.parseLong(getNextArgRequired());
923a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (duration > MAX_VIBRATION_MS) {
924a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS);
925a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
926a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String description = getNextArg();
927a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (description == null) {
928a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                description = "Shell command";
929a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
9307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
9317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect =
9327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
9337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
934a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                    mToken);
935a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return 0;
936a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
937a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
938a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
939a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public void onHelp() {
940a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            try (PrintWriter pw = getOutPrintWriter();) {
941a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("Vibrator commands:");
942a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  help");
943a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Prints this help text.");
944a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
945a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  vibrate duration [description]");
946a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Vibrates for duration milliseconds.");
947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
950a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
951a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
953