Merge "Merge TP1A.221105.002 to aosp-master - DO NOT MERGE"
This commit is contained in:
@@ -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,14 @@ 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, android.net.Uri.class);
|
||||
owner = source.readParcelable(null, android.content.ComponentName.class);
|
||||
configurationActivity = source.readParcelable(null, android.content.ComponentName.class);
|
||||
conditionId = getTrimmedUri(source.readParcelable(null, android.net.Uri.class));
|
||||
owner = getTrimmedComponentName(
|
||||
source.readParcelable(null, android.content.ComponentName.class));
|
||||
configurationActivity = getTrimmedComponentName(
|
||||
source.readParcelable(null, android.content.ComponentName.class));
|
||||
creationTime = source.readLong();
|
||||
mZenPolicy = source.readParcelable(null, android.service.notification.ZenPolicy.class);
|
||||
mModified = source.readInt() == ENABLED;
|
||||
@@ -196,7 +205,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 +220,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 +252,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 +342,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,8 +438,11 @@ public class BaseBundle {
|
||||
map.ensureCapacity(count);
|
||||
}
|
||||
try {
|
||||
// recycleParcel being false implies that we do not own the parcel. In this case, do
|
||||
// not use lazy values to be safe, as the parcel could be recycled outside of our
|
||||
// control.
|
||||
recycleParcel &= parcelledData.readArrayMap(map, count, !parcelledByNative,
|
||||
/* lazy */ true, mClassLoader);
|
||||
/* lazy */ recycleParcel, mClassLoader);
|
||||
} catch (BadParcelableException e) {
|
||||
if (sShouldDefuse) {
|
||||
Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
|
||||
@@ -1845,7 +1848,6 @@ public class BaseBundle {
|
||||
// bundle immediately; neither of which is obvious.
|
||||
synchronized (this) {
|
||||
initializeFromParcelLocked(parcel, /*recycleParcel=*/ false, isNativeBundle);
|
||||
unparcel(/* itemwise */ true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
153
core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
Normal file
153
core/tests/coretests/src/android/app/AutomaticZenRuleTest.java
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.app;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.net.Uri;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
public class AutomaticZenRuleTest {
|
||||
private static final String CLASS = "android.app.AutomaticZenRule";
|
||||
|
||||
@Test
|
||||
public void testLongFields_inConstructor() {
|
||||
String longString = Strings.repeat("A", 65536);
|
||||
Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
|
||||
|
||||
// test both variants where there's an owner, and where there's a configuration activity
|
||||
AutomaticZenRule rule1 = new AutomaticZenRule(
|
||||
longString, // name
|
||||
new ComponentName("pkg", longString), // owner
|
||||
null, // configuration activity
|
||||
longUri, // conditionId
|
||||
null, // zen policy
|
||||
0, // interruption filter
|
||||
true); // enabled
|
||||
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule1.getName().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
rule1.getConditionId().toString().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule1.getOwner().getClassName().length());
|
||||
|
||||
AutomaticZenRule rule2 = new AutomaticZenRule(
|
||||
longString, // name
|
||||
null, // owner
|
||||
new ComponentName(longString, "SomeClassName"), // configuration activity
|
||||
longUri, // conditionId
|
||||
null, // zen policy
|
||||
0, // interruption filter
|
||||
false); // enabled
|
||||
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule2.getName().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
rule2.getConditionId().toString().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
rule2.getConfigurationActivity().getPackageName().length());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongFields_inSetters() {
|
||||
String longString = Strings.repeat("A", 65536);
|
||||
Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
|
||||
|
||||
AutomaticZenRule rule = new AutomaticZenRule(
|
||||
"sensible name",
|
||||
new ComponentName("pkg", "ShortClass"),
|
||||
null,
|
||||
Uri.parse("uri://short"),
|
||||
null, 0, true);
|
||||
|
||||
rule.setName(longString);
|
||||
rule.setConditionId(longUri);
|
||||
rule.setConfigurationActivity(new ComponentName(longString, longString));
|
||||
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, rule.getName().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
rule.getConditionId().toString().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
rule.getConfigurationActivity().getPackageName().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
rule.getConfigurationActivity().getClassName().length());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLongInputsFromParcel() {
|
||||
// Create a rule with long fields, set directly via reflection so that we can confirm that
|
||||
// a rule with too-long fields that comes in via a parcel has its fields truncated directly.
|
||||
AutomaticZenRule rule = new AutomaticZenRule(
|
||||
"placeholder",
|
||||
new ComponentName("place", "holder"),
|
||||
null,
|
||||
Uri.parse("uri://placeholder"),
|
||||
null, 0, true);
|
||||
|
||||
try {
|
||||
String longString = Strings.repeat("A", 65536);
|
||||
Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530));
|
||||
Field name = Class.forName(CLASS).getDeclaredField("name");
|
||||
name.setAccessible(true);
|
||||
name.set(rule, longString);
|
||||
Field conditionId = Class.forName(CLASS).getDeclaredField("conditionId");
|
||||
conditionId.setAccessible(true);
|
||||
conditionId.set(rule, longUri);
|
||||
Field owner = Class.forName(CLASS).getDeclaredField("owner");
|
||||
owner.setAccessible(true);
|
||||
owner.set(rule, new ComponentName(longString, longString));
|
||||
Field configActivity = Class.forName(CLASS).getDeclaredField("configurationActivity");
|
||||
configActivity.setAccessible(true);
|
||||
configActivity.set(rule, new ComponentName(longString, longString));
|
||||
} catch (NoSuchFieldException e) {
|
||||
fail(e.toString());
|
||||
} catch (ClassNotFoundException e) {
|
||||
fail(e.toString());
|
||||
} catch (IllegalAccessException e) {
|
||||
fail(e.toString());
|
||||
}
|
||||
|
||||
Parcel parcel = Parcel.obtain();
|
||||
rule.writeToParcel(parcel, 0);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
AutomaticZenRule fromParcel = new AutomaticZenRule(parcel);
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH, fromParcel.getName().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
fromParcel.getConditionId().toString().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
fromParcel.getConfigurationActivity().getPackageName().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
fromParcel.getConfigurationActivity().getClassName().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
fromParcel.getOwner().getPackageName().length());
|
||||
assertEquals(AutomaticZenRule.MAX_STRING_LENGTH,
|
||||
fromParcel.getOwner().getClassName().length());
|
||||
}
|
||||
}
|
||||
@@ -408,6 +408,69 @@ public class BundleTest {
|
||||
assertThat(bundle.<Parcelable>getParcelable("key")).isEqualTo(parcelable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readFromParcel_withLazyValues_copiesUnderlyingParcel() {
|
||||
Bundle bundle = new Bundle();
|
||||
Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
|
||||
bundle.putParcelable("key", parcelable);
|
||||
bundle.putString("string", "value");
|
||||
Parcel parcelledBundle = getParcelledBundle(bundle);
|
||||
|
||||
Bundle testBundle = new Bundle();
|
||||
testBundle.setClassLoader(getClass().getClassLoader());
|
||||
testBundle.readFromParcel(parcelledBundle);
|
||||
// Recycle the parcel as it should have been copied
|
||||
parcelledBundle.recycle();
|
||||
assertThat(testBundle.getString("string")).isEqualTo("value");
|
||||
assertThat(testBundle.<Parcelable>getParcelable("key")).isEqualTo(parcelable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readFromParcelWithRwHelper_whenThrowingAndNotDefusing_throws() {
|
||||
Bundle bundle = new Bundle();
|
||||
Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
|
||||
bundle.putParcelable("key", parcelable);
|
||||
bundle.putString("string", "value");
|
||||
Parcel parcelledBundle = getParcelledBundle(bundle);
|
||||
parcelledBundle.setReadWriteHelper(new Parcel.ReadWriteHelper());
|
||||
|
||||
Bundle testBundle = new Bundle();
|
||||
assertThrows(BadParcelableException.class,
|
||||
() -> testBundle.readFromParcel(parcelledBundle));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readFromParcelWithRwHelper_whenThrowingAndDefusing_returnsNull() {
|
||||
Bundle bundle = new Bundle();
|
||||
Parcelable parcelable = new CustomParcelable(13, "Tiramisu");
|
||||
bundle.putParcelable("key", parcelable);
|
||||
bundle.putString("string", "value");
|
||||
Parcel parcelledBundle = getParcelledBundle(bundle);
|
||||
parcelledBundle.setReadWriteHelper(new Parcel.ReadWriteHelper());
|
||||
|
||||
Bundle.setShouldDefuse(true);
|
||||
Bundle testBundle = new Bundle();
|
||||
testBundle.readFromParcel(parcelledBundle);
|
||||
// Recycle the parcel as it should not be referenced
|
||||
parcelledBundle.recycle();
|
||||
assertThat(testBundle.getString("string")).isNull();
|
||||
assertThat(testBundle.<Parcelable>getParcelable("key")).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void readFromParcelWithRwHelper_withoutLazyObject_returnsValue() {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putString("string", "value");
|
||||
Parcel parcelledBundle = getParcelledBundle(bundle);
|
||||
parcelledBundle.setReadWriteHelper(new Parcel.ReadWriteHelper());
|
||||
|
||||
Bundle testBundle = new Bundle();
|
||||
testBundle.readFromParcel(parcelledBundle);
|
||||
// Recycle the parcel as it should not be referenced
|
||||
parcelledBundle.recycle();
|
||||
assertThat(testBundle.getString("string")).isEqualTo("value");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void partialDeserialization_whenNotDefusing_throws() throws Exception {
|
||||
Bundle.setShouldDefuse(false);
|
||||
|
||||
@@ -33,6 +33,7 @@ import android.view.SurfaceView;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.keyguard.dagger.KeyguardBouncerScope;
|
||||
import com.android.systemui.dagger.qualifiers.Main;
|
||||
|
||||
@@ -208,7 +209,7 @@ public class AdminSecondaryLockScreenController {
|
||||
hide();
|
||||
if (mKeyguardCallback != null) {
|
||||
mKeyguardCallback.dismiss(/* securityVerified= */ true, userId,
|
||||
/* bypassSecondaryLockScreen= */true);
|
||||
/* bypassSecondaryLockScreen= */true, SecurityMode.Invalid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey
|
||||
if (dismissKeyguard) {
|
||||
mDismissing = true;
|
||||
mLatencyTracker.onActionStart(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
|
||||
getKeyguardSecurityCallback().dismiss(true, userId);
|
||||
getKeyguardSecurityCallback().dismiss(true, userId, getSecurityMode());
|
||||
}
|
||||
} else {
|
||||
if (isValidPassword) {
|
||||
|
||||
@@ -90,7 +90,7 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
|
||||
Log.i(TAG, "TrustAgent dismissed Keyguard.");
|
||||
}
|
||||
mSecurityCallback.dismiss(false /* authenticated */, userId,
|
||||
/* bypassSecondaryLockScreen */ false);
|
||||
/* bypassSecondaryLockScreen */ false, SecurityMode.Invalid);
|
||||
} else {
|
||||
mViewMediatorCallback.playTrustedSound();
|
||||
}
|
||||
@@ -102,9 +102,9 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
|
||||
|
||||
@Override
|
||||
public boolean dismiss(boolean authenticated, int targetUserId,
|
||||
boolean bypassSecondaryLockScreen) {
|
||||
boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
|
||||
return mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
|
||||
authenticated, targetUserId, bypassSecondaryLockScreen);
|
||||
authenticated, targetUserId, bypassSecondaryLockScreen, expectedSecurityMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -212,7 +212,8 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
|
||||
* @return True if the keyguard is done.
|
||||
*/
|
||||
public boolean dismiss(int targetUserId) {
|
||||
return mSecurityCallback.dismiss(false, targetUserId, false);
|
||||
return mSecurityCallback.dismiss(false, targetUserId, false,
|
||||
getCurrentSecurityMode());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -355,10 +356,10 @@ public class KeyguardHostViewController extends ViewController<KeyguardHostView>
|
||||
}
|
||||
|
||||
public boolean handleBackKey() {
|
||||
if (mKeyguardSecurityContainerController.getCurrentSecurityMode()
|
||||
!= SecurityMode.None) {
|
||||
SecurityMode securityMode = mKeyguardSecurityContainerController.getCurrentSecurityMode();
|
||||
if (securityMode != SecurityMode.None) {
|
||||
mKeyguardSecurityContainerController.dismiss(
|
||||
false, KeyguardUpdateMonitor.getCurrentUser());
|
||||
false, KeyguardUpdateMonitor.getCurrentUser(), securityMode);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -59,10 +59,11 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView>
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void dismiss(boolean securityVerified, int targetUserId) { }
|
||||
public void dismiss(boolean securityVerified, int targetUserId,
|
||||
SecurityMode expectedSecurityMode) { }
|
||||
@Override
|
||||
public void dismiss(boolean authenticated, int targetId,
|
||||
boolean bypassSecondaryLockScreen) { }
|
||||
boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) { }
|
||||
@Override
|
||||
public void onUserInput() { }
|
||||
@Override
|
||||
|
||||
@@ -171,7 +171,7 @@ public class KeyguardPatternViewController
|
||||
if (dismissKeyguard) {
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Correct);
|
||||
mLatencyTracker.onActionStart(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK);
|
||||
getKeyguardSecurityCallback().dismiss(true, userId);
|
||||
getKeyguardSecurityCallback().dismiss(true, userId, SecurityMode.Pattern);
|
||||
}
|
||||
} else {
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
|
||||
|
||||
@@ -15,14 +15,17 @@
|
||||
*/
|
||||
package com.android.keyguard;
|
||||
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
|
||||
public interface KeyguardSecurityCallback {
|
||||
|
||||
/**
|
||||
* Dismiss the given security screen.
|
||||
* @param securityVerified true if the user correctly entered credentials for the given screen.
|
||||
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
|
||||
* @param expectedSecurityMode The security mode that is invoking this dismiss.
|
||||
*/
|
||||
void dismiss(boolean securityVerified, int targetUserId);
|
||||
void dismiss(boolean securityVerified, int targetUserId, SecurityMode expectedSecurityMode);
|
||||
|
||||
/**
|
||||
* Dismiss the given security screen.
|
||||
@@ -30,8 +33,10 @@ public interface KeyguardSecurityCallback {
|
||||
* @param targetUserId a user that needs to be the foreground user at the dismissal completion.
|
||||
* @param bypassSecondaryLockScreen true if the user can bypass the secondary lock screen,
|
||||
* if any, during this dismissal.
|
||||
* @param expectedSecurityMode The security mode that is invoking this dismiss.
|
||||
*/
|
||||
void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen);
|
||||
void dismiss(boolean securityVerified, int targetUserId, boolean bypassSecondaryLockScreen,
|
||||
SecurityMode expectedSecurityMode);
|
||||
|
||||
/**
|
||||
* Manually report user activity to keep the device awake.
|
||||
|
||||
@@ -233,7 +233,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
|
||||
|
||||
// Used to notify the container when something interesting happens.
|
||||
public interface SecurityCallback {
|
||||
boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
|
||||
/**
|
||||
* Potentially dismiss the current security screen, after validating that all device
|
||||
* security has been unlocked. Otherwise show the next screen.
|
||||
*/
|
||||
boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen,
|
||||
SecurityMode expectedSecurityMode);
|
||||
|
||||
void userActivity();
|
||||
|
||||
|
||||
@@ -153,14 +153,17 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss(boolean authenticated, int targetId) {
|
||||
dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false);
|
||||
public void dismiss(boolean authenticated, int targetId,
|
||||
SecurityMode expectedSecurityMode) {
|
||||
dismiss(authenticated, targetId, /* bypassSecondaryLockScreen */ false,
|
||||
expectedSecurityMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss(boolean authenticated, int targetId,
|
||||
boolean bypassSecondaryLockScreen) {
|
||||
mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen);
|
||||
boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
|
||||
mSecurityCallback.dismiss(authenticated, targetId, bypassSecondaryLockScreen,
|
||||
expectedSecurityMode);
|
||||
}
|
||||
|
||||
public boolean isVerifyUnlockOnly() {
|
||||
@@ -350,8 +353,13 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
return mCurrentSecurityMode;
|
||||
}
|
||||
|
||||
public void dismiss(boolean authenticated, int targetUserId) {
|
||||
mKeyguardSecurityCallback.dismiss(authenticated, targetUserId);
|
||||
/**
|
||||
* Potentially dismiss the current security screen, after validating that all device
|
||||
* security has been unlocked. Otherwise show the next screen.
|
||||
*/
|
||||
public void dismiss(boolean authenticated, int targetUserId,
|
||||
SecurityMode expectedSecurityMode) {
|
||||
mKeyguardSecurityCallback.dismiss(authenticated, targetUserId, expectedSecurityMode);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
@@ -410,12 +418,21 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
* completion.
|
||||
* @param bypassSecondaryLockScreen true if the user is allowed to bypass the secondary
|
||||
* secondary lock screen requirement, if any.
|
||||
* @param expectedSecurityMode SecurityMode that is invoking this request. SecurityMode.Invalid
|
||||
* indicates that no check should be done
|
||||
* @return true if keyguard is done
|
||||
*/
|
||||
public boolean showNextSecurityScreenOrFinish(boolean authenticated, int targetUserId,
|
||||
boolean bypassSecondaryLockScreen) {
|
||||
boolean bypassSecondaryLockScreen, SecurityMode expectedSecurityMode) {
|
||||
|
||||
if (DEBUG) Log.d(TAG, "showNextSecurityScreenOrFinish(" + authenticated + ")");
|
||||
if (expectedSecurityMode != SecurityMode.Invalid
|
||||
&& expectedSecurityMode != getCurrentSecurityMode()) {
|
||||
Log.w(TAG, "Attempted to invoke showNextSecurityScreenOrFinish with securityMode "
|
||||
+ expectedSecurityMode + ", but current mode is " + getCurrentSecurityMode());
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean finish = false;
|
||||
boolean strongAuth = false;
|
||||
int eventSubtype = -1;
|
||||
|
||||
@@ -170,7 +170,8 @@ public class KeyguardSimPinViewController
|
||||
mRemainingAttempts = -1;
|
||||
mShowDefaultMessage = true;
|
||||
getKeyguardSecurityCallback().dismiss(
|
||||
true, KeyguardUpdateMonitor.getCurrentUser());
|
||||
true, KeyguardUpdateMonitor.getCurrentUser(),
|
||||
SecurityMode.SimPin);
|
||||
} else {
|
||||
mShowDefaultMessage = false;
|
||||
if (result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
|
||||
|
||||
@@ -69,7 +69,8 @@ public class KeyguardSimPukViewController
|
||||
if (simState == TelephonyManager.SIM_STATE_READY) {
|
||||
mRemainingAttempts = -1;
|
||||
mShowDefaultMessage = true;
|
||||
getKeyguardSecurityCallback().dismiss(true, KeyguardUpdateMonitor.getCurrentUser());
|
||||
getKeyguardSecurityCallback().dismiss(true, KeyguardUpdateMonitor.getCurrentUser(),
|
||||
SecurityMode.SimPuk);
|
||||
} else {
|
||||
resetState();
|
||||
}
|
||||
@@ -278,7 +279,8 @@ public class KeyguardSimPukViewController
|
||||
mShowDefaultMessage = true;
|
||||
|
||||
getKeyguardSecurityCallback().dismiss(
|
||||
true, KeyguardUpdateMonitor.getCurrentUser());
|
||||
true, KeyguardUpdateMonitor.getCurrentUser(),
|
||||
SecurityMode.SimPuk);
|
||||
} else {
|
||||
mShowDefaultMessage = false;
|
||||
if (result.getResult() == PinResult.PIN_RESULT_TYPE_INCORRECT) {
|
||||
|
||||
@@ -44,6 +44,7 @@ import android.view.SurfaceView;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.After;
|
||||
@@ -190,7 +191,7 @@ public class AdminSecondaryLockScreenControllerTest extends SysuiTestCase {
|
||||
|
||||
private void verifyViewDismissed(SurfaceView v) throws Exception {
|
||||
verify(mKeyguardSecurityContainer).removeView(v);
|
||||
verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true);
|
||||
verify(mKeyguardCallback).dismiss(true, TARGET_USER_ID, true, SecurityMode.Invalid);
|
||||
assertThat(mContext.isBound(mComponentName)).isFalse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ import static android.view.WindowInsets.Type.ime;
|
||||
import static com.android.keyguard.KeyguardSecurityContainer.MODE_DEFAULT;
|
||||
import static com.android.keyguard.KeyguardSecurityContainer.MODE_ONE_HANDED;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
@@ -69,6 +72,7 @@ import org.mockito.junit.MockitoRule;
|
||||
@TestableLooper.RunWithLooper()
|
||||
public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
private static final int VIEW_WIDTH = 1600;
|
||||
private static final int TARGET_USER_ID = 100;
|
||||
|
||||
@Rule
|
||||
public MockitoRule mRule = MockitoJUnit.rule();
|
||||
@@ -299,4 +303,42 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
verify(mUserSwitcherController)
|
||||
.removeUserSwitchCallback(any(UserSwitcherController.UserSwitchCallback.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
|
||||
// GIVEN the current security method is SimPin
|
||||
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
|
||||
when(mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(TARGET_USER_ID)).thenReturn(false);
|
||||
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.SimPin);
|
||||
|
||||
// WHEN a request is made from the SimPin screens to show the next security method
|
||||
when(mKeyguardSecurityModel.getSecurityMode(TARGET_USER_ID)).thenReturn(SecurityMode.PIN);
|
||||
mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
|
||||
/* authenticated= */true,
|
||||
TARGET_USER_ID,
|
||||
/* bypassSecondaryLockScreen= */true,
|
||||
SecurityMode.SimPin);
|
||||
|
||||
// THEN the next security method of PIN is set, and the keyguard is not marked as done
|
||||
verify(mSecurityCallback, never()).finish(anyBoolean(), anyInt());
|
||||
assertThat(mKeyguardSecurityContainerController.getCurrentSecurityMode())
|
||||
.isEqualTo(SecurityMode.PIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void showNextSecurityScreenOrFinish_ignoresCallWhenSecurityMethodHasChanged() {
|
||||
//GIVEN current security mode has been set to PIN
|
||||
mKeyguardSecurityContainerController.showSecurityScreen(SecurityMode.PIN);
|
||||
|
||||
//WHEN a request comes from SimPin to dismiss the security screens
|
||||
boolean keyguardDone = mKeyguardSecurityContainerController.showNextSecurityScreenOrFinish(
|
||||
/* authenticated= */true,
|
||||
TARGET_USER_ID,
|
||||
/* bypassSecondaryLockScreen= */true,
|
||||
SecurityMode.SimPin);
|
||||
|
||||
//THEN no action has happened, which will not dismiss the security screens
|
||||
assertThat(keyguardDone).isEqualTo(false);
|
||||
verify(mKeyguardUpdateMonitor, never()).getUserHasTrust(anyInt());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,10 @@ package com.android.server;
|
||||
import static android.Manifest.permission.ACCESS_MTP;
|
||||
import static android.Manifest.permission.INSTALL_PACKAGES;
|
||||
import static android.Manifest.permission.MANAGE_EXTERNAL_STORAGE;
|
||||
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
|
||||
import static android.app.AppOpsManager.MODE_ALLOWED;
|
||||
import static android.app.AppOpsManager.OP_LEGACY_STORAGE;
|
||||
import static android.app.AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE;
|
||||
import static android.app.AppOpsManager.OP_REQUEST_INSTALL_PACKAGES;
|
||||
import static android.app.AppOpsManager.OP_WRITE_EXTERNAL_STORAGE;
|
||||
import static android.app.PendingIntent.FLAG_CANCEL_CURRENT;
|
||||
import static android.app.PendingIntent.FLAG_IMMUTABLE;
|
||||
import static android.app.PendingIntent.FLAG_ONE_SHOT;
|
||||
@@ -4461,11 +4459,7 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if caller is holding runtime permission
|
||||
final boolean hasWrite = StorageManager.checkPermissionAndCheckOp(mContext, false, 0,
|
||||
uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
|
||||
|
||||
// We're only willing to give out installer access if they also hold
|
||||
// We're only willing to give out installer access if they hold
|
||||
// runtime permission; this is a firm CDD requirement
|
||||
final boolean hasInstall = mIPackageManager.checkUidPermission(INSTALL_PACKAGES,
|
||||
uid) == PERMISSION_GRANTED;
|
||||
@@ -4481,7 +4475,7 @@ class StorageManagerService extends IStorageManager.Stub
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((hasInstall || hasInstallOp) && hasWrite) {
|
||||
if (hasInstall || hasInstallOp) {
|
||||
return StorageManager.MOUNT_MODE_EXTERNAL_INSTALLER;
|
||||
}
|
||||
return StorageManager.MOUNT_MODE_EXTERNAL_DEFAULT;
|
||||
|
||||
@@ -4927,7 +4927,16 @@ public class NotificationManagerService extends SystemService {
|
||||
}
|
||||
enforcePolicyAccess(Binder.getCallingUid(), "addAutomaticZenRule");
|
||||
|
||||
return mZenModeHelper.addAutomaticZenRule(pkg, automaticZenRule,
|
||||
// If the caller is system, take the package name from the rule's owner rather than
|
||||
// from the caller's package.
|
||||
String rulePkg = pkg;
|
||||
if (isCallingUidSystem()) {
|
||||
if (automaticZenRule.getOwner() != null) {
|
||||
rulePkg = automaticZenRule.getOwner().getPackageName();
|
||||
}
|
||||
}
|
||||
|
||||
return mZenModeHelper.addAutomaticZenRule(rulePkg, automaticZenRule,
|
||||
"addAutomaticZenRule");
|
||||
}
|
||||
|
||||
@@ -7850,7 +7859,8 @@ public class NotificationManagerService extends SystemService {
|
||||
&& (record.getSuppressedVisualEffects() & SUPPRESSED_EFFECT_STATUS_BAR) != 0;
|
||||
if (!record.isUpdate
|
||||
&& record.getImportance() > IMPORTANCE_MIN
|
||||
&& !suppressedByDnd) {
|
||||
&& !suppressedByDnd
|
||||
&& isNotificationForCurrentUser(record)) {
|
||||
sendAccessibilityEvent(record);
|
||||
sentAccessibilityEvent = true;
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ public class ZenModeHelper {
|
||||
|
||||
public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
|
||||
String reason) {
|
||||
if (!isSystemRule(automaticZenRule)) {
|
||||
if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) {
|
||||
PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
|
||||
if (component == null) {
|
||||
component = getActivityInfo(automaticZenRule.getConfigurationActivity());
|
||||
@@ -570,11 +570,6 @@ public class ZenModeHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSystemRule(AutomaticZenRule rule) {
|
||||
return rule.getOwner() != null
|
||||
&& ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
|
||||
}
|
||||
|
||||
private ServiceInfo getServiceInfo(ComponentName owner) {
|
||||
Intent queryIntent = new Intent();
|
||||
queryIntent.setComponent(owner);
|
||||
|
||||
@@ -2664,7 +2664,6 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
|
||||
final Permission bp = mRegistry.getPermission(permName);
|
||||
final boolean appSupportsRuntimePermissions =
|
||||
pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
|
||||
String legacyActivityRecognitionPermission = null;
|
||||
|
||||
if (DEBUG_INSTALL && bp != null) {
|
||||
Log.i(TAG, "Package " + friendlyName
|
||||
@@ -2688,47 +2687,12 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
|
||||
// Cache newImplicitPermissions before modifing permissionsState as for the
|
||||
// shared uids the original and new state are the same object
|
||||
if (!origState.hasPermissionState(permName)
|
||||
&& (pkg.getImplicitPermissions().contains(permName)
|
||||
|| (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) {
|
||||
if (pkg.getImplicitPermissions().contains(permName)) {
|
||||
&& (pkg.getImplicitPermissions().contains(permName))) {
|
||||
// If permName is an implicit permission, try to auto-grant
|
||||
newImplicitPermissions.add(permName);
|
||||
|
||||
if (DEBUG_PERMISSIONS) {
|
||||
Slog.i(TAG, permName + " is newly added for " + friendlyName);
|
||||
}
|
||||
} else {
|
||||
// Special case for Activity Recognition permission. Even if AR
|
||||
// permission is not an implicit permission we want to add it to the
|
||||
// list (try to auto-grant it) if the app was installed on a device
|
||||
// before AR permission was split, regardless of if the app now requests
|
||||
// the new AR permission or has updated its target SDK and AR is no
|
||||
// longer implicit to it. This is a compatibility workaround for apps
|
||||
// when AR permission was split in Q.
|
||||
// TODO(zhanghai): This calls into SystemConfig, which generally
|
||||
// shouldn't cause deadlock, but maybe we should keep a cache of the
|
||||
// split permission list and just eliminate the possibility.
|
||||
final List<PermissionManager.SplitPermissionInfo> permissionList =
|
||||
getSplitPermissionInfos();
|
||||
int numSplitPerms = permissionList.size();
|
||||
for (int splitPermNum = 0; splitPermNum < numSplitPerms;
|
||||
splitPermNum++) {
|
||||
PermissionManager.SplitPermissionInfo sp = permissionList.get(
|
||||
splitPermNum);
|
||||
String splitPermName = sp.getSplitPermission();
|
||||
if (sp.getNewPermissions().contains(permName)
|
||||
&& origState.isPermissionGranted(splitPermName)) {
|
||||
legacyActivityRecognitionPermission = splitPermName;
|
||||
newImplicitPermissions.add(permName);
|
||||
|
||||
if (DEBUG_PERMISSIONS) {
|
||||
Slog.i(TAG, permName + " is newly added for "
|
||||
+ friendlyName);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(b/140256621): The package instant app method has been removed
|
||||
@@ -2862,8 +2826,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
|
||||
// Hard restricted permissions cannot be held.
|
||||
} else if (!permissionPolicyInitialized
|
||||
|| (!hardRestricted || restrictionExempt)) {
|
||||
if ((origPermState != null && origPermState.isGranted())
|
||||
|| legacyActivityRecognitionPermission != null) {
|
||||
if ((origPermState != null && origPermState.isGranted())) {
|
||||
if (!uidState.grantPermission(bp)) {
|
||||
wasChanged = true;
|
||||
}
|
||||
|
||||
@@ -5458,7 +5458,23 @@ class Task extends TaskFragment {
|
||||
parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
|
||||
parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
|
||||
(destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
|
||||
parent.deliverNewIntentLocked(callingUid, destIntent, destGrants, srec.packageName);
|
||||
boolean abort;
|
||||
try {
|
||||
abort = !mTaskSupervisor.checkStartAnyActivityPermission(destIntent,
|
||||
parent.info, null /* resultWho */, -1 /* requestCode */, srec.getPid(),
|
||||
callingUid, srec.info.packageName, null /* callingFeatureId */,
|
||||
false /* ignoreTargetSecurity */, false /* launchingInTask */, srec.app,
|
||||
null /* resultRecord */, null /* resultRootTask */);
|
||||
} catch (SecurityException e) {
|
||||
abort = true;
|
||||
}
|
||||
if (abort) {
|
||||
android.util.EventLog.writeEvent(0x534e4554, "238605611", callingUid, "");
|
||||
foundParentInTask = false;
|
||||
} else {
|
||||
parent.deliverNewIntentLocked(callingUid, destIntent, destGrants,
|
||||
srec.packageName);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
|
||||
|
||||
@@ -1300,6 +1300,21 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
|
||||
verify(mAccessibilityService, times(1)).sendAccessibilityEvent(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testA11yCrossUserEventNotSent() throws Exception {
|
||||
final Notification n = new Builder(getContext(), "test")
|
||||
.setSmallIcon(android.R.drawable.sym_def_app_icon).build();
|
||||
int userId = mUser.getIdentifier() + 1;
|
||||
StatusBarNotification sbn = new StatusBarNotification(mPkg, mPkg, 0, mTag, mUid,
|
||||
mPid, n, UserHandle.of(userId), null, System.currentTimeMillis());
|
||||
NotificationRecord r = new NotificationRecord(getContext(), sbn,
|
||||
new NotificationChannel("test", "test", IMPORTANCE_HIGH));
|
||||
|
||||
mService.buzzBeepBlinkLocked(r);
|
||||
|
||||
verify(mAccessibilityService, never()).sendAccessibilityEvent(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLightsScreenOn() {
|
||||
mService.mScreenOn = true;
|
||||
|
||||
@@ -7508,6 +7508,43 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
||||
mBinderService.addAutomaticZenRule(rule, mContext.getPackageName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAutomaticZenRule_systemCallTakesPackageFromOwner() throws Exception {
|
||||
mService.isSystemUid = true;
|
||||
ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
|
||||
when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
|
||||
.thenReturn(true);
|
||||
mService.setZenHelper(mockZenModeHelper);
|
||||
ComponentName owner = new ComponentName("android", "ProviderName");
|
||||
ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
|
||||
boolean isEnabled = true;
|
||||
AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
|
||||
zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
|
||||
mBinderService.addAutomaticZenRule(rule, "com.android.settings");
|
||||
|
||||
// verify that zen mode helper gets passed in a package name of "android"
|
||||
verify(mockZenModeHelper).addAutomaticZenRule(eq("android"), eq(rule), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAutomaticZenRule_nonSystemCallTakesPackageFromArg() throws Exception {
|
||||
mService.isSystemUid = false;
|
||||
ZenModeHelper mockZenModeHelper = mock(ZenModeHelper.class);
|
||||
when(mConditionProviders.isPackageOrComponentAllowed(anyString(), anyInt()))
|
||||
.thenReturn(true);
|
||||
mService.setZenHelper(mockZenModeHelper);
|
||||
ComponentName owner = new ComponentName("android", "ProviderName");
|
||||
ZenPolicy zenPolicy = new ZenPolicy.Builder().allowAlarms(true).build();
|
||||
boolean isEnabled = true;
|
||||
AutomaticZenRule rule = new AutomaticZenRule("test", owner, owner, mock(Uri.class),
|
||||
zenPolicy, NotificationManager.INTERRUPTION_FILTER_PRIORITY, isEnabled);
|
||||
mBinderService.addAutomaticZenRule(rule, "another.package");
|
||||
|
||||
// verify that zen mode helper gets passed in the package name from the arg, not the owner
|
||||
verify(mockZenModeHelper).addAutomaticZenRule(
|
||||
eq("another.package"), eq(rule), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAreNotificationsEnabledForPackage() throws Exception {
|
||||
mBinderService.areNotificationsEnabledForPackage(mContext.getPackageName(),
|
||||
|
||||
@@ -1671,6 +1671,36 @@ public class ZenModeHelperTest extends UiServiceTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAutomaticZenRule_claimedSystemOwner() {
|
||||
// Make sure anything that claims to have a "system" owner but not actually part of the
|
||||
// system package still gets limited on number of rules
|
||||
for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
|
||||
ScheduleInfo si = new ScheduleInfo();
|
||||
si.startHour = i;
|
||||
AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
|
||||
new ComponentName("android", "ScheduleConditionProvider" + i),
|
||||
null, // configuration activity
|
||||
ZenModeConfig.toScheduleConditionId(si),
|
||||
new ZenPolicy.Builder().build(),
|
||||
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
|
||||
String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
|
||||
assertNotNull(id);
|
||||
}
|
||||
try {
|
||||
AutomaticZenRule zenRule = new AutomaticZenRule("name",
|
||||
new ComponentName("android", "ScheduleConditionProviderFinal"),
|
||||
null, // configuration activity
|
||||
ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
|
||||
new ZenPolicy.Builder().build(),
|
||||
NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
|
||||
String id = mZenModeHelperSpy.addAutomaticZenRule("pkgname", zenRule, "test");
|
||||
fail("allowed too many rules to be created");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// yay
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAddAutomaticZenRule_CA() {
|
||||
AutomaticZenRule zenRule = new AutomaticZenRule("name",
|
||||
|
||||
@@ -1269,7 +1269,7 @@ public class TelecomManager {
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getPhoneAccountsSupportingScheme(uriScheme,
|
||||
mContext.getOpPackageName());
|
||||
mContext.getOpPackageName()).getList();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsSupportingScheme", e);
|
||||
}
|
||||
@@ -1312,7 +1312,7 @@ public class TelecomManager {
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getSelfManagedPhoneAccounts(mContext.getOpPackageName(),
|
||||
mContext.getAttributionTag());
|
||||
mContext.getAttributionTag()).getList();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error calling ITelecomService#getSelfManagedPhoneAccounts()", e);
|
||||
}
|
||||
@@ -1340,7 +1340,7 @@ public class TelecomManager {
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getOwnSelfManagedPhoneAccounts(mContext.getOpPackageName(),
|
||||
mContext.getAttributionTag());
|
||||
mContext.getAttributionTag()).getList();
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -1366,7 +1366,7 @@ public class TelecomManager {
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getCallCapablePhoneAccounts(includeDisabledAccounts,
|
||||
mContext.getOpPackageName(), mContext.getAttributionTag());
|
||||
mContext.getOpPackageName(), mContext.getAttributionTag()).getList();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error calling ITelecomService#getCallCapablePhoneAccounts("
|
||||
+ includeDisabledAccounts + ")", e);
|
||||
@@ -1390,7 +1390,7 @@ public class TelecomManager {
|
||||
ITelecomService service = getTelecomService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getPhoneAccountsForPackage(mContext.getPackageName());
|
||||
return service.getPhoneAccountsForPackage(mContext.getPackageName()).getList();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error calling ITelecomService#getPhoneAccountsForPackage", e);
|
||||
}
|
||||
@@ -1450,7 +1450,7 @@ public class TelecomManager {
|
||||
ITelecomService service = getTelecomService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getAllPhoneAccounts();
|
||||
return service.getAllPhoneAccounts().getList();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error calling ITelecomService#getAllPhoneAccounts", e);
|
||||
}
|
||||
@@ -1469,7 +1469,7 @@ public class TelecomManager {
|
||||
ITelecomService service = getTelecomService();
|
||||
if (service != null) {
|
||||
try {
|
||||
return service.getAllPhoneAccountHandles();
|
||||
return service.getAllPhoneAccountHandles().getList();
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error calling ITelecomService#getAllPhoneAccountHandles", e);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.telecom.PhoneAccount;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
|
||||
/**
|
||||
* Interface used to interact with Telecom. Mostly this is used by TelephonyManager for passing
|
||||
@@ -57,31 +58,31 @@ interface ITelecomService {
|
||||
/**
|
||||
* @see TelecomServiceImpl#getCallCapablePhoneAccounts
|
||||
*/
|
||||
List<PhoneAccountHandle> getCallCapablePhoneAccounts(
|
||||
ParceledListSlice<PhoneAccountHandle> getCallCapablePhoneAccounts(
|
||||
boolean includeDisabledAccounts, String callingPackage, String callingFeatureId);
|
||||
|
||||
/**
|
||||
* @see TelecomServiceImpl#getSelfManagedPhoneAccounts
|
||||
*/
|
||||
List<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage,
|
||||
ParceledListSlice<PhoneAccountHandle> getSelfManagedPhoneAccounts(String callingPackage,
|
||||
String callingFeatureId);
|
||||
|
||||
/**
|
||||
* @see TelecomServiceImpl#getOwnSelfManagedPhoneAccounts
|
||||
*/
|
||||
List<PhoneAccountHandle> getOwnSelfManagedPhoneAccounts(String callingPackage,
|
||||
ParceledListSlice<PhoneAccountHandle> getOwnSelfManagedPhoneAccounts(String callingPackage,
|
||||
String callingFeatureId);
|
||||
|
||||
/**
|
||||
* @see TelecomManager#getPhoneAccountsSupportingScheme
|
||||
*/
|
||||
List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
|
||||
ParceledListSlice<PhoneAccountHandle> getPhoneAccountsSupportingScheme(in String uriScheme,
|
||||
String callingPackage);
|
||||
|
||||
/**
|
||||
* @see TelecomManager#getPhoneAccountsForPackage
|
||||
*/
|
||||
List<PhoneAccountHandle> getPhoneAccountsForPackage(in String packageName);
|
||||
ParceledListSlice<PhoneAccountHandle> getPhoneAccountsForPackage(in String packageName);
|
||||
|
||||
/**
|
||||
* @see TelecomManager#getPhoneAccount
|
||||
@@ -96,12 +97,12 @@ interface ITelecomService {
|
||||
/**
|
||||
* @see TelecomManager#getAllPhoneAccounts
|
||||
*/
|
||||
List<PhoneAccount> getAllPhoneAccounts();
|
||||
ParceledListSlice<PhoneAccount> getAllPhoneAccounts();
|
||||
|
||||
/**
|
||||
* @see TelecomManager#getAllPhoneAccountHandles
|
||||
*/
|
||||
List<PhoneAccountHandle> getAllPhoneAccountHandles();
|
||||
ParceledListSlice<PhoneAccountHandle> getAllPhoneAccountHandles();
|
||||
|
||||
/**
|
||||
* @see TelecomServiceImpl#getSimCallManager
|
||||
|
||||
Reference in New Issue
Block a user