Merge "Merge TP1A.221105.002 to aosp-master - DO NOT MERGE"

This commit is contained in:
Bill Yi
2022-11-09 22:54:28 +00:00
committed by Gerrit Code Review
26 changed files with 504 additions and 109 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}

View 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());
}
}

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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

View File

@@ -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);

View File

@@ -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.

View File

@@ -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();

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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();
}
}

View File

@@ -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());
}
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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(

View File

@@ -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;

View File

@@ -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(),

View File

@@ -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",

View File

@@ -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);
}

View File

@@ -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