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

Commit eade1a50 authored by /e/ robot's avatar /e/ robot
Browse files

Merge remote-tracking branch 'origin/lineage-17.1' into v1-q

parents 45553eb0 5a07c6e5
Loading
Loading
Loading
Loading
+0 −7
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@ import android.util.Log;

import com.android.internal.annotations.GuardedBy;

import java.util.Objects;
import java.util.Set;

/**
@@ -86,12 +85,6 @@ public class Account implements Parcelable {
        if (TextUtils.isEmpty(type)) {
            throw new IllegalArgumentException("the type must not be empty: " + type);
        }
        if (name.length() > 200) {
            throw new IllegalArgumentException("account name is longer than 200 characters");
        }
        if (type.length() > 200) {
            throw new IllegalArgumentException("account type is longer than 200 characters");
        }
        this.name = name;
        this.type = type;
        this.accessId = accessId;
+48 −10
Original line number Diff line number Diff line
@@ -47,6 +47,13 @@ public final class AutomaticZenRule implements Parcelable {
    private boolean mModified = false;
    private String mPkg;

    /**
     * The maximum string length for any string contained in this automatic zen rule. This pertains
     * both to fields in the rule itself (such as its name) and items with sub-fields.
     * @hide
     */
    public static final int MAX_STRING_LENGTH = 1000;

    /**
     * Creates an automatic zen rule.
     *
@@ -93,10 +100,10 @@ public final class AutomaticZenRule implements Parcelable {
    public AutomaticZenRule(@NonNull String name, @Nullable ComponentName owner,
            @Nullable ComponentName configurationActivity, @NonNull Uri conditionId,
            @Nullable ZenPolicy policy, int interruptionFilter, boolean enabled) {
        this.name = name;
        this.owner = owner;
        this.configurationActivity = configurationActivity;
        this.conditionId = conditionId;
        this.name = getTrimmedString(name);
        this.owner = getTrimmedComponentName(owner);
        this.configurationActivity = getTrimmedComponentName(configurationActivity);
        this.conditionId = getTrimmedUri(conditionId);
        this.interruptionFilter = interruptionFilter;
        this.enabled = enabled;
        this.mZenPolicy = policy;
@@ -115,12 +122,12 @@ public final class AutomaticZenRule implements Parcelable {
    public AutomaticZenRule(Parcel source) {
        enabled = source.readInt() == ENABLED;
        if (source.readInt() == ENABLED) {
            name = source.readString();
            name = getTrimmedString(source.readString());
        }
        interruptionFilter = source.readInt();
        conditionId = source.readParcelable(null);
        owner = source.readParcelable(null);
        configurationActivity = source.readParcelable(null);
        owner = getTrimmedComponentName(source.readParcelable(null));
        configurationActivity = getTrimmedComponentName(source.readParcelable(null));
        creationTime = source.readLong();
        mZenPolicy = source.readParcelable(null);
        mModified = source.readInt() == ENABLED;
@@ -196,7 +203,7 @@ public final class AutomaticZenRule implements Parcelable {
     * Sets the representation of the state that causes this rule to become active.
     */
    public void setConditionId(Uri conditionId) {
        this.conditionId = conditionId;
        this.conditionId = getTrimmedUri(conditionId);
    }

    /**
@@ -211,7 +218,7 @@ public final class AutomaticZenRule implements Parcelable {
     * Sets the name of this rule.
     */
    public void setName(String name) {
        this.name = name;
        this.name = getTrimmedString(name);
    }

    /**
@@ -243,7 +250,7 @@ public final class AutomaticZenRule implements Parcelable {
     * that are not backed by {@link android.service.notification.ConditionProviderService}.
     */
    public void setConfigurationActivity(@Nullable ComponentName componentName) {
        this.configurationActivity = componentName;
        this.configurationActivity = getTrimmedComponentName(componentName);
    }

    /**
@@ -333,4 +340,35 @@ public final class AutomaticZenRule implements Parcelable {
            return new AutomaticZenRule[size];
        }
    };

    /**
     * If the package or class name of the provided ComponentName are longer than MAX_STRING_LENGTH,
     * return a trimmed version that truncates each of the package and class name at the max length.
     */
    private static ComponentName getTrimmedComponentName(ComponentName cn) {
        if (cn == null) return null;
        return new ComponentName(getTrimmedString(cn.getPackageName()),
                getTrimmedString(cn.getClassName()));
    }

    /**
     * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH.
     */
    private static String getTrimmedString(String input) {
        if (input != null && input.length() > MAX_STRING_LENGTH) {
            return input.substring(0, MAX_STRING_LENGTH);
        }
        return input;
    }

    /**
     * Returns a truncated copy of the Uri by trimming the string representation to the maximum
     * string length.
     */
    private static Uri getTrimmedUri(Uri input) {
        if (input != null && input.toString().length() > MAX_STRING_LENGTH) {
            return Uri.parse(getTrimmedString(input.toString()));
        }
        return input;
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -1011,4 +1011,10 @@ public abstract class PackageManagerInternal {
     * that b/141413692 is not reproducible on Q.
     */
    public abstract void userRemovedForTest();

    /**
     * Get installed SDK version of the package
     * @param pkg package for which to retrieve the installed sdk version
     */
    public abstract int getInstalledSdkVersion(PackageParser.Package pkg);
}
+38 −2
Original line number Diff line number Diff line
@@ -16,12 +16,15 @@

package android.service.voice;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.soundtrigger.IRecognitionStatusCallback;
import android.hardware.soundtrigger.KeyphraseEnrollmentInfo;
import android.hardware.soundtrigger.KeyphraseMetadata;
@@ -195,8 +198,10 @@ public class AlwaysOnHotwordDetector {
    private final Callback mExternalCallback;
    private final Object mLock = new Object();
    private final Handler mHandler;
    private final Context mContext;

    private int mAvailability = STATE_NOT_READY;
    private boolean mIsGrantedHotwordPermission;

    /**
     * Additional payload for {@link Callback#onDetected}.
@@ -324,19 +329,32 @@ public class AlwaysOnHotwordDetector {
        public abstract void onRecognitionResumed();
    }

    private static boolean hasHotwordPermission(Context context) {
        return context.checkSelfPermission(Manifest.permission.CAPTURE_AUDIO_HOTWORD)
            == PackageManager.PERMISSION_GRANTED;
    }

    private static boolean hasRecordAudioPermission(Context context) {
        return context.checkSelfPermission(Manifest.permission.RECORD_AUDIO)
            == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * @param context The context to check permission
     * @param text The keyphrase text to get the detector for.
     * @param locale The java locale for the detector.
     * @param callback A non-null Callback for receiving the recognition events.
     * @param keyphraseEnrollmentInfo The Enrollment info of key phrase
     * @param voiceInteractionService The current voice interaction service.
     * @param modelManagementService A service that allows management of sound models.
     *
     * @hide
     */
    public AlwaysOnHotwordDetector(String text, Locale locale, Callback callback,
    public AlwaysOnHotwordDetector(Context context, String text, Locale locale, Callback callback,
            KeyphraseEnrollmentInfo keyphraseEnrollmentInfo,
            IVoiceInteractionService voiceInteractionService,
            IVoiceInteractionManagerService modelManagementService) {
        mContext = context;
        mText = text;
        mLocale = locale;
        mKeyphraseEnrollmentInfo = keyphraseEnrollmentInfo;
@@ -346,6 +364,7 @@ public class AlwaysOnHotwordDetector {
        mInternalCallback = new SoundTriggerListener(mHandler);
        mVoiceInteractionService = voiceInteractionService;
        mModelManagementService = modelManagementService;
        mIsGrantedHotwordPermission = hasHotwordPermission(mContext);
        new RefreshAvailabiltyTask().execute();
    }

@@ -402,6 +421,12 @@ public class AlwaysOnHotwordDetector {
     */
    public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
        if (DBG) Slog.d(TAG, "startRecognition(" + recognitionFlags + ")");

        if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
            throw new IllegalStateException("Must have the RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD "
                + "permissions to access the detector.");
        }

        synchronized (mLock) {
            if (mAvailability == STATE_INVALID) {
                throw new IllegalStateException("startRecognition called on an invalid detector");
@@ -430,6 +455,12 @@ public class AlwaysOnHotwordDetector {
     */
    public boolean stopRecognition() {
        if (DBG) Slog.d(TAG, "stopRecognition()");

        if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
            throw new IllegalStateException("Must have the RECORD_AUDIO and CAPTURE_AUDIO_HOTWORD "
                + "permissions to access the detector.");
        }

        synchronized (mLock) {
            if (mAvailability == STATE_INVALID) {
                throw new IllegalStateException("stopRecognition called on an invalid detector");
@@ -546,7 +577,8 @@ public class AlwaysOnHotwordDetector {
        synchronized (mLock) {
            if (mAvailability == STATE_INVALID
                    || mAvailability == STATE_HARDWARE_UNAVAILABLE
                    || mAvailability == STATE_KEYPHRASE_UNSUPPORTED) {
                    || mAvailability == STATE_KEYPHRASE_UNSUPPORTED
                    || !hasRecordAudioPermission(mContext)) {
                Slog.w(TAG, "Received onSoundModelsChanged for an unsupported keyphrase/config");
                return;
            }
@@ -717,6 +749,10 @@ public class AlwaysOnHotwordDetector {
         * @return The initial availability without checking the enrollment status.
         */
        private int internalGetInitialAvailability() {
            if (!mIsGrantedHotwordPermission) {
                return STATE_HARDWARE_UNAVAILABLE;
            }

            synchronized (mLock) {
                // This detector has already been invalidated.
                if (mAvailability == STATE_INVALID) {
+1 −1
Original line number Diff line number Diff line
@@ -297,7 +297,7 @@ public class VoiceInteractionService extends Service {
        synchronized (mLock) {
            // Allow only one concurrent recognition via the APIs.
            safelyShutdownHotwordDetector();
            mHotwordDetector = new AlwaysOnHotwordDetector(keyphrase, locale, callback,
            mHotwordDetector = new AlwaysOnHotwordDetector(this, keyphrase, locale, callback,
                    mKeyphraseEnrollmentInfo, mInterface, mSystemService);
        }
        return mHotwordDetector;
Loading