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

Commit 4f07fa4e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add support for vibrator HAL 1.2 effects."

parents 9eb34faa f268bf57
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -670,8 +670,9 @@ java_library {
        "android.hardware.tv.input-V1.0-java-constants",
        "android.hardware.usb-V1.0-java-constants",
        "android.hardware.usb-V1.1-java-constants",
        "android.hardware.vibrator-V1.0-java-constants",
        "android.hardware.vibrator-V1.1-java-constants",
        "android.hardware.vibrator-V1.0-java",
        "android.hardware.vibrator-V1.1-java",
        "android.hardware.vibrator-V1.2-java",
        "android.hardware.wifi-V1.0-java-constants",
        "android.hardware.radio-V1.0-java",
        "android.hardware.usb.gadget-V1.0-java",
+96 −7
Original line number Diff line number Diff line
@@ -16,10 +16,15 @@

package android.os;

import android.hardware.vibrator.V1_0.Constants.EffectStrength;
import android.hardware.vibrator.V1_1.Constants.Effect_1_1;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.vibrator.V1_0.EffectStrength;
import android.hardware.vibrator.V1_2.Effect;
import android.net.Uri;
import android.util.MathUtils;

import com.android.internal.annotations.VisibleForTesting;

import java.util.Arrays;

/**
@@ -49,7 +54,7 @@ public abstract class VibrationEffect implements Parcelable {
     * @see #get(int)
     * @hide
     */
    public static final int EFFECT_CLICK = Effect_1_1.CLICK;
    public static final int EFFECT_CLICK = Effect.CLICK;

    /**
     * A double click effect.
@@ -57,14 +62,62 @@ public abstract class VibrationEffect implements Parcelable {
     * @see #get(int)
     * @hide
     */
    public static final int EFFECT_DOUBLE_CLICK = Effect_1_1.DOUBLE_CLICK;
    public static final int EFFECT_DOUBLE_CLICK = Effect.DOUBLE_CLICK;

    /**
     * A tick effect.
     * @see #get(int)
     * @hide
     */
    public static final int EFFECT_TICK = Effect_1_1.TICK;
    public static final int EFFECT_TICK = Effect.TICK;

    /**
     * A thud effect.
     * @see #get(int)
     * @hide
     */
    public static final int EFFECT_THUD = Effect.THUD;

    /**
     * A pop effect.
     * @see #get(int)
     * @hide
     */
    public static final int EFFECT_POP = Effect.POP;

    /**
     * A heavy click effect.
     * @see #get(int)
     * @hide
     */
    public static final int EFFECT_HEAVY_CLICK = Effect.HEAVY_CLICK;


    /**
     * Ringtone patterns. They may correspond with the device's ringtone audio, or may just be a
     * pattern that can be played as a ringtone with any audio, depending on the device.
     *
     * @see #get(Uri, Context)
     * @hide
     */
    @VisibleForTesting
    public static final int[] RINGTONES = {
        Effect.RINGTONE_1,
        Effect.RINGTONE_2,
        Effect.RINGTONE_3,
        Effect.RINGTONE_4,
        Effect.RINGTONE_5,
        Effect.RINGTONE_6,
        Effect.RINGTONE_7,
        Effect.RINGTONE_8,
        Effect.RINGTONE_9,
        Effect.RINGTONE_10,
        Effect.RINGTONE_11,
        Effect.RINGTONE_12,
        Effect.RINGTONE_13,
        Effect.RINGTONE_14,
        Effect.RINGTONE_15
    };

    /** @hide to prevent subclassing from outside of the framework */
    public VibrationEffect() { }
@@ -198,6 +251,37 @@ public abstract class VibrationEffect implements Parcelable {
        return effect;
    }

    /**
     * Get a predefined vibration effect associated with a given URI.
     *
     * Predefined effects are a set of common vibration effects that should be identical, regardless
     * of the app they come from, in order to provide a cohesive experience for users across
     * the entire device. They also may be custom tailored to the device hardware in order to
     * provide a better experience than you could otherwise build using the generic building
     * blocks.
     *
     * @param uri The URI associated with the haptic effect.
     * @param context The context used to get the URI to haptic effect association.
     *
     * @return The desired effect, or {@code null} if there's no associated effect.
     *
     * @hide
     */
    @Nullable
    public static VibrationEffect get(Uri uri, Context context) {
        String[] uris = context.getResources().getStringArray(
                com.android.internal.R.array.config_ringtoneEffectUris);
        for (int i = 0; i < uris.length && i < RINGTONES.length; i++) {
            if (uris[i] == null) {
                continue;
            }
            if (Uri.parse(uris[i]).equals(uri)) {
                return get(RINGTONES[i]);
            }
        }
        return null;
    }

    @Override
    public int describeContents() {
        return 0;
@@ -548,11 +632,16 @@ public abstract class VibrationEffect implements Parcelable {
                case EFFECT_CLICK:
                case EFFECT_DOUBLE_CLICK:
                case EFFECT_TICK:
                case EFFECT_THUD:
                case EFFECT_POP:
                case EFFECT_HEAVY_CLICK:
                    break;
                default:
                    if (mEffectId < RINGTONES[0] || mEffectId > RINGTONES[RINGTONES.length - 1]) {
                        throw new IllegalArgumentException(
                                "Unknown prebaked effect type (value=" + mEffectId + ")");
                    }
            }
            if (!isValidEffectStrength(mEffectStrength)) {
                throw new IllegalArgumentException(
                        "Unknown prebaked effect strength (value=" + mEffectStrength + ")");
+8 −0
Original line number Diff line number Diff line
@@ -1075,6 +1075,14 @@
        <item>10</item>
    </integer-array>

    <!-- The URI to associate with each ringtone effect constant, intended to be used with the
         android.os.VibrationEffect#get(Uri, Context) API.
         The position of the string in the string-array determines which ringtone effect is chosen.
         For example, if the URI passed into get match the third string in the string-array, then
         RINGTONE_3 will be the returned effect -->
    <string-array translatable="false" name="config_ringtoneEffectUris">
    </string-array>

    <bool name="config_use_strict_phone_number_comparation">false</bool>

    <!-- Display low battery warning when battery level dips to this value.
+2 −0
Original line number Diff line number Diff line
@@ -3252,4 +3252,6 @@
  <java-symbol type="string" name="screenshot_edit" />

  <java-symbol type="bool" name="config_keepRestrictedProfilesInBackground" />

  <java-symbol type="array" name="config_ringtoneEffectUris" />
</resources>
+90 −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 static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.res.Resources;
import android.net.Uri;

import com.android.internal.R;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class VibrationEffectTest {
    private static final String RINGTONE_URI_1 = "content://test/system/ringtone_1";
    private static final String RINGTONE_URI_2 = "content://test/system/ringtone_2";
    private static final String RINGTONE_URI_3 = "content://test/system/ringtone_3";
    private static final String UNKNOWN_URI = "content://test/system/other_audio";

    @Test
    public void getRingtones_noPrebakedRingtones() {
        Resources r = mockRingtoneResources(new String[0]);
        Context context = mockContext(r);
        VibrationEffect effect = VibrationEffect.get(Uri.parse(RINGTONE_URI_1), context);
        assertNull(effect);
    }

    @Test
    public void getRingtones_noPrebakedRingtoneForUri() {
        Resources r = mockRingtoneResources();
        Context context = mockContext(r);
        VibrationEffect effect = VibrationEffect.get(Uri.parse(UNKNOWN_URI), context);
        assertNull(effect);
    }

    @Test
    public void getRingtones_getPrebakedRingtone() {
        Resources r = mockRingtoneResources();
        Context context = mockContext(r);
        VibrationEffect effect = VibrationEffect.get(Uri.parse(RINGTONE_URI_2), context);
        VibrationEffect expectedEffect = VibrationEffect.get(VibrationEffect.RINGTONES[1]);
        assertNotNull(expectedEffect);
        assertEquals(expectedEffect, effect);
    }


    private Resources mockRingtoneResources() {
        return mockRingtoneResources(new String[] {
                RINGTONE_URI_1,
                RINGTONE_URI_2,
                RINGTONE_URI_3
        });
    }

    private Resources mockRingtoneResources(String[] ringtoneUris) {
        Resources mockResources = mock(Resources.class);
        when(mockResources.getStringArray(R.array.config_ringtoneEffectUris))
                .thenReturn(ringtoneUris);
        return mockResources;
    }

    private Context mockContext(Resources r) {
        Context ctx = mock(Context.class);
        when(ctx.getResources()).thenReturn(r);
        return ctx;
    }
}
Loading