Skip to content

Commit

Permalink
Merge tag 'android-security-11.0.0_r61' of https://android.googlesour…
Browse files Browse the repository at this point in the history
…ce.com/platform/frameworks/base into staging/lineage-18.1_merge_android-security-11.0.0_r61

Android security 11.0.0 release 61

* tag 'android-security-11.0.0_r61' of https://android.googlesource.com/platform/frameworks/base:
  [DO NOT MERGE] Do not dismiss keyguard after SIM PUK unlock
  DO NOT MERGE Move accountname and typeName length check from Account.java to AccountManagerService.
  Prevent apps from spamming addAccountExplicitly. See comment here for the discussion on solution https://b.corp.google.com/issues/169762606#comment14
  Fix system zen rules by using owner package name if caller is system
  [RESTRICT AUTOMERGE] Check permission for VoiceInteraction
  Trim any long string inputs that come in to AutomaticZenRule
  Check rule package name in ZenModeHelper.addAutomaticRule
  DO NOT MERGE Fix auto-grant of AR runtime permission if device is upgrading from pre-Q
  Do not send AccessibilityEvent if notification is for different user.
  [RESTRICT AUTOMERGE] Do not send new Intent to non-exported activity when navigateUpTo
  switch TelecomManager List getters to ParceledListSlice
  DO NOT MERGE Move accountname and typeName length check from Account.java to AccountManagerService.

Conflicts:
	services/core/java/com/android/server/pm/permission/PermissionManagerService.java

Change-Id: Ib35acb1b73ecab5019a49da7281113716f25f20d
  • Loading branch information
haggertk authored and darknius09 committed Nov 19, 2022
1 parent 8d192b4 commit 969cf63
Show file tree
Hide file tree
Showing 30 changed files with 546 additions and 81 deletions.
7 changes: 0 additions & 7 deletions core/java/android/accounts/Account.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@

import com.android.internal.annotations.GuardedBy;

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

/**
Expand Down Expand Up @@ -86,12 +85,6 @@ public Account(String name, String type, String accessId) {
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;
Expand Down
58 changes: 48 additions & 10 deletions core/java/android/app/AutomaticZenRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down Expand Up @@ -93,10 +100,10 @@ public AutomaticZenRule(String name, ComponentName owner, Uri conditionId,
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;
Expand All @@ -115,12 +122,12 @@ public AutomaticZenRule(String name, ComponentName owner, ComponentName configur
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;
Expand Down Expand Up @@ -196,7 +203,7 @@ public long getCreationTime() {
* 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);
}

/**
Expand All @@ -211,7 +218,7 @@ public void setInterruptionFilter(@InterruptionFilter int interruptionFilter) {
* Sets the name of this rule.
*/
public void setName(String name) {
this.name = name;
this.name = getTrimmedString(name);
}

/**
Expand Down Expand Up @@ -243,7 +250,7 @@ public void setZenPolicy(ZenPolicy zenPolicy) {
* that are not backed by {@link android.service.notification.ConditionProviderService}.
*/
public void setConfigurationActivity(@Nullable ComponentName componentName) {
this.configurationActivity = componentName;
this.configurationActivity = getTrimmedComponentName(componentName);
}

/**
Expand Down Expand Up @@ -333,4 +340,35 @@ public AutomaticZenRule[] newArray(int size) {
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;
}
}
57 changes: 54 additions & 3 deletions core/java/android/service/voice/AlwaysOnHotwordDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@

package android.service.voice;

import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
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;
Expand Down Expand Up @@ -232,8 +234,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;

/**
* A ModelParamRange is a representation of supported parameter range for a
Expand Down Expand Up @@ -408,23 +412,37 @@ public static abstract class Callback {
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 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,
IVoiceInteractionManagerService modelManagementService) {
mText = text;
mContext = context;
mLocale = locale;
mKeyphraseEnrollmentInfo = keyphraseEnrollmentInfo;
mExternalCallback = callback;
mHandler = new MyHandler();
mInternalCallback = new SoundTriggerListener(mHandler);
mModelManagementService = modelManagementService;
mIsGrantedHotwordPermission = hasHotwordPermission(mContext);
new RefreshAvailabiltyTask().execute();
}

Expand Down Expand Up @@ -477,6 +495,11 @@ private int getSupportedRecognitionModesLocked() {
@AudioCapabilities
public int getSupportedAudioCapabilities() {
if (DBG) Slog.d(TAG, "getSupportedAudioCapabilities()");

if (!mIsGrantedHotwordPermission) {
return 0;
}

synchronized (mLock) {
return getSupportedAudioCapabilitiesLocked();
}
Expand Down Expand Up @@ -515,6 +538,12 @@ private int getSupportedAudioCapabilitiesLocked() {
*/
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");
Expand Down Expand Up @@ -545,6 +574,12 @@ public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
*/
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");
Expand Down Expand Up @@ -582,6 +617,10 @@ public int setParameter(@ModelParams int modelParam, int value) {
Slog.d(TAG, "setParameter(" + modelParam + ", " + value + ")");
}

if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
return SoundTrigger.STATUS_INVALID_OPERATION;
}

synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("setParameter called on an invalid detector");
Expand Down Expand Up @@ -609,6 +648,10 @@ public int getParameter(@ModelParams int modelParam) {
Slog.d(TAG, "getParameter(" + modelParam + ")");
}

if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
return MODEL_PARAM_THRESHOLD_FACTOR;
}

synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("getParameter called on an invalid detector");
Expand All @@ -634,6 +677,10 @@ public ModelParamRange queryParameter(@ModelParams int modelParam) {
Slog.d(TAG, "queryParameter(" + modelParam + ")");
}

if (!mIsGrantedHotwordPermission || !hasRecordAudioPermission(mContext)) {
return null;
}

synchronized (mLock) {
if (mAvailability == STATE_INVALID) {
throw new IllegalStateException("queryParameter called on an invalid detector");
Expand Down Expand Up @@ -742,8 +789,8 @@ void invalidate() {
*/
void onSoundModelsChanged() {
synchronized (mLock) {
if (mAvailability == STATE_INVALID
|| mAvailability == STATE_HARDWARE_UNAVAILABLE) {
if (mAvailability == STATE_INVALID || mAvailability == STATE_HARDWARE_UNAVAILABLE
|| !hasRecordAudioPermission(mContext)) {
Slog.w(TAG, "Received onSoundModelsChanged for an unsupported keyphrase/config");
return;
}
Expand Down Expand Up @@ -962,6 +1009,10 @@ public Void doInBackground(Void... params) {
* @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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,7 @@ public final AlwaysOnHotwordDetector createAlwaysOnHotwordDetector(
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, mSystemService);
}
return mHotwordDetector;
Expand Down
Loading

0 comments on commit 969cf63

Please sign in to comment.