VibratorService.java revision 7121697a5e2d4458f6f63e9eb3b5deec62ee6202
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;
57455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyuleiimport com.android.server.power.BatterySaverPolicy.ServiceType;
58a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
593a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.FileDescriptor;
603a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.io.PrintWriter;
617f6c231a76f0bedaf9655a24707737d343244312Jeff Brownimport java.util.ArrayList;
623a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynskiimport java.util.Arrays;
63969579bb9d208c91e081ff96d2fd788269d254bdJeff Brownimport java.util.Iterator;
6418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.LinkedList;
6518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scottimport java.util.ListIterator;
6618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
677f6c231a76f0bedaf9655a24707737d343244312Jeff Brownpublic class VibratorService extends IVibratorService.Stub
687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        implements InputManager.InputDeviceListener {
693a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    private static final String TAG = "VibratorService";
7082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    private static final boolean DEBUG = false;
7118f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi    private static final String SYSTEM_UI_PACKAGE = "com.android.systemui";
72cc9a63dbc2b5569ef65ec3a04d86dbdfdee3f134Mike Lockwood
733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private final LinkedList<VibrationInfo> mPreviousVibrations;
743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private final int mPreviousVibrationsLimit;
757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final boolean mSupportsAmplitudeControl;
767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final int mDefaultVibrationAmplitude;
777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final VibrationEffect[] mFallbackEffects;
787e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn    private final WorkSource mTmpWorkSource = new WorkSource();
797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Handler mH = new Handler();
807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Object mLock = new Object();
817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final Context mContext;
837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final PowerManager.WakeLock mWakeLock;
84a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IAppOpsService mAppOpsService;
85a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private final IBatteryStats mBatteryStatsService;
86eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn    private PowerManagerInternal mPowerManagerInternal;
877f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private InputManager mIm;
887f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private volatile VibrateThread mThread;
907f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // mInputDeviceVibrators lock should be acquired after mLock, if both are
927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    // to be acquired
937f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private final ArrayList<Vibrator> mInputDeviceVibrators = new ArrayList<Vibrator>();
947f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mVibrateInputDevicesSetting; // guarded by mInputDeviceVibrators
957f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean mInputDeviceListenerRegistered; // guarded by mInputDeviceVibrators
967f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private Vibration mCurrentVibration;
98a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private int mCurVibUid = -1;
9913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private boolean mLowPowerMode;
10013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private SettingsObserver mSettingObserver;
101a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
1027f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static boolean vibratorExists();
103e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker    native static void vibratorInit();
1047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOn(long milliseconds);
1057f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    native static void vibratorOff();
1067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static boolean vibratorSupportsAmplitudeControl();
1077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static void vibratorSetAmplitude(int amplitude);
1087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    native static long vibratorPerformEffect(long effect, long strength);
10918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
11018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private class Vibration implements IBinder.DeathRecipient {
11118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        private final IBinder mToken;
1127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect mEffect;
1137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final long mStartTime;
1147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
1157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
1167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final String mOpPkg;
11718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private Vibration(IBinder token, VibrationEffect effect,
1197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int usageHint, int uid, String opPkg) {
12018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mToken = token;
1217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mEffect = effect;
12218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mStartTime = SystemClock.uptimeMillis();
1237b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock            mUsageHint = usageHint;
1247e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mUid = uid;
1258fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer            mOpPkg = opPkg;
12618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
12718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
12818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void binderDied() {
1297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
13018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                if (this == mCurrentVibration) {
13118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
13218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
13318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
13418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
13518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
13618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public boolean hasLongerTimeout(long millis) {
1377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // If the current effect is a one shot vibration that will end after the given timeout
1387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // for the new one shot vibration, then just let the current vibration finish. All
1397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // other effect types will get pre-empted.
1407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mEffect instanceof VibrationEffect.OneShot) {
1417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) mEffect;
1427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return mStartTime + oneShot.getTiming() > SystemClock.uptimeMillis() + millis;
14318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
1447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
14518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
146969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown
147969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        public boolean isSystemHapticFeedback() {
1487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean repeating = false;
1497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mEffect instanceof VibrationEffect.Waveform) {
1507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) mEffect;
1517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                repeating = (waveform.getRepeatIndex() < 0);
1527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
15318f18ae078ee97bbdfc9da39d4a19866dceb6a3eJorim Jaggi            return (mUid == Process.SYSTEM_UID || mUid == 0 || SYSTEM_UI_PACKAGE.equals(mOpPkg))
1547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && !repeating;
155969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        }
15618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
15718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
1583a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private static class VibrationInfo {
1597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final long mStartTime;
1607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect mEffect;
1617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
1627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
1637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final String mOpPkg;
1647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
1657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public VibrationInfo(long startTime, VibrationEffect effect,
1663a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                int usageHint, int uid, String opPkg) {
1677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mStartTime = startTime;
1687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mEffect = effect;
1697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
1707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
1717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mOpPkg = opPkg;
1723a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
1733a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
1743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        @Override
1753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        public String toString() {
1763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            return new StringBuilder()
1773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", startTime: ")
1787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mStartTime)
1797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(", effect: ")
1807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mEffect)
1813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", usageHint: ")
1827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mUsageHint)
1833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", uid: ")
1847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mUid)
1853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .append(", opPkg: ")
1867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    .append(mOpPkg)
1873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    .toString();
1883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
1893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
1903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
1913a32213c4029a03fe39486f3d6ebd0ea18928ee1Mike Lockwood    VibratorService(Context context) {
192e6904fbdf7976abbadf3e7e658e9416ca49402f9Vincent Becker        vibratorInit();
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Reset the hardware to a default state, in case this is a runtime
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // restart instead of a fresh boot.
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        vibratorOff();
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mSupportsAmplitudeControl = vibratorSupportsAmplitudeControl();
1987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
2007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
2017e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "*vibrator*");
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWakeLock.setReferenceCounted(true);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mAppOpsService =
2057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IAppOpsService.Stub.asInterface(ServiceManager.getService(Context.APP_OPS_SERVICE));
20691268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn        mBatteryStatsService = IBatteryStats.Stub.asInterface(ServiceManager.getService(
20791268cf21eace600792d04db1ac62e9268f48002Dianne Hackborn                BatteryStats.SERVICE_NAME));
208a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
2093a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        mPreviousVibrationsLimit = mContext.getResources().getInteger(
2103a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                com.android.internal.R.integer.config_previousVibrationsDumpLimit);
2113a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
2127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mDefaultVibrationAmplitude = mContext.getResources().getInteger(
2137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                com.android.internal.R.integer.config_defaultVibrationAmplitude);
2147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2153a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        mPreviousVibrations = new LinkedList<>();
21618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IntentFilter filter = new IntentFilter();
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        filter.addAction(Intent.ACTION_SCREEN_OFF);
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        context.registerReceiver(mIntentReceiver, filter);
2207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] clickEffectTimings = getLongIntArray(context.getResources(),
2227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                com.android.internal.R.array.config_virtualKeyVibePattern);
2237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrationEffect clickEffect = VibrationEffect.createWaveform(clickEffectTimings, -1);
2247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrationEffect doubleClickEffect = VibrationEffect.createWaveform(
2257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                new long[] {0, 30, 100, 30} /*timings*/, -1);
2267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mFallbackEffects = new VibrationEffect[] { clickEffect, doubleClickEffect };
2287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2317f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void systemReady() {
2328ce2a538d9b94a0d8e1543c4ee4620a8af525276Yohei Yukawa        mIm = mContext.getSystemService(InputManager.class);
23313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        mSettingObserver = new SettingsObserver(mH);
234d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
235eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
236eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        mPowerManagerInternal.registerLowPowerModeObserver(
237eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn                new PowerManagerInternal.LowPowerModeListener() {
238455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
239455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public int getServiceType() {
240455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                        return ServiceType.VIBRATION;
241455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
242455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei
243455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    @Override
244455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    public void onLowPowerModeChanged(PowerSaveState result) {
2457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        updateVibrators();
246455e90add22835d0744fc0f5c2feb5fcaf03b28fjackqdyulei                    }
247eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn        });
248eb94fa7975b1e8742f3b00cec6bd4f9d6b329e3aDianne Hackborn
2497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        mContext.getContentResolver().registerContentObserver(
25013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                Settings.System.getUriFor(Settings.System.VIBRATE_INPUT_DEVICES),
25113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi                true, mSettingObserver, UserHandle.USER_ALL);
25213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
253d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        mContext.registerReceiver(new BroadcastReceiver() {
254d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            @Override
255d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            public void onReceive(Context context, Intent intent) {
2567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                updateVibrators();
257d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown            }
258d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH);
259d49359631bc2642be73dc162a8a73207df1e0bafJeff Brown
2607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
2617f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
2627f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
26313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    private final class SettingsObserver extends ContentObserver {
26413b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public SettingsObserver(Handler handler) {
26513b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi            super(handler);
26613b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
26713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
26813b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        @Override
26913b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        public void onChange(boolean SelfChange) {
2707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            updateVibrators();
27113b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi        }
27213b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi    }
27313b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
27482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
275ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    public boolean hasVibrator() {
2767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        return doVibratorExists();
277ea9020e0854427d47e566a1394df6749f3265410Dianne Hackborn    }
2787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
2797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    @Override // Binder call
2807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public boolean hasAmplitudeControl() {
2817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
2827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input device vibrators don't support amplitude controls yet, but are still used over
2837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // the system vibrator when connected.
2847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return mSupportsAmplitudeControl && mInputDeviceVibrators.isEmpty();
2857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
2867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
2877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
288f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    private void verifyIncomingUid(int uid) {
289f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (uid == Binder.getCallingUid()) {
290f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
291f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
292f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        if (Binder.getCallingPid() == Process.myPid()) {
293f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn            return;
294f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        }
295f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        mContext.enforcePermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
296f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn                Binder.getCallingPid(), Binder.getCallingUid(), null);
297f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn    }
298f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn
2997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    /**
3007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * Validate the incoming VibrationEffect.
3017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * We can't throw exceptions here since we might be called from some system_server component,
3037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * which would bring the whole system down.
3047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     *
3057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     * @return whether the VibrationEffect is valid
3067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright     */
3077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static boolean verifyVibrationEffect(VibrationEffect effect) {
3087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect == null) {
3097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Effect must not be null.
3107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "effect must not be null");
3117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
312105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
313a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        try {
3147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            effect.validate();
3157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (Exception e) {
3167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.wtf(TAG, "Encountered issue when verifying VibrationEffect.", e);
3177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return false;
31818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
3197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return true;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private static long[] getLongIntArray(Resources r, int resid) {
3237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int[] ar = r.getIntArray(resid);
3247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (ar == null) {
3257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return null;
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long[] out = new long[ar.length];
3287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        for (int i = 0; i < ar.length; i++) {
3297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            out[i] = ar[i];
3307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return out;
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33482379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
3357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void vibrate(int uid, String opPkg, VibrationEffect effect, int usageHint,
3367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            IBinder token) {
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new SecurityException("Requires VIBRATE permission");
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (token == null) {
3427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "token must not be null");
3437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
345f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn        verifyIncomingUid(uid);
3467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (!verifyVibrationEffect(effect)) {
3477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
3487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // If our current vibration is longer than the new vibration and is the same amplitude,
3517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // then just let the current one finish.
3527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.OneShot
3537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration != null
3547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                && mCurrentVibration.mEffect instanceof VibrationEffect.OneShot) {
3557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot newOneShot = (VibrationEffect.OneShot) effect;
3567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot currentOneShot =
3577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    (VibrationEffect.OneShot) mCurrentVibration.mEffect;
3587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration.hasLongerTimeout(newOneShot.getTiming())
3597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    && newOneShot.getAmplitude() == currentOneShot.getAmplitude()) {
3607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
3617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.e(TAG, "Ignoring incoming vibration in favor of current vibration");
3627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
3677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        Vibration vib = new Vibration(token, effect, usageHint, uid, opPkg);
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // Only link against waveforms since they potentially don't have a finish if
3707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        // they're repeating. Let other effects just play out until they're done.
3717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (effect instanceof VibrationEffect.Waveform) {
37218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            try {
37318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                token.linkToDeath(vib, 0);
37418dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            } catch (RemoteException e) {
37518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                return;
37618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
3777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
3807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        long ident = Binder.clearCallingIdentity();
3817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
3827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (mLock) {
38318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                doCancelVibrateLocked();
3847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                startVibrationLocked(vib);
3853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                addToPreviousVibrationsLocked(vib);
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } finally {
3887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Binder.restoreCallingIdentity(ident);
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    private void addToPreviousVibrationsLocked(Vibration vib) {
3933a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        if (mPreviousVibrations.size() > mPreviousVibrationsLimit) {
3943a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            mPreviousVibrations.removeFirst();
3953a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
3967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mPreviousVibrations.addLast(new VibrationInfo(
3977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mStartTime, vib.mEffect, vib.mUsageHint, vib.mUid, vib.mOpPkg));
3983a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
3993a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
40082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown    @Override // Binder call
40118dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    public void cancelVibrate(IBinder token) {
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext.enforceCallingOrSelfPermission(
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                android.Manifest.permission.VIBRATE,
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                "cancelVibrate");
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mCurrentVibration != null && mCurrentVibration.mToken == token) {
4087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (DEBUG) {
4097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Slog.d(TAG, "Canceling vibration.");
4107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
4117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long ident = Binder.clearCallingIdentity();
4127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                try {
41318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                    doCancelVibrateLocked();
4147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } finally {
4157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Binder.restoreCallingIdentity(ident);
41618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
41718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
420f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
4217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private final Runnable mVibrationEndRunnable = new Runnable() {
42282379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown        @Override
42318dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        public void run() {
4247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            onVibrationFinished();
42518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
42618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    };
42718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
42818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void doCancelVibrateLocked() {
4297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mH.removeCallbacks(mVibrationEndRunnable);
43018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        if (mThread != null) {
4317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread.cancel();
43218dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread = null;
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        doVibratorOff();
435a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        reportFinishVibrationLocked();
43618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
43718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
4387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    // Callback for whenever the current vibration has finished played out
4397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    public void onVibrationFinished() {
4407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (DEBUG) {
4417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Vibration finished, cleaning up");
4427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
4437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
4447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Make sure the vibration is really done. This also reports that the vibration is
4457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // finished.
4467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doCancelVibrateLocked();
44718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
44818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
44918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
45018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    private void startVibrationLocked(final Vibration vib) {
4517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
4527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, low power mode");
454664703d6be542d6feb64bca9ca5b2a7dbb8abd84Ruchi Kandoi            }
4557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
45713b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
4587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE &&
4597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                !shouldVibrateForRingtone()) {
4607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
4617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.e(TAG, "Vibrate ignored, not vibrating for ringtones");
462d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds            }
4637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
4647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
465d28967f489996d1d74ff5c0bbb9c19d158efbf37Julia Reynolds
4667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        final int mode = getAppOpMode(vib);
4677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mode != AppOpsManager.MODE_ALLOWED) {
4687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ERRORED) {
4697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // We might be getting calls from within system_server, so we don't actually want
4707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // to throw a SecurityException here.
4717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Would be an error: vibrate from uid " + vib.mUid);
4721af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock            }
4737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return;
474a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
4757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        startVibrationInnerLocked(vib);
4767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
4777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
4787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void startVibrationInnerLocked(Vibration vib) {
4797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mCurrentVibration = vib;
4807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.OneShot) {
4817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.OneShot oneShot = (VibrationEffect.OneShot) vib.mEffect;
4827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            doVibratorOn(oneShot.getTiming(), oneShot.getAmplitude(), vib.mUid, vib.mUsageHint);
4837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mH.postDelayed(mVibrationEndRunnable, oneShot.getTiming());
4847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Waveform) {
48518dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // mThread better be null here. doCancelVibrate should always be
48618dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            // called before startNextVibrationLocked or startVibrationLocked.
4877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Waveform waveform = (VibrationEffect.Waveform) vib.mEffect;
4887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mThread = new VibrateThread(waveform, vib.mUid, vib.mUsageHint);
48918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott            mThread.start();
4907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else if (vib.mEffect instanceof VibrationEffect.Prebaked) {
4917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timeout = doVibratorPrebakedEffectLocked(vib);
4927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (timeout > 0) {
4937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mH.postDelayed(mVibrationEndRunnable, timeout);
4947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
4957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
4967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Unknown vibration type, ignoring");
49718dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott        }
49818dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott    }
49918dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott
5002d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    private boolean shouldVibrateForRingtone() {
5012d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
502dcbdc0df43310d9ecb2324be8c5bd54d7727230eBrad Ebinger        int ringerMode = audioManager.getRingerModeInternal();
5032d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        // "Also vibrate for calls" Setting in Sound
5042d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        if (Settings.System.getInt(
5052d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger                mContext.getContentResolver(), Settings.System.VIBRATE_WHEN_RINGING, 0) != 0) {
5062d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode != AudioManager.RINGER_MODE_SILENT;
5072d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        } else {
5082d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger            return ringerMode == AudioManager.RINGER_MODE_VIBRATE;
5092d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger        }
5102d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger    }
5112d1c3b3a6cffd0a573aab5ac19f89a70d334540dBrad Ebinger
5127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private int getAppOpMode(Vibration vib) {
5137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        int mode;
5147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
5167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    vib.mUsageHint, vib.mUid, vib.mOpPkg);
5177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mode == AppOpsManager.MODE_ALLOWED) {
5187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
5197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
5207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
5227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Slog.e(TAG, "Failed to get appop mode for vibration!", e);
5237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mode = AppOpsManager.MODE_IGNORED;
5247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return mode;
5267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
528a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    private void reportFinishVibrationLocked() {
529a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        if (mCurrentVibration != null) {
530a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            try {
531e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
532e98f5dbe6b6f9f2cb6a73ee750faacda2596b34fDianne Hackborn                        AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
5338fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer                        mCurrentVibration.mOpPkg);
5347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
535a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            mCurrentVibration = null;
536a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn        }
537a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn    }
538a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn
539b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    private void unlinkVibration(Vibration vib) {
5407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vib.mEffect instanceof VibrationEffect.Waveform) {
541b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson            vib.mToken.unlinkToDeath(vib, 0);
542b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson        }
543b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson    }
544b23949b7454ddb65f81e1bd4426b2cc714ab9c3eMathias Jeppsson
5457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void updateVibrators() {
5467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
5477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean devicesUpdated = updateInputDeviceVibratorsLocked();
5487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            boolean lowPowerModeUpdated = updateLowPowerModeLocked();
5497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (devicesUpdated || lowPowerModeUpdated) {
5517121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // If the state changes out from under us then just reset.
5527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doCancelVibrateLocked();
5537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5568206525b242ceb012d882849c4e355223ba81b9dJeff Brown
5577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateInputDeviceVibratorsLocked() {
5587121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean changed = false;
5597121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean vibrateInputDevices = false;
5607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
5617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrateInputDevices = Settings.System.getIntForUser(
5627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mContext.getContentResolver(),
5637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    Settings.System.VIBRATE_INPUT_DEVICES, UserHandle.USER_CURRENT) > 0;
5647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (SettingNotFoundException snfe) {
5657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (vibrateInputDevices != mVibrateInputDevicesSetting) {
5677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            changed = true;
5687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mVibrateInputDevicesSetting = vibrateInputDevices;
5697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
57013b03aff2993653ef8bde8bedb1bbcc0fe09ba94Ruchi Kandoi
5717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
5727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (!mInputDeviceListenerRegistered) {
5737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = true;
5747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.registerInputDeviceListener(this, mH);
5757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } else {
5777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (mInputDeviceListenerRegistered) {
5787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mInputDeviceListenerRegistered = false;
5797121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mIm.unregisterInputDeviceListener(this);
5807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
5817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5828206525b242ceb012d882849c4e355223ba81b9dJeff Brown
5837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        mInputDeviceVibrators.clear();
5847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mVibrateInputDevicesSetting) {
5857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int[] ids = mIm.getInputDeviceIds();
5867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            for (int i = 0; i < ids.length; i++) {
5877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                InputDevice device = mIm.getInputDevice(ids[i]);
5887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Vibrator vibrator = device.getVibrator();
5897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (vibrator.hasVibrator()) {
5907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    mInputDeviceVibrators.add(vibrator);
5917f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
5927f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
5937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
5947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
5957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return changed;
5967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
5977f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
5987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private boolean updateLowPowerModeLocked() {
5997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        boolean lowPowerMode = mPowerManagerInternal
6007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                .getLowPowerState(ServiceType.VIBRATION).batterySaverEnabled;
6017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (lowPowerMode != mLowPowerMode) {
6027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mLowPowerMode = lowPowerMode;
6037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return true;
6047f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return false;
6067f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6077f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6087f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6097f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceAdded(int deviceId) {
6107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6117f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6127f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6137f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6147f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceChanged(int deviceId) {
6157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6167f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6177f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6187f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    @Override
6197f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    public void onInputDeviceRemoved(int deviceId) {
6207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        updateVibrators();
6217f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6227f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6237f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private boolean doVibratorExists() {
6241064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // For now, we choose to ignore the presence of input devices that have vibrators
6251064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // when reporting whether the device has a vibrator.  Applications often use this
6261064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // information to decide whether to enable certain features so they expect the
6271064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // result of hasVibrator() to be constant.  For now, just report whether
6281064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        // the device has a built-in vibrator.
6291064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //synchronized (mInputDeviceVibrators) {
6301064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //    return !mInputDeviceVibrators.isEmpty() || vibratorExists();
6311064a50dc86c2aea54bc6830c6cae464feb27febJeff Brown        //}
632c2293025a25e04b26bf53713d71f85fd9ca5e8e9Dianne Hackborn        return vibratorExists();
6337f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6347f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorOn(long millis, int amplitude, int uid, int usageHint) {
6367f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
6377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (amplitude == VibrationEffect.DEFAULT_AMPLITUDE) {
6387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                amplitude = mDefaultVibrationAmplitude;
63982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (DEBUG) {
6417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.d(TAG, "Turning vibrator on for " + millis + " ms" +
6427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        " with amplitude " + amplitude + ".");
643a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn            }
6447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOnLocked(uid, millis);
6457f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
6467f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
6477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final AudioAttributes attributes =
6487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        new AudioAttributes.Builder().setUsage(usageHint).build();
6497f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
6507b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock                    mInputDeviceVibrators.get(i).vibrate(millis, attributes);
6517f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6527f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
6537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // Note: ordering is important here! Many haptic drivers will reset their amplitude
6547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                // when enabled, so we always have to enable frst, then set the amplitude.
6557f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOn(millis);
6567121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                doVibratorSetAmplitude(amplitude);
6577f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6587f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6597f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6607f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6617121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void doVibratorSetAmplitude(int amplitude) {
6627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mSupportsAmplitudeControl) {
6637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibratorSetAmplitude(amplitude);
6647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
6657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
6667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
6677f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    private void doVibratorOff() {
6687f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        synchronized (mInputDeviceVibrators) {
66982379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            if (DEBUG) {
67082379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown                Slog.d(TAG, "Turning vibrator off.");
67182379ba8ddc04116a40aa177df4ef6c2aa428a69Jeff Brown            }
6727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            noteVibratorOffLocked();
6737f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            final int vibratorCount = mInputDeviceVibrators.size();
6747f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            if (vibratorCount != 0) {
6757f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                for (int i = 0; i < vibratorCount; i++) {
6767f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                    mInputDeviceVibrators.get(i).cancel();
6777f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                }
6787f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            } else {
6797f6c231a76f0bedaf9655a24707737d343244312Jeff Brown                vibratorOff();
6807f6c231a76f0bedaf9655a24707737d343244312Jeff Brown            }
6817f6c231a76f0bedaf9655a24707737d343244312Jeff Brown        }
6827f6c231a76f0bedaf9655a24707737d343244312Jeff Brown    }
6837f6c231a76f0bedaf9655a24707737d343244312Jeff Brown
6847121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private long doVibratorPrebakedEffectLocked(Vibration vib) {
6857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mInputDeviceVibrators) {
6867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect.Prebaked prebaked = (VibrationEffect.Prebaked) vib.mEffect;
6877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            // Input devices don't support prebaked effect, so skip trying it with them.
6887121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int vibratorCount = mInputDeviceVibrators.size();
6897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (vibratorCount == 0) {
6907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long timeout = vibratorPerformEffect(prebaked.getId(), EffectStrength.MEDIUM);
6917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (timeout > 0) {
6927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    noteVibratorOnLocked(vib.mUid, timeout);
6937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return timeout;
6947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
6957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
6967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            final int id = prebaked.getId();
6977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            if (id < 0 || id >= mFallbackEffects.length) {
6987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                Slog.w(TAG, "Failed to play prebaked effect, no fallback");
6997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return 0;
7007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect = mFallbackEffects[id];
7027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            Vibration fallbackVib =
7037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    new Vibration(vib.mToken, effect, vib.mUsageHint, vib.mUid, vib.mOpPkg);
7047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            startVibrationInnerLocked(fallbackVib);
7057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        return 0;
7077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7097121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOnLocked(int uid, long millis) {
7107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        try {
7117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mBatteryStatsService.noteVibratorOn(uid, millis);
7127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = uid;
7137121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        } catch (RemoteException e) {
7147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7167121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    private void noteVibratorOffLocked() {
7187121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        if (mCurVibUid >= 0) {
7197121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mBatteryStatsService.noteVibratorOff(mCurVibUid);
7217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } catch (RemoteException e) { }
7227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mCurVibUid = -1;
7237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright    }
7257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private class VibrateThread extends Thread {
7277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final VibrationEffect.Waveform mWaveform;
7287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUid;
7297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private final int mUsageHint;
730f42f15cf450772d8eeb9c0c81a8403d33ffe1c9bEric Olsen
7317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private boolean mForceStop;
7327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        VibrateThread(VibrationEffect.Waveform waveform, int uid, int usageHint) {
7347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWaveform = waveform;
7357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUid = uid;
7367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mUsageHint = usageHint;
7377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mTmpWorkSource.set(uid);
7387e9f4eb2608148436cef36c9969bf8a599b39e72Dianne Hackborn            mWakeLock.setWorkSource(mTmpWorkSource);
7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long delayLocked(long duration) {
7427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long durationRemaining = duration;
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (duration > 0) {
7447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long bedtime = duration + SystemClock.uptimeMillis();
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                do {
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
7477121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        this.wait(durationRemaining);
7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    catch (InterruptedException e) { }
7507121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (mForceStop) {
7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7537121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    durationRemaining = bedtime - SystemClock.uptimeMillis();
7547121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                } while (durationRemaining > 0);
7557121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return duration - durationRemaining;
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7577121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return 0;
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void run() {
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_DISPLAY);
7627121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            mWakeLock.acquire();
7637121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            try {
7647121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                boolean finished = playWaveform();
7657121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (finished) {
7667121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    onVibrationFinished();
7677121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                }
7687121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            } finally {
7697121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mWakeLock.release();
7707121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
7717121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
7727121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
7737121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
7747121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Play the waveform.
7757121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         *
7767121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * @return true if it finished naturally, false otherwise (e.g. it was canceled).
7777121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
7787121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public boolean playWaveform() {
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (this) {
7807121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final long[] timings = mWaveform.getTimings();
7817121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int[] amplitudes = mWaveform.getAmplitudes();
7827121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int len = timings.length;
7837121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                final int repeat = mWaveform.getRepeatIndex();
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7857121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                int index = 0;
7867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long onDuration = 0;
7877121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                while (!mForceStop) {
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (index < len) {
7897121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final int amplitude = amplitudes[index];
7907121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        final long duration = timings[index++];
7917121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (duration <= 0) {
7927121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            continue;
7937121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
7947121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
7957121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            if (onDuration <= 0) {
7967121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // Telling the vibrator to start multiple times usually causes
7977121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // effects to feel "choppy" because the motor resets at every on
7987121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // command.  Instead we figure out how long our next "on" period is
7997121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // going to be, tell the motor to stay on for the full duration,
8007121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // and then wake up to change the amplitude at the appropriate
8017121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                // intervals.
8027121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                onDuration =
8037121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                        getTotalOnDuration(timings, amplitudes, index - 1, repeat);
8047121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorOn(onDuration, amplitude, mUid, mUsageHint);
8057121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            } else {
8067121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                                doVibratorSetAmplitude(amplitude);
8077121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            }
8087121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        }
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8107121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        long waitTime = delayLocked(duration);
8117121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        if (amplitude != 0) {
8127121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                            onDuration -= waitTime;
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
8147121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else if (repeat < 0) {
8157121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } else {
8177121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        index = repeat;
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8207121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                return !mForceStop;
8217121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            }
8227121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8237121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8247121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        public void cancel() {
8257121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            synchronized (this) {
8267121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.mForceStop = true;
8277121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                mThread.notify();
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        }
8307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
8317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        /**
8327121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * Get the duration the vibrator will be on starting at startIndex until the next time it's
8337121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         * off.
8347121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright         */
8357121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        private long getTotalOnDuration(
8367121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                long[] timings, int[] amplitudes, int startIndex, int repeatIndex) {
8377121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            int i = startIndex;
8387121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            long timing = 0;
8397121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            while(amplitudes[i] != 0) {
8407121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                timing += timings[i++];
8417121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i >= timings.length) {
8427121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    if (repeatIndex >= 0) {
8437121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        i = repeatIndex;
8447121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    } else {
8457121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                        break;
8467121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8487121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                if (i == startIndex) {
8497121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    return 1000;
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8527121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            return timing;
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
854969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown    }
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
857969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown        @Override
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
8607121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                synchronized (mLock) {
861969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // When the system is entering a non-interactive state, we want
862969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // to cancel vibrations in case a misbehaving app has abandoned
863969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // them.  However it may happen that the system is currently playing
864969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // haptic feedback as part of the transition.  So we don't cancel
865969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    // system vibrations.
866969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                    if (mCurrentVibration != null
867969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                            && !mCurrentVibration.isSystemHapticFeedback()) {
868969579bb9d208c91e081ff96d2fd788269d254bdJeff Brown                        doCancelVibrateLocked();
8698a61f496919504a86244d2f833acfec9bc20a745Vairavan Srinivasan                    }
87018dd5f0d25f1004e123dc265dc498a8bf8897af9Patrick Scott                }
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
8743a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
8753a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    @Override
8763a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
8773a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
8783a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                != PackageManager.PERMISSION_GRANTED) {
8793a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski
8803a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            pw.println("Permission Denial: can't dump vibrator service from from pid="
8813a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    + Binder.getCallingPid()
8823a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                    + ", uid=" + Binder.getCallingUid());
8833a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            return;
8843a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
8853a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        pw.println("Previous vibrations:");
8867121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright        synchronized (mLock) {
8873a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            for (VibrationInfo info : mPreviousVibrations) {
8883a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.print("  ");
8893a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski                pw.println(info.toString());
8903a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski            }
8913a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski        }
8923a8eb0f670cc331b9e16fdedfab8b89ed9254317Filip Gruszczynski    }
893a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
894a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    @Override
895a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
896a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String[] args, ShellCallback callback, ResultReceiver resultReceiver)
897a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            throws RemoteException {
898a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        new VibratorShellCommand(this).exec(this, in, out, err, args, callback, resultReceiver);
899a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
900a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
901a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    private final class VibratorShellCommand extends ShellCommand {
902a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
903a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private static final long MAX_VIBRATION_MS = 200;
904a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
905a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private final IBinder mToken;
906a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
907a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private VibratorShellCommand(IBinder token) {
908a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            mToken = token;
909a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
910a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
911a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
912a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public int onCommand(String cmd) {
913a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if ("vibrate".equals(cmd)) {
914a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                return runVibrate();
915a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
916a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return handleDefaultCommands(cmd);
917a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
918a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
919a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        private int runVibrate() {
920a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            final long duration = Long.parseLong(getNextArgRequired());
921a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (duration > MAX_VIBRATION_MS) {
922a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                throw new IllegalArgumentException("maximum duration is " + MAX_VIBRATION_MS);
923a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
924a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            String description = getNextArg();
925a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            if (description == null) {
926a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                description = "Shell command";
927a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
9287121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright
9297121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            VibrationEffect effect =
9307121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright                    VibrationEffect.createOneShot(duration, VibrationEffect.DEFAULT_AMPLITUDE);
9317121697a5e2d4458f6f63e9eb3b5deec62ee6202Michael Wright            vibrate(Binder.getCallingUid(), description, effect, AudioAttributes.USAGE_UNKNOWN,
932a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                    mToken);
933a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            return 0;
934a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
935a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
936a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        @Override
937a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        public void onHelp() {
938a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            try (PrintWriter pw = getOutPrintWriter();) {
939a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("Vibrator commands:");
940a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  help");
941a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Prints this help text.");
942a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
943a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("  vibrate duration [description]");
944a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("    Vibrates for duration milliseconds.");
945a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme                pw.println("");
946a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme            }
947a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme        }
948a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme    }
949a5281001dcd420e0d14ccb3d4872da0f200bc9b2Felipe Leme
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
951