Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6a4f9c0 authored by Michael Wright's avatar Michael Wright Committed by Android (Google) Code Review
Browse files

Merge "Add new ExternalVibratorService."

parents b6c8094b c390fbe9
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -271,6 +271,7 @@ java_defaults {
        "core/java/android/os/IThermalService.aidl",
        "core/java/android/os/IUpdateLock.aidl",
        "core/java/android/os/IUserManager.aidl",
        ":libvibrator_aidl",
        "core/java/android/os/IVibratorService.aidl",
        "core/java/android/os/storage/IStorageManager.aidl",
        "core/java/android/os/storage/IStorageEventListener.aidl",
@@ -794,6 +795,14 @@ filegroup {
    ],
}

filegroup {
    name: "libvibrator_aidl",
    srcs: [
        "core/java/android/os/IExternalVibrationController.aidl",
        "core/java/android/os/IExternalVibratorService.aidl",
    ],
}

java_library {
    name: "framework",
    defaults: ["framework-defaults"],
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

parcelable ExternalVibration cpp_header "vibrator/ExternalVibration.h";
+171 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

import android.annotation.NonNull;
import android.media.AudioAttributes;
import android.util.Slog;

import com.android.internal.util.Preconditions;

/**
 * An ExternalVibration represents an on-going vibration being controlled by something other than
 * the core vibrator service.
 *
 * @hide
 */
public class ExternalVibration implements Parcelable {
    private static final String TAG = "ExternalVibration";
    private int mUid;
    @NonNull
    private String mPkg;
    @NonNull
    private AudioAttributes mAttrs;
    @NonNull
    private IExternalVibrationController mController;
    // A token used to maintain equality comparisons when passing objects across process
    // boundaries.
    @NonNull
    private IBinder mToken;

    public ExternalVibration(int uid, @NonNull String pkg, @NonNull AudioAttributes attrs,
            @NonNull IExternalVibrationController controller) {
        mUid = uid;
        mPkg = Preconditions.checkNotNull(pkg);
        mAttrs = Preconditions.checkNotNull(attrs);
        mController = Preconditions.checkNotNull(controller);
        mToken = new Binder();
    }

    private ExternalVibration(Parcel in) {
        mUid = in.readInt();
        mPkg = in.readString();
        mAttrs = readAudioAttributes(in);
        mController = IExternalVibrationController.Stub.asInterface(in.readStrongBinder());
        mToken = in.readStrongBinder();
    }

    private AudioAttributes readAudioAttributes(Parcel in) {
        int usage = in.readInt();
        int contentType = in.readInt();
        int capturePreset = in.readInt();
        int flags = in.readInt();
        AudioAttributes.Builder builder = new AudioAttributes.Builder();
        return builder.setUsage(usage)
                .setContentType(contentType)
                .setCapturePreset(capturePreset)
                .setFlags(flags)
                .build();
    }

    public int getUid() {
        return mUid;
    }

    public String getPackage() {
        return mPkg;
    }

    public AudioAttributes getAudioAttributes() {
        return mAttrs;
    }

    /**
     * Mutes the external vibration if it's playing and unmuted.
     *
     * @return whether the muting operation was successful
     */
    public boolean mute() {
        try {
            mController.mute();
        } catch (RemoteException e) {
            Slog.wtf(TAG, "Failed to mute vibration stream: " + this, e);
            return false;
        }
        return true;
    }

    /**
     * Unmutes the external vibration if it's playing and muted.
     *
     * @return whether the unmuting operation was successful
     */
    public boolean unmute() {
        try {
            mController.unmute();
        } catch (RemoteException e) {
            Slog.wtf(TAG, "Failed to unmute vibration stream: " + this, e);
            return false;
        }
        return true;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null || !(o instanceof ExternalVibration)) {
            return false;
        }
        ExternalVibration other = (ExternalVibration) o;
        return mToken.equals(other.mToken);
    }

    @Override
    public String toString() {
        return "ExternalVibration{"
            + "uid=" + mUid + ", "
            + "pkg=" + mPkg + ", "
            + "attrs=" + mAttrs + ", "
            + "controller=" + mController
            + "token=" + mController
            + "}";
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        out.writeInt(mUid);
        out.writeString(mPkg);
        writeAudioAttributes(mAttrs, out, flags);
        out.writeParcelable(mAttrs, flags);
        out.writeStrongBinder(mController.asBinder());
        out.writeStrongBinder(mToken);
    }

    private static void writeAudioAttributes(AudioAttributes attrs, Parcel out, int flags) {
        out.writeInt(attrs.getUsage());
        out.writeInt(attrs.getContentType());
        out.writeInt(attrs.getCapturePreset());
        out.writeInt(attrs.getAllFlags());
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Parcelable.Creator<ExternalVibration> CREATOR =
            new Parcelable.Creator<ExternalVibration>() {
                @Override
                public ExternalVibration createFromParcel(Parcel in) {
                    return new ExternalVibration(in);
                }

                @Override
                public ExternalVibration[] newArray(int size) {
                    return new ExternalVibration[size];
                }
            };
}
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

/**
 * {@hide}
 */

interface IExternalVibrationController {
    /**
     * A method to ask a currently playing vibration to mute (i.e. not vibrate).
     *
     * This method is only valid from the time that
     * {@link IExternalVibratorService#onExternalVibrationStart} returns until
     * {@link IExternalVibratorService#onExternalVibrationStop} returns.
     *
     * @return whether the mute operation was successful
     */
    boolean mute();

    /**
     * A method to ask a currently playing vibration to unmute (i.e. start vibrating).
     *
     * This method is only valid from the time that
     * {@link IExternalVibratorService#onExternalVibrationStart} returns until
     * {@link IExternalVibratorService#onExternalVibrationStop} returns.
     *
     * @return whether the unmute operation was successful
     */
    boolean unmute();
}
+63 −0
Original line number Diff line number Diff line
/**
 * Copyright (c) 2018, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.os;

import android.os.ExternalVibration;

/**
 * The communication channel by which an external system that wants to control the system
 * vibrator can notify the vibrator subsystem.
 *
 * Some vibrators can be driven via multiple paths (e.g. as an audio channel) in addition to
 * the usual interface, but we typically only want one vibration at a time playing because they
 * don't mix well. In order to synchronize the two places where vibration might be controlled,
 * we provide this interface so the vibrator subsystem has a chance to:
 *
 * 1) Decide whether the current vibration should play based on the current system policy.
 * 2) Stop any currently on-going vibrations.
 * {@hide}
 */
interface IExternalVibratorService {
    const int SCALE_MUTE = -100;
    const int SCALE_VERY_LOW = -2;
    const int SCALE_LOW = -1;
    const int SCALE_NONE = 0;
    const int SCALE_HIGH = 1;
    const int SCALE_VERY_HIGH = 2;

    /**
     * A method called by the external system to start a vibration.
     *
     * If this returns {@code SCALE_MUTE}, then the vibration should <em>not</em> play. If this
     * returns any other scale level, then any currently playing vibration controlled by the
     * requesting system must be muted and this vibration can begin playback.
     *
     * Note that the IExternalVibratorService implementation will not call mute on any currently
     * playing external vibrations in order to avoid re-entrancy with the system on the other side.
     *
     * @param vibration An ExternalVibration
     *
     * @return {@code SCALE_MUTE} if the external vibration should not play, and any other scale
     *         level if it should.
     */
    int onExternalVibrationStart(in ExternalVibration vib);

    /**
     * A method called by the external system when a vibration no longer wants to play.
     */
    void onExternalVibrationStop(in ExternalVibration vib);
}
Loading