VibratorService.java revision 57d94d9fb1e55345307e579977138aaf6177e388
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);
22457d94d9fb1e55345307e579977138aaf6177e388Michael Wright        VibrationEffect clickEffect = createEffect(clickEffectTimings);
2257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
2267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                new long[] {0, 30, 100, 30} /*timings*/, -1);
22757d94d9fb1e55345307e579977138aaf6177e388Michael Wright        long[] tickEffectTimings = getLongIntArray(context.getResources(),
22857d94d9fb1e55345307e579977138aaf6177e388Michael Wright                com.android.internal.R.array.config_clockTickVibePattern);
22957d94d9fb1e55345307e579977138aaf6177e388Michael Wright        VibrationEffect tickEffect = createEffect(tickEffectTimings);
23057d94d9fb1e55345307e579977138aaf6177e388Michael Wright
23157d94d9fb1e55345307e579977138aaf6177e388Michael Wright        mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect, tickEffect };
23257d94d9fb1e55345307e579977138aaf6177e388Michael Wright    }
2337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
23457d94d9fb1e55345307e579977138aaf6177e388Michael Wright    private static VibrationEffect createEffect(long[] timings) {
23557d94d9fb1e55345307e579977138aaf6177e388Michael Wright        if (timings == null || timings.length == 0) {
23657d94d9fb1e55345307e579977138aaf6177e388Michael Wright            return null;
23757d94d9fb1e55345307e579977138aaf6177e388Michael Wright        } else if (timings.length == 1) {
23857d94d9fb1e55345307e579977138aaf6177e388Michael Wright            return VibrationEffect.createOneShot(timings[0], VibrationEffect.DEFAULT_AMPLITUDE);
23957d94d9fb1e55345307e579977138aaf6177e388Michael Wright        } else {
24057d94d9fb1e55345307e579977138aaf6177e388Michael Wright            return VibrationEffect.createWaveform(timings, -1);
24157d94d9fb1e55345307e579977138aaf6177e388Michael Wright        }
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2447f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void systemReady() {
2458ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa        mIm = mContext.getSystemService(InputManager.class);
24613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        mSettingObserver = new SettingsObserver(mH);
247d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
248eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
249eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal.registerLowPowerModeObserver(
250eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn                new PowerManagerInternal.LowPowerModeListener() {
251455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
252455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public int getServiceType() {
253455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                        return ServiceType.VIBRATION;
254455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
255455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei
256455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
257455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public void onLowPowerModeChanged(PowerSaveState result) {
2587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        updateVibrators();
259455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
260eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        });
261eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn
2627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        mContext.getContentResolver().registerContentObserver(
26313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
26413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                true, mSettingObserver, UserHandle.USER_ALL);
26513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
266d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
267d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            @Override
268d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            public void onReceive(Context context, Intent intent) {
2697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                updateVibrators();
270d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            }
271d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
272d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
2737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
2747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
2757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
27613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private final class SettingsObserver extends ContentObserver {
27713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public SettingsObserver(Handler handler) {
27813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi            super(handler);
27913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
28013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
28113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        @Override
28213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public void onChange(boolean SelfChange) {
2837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            updateVibrators();
28413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
28513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    }
28613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
28782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
288ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    public boolean hasVibrator() {
2897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        return doVibratorExists();
290ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    }
2917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
2927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    @Override // Binder call
2937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public boolean hasAmplitudeControl() {
2947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
2957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input device vibrators don't support amplitude controls yet, but are still used over
2967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // the system vibrator when connected.
2977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty();
2987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
2997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
3007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
301f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
302f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (uid == Binder.getCallingUid()) {
303f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
304f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
305f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
306f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
307f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
308f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
309f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
310f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
311f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
3127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    /**
3137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * Validate the incoming VibrationEffect.
3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * We can't throw exceptions here since we might be called from some system_server component,
3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * which would bring the whole system down.
3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * @return whether the VibrationEffect is valid
3197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     */
3207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static boolean verifyVibrationEffect(VibrationEffect effect) {
3217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect == null) {
3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Effect must not be null.
3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "effect must not be null");
3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
325105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
326a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        try {
3277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            effect.validate();
3287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (Exception e) {
3297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e);
3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
33118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
3327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return true;
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static long[] getLongIntArray(Resources r, int resid) {
3367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int[] ar = r.getIntArray(resid);
3377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (ar == null) {
3387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return null;
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] out = new long[ar.length];
3417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        for (int i = 0; i < ar.length; i++) {
3427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            out[i] = ar[i];
3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return out;
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34782379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
3487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint,
3497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IBinder token) {
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires VIBRATE permission");
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (token == null) {
3557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "token must not be null");
3567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
358f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (!verifyVibrationEffect(effect)) {
3607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // If our current vibration is longer than the new vibration and is the same amplitude,
3647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // then just let the current one finish.
3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.OneShot
3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration != null
3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) {
3687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect;
3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot currentOneShot =
3707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    (VibrationEffect.OneShot) mCurrentVibration.mEffect;
3717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming())
3727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
3737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
3747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration");
3757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
3807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // Only link against waveforms since they potentially don't have a finish if
3837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // they're repeating. Let other effects just play out until they're done.
3847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.Waveform) {
38518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            try {
38618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                token.linkToDeath(vib, 0);
38718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            } catch (RemoteException e) {
38818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return;
38918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
3907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
3937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long ident = Binder.clearCallingIdentity();
3947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
3957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
39618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                doCancelVibrateLocked();
3977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                startVibrationLocked(vib);
3983a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                addToPreviousVibrationsLocked(vib);
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } finally {
4017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Binder.restoreCallingIdentity(ident);
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4053a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private void addToPreviousVibrationsLocked(Vibration vib) {
4063a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
4073a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            mPreviousVibrations.removeFirst();
4083a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
4097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mPreviousVibrations.addLast(new VibrationInfo(
4107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg));
4113a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
4123a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
41382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
41418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    public void cancelVibrate(IBinder token) {
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.VIBRATE,
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "cancelVibrate");
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration != null && mCurrentVibration.mToken == token) {
4217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
4227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.d(TAG, "Canceling vibration.");
4237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
4247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long ident = Binder.clearCallingIdentity();
4257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                try {
42618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
4277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } finally {
4287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Binder.restoreCallingIdentity(ident);
42918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
43018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
433f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
4347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Runnable mVibrationEndRunnable = new Runnable() {
43582379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown        @Override
43618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void run() {
4377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            onVibrationFinished();
43818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
43918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    };
44018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
44118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void doCancelVibrateLocked() {
4427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mH.removeCallbacks(mVibrationEndRunnable);
44318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (mThread != null) {
4447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread.cancel();
44518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread = null;
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4477f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        doVibratorOff();
448a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        reportFinishVibrationLocked();
44918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
45018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // Callback for whenever the current vibration has finished played out
4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void onVibrationFinished() {
4537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (DEBUG) {
4547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Vibration finished, cleaning up");
4557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
4567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Make sure the vibration is really done. This also reports that the vibration is
4587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // finished.
4597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doCancelVibrateLocked();
46018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
46118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
46218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
46318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void startVibrationLocked(final Vibration vib) {
4647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
4657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, low power mode");
467664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi            }
4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
47013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
4717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE &&
4727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                !shouldVibrateForRingtone()) {
4737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
475d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds            }
4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
478d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds
4797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        final int mode = getAppOpMode(vib);
4807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mode != AppOpsManager.MODE_ALLOWED) {
4817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ERRORED) {
4827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // We might be getting calls from within system_server, so we don't actually want
4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // to throw a SecurityException here.
4847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);
4851af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
4867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
487a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
4887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        startVibrationInnerLocked(vib);
4897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
4917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void startVibrationInnerLocked(Vibration vib) {
4927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mCurrentVibration = vib;
4937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.OneShot) {
4947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect;
4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint);
4967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming());
4977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Waveform) {
49818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // mThread better be null here. doCancelVibrate should always be
49918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // called before startNextVibrationLocked or startVibrationLocked.
5007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect;
5017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint);
50218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread.start();
5037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Prebaked) {
5047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timeout = doVibratorPrebakedEffectLocked(vib);
5057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (timeout > 0) {
5067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mH.postDelayed(mVibrationEndRunnable, timeout);
5077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
5097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Unknown vibration type, ignoring");
51018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
51118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
51218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
5132d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    private boolean shouldVibrateForRingtone() {
5142d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
515dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger        int ringerMode = audioManager.getRingerModeInternal();
5162d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        // "Also vibrate for calls" Setting in Sound
5172d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        if (Settings.System.getInt(
5182d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger                mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) {
5192d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode != AudioManager.RINGER_MODE_SILENT;
5202d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        } else {
5212d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
5222d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        }
5232d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    }
5242d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger
5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private int getAppOpMode(Vibration vib) {
5267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int mode;
5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
5297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mUsageHint, vib.mUid, vib.mOpPkg);
5307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ALLOWED) {
5317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
5327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
5337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
5357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Failed to get appop mode for vibration!", e);
5367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = AppOpsManager.MODE_IGNORED;
5377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return mode;
5397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
541a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private void reportFinishVibrationLocked() {
542a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mCurrentVibration != null) {
543a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            try {
544e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
545e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
5468fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer                        mCurrentVibration.mOpPkg);
5477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
548a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mCurrentVibration = null;
549a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
550a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
551a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
552b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    private void unlinkVibration(Vibration vib) {
5537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.Waveform) {
554b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            vib.mToken.unlinkToDeath(vib, 0);
555b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson        }
556b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    }
557b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson
5587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void updateVibrators() {
5597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
5607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean devicesUpdated = updateInputDeviceVibratorsLocked();
5617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean lowPowerModeUpdated = updateLowPowerModeLocked();
5627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (devicesUpdated || lowPowerModeUpdated) {
5647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // If the state changes out from under us then just reset.
5657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doCancelVibrateLocked();
5667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5698206525b242ceb012d882849c4e355223ba81b9dJeff Brown
5707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateInputDeviceVibratorsLocked() {
5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean changed = false;
5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean vibrateInputDevices = false;
5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrateInputDevices = Settings.System.getIntForUser(
5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mContext.getContentResolver(),
5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0;
5777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (SettingNotFoundException snfe) {
5787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vibrateInputDevices != mVibrateInputDevicesSetting) {
5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            changed = true;
5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mVibrateInputDevicesSetting = vibrateInputDevices;
5827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
58313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
5857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (!mInputDeviceListenerRegistered) {
5867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = true;
5877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.registerInputDeviceListener(this, mH);
5887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
5907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mInputDeviceListenerRegistered) {
5917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = false;
5927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.unregisterInputDeviceListener(this);
5937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5958206525b242ceb012d882849c4e355223ba81b9dJeff Brown
5967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mInputDeviceVibrators.clear();
5977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
5987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int[] ids = mIm.getInputDeviceIds();
5997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            for (int i = 0; i < ids.length; i++) {
6007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                InputDevice device = mIm.getInputDevice(ids[i]);
6017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Vibrator vibrator = device.getVibrator();
6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (vibrator.hasVibrator()) {
6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mInputDeviceVibrators.add(vibrator);
6047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return changed;
6097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6107f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateLowPowerModeLocked() {
6127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean lowPowerMode = mPowerManagerInternal
6137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
6147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (lowPowerMode != mLowPowerMode) {
6157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mLowPowerMode = lowPowerMode;
6167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return false;
6197f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6207f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6217f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6227f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceAdded(int deviceId) {
6237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6247f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6257f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6267f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6277f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceChanged(int deviceId) {
6287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6297f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6307f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6327f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
6337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6357f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean doVibratorExists() {
6371064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // For now, we choose to ignore the presence of input devices that have vibrators
6381064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // when reporting whether the device has a vibrator.  Applications often use this
6391064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // information to decide whether to enable certain features so they expect the
6401064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // result of hasVibrator() to be constant.  For now, just report whether
6411064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // the device has a built-in vibrator.
6421064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //synchronized (mInputDeviceVibrators) {
6431064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //    return !mInputDeviceVibrators.isEmpty() || vibratorExists();
6441064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //}
645c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        return vibratorExists();
6467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6477f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) {
6497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
6507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
6517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                amplitude = mDefaultVibrationAmplitude;
65282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
6547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.d(TAG, "Turning vibrator on for " + millis + " ms" +
6557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        " with amplitude " + amplitude + ".");
656a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
6577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOnLocked(uid, millis);
6587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
6597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
6607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final AudioAttributes attributes =
6617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        new AudioAttributes.Builder().setUsage(usageHint).build();
6627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
6637b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                    mInputDeviceVibrators.get(i).vibrate(millis, attributes);
6647f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6657f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
6667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // Note: ordering is important here! Many haptic drivers will reset their amplitude
6677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // when enabled, so we always have to enable frst, then set the amplitude.
6687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOn(millis);
6697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doVibratorSetAmplitude(amplitude);
6707f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6717f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6727f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorSetAmplitude(int amplitude) {
6757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mSupportsAmplitudeControl) {
6767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibratorSetAmplitude(amplitude);
6777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
6807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private void doVibratorOff() {
6817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
68282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            if (DEBUG) {
68382379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown                Slog.d(TAG, "Turning vibrator off.");
68482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOffLocked();
6867f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
6877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
6887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
6897f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    mInputDeviceVibrators.get(i).cancel();
6907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
6927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOff();
6937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private long doVibratorPrebakedEffectLocked(Vibration vib) {
6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect;
7007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input devices don't support prebaked effect, so skip trying it with them.
7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int vibratorCount = mInputDeviceVibrators.size();
7027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (vibratorCount == 0) {
7037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM);
7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (timeout > 0) {
7057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    noteVibratorOnLocked(vib.mUid, timeout);
7067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return timeout;
7077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
7087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int id = prebaked.getId();
710017939e43ceb847333d1115258c3db1411dbc03aErik Wolsheimer            if (id < 0 || id >= mFallbackEffects.length || mFallbackEffects[id] == null) {
7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Failed to play prebaked effect, no fallback");
7127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return 0;
7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect = mFallbackEffects[id];
7157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Vibration fallbackVib =
7167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg);
7177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            startVibrationInnerLocked(fallbackVib);
7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return 0;
7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOnLocked(int uid, long millis) {
7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
7247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mBatteryStatsService.noteVibratorOn(uid, millis);
7257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = uid;
7267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
7277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOffLocked() {
7317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mCurVibUid >= 0) {
7327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mBatteryStatsService.noteVibratorOff(mCurVibUid);
7347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
7357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = -1;
7367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class VibrateThread extends Thread {
7407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect.Waveform mWaveform;
7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
743f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private boolean mForceStop;
7457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) {
7477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWaveform = waveform;
7487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
7507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mTmpWorkSource.set(uid);
7517e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.setWorkSource(mTmpWorkSource);
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long delayLocked(long duration) {
7557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long durationRemaining = duration;
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration > 0) {
7577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long bedtime = duration + SystemClock.uptimeMillis();
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
7607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        this.wait(durationRemaining);
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    catch (InterruptedException e) { }
7637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (mForceStop) {
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    durationRemaining = bedtime - SystemClock.uptimeMillis();
7677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } while (durationRemaining > 0);
7687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return duration - durationRemaining;
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return 0;
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWakeLock.acquire();
7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                boolean finished = playWaveform();
7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (finished) {
7797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    onVibrationFinished();
7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } finally {
7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mWakeLock.release();
7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
7877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Play the waveform.
7887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         *
7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * @return true if it finished naturally, false otherwise (e.g. it was canceled).
7907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
7917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public boolean playWaveform() {
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long[] timings = mWaveform.getTimings();
7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int[] amplitudes = mWaveform.getAmplitudes();
7957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int len = timings.length;
7967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int repeat = mWaveform.getRepeatIndex();
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int index = 0;
7997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long onDuration = 0;
8007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                while (!mForceStop) {
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (index < len) {
8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final int amplitude = amplitudes[index];
8037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final long duration = timings[index++];
8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (duration <= 0) {
8057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            continue;
8067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            if (onDuration <= 0) {
8097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // Telling the vibrator to start multiple times usually causes
8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // effects to feel "choppy" because the motor resets at every on
8117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // command.  Instead we figure out how long our next "on" period is
8127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // going to be, tell the motor to stay on for the full duration,
8137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // and then wake up to change the amplitude at the appropriate
8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // intervals.
8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                onDuration =
8167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                        getTotalOnDuration(timings, amplitudes, index - 1, repeat);
8177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorOn(onDuration, amplitude, mUid, mUsageHint);
8187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            } else {
8197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorSetAmplitude(amplitude);
8207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            }
8217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        long waitTime = delayLocked(duration);
8247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            onDuration -= waitTime;
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else if (repeat < 0) {
8287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        index = repeat;
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return !mForceStop;
8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
8357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public void cancel() {
8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (this) {
8397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.mForceStop = true;
8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.notify();
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Get the duration the vibrator will be on starting at startIndex until the next time it's
8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * off.
8477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
8487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long getTotalOnDuration(
8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long[] timings, int[] amplitudes, int startIndex, int repeatIndex) {
8507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int i = startIndex;
8517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timing = 0;
8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            while(amplitudes[i] != 0) {
8537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                timing += timings[i++];
8547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i >= timings.length) {
8557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (repeatIndex >= 0) {
8567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        i = repeatIndex;
8577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else {
8587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    }
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i == startIndex) {
8627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return 1000;
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return timing;
8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
867969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown    }
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
870969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        @Override
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
8737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                synchronized (mLock) {
874969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // When the system is entering a non-interactive state, we want
875969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // to cancel vibrations in case a misbehaving app has abandoned
876969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // them.  However it may happen that the system is currently playing
877969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // haptic feedback as part of the transition.  So we don't cancel
878969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // system vibrations.
879969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    if (mCurrentVibration != null
880969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                            && !mCurrentVibration.isSystemHapticFeedback()) {
881969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        doCancelVibrateLocked();
8828a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan                    }
88318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
8873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
8883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    @Override
8893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
890fe9a53bc45fd0124a876dc0a49680aaf86641d3eJeff Sharkey        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
8913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
8923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        pw.println("Previous vibrations:");
8937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
8943a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            for (VibrationInfo info : mPreviousVibrations) {
8953a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.print("  ");
8963a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.println(info.toString());
8973a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            }
8983a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
8993a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
900a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
901a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    @Override
902a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
903a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
904a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            throws RemoteException {
905a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
906a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
907a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
908a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    private final class VibratorShellCommand extends ShellCommand {
909a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
910a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private static final long MAX_VIBRATION_MS = 200;
911a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
912a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private final IBinder mToken;
913a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
914a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private VibratorShellCommand(IBinder token) {
915a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            mToken = token;
916a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
917a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
918a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
919a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public int onCommand(String cmd) {
920a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if ("vibrate".equals(cmd)) {
921a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                return runVibrate();
922a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
923a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return handleDefaultCommands(cmd);
924a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
925a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
926a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private int runVibrate() {
927a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            final long duration = Long.parseLong(getNextArgRequired());
928a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (duration > MAX_VIBRATION_MS) {
929a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS);
930a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
931a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String description = getNextArg();
932a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (description == null) {
933a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                description = "Shell command";
934a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
9357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
9367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect =
9377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
9387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
939a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                    mToken);
940a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return 0;
941a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
942a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
943a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
944a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public void onHelp() {
945a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            try (PrintWriter pw = getOutPrintWriter();) {
946a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("Vibrator commands:");
947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  help");
948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Prints this help text.");
949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
950a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  vibrate duration [description]");
951a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Vibrates for duration milliseconds.");
952a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
953a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
954a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
955a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
956a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
958