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

Commit 941ce0ca authored by Nishith  Khanna's avatar Nishith Khanna
Browse files

Merge remote-tracking branch 'origin/lineage-21.0' into a14

parents 253c5e46 1bf856ce
Loading
Loading
Loading
Loading
+53 −6
Original line number Diff line number Diff line
@@ -139,7 +139,11 @@ public final class NotificationChannel implements Parcelable {
    /**
     * @hide
     */
    public static final int MAX_VIBRATION_LENGTH = 1000;
    public static final int MAX_VIBRATION_LENGTH = 500;
    /**
     * @hide
     */
    public static final int MAX_SERIALIZED_VIBRATION_LENGTH = 32_768;

    private static final String TAG_CHANNEL = "channel";
    private static final String ATT_NAME = "name";
@@ -339,6 +343,9 @@ public final class NotificationChannel implements Parcelable {
        if (Flags.notificationChannelVibrationEffectApi()) {
            mVibrationEffect =
                    in.readInt() != 0 ? VibrationEffect.CREATOR.createFromParcel(in) : null;
            if (Flags.notifChannelCropVibrationEffects() && mVibrationEffect != null) {
                mVibrationEffect = getTrimmedVibrationEffect(mVibrationEffect);
            }
        }
        mUserLockedFields = in.readInt();
        mUserVisibleTaskShown = in.readByte() != 0;
@@ -519,6 +526,23 @@ public final class NotificationChannel implements Parcelable {
        return input;
    }

    // Returns trimmed vibration effect or null if not trimmable.
    private VibrationEffect getTrimmedVibrationEffect(VibrationEffect effect) {
        if (effect == null) {
            return null;
        }
        // trim if possible; check serialized length; reject if it is still too long
        VibrationEffect result = effect;
        VibrationEffect trimmed = effect.cropToLengthOrNull(MAX_VIBRATION_LENGTH);
        if (trimmed != null) {
            result = trimmed;
        }
        if (vibrationToString(result).length() > MAX_SERIALIZED_VIBRATION_LENGTH) {
            return null;
        }
        return result;
    }

    /**
     * @hide
     */
@@ -616,6 +640,11 @@ public final class NotificationChannel implements Parcelable {
    public void setVibrationPattern(long[] vibrationPattern) {
        this.mVibrationEnabled = vibrationPattern != null && vibrationPattern.length > 0;
        this.mVibrationPattern = vibrationPattern;
        if (Flags.notifChannelCropVibrationEffects()) {
            if (vibrationPattern != null && vibrationPattern.length > MAX_VIBRATION_LENGTH) {
                this.mVibrationPattern = Arrays.copyOf(vibrationPattern, MAX_VIBRATION_LENGTH);
            }
        }
        if (Flags.notificationChannelVibrationEffectApi()) {
            try {
                this.mVibrationEffect =
@@ -662,9 +691,21 @@ public final class NotificationChannel implements Parcelable {
    public void setVibrationEffect(@Nullable VibrationEffect effect) {
        this.mVibrationEnabled = effect != null;
        this.mVibrationEffect = effect;
        if (Flags.notifChannelCropVibrationEffects() && effect != null) {
            // Try converting to a vibration pattern and trimming that array. If not convertible
            // to a pattern directly, try trimming the vibration effect if possible and storing
            // that version instead.
            long[] pattern = effect.computeCreateWaveformOffOnTimingsOrNull();
            if (pattern != null) {
                setVibrationPattern(pattern);
            } else {
                this.mVibrationEffect = getTrimmedVibrationEffect(mVibrationEffect);
            }
        } else {
            this.mVibrationPattern =
                effect == null
                ? null : effect.computeCreateWaveformOffOnTimingsOrNull();
                    mVibrationEffect == null
                            ? null : mVibrationEffect.computeCreateWaveformOffOnTimingsOrNull();
        }
    }

    /**
@@ -1097,7 +1138,9 @@ public final class NotificationChannel implements Parcelable {
            if (vibrationEffect != null) {
                // Restore the effect only if it is not null. This allows to avoid undoing a
                // `setVibrationPattern` call above, if that was done with a non-null pattern
                // (e.g. back up from a version that did not support `setVibrationEffect`).
                // (e.g. back up from a version that did not support `setVibrationEffect`), or
                // when notif_channel_crop_vibration_effects is true, if there is an equivalent
                // vibration pattern available.
                setVibrationEffect(vibrationEffect);
            }
        }
@@ -1290,8 +1333,12 @@ public final class NotificationChannel implements Parcelable {
            out.attribute(null, ATT_VIBRATION, longArrayToString(getVibrationPattern()));
        }
        if (getVibrationEffect() != null) {
            if (!Flags.notifChannelCropVibrationEffects() || getVibrationPattern() == null) {
                // When notif_channel_crop_vibration_effects is on, only serialize the vibration
                // effect if we do not already have an equivalent vibration pattern.
                out.attribute(null, ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));
            }
        }
        if (getUserLockedFields() != 0) {
            out.attributeInt(null, ATT_USER_LOCKED, getUserLockedFields());
        }
+10 −0
Original line number Diff line number Diff line
@@ -58,6 +58,16 @@ flag {
  bug: "241732519"
}

flag {
  name: "notif_channel_crop_vibration_effects"
  namespace: "systemui"
  description: "Limits the size of vibration effects that can be stored in a NotificationChannel"
  bug: "345881518"
  metadata {
    purpose: PURPOSE_BUGFIX
  }
}

flag {
  name: "evenly_divided_call_style_action_layout"
  namespace: "systemui"
+35 −0
Original line number Diff line number Diff line
@@ -504,6 +504,17 @@ public abstract class VibrationEffect implements Parcelable {
    /** @hide */
    public abstract void validate();


    /**
     * If supported, truncate the length of this vibration effect to the provided length and return
     * the result. Will always return null for repeating effects.
     *
     * @return The desired effect, or {@code null} if truncation is not applicable.
     * @hide
     */
    @Nullable
    public abstract VibrationEffect cropToLengthOrNull(int length);

    /**
     * Gets the estimated duration of the vibration in milliseconds.
     *
@@ -805,6 +816,30 @@ public abstract class VibrationEffect implements Parcelable {
            }
        }

        /** @hide */
        @Override
        @Nullable
        public VibrationEffect cropToLengthOrNull(int length) {
            // drop repeating effects
            if (mRepeatIndex >= 0) {
                return null;
            }

            int segmentCount = mSegments.size();
            if (segmentCount <= length) {
                return this;
            }

            ArrayList truncated = new ArrayList(mSegments.subList(0, length));
            Composed updated = new Composed(truncated, mRepeatIndex);
            try {
                updated.validate();
            } catch (IllegalArgumentException e) {
                return null;
            }
            return updated;
        }

        @Override
        public long getDuration() {
            if (mRepeatIndex >= 0) {
+27 −0
Original line number Diff line number Diff line
@@ -230,6 +230,33 @@ public class NotificationChannelTest {
                fromParcel.getSound().toString().length());
    }

    @Test
    @EnableFlags({Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API,
            Flags.FLAG_NOTIF_CHANNEL_CROP_VIBRATION_EFFECTS})
    public void testLongVibrationFields_canWriteToXml() throws Exception {
        NotificationChannel channel = new NotificationChannel("id", "name", 3);
        // populate pattern with contents
        long[] pattern = new long[65550 / 2];
        for (int i = 0; i < pattern.length; i++) {
            pattern[i] = 100;
        }
        channel.setVibrationPattern(pattern);  // with flag on, also sets effect

        // Send it through parceling & unparceling to simulate being passed through a binder call
        NotificationChannel fromParcel = writeToAndReadFromParcel(channel);
        assertThat(fromParcel.getVibrationPattern().length).isEqualTo(
                NotificationChannel.MAX_VIBRATION_LENGTH);

        // Confirm that this also survives writing to & restoring from XML
        NotificationChannel result = backUpAndRestore(fromParcel);
        assertThat(result.getVibrationPattern().length).isEqualTo(
                NotificationChannel.MAX_VIBRATION_LENGTH);
        assertThat(result.getVibrationEffect()).isNotNull();
        assertThat(result.getVibrationEffect()
                .computeCreateWaveformOffOnTimingsOrNull())
                .isEqualTo(result.getVibrationPattern());
    }

    @Test
    public void testRestoreSoundUri_customLookup() throws Exception {
        Uri uriToBeRestoredUncanonicalized = Uri.parse("content://media/1");
+80 −0
Original line number Diff line number Diff line
@@ -419,6 +419,86 @@ public class VibrationEffectTest {
        assertNull(effect.computeCreateWaveformOffOnTimingsOrNull());
    }

    @Test
    public void cropToLength_waveform_underLength() {
        VibrationEffect effect = VibrationEffect.createWaveform(
                /* timings= */ new long[]{0, 1, 2},
                /* repeatIndex= */ -1);
        VibrationEffect result = effect.cropToLengthOrNull(5);

        assertThat(result).isEqualTo(effect); // unchanged
    }

    @Test
    public void cropToLength_waveform_overLength() {
        VibrationEffect effect = VibrationEffect.createWaveform(
                /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
                /* repeatIndex= */ -1);
        VibrationEffect result = effect.cropToLengthOrNull(4);

        assertThat(result).isEqualTo(VibrationEffect.createWaveform(
                new long[]{0, 1, 2, 3},
                -1));
    }

    @Test
    public void cropToLength_waveform_repeating() {
        // repeating waveforms cannot be truncated
        VibrationEffect effect = VibrationEffect.createWaveform(
                /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
                /* repeatIndex= */ 2);
        VibrationEffect result = effect.cropToLengthOrNull(3);

        assertThat(result).isNull();
    }

    @Test
    public void cropToLength_waveform_withAmplitudes() {
        VibrationEffect effect = VibrationEffect.createWaveform(
                /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
                /* amplitudes= */ new int[]{10, 20, 40, 10, 20, 40, 10},
                /* repeatIndex= */ -1);
        VibrationEffect result = effect.cropToLengthOrNull(3);

        assertThat(result).isEqualTo(VibrationEffect.createWaveform(
                new long[]{0, 1, 2},
                new int[]{10, 20, 40},
                -1));
    }

    @Test
    public void cropToLength_composed() {
        VibrationEffect effect = VibrationEffect.startComposition()
                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
                .compose();
        VibrationEffect result = effect.cropToLengthOrNull(1);

        assertThat(result).isNotNull();
        assertThat(result).isEqualTo(VibrationEffect.startComposition()
                        .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
                        .compose());
    }

    @Test
    public void cropToLength_composed_repeating() {
        VibrationEffect effect = VibrationEffect.startComposition()
                .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
                .repeatEffectIndefinitely(TEST_ONE_SHOT)
                .compose();
        assertThat(effect.cropToLengthOrNull(1)).isNull();
    }

    @Test
    @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
    public void cropToLength_vendorEffect() {
        PersistableBundle vendorData = new PersistableBundle();
        vendorData.putInt("key", 1);
        VibrationEffect effect = VibrationEffect.createVendorEffect(vendorData);

        assertThat(effect.cropToLengthOrNull(2)).isNull();
    }

    @Test
    public void getRingtones_noPrebakedRingtones() {
        Resources r = mockRingtoneResources(new String[0]);
Loading