1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.os;
18 
19 import android.annotation.NonNull;
20 import android.media.AudioAttributes;
21 import android.util.Slog;
22 
23 import com.android.internal.util.Preconditions;
24 
25 /**
26  * An ExternalVibration represents an on-going vibration being controlled by something other than
27  * the core vibrator service.
28  *
29  * @hide
30  */
31 public class ExternalVibration implements Parcelable {
32     private static final String TAG = "ExternalVibration";
33     private int mUid;
34     @NonNull
35     private String mPkg;
36     @NonNull
37     private AudioAttributes mAttrs;
38     @NonNull
39     private IExternalVibrationController mController;
40     // A token used to maintain equality comparisons when passing objects across process
41     // boundaries.
42     @NonNull
43     private IBinder mToken;
44 
ExternalVibration(int uid, @NonNull String pkg, @NonNull AudioAttributes attrs, @NonNull IExternalVibrationController controller)45     public ExternalVibration(int uid, @NonNull String pkg, @NonNull AudioAttributes attrs,
46             @NonNull IExternalVibrationController controller) {
47         mUid = uid;
48         mPkg = Preconditions.checkNotNull(pkg);
49         mAttrs = Preconditions.checkNotNull(attrs);
50         mController = Preconditions.checkNotNull(controller);
51         mToken = new Binder();
52     }
53 
ExternalVibration(Parcel in)54     private ExternalVibration(Parcel in) {
55         mUid = in.readInt();
56         mPkg = in.readString();
57         mAttrs = readAudioAttributes(in);
58         mController = IExternalVibrationController.Stub.asInterface(in.readStrongBinder());
59         mToken = in.readStrongBinder();
60     }
61 
readAudioAttributes(Parcel in)62     private AudioAttributes readAudioAttributes(Parcel in) {
63         int usage = in.readInt();
64         int contentType = in.readInt();
65         int capturePreset = in.readInt();
66         int flags = in.readInt();
67         AudioAttributes.Builder builder = new AudioAttributes.Builder();
68         return builder.setUsage(usage)
69                 .setContentType(contentType)
70                 .setCapturePreset(capturePreset)
71                 .setFlags(flags)
72                 .build();
73     }
74 
getUid()75     public int getUid() {
76         return mUid;
77     }
78 
getPackage()79     public String getPackage() {
80         return mPkg;
81     }
82 
getAudioAttributes()83     public AudioAttributes getAudioAttributes() {
84         return mAttrs;
85     }
86 
getVibrationAttributes()87     public VibrationAttributes getVibrationAttributes() {
88         return new VibrationAttributes.Builder(mAttrs, null).build();
89     }
90 
91     /**
92      * Mutes the external vibration if it's playing and unmuted.
93      *
94      * @return whether the muting operation was successful
95      */
mute()96     public boolean mute() {
97         try {
98             mController.mute();
99         } catch (RemoteException e) {
100             Slog.wtf(TAG, "Failed to mute vibration stream: " + this, e);
101             return false;
102         }
103         return true;
104     }
105 
106     /**
107      * Unmutes the external vibration if it's playing and muted.
108      *
109      * @return whether the unmuting operation was successful
110      */
unmute()111     public boolean unmute() {
112         try {
113             mController.unmute();
114         } catch (RemoteException e) {
115             Slog.wtf(TAG, "Failed to unmute vibration stream: " + this, e);
116             return false;
117         }
118         return true;
119     }
120 
121     /**
122      * Links a recipient to death against this external vibration token
123      */
linkToDeath(IBinder.DeathRecipient recipient)124     public void linkToDeath(IBinder.DeathRecipient recipient) {
125         try {
126             mToken.linkToDeath(recipient, 0);
127         } catch (RemoteException e) {
128             return;
129         }
130     }
131 
132     /**
133      * Unlinks a recipient to death against this external vibration token
134      */
unlinkToDeath(IBinder.DeathRecipient recipient)135     public void unlinkToDeath(IBinder.DeathRecipient recipient) {
136         mToken.unlinkToDeath(recipient, 0);
137     }
138 
139     @Override
equals(Object o)140     public boolean equals(Object o) {
141         if (o == null || !(o instanceof ExternalVibration)) {
142             return false;
143         }
144         ExternalVibration other = (ExternalVibration) o;
145         return mToken.equals(other.mToken);
146     }
147 
148     @Override
toString()149     public String toString() {
150         return "ExternalVibration{"
151             + "uid=" + mUid + ", "
152             + "pkg=" + mPkg + ", "
153             + "attrs=" + mAttrs + ", "
154             + "controller=" + mController
155             + "token=" + mController
156             + "}";
157     }
158 
159     @Override
writeToParcel(Parcel out, int flags)160     public void writeToParcel(Parcel out, int flags) {
161         out.writeInt(mUid);
162         out.writeString(mPkg);
163         writeAudioAttributes(mAttrs, out, flags);
164         out.writeStrongBinder(mController.asBinder());
165         out.writeStrongBinder(mToken);
166     }
167 
writeAudioAttributes(AudioAttributes attrs, Parcel out, int flags)168     private static void writeAudioAttributes(AudioAttributes attrs, Parcel out, int flags) {
169         out.writeInt(attrs.getUsage());
170         out.writeInt(attrs.getContentType());
171         out.writeInt(attrs.getCapturePreset());
172         out.writeInt(attrs.getAllFlags());
173     }
174 
175     @Override
describeContents()176     public int describeContents() {
177         return 0;
178     }
179 
180     public static final @android.annotation.NonNull Parcelable.Creator<ExternalVibration> CREATOR =
181             new Parcelable.Creator<ExternalVibration>() {
182                 @Override
183                 public ExternalVibration createFromParcel(Parcel in) {
184                     return new ExternalVibration(in);
185                 }
186 
187                 @Override
188                 public ExternalVibration[] newArray(int size) {
189                     return new ExternalVibration[size];
190                 }
191             };
192 }
193