Merge "Merge rvc-release RP1A.201105.002 to stage-aosp-master - DO NOT MERGE" into stage-aosp-master
This commit is contained in:
@@ -207,7 +207,7 @@ public class Notification implements Parcelable
|
||||
* <p>
|
||||
* Avoids spamming the system with overly large strings such as full e-mails.
|
||||
*/
|
||||
private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024;
|
||||
private static final int MAX_CHARSEQUENCE_LENGTH = 1024;
|
||||
|
||||
/**
|
||||
* Maximum entries of reply text that are accepted by Builder and friends.
|
||||
@@ -7830,7 +7830,7 @@ public class Notification implements Parcelable
|
||||
*/
|
||||
public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender,
|
||||
boolean remoteInputHistory) {
|
||||
mText = text;
|
||||
mText = safeCharSequence(text);
|
||||
mTimestamp = timestamp;
|
||||
mSender = sender;
|
||||
mRemoteInputHistory = remoteInputHistory;
|
||||
@@ -7944,7 +7944,7 @@ public class Notification implements Parcelable
|
||||
bundle.putLong(KEY_TIMESTAMP, mTimestamp);
|
||||
if (mSender != null) {
|
||||
// Legacy listeners need this
|
||||
bundle.putCharSequence(KEY_SENDER, mSender.getName());
|
||||
bundle.putCharSequence(KEY_SENDER, safeCharSequence(mSender.getName()));
|
||||
bundle.putParcelable(KEY_SENDER_PERSON, mSender);
|
||||
}
|
||||
if (mDataMimeType != null) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.icu.util.ULocale;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -151,18 +152,18 @@ public final class LocaleList implements Parcelable {
|
||||
/**
|
||||
* Creates a new {@link LocaleList}.
|
||||
*
|
||||
* If two or more same locales are passed, the repeated locales will be dropped.
|
||||
* <p>For empty lists of {@link Locale} items it is better to use {@link #getEmptyLocaleList()},
|
||||
* which returns a pre-constructed empty list.</p>
|
||||
*
|
||||
* @throws NullPointerException if any of the input locales is <code>null</code>.
|
||||
* @throws IllegalArgumentException if any of the input locales repeat.
|
||||
*/
|
||||
public LocaleList(@NonNull Locale... list) {
|
||||
if (list.length == 0) {
|
||||
mList = sEmptyList;
|
||||
mStringRepresentation = "";
|
||||
} else {
|
||||
final Locale[] localeList = new Locale[list.length];
|
||||
final ArrayList<Locale> localeList = new ArrayList<>();
|
||||
final HashSet<Locale> seenLocales = new HashSet<Locale>();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
@@ -170,10 +171,10 @@ public final class LocaleList implements Parcelable {
|
||||
if (l == null) {
|
||||
throw new NullPointerException("list[" + i + "] is null");
|
||||
} else if (seenLocales.contains(l)) {
|
||||
throw new IllegalArgumentException("list[" + i + "] is a repetition");
|
||||
// Dropping duplicated locale entries.
|
||||
} else {
|
||||
final Locale localeClone = (Locale) l.clone();
|
||||
localeList[i] = localeClone;
|
||||
localeList.add(localeClone);
|
||||
sb.append(localeClone.toLanguageTag());
|
||||
if (i < list.length - 1) {
|
||||
sb.append(',');
|
||||
@@ -181,7 +182,7 @@ public final class LocaleList implements Parcelable {
|
||||
seenLocales.add(localeClone);
|
||||
}
|
||||
}
|
||||
mList = localeList;
|
||||
mList = localeList.toArray(new Locale[localeList.size()]);
|
||||
mStringRepresentation = sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1134,15 +1134,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
if (invokeCallback) {
|
||||
control.cancel();
|
||||
}
|
||||
boolean stateChanged = false;
|
||||
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
|
||||
RunningAnimation runningAnimation = mRunningAnimations.get(i);
|
||||
if (runningAnimation.runner == control) {
|
||||
mRunningAnimations.remove(i);
|
||||
ArraySet<Integer> types = toInternalType(control.getTypes());
|
||||
for (int j = types.size() - 1; j >= 0; j--) {
|
||||
if (getSourceConsumer(types.valueAt(j)).notifyAnimationFinished()) {
|
||||
mHost.notifyInsetsChanged();
|
||||
}
|
||||
stateChanged |= getSourceConsumer(types.valueAt(j)).notifyAnimationFinished();
|
||||
}
|
||||
if (invokeCallback && runningAnimation.startDispatched) {
|
||||
dispatchAnimationEnd(runningAnimation.runner.getAnimation());
|
||||
@@ -1150,6 +1149,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stateChanged) {
|
||||
mHost.notifyInsetsChanged();
|
||||
updateRequestedState();
|
||||
}
|
||||
}
|
||||
|
||||
private void applyLocalVisibilityOverride() {
|
||||
|
||||
@@ -2792,6 +2792,7 @@
|
||||
<item>power</item>
|
||||
<item>restart</item>
|
||||
<item>logout</item>
|
||||
<item>screenshot</item>
|
||||
<item>bugreport</item>
|
||||
</string-array>
|
||||
|
||||
@@ -3506,6 +3507,7 @@
|
||||
mode -->
|
||||
<string-array translatable="false" name="config_priorityOnlyDndExemptPackages">
|
||||
<item>com.android.dialer</item>
|
||||
<item>com.android.server.telecom</item>
|
||||
<item>com.android.systemui</item>
|
||||
<item>android</item>
|
||||
</string-array>
|
||||
|
||||
@@ -27,6 +27,7 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||
import static android.view.ViewRootImpl.NEW_INSETS_MODE_FULL;
|
||||
import static android.view.WindowInsets.Type.ime;
|
||||
import static android.view.WindowInsets.Type.navigationBars;
|
||||
import static android.view.WindowInsets.Type.statusBars;
|
||||
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
|
||||
@@ -742,6 +743,20 @@ public class InsetsControllerTest {
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_IME));
|
||||
assertEquals(newState.getSource(ITYPE_IME),
|
||||
mTestHost.getModifiedState().peekSource(ITYPE_IME));
|
||||
|
||||
// The modified frames cannot be updated if there is an animation.
|
||||
mController.onControlsChanged(createSingletonControl(ITYPE_NAVIGATION_BAR));
|
||||
mController.hide(navigationBars());
|
||||
newState = new InsetsState(mController.getState(), true /* copySource */);
|
||||
newState.getSource(ITYPE_NAVIGATION_BAR).getFrame().top--;
|
||||
mController.onStateChanged(newState);
|
||||
assertNotEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
|
||||
mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
|
||||
|
||||
// The modified frames can be updated while the animation is done.
|
||||
mController.cancelExistingAnimations();
|
||||
assertEquals(newState.getSource(ITYPE_NAVIGATION_BAR),
|
||||
mTestHost.getModifiedState().peekSource(ITYPE_NAVIGATION_BAR));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS;
|
||||
import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
|
||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
|
||||
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
|
||||
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
|
||||
@@ -547,7 +548,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return action.shouldShow();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -962,6 +963,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
|
||||
@VisibleForTesting
|
||||
class ScreenshotAction extends SinglePressAction implements LongPressAction {
|
||||
final String KEY_SYSTEM_NAV_2BUTTONS = "system_nav_2buttons";
|
||||
|
||||
public ScreenshotAction() {
|
||||
super(R.drawable.ic_screenshot, R.string.global_action_screenshot);
|
||||
}
|
||||
@@ -993,6 +996,19 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldShow() {
|
||||
// Include screenshot in power menu for legacy nav because it is not accessible
|
||||
// through Recents in that mode
|
||||
return is2ButtonNavigationEnabled();
|
||||
}
|
||||
|
||||
boolean is2ButtonNavigationEnabled() {
|
||||
return NAV_BAR_MODE_2BUTTON == mContext.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onLongPress() {
|
||||
if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SCREENRECORD_LONG_PRESS)) {
|
||||
@@ -1616,6 +1632,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
|
||||
* @return
|
||||
*/
|
||||
CharSequence getMessage();
|
||||
|
||||
default boolean shouldShow() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,6 +49,7 @@ import android.testing.TestableLooper;
|
||||
import android.util.FeatureFlagUtils;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.View;
|
||||
import android.view.WindowManagerPolicyConstants;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -241,6 +242,28 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
|
||||
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SCREENSHOT_LONG_PRESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldShowScreenshot() {
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode,
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON);
|
||||
|
||||
GlobalActionsDialog.ScreenshotAction screenshotAction =
|
||||
mGlobalActionsDialog.makeScreenshotActionForTesting();
|
||||
assertThat(screenshotAction.shouldShow()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShouldNotShowScreenshot() {
|
||||
mContext.getOrCreateTestableResources().addOverride(
|
||||
com.android.internal.R.integer.config_navBarInteractionMode,
|
||||
WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON);
|
||||
|
||||
GlobalActionsDialog.ScreenshotAction screenshotAction =
|
||||
mGlobalActionsDialog.makeScreenshotActionForTesting();
|
||||
assertThat(screenshotAction.shouldShow()).isFalse();
|
||||
}
|
||||
|
||||
private void verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent event) {
|
||||
mTestableLooper.processAllMessages();
|
||||
verify(mUiEventLogger, times(1))
|
||||
|
||||
@@ -4206,13 +4206,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
Iterator<ResolveInfo> iter = matches.iterator();
|
||||
while (iter.hasNext()) {
|
||||
final ResolveInfo rInfo = iter.next();
|
||||
final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName);
|
||||
if (ps != null) {
|
||||
final PermissionsState permissionsState = ps.getPermissionsState();
|
||||
if (permissionsState.hasPermission(Manifest.permission.INSTALL_PACKAGES, 0)
|
||||
|| Build.IS_ENG) {
|
||||
continue;
|
||||
}
|
||||
if (checkPermission(Manifest.permission.INSTALL_PACKAGES,
|
||||
rInfo.activityInfo.packageName, 0) == PERMISSION_GRANTED || Build.IS_ENG) {
|
||||
continue;
|
||||
}
|
||||
iter.remove();
|
||||
}
|
||||
@@ -4388,8 +4384,24 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final int[] gids = (flags & PackageManager.GET_GIDS) == 0
|
||||
? EMPTY_INT_ARRAY : permissionsState.computeGids(userId);
|
||||
// Compute granted permissions only if package has requested permissions
|
||||
final Set<String> permissions = ArrayUtils.isEmpty(p.getRequestedPermissions())
|
||||
Set<String> permissions = ArrayUtils.isEmpty(p.getRequestedPermissions())
|
||||
? Collections.emptySet() : permissionsState.getPermissions(userId);
|
||||
if (state.instantApp) {
|
||||
permissions = new ArraySet<>(permissions);
|
||||
permissions.removeIf(permissionName -> {
|
||||
BasePermission permission = mPermissionManager.getPermissionTEMP(
|
||||
permissionName);
|
||||
if (permission == null) {
|
||||
return true;
|
||||
}
|
||||
if (!permission.isInstant()) {
|
||||
EventLog.writeEvent(0x534e4554, "140256621", UserHandle.getUid(userId,
|
||||
ps.appId), permissionName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags,
|
||||
ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId, ps);
|
||||
@@ -8587,10 +8599,9 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
|
||||
String[] permissions, boolean[] tmp, int flags, int userId) {
|
||||
int numMatch = 0;
|
||||
final PermissionsState permissionsState = ps.getPermissionsState();
|
||||
for (int i=0; i<permissions.length; i++) {
|
||||
final String permission = permissions[i];
|
||||
if (permissionsState.hasPermission(permission, userId)) {
|
||||
if (checkPermission(permission, ps.name, userId) == PERMISSION_GRANTED) {
|
||||
tmp[i] = true;
|
||||
numMatch++;
|
||||
} else {
|
||||
@@ -19199,6 +19210,14 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
final int flags = action.flags;
|
||||
final boolean systemApp = isSystemApp(ps);
|
||||
|
||||
// We need to get the permission state before package state is (potentially) destroyed.
|
||||
final SparseBooleanArray hadSuspendAppsPermission = new SparseBooleanArray();
|
||||
// allUserHandles could be null, so call mUserManager.getUserIds() directly which is cached anyway.
|
||||
for (int userId : mUserManager.getUserIds()) {
|
||||
hadSuspendAppsPermission.put(userId, checkPermission(Manifest.permission.SUSPEND_APPS,
|
||||
packageName, userId) == PERMISSION_GRANTED);
|
||||
}
|
||||
|
||||
final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
|
||||
|
||||
if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
|
||||
@@ -19265,8 +19284,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
affectedUserIds = resolveUserIds(userId);
|
||||
}
|
||||
for (final int affectedUserId : affectedUserIds) {
|
||||
if (ps.getPermissionsState().hasPermission(Manifest.permission.SUSPEND_APPS,
|
||||
affectedUserId)) {
|
||||
if (hadSuspendAppsPermission.get(affectedUserId)) {
|
||||
unsuspendForSuspendingPackage(packageName, affectedUserId);
|
||||
removeAllDistractingPackageRestrictions(affectedUserId);
|
||||
}
|
||||
@@ -21036,8 +21054,8 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
pkgSetting.setEnabled(newState, userId, callingPackage);
|
||||
if ((newState == COMPONENT_ENABLED_STATE_DISABLED_USER
|
||||
|| newState == COMPONENT_ENABLED_STATE_DISABLED)
|
||||
&& pkgSetting.getPermissionsState().hasPermission(
|
||||
Manifest.permission.SUSPEND_APPS, userId)) {
|
||||
&& checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId)
|
||||
== PERMISSION_GRANTED) {
|
||||
// This app should not generally be allowed to get disabled by the UI, but if it
|
||||
// ever does, we don't want to end up with some of the user's apps permanently
|
||||
// suspended.
|
||||
|
||||
@@ -4578,15 +4578,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the activity is on a sleeping display, and if it can turn it ON.
|
||||
if (getDisplay().isSleeping()) {
|
||||
final boolean canTurnScreenOn = !mSetToSleep || canTurnScreenOn()
|
||||
|| canShowWhenLocked() || containsDismissKeyguardWindow();
|
||||
if (!canTurnScreenOn) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now check whether it's really visible depending on Keyguard state, and update
|
||||
// {@link ActivityStack} internal states.
|
||||
// Inform the method if this activity is the top activity of this stack, but exclude the
|
||||
@@ -4597,6 +4588,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|
||||
final boolean visibleIgnoringDisplayStatus = stack.checkKeyguardVisibility(this,
|
||||
visibleIgnoringKeyguard, isTop && isTopNotPinnedStack);
|
||||
|
||||
// Check if the activity is on a sleeping display, and if it can turn it ON.
|
||||
// TODO(b/163993448): Do not make activity visible before display awake.
|
||||
if (visibleIgnoringDisplayStatus && getDisplay().isSleeping()) {
|
||||
return !mSetToSleep || canTurnScreenOn();
|
||||
}
|
||||
|
||||
return visibleIgnoringDisplayStatus;
|
||||
}
|
||||
|
||||
|
||||
@@ -1704,8 +1704,9 @@ class ActivityStack extends Task {
|
||||
// If the most recent activity was noHistory but was only stopped rather
|
||||
// than stopped+finished because the device went to sleep, we need to make
|
||||
// sure to finish it as we're making a new activity topmost.
|
||||
if (shouldSleepActivities() && mLastNoHistoryActivity != null &&
|
||||
!mLastNoHistoryActivity.finishing) {
|
||||
if (shouldSleepActivities() && mLastNoHistoryActivity != null
|
||||
&& !mLastNoHistoryActivity.finishing
|
||||
&& mLastNoHistoryActivity != next) {
|
||||
if (DEBUG_STATES) Slog.d(TAG_STATES,
|
||||
"no-history finish of " + mLastNoHistoryActivity + " on new resume");
|
||||
mLastNoHistoryActivity.finishIfPossible("resume-no-history", false /* oomAdj */);
|
||||
|
||||
@@ -1481,9 +1481,10 @@ class ActivityStarter {
|
||||
// anyone interested in this piece of information.
|
||||
final ActivityStack homeStack = targetTask.getDisplayArea().getRootHomeTask();
|
||||
final boolean homeTaskVisible = homeStack != null && homeStack.shouldBeVisible(null);
|
||||
final ActivityRecord top = targetTask.getTopNonFinishingActivity();
|
||||
final boolean visible = top != null && top.isVisible();
|
||||
mService.getTaskChangeNotificationController().notifyActivityRestartAttempt(
|
||||
targetTask.getTaskInfo(), homeTaskVisible, clearedTask,
|
||||
targetTask.getTopNonFinishingActivity().isVisible());
|
||||
targetTask.getTaskInfo(), homeTaskVisible, clearedTask, visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1099,6 +1099,34 @@ public class ActivityRecordTests extends ActivityTestsBase {
|
||||
verify(topActivity).destroyIfPossible(anyString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the visibility of a show-when-locked and dismiss keyguard activity on sleeping
|
||||
* display.
|
||||
*/
|
||||
@Test
|
||||
public void testDisplaySleeping_activityInvisible() {
|
||||
final KeyguardController keyguardController =
|
||||
mActivity.mStackSupervisor.getKeyguardController();
|
||||
doReturn(true).when(keyguardController).isKeyguardLocked();
|
||||
final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
|
||||
topActivity.mVisibleRequested = true;
|
||||
topActivity.nowVisible = true;
|
||||
topActivity.setState(RESUMED, "test" /*reason*/);
|
||||
doReturn(true).when(topActivity).containsDismissKeyguardWindow();
|
||||
doCallRealMethod().when(mRootWindowContainer).ensureActivitiesVisible(
|
||||
any() /* starting */, anyInt() /* configChanges */,
|
||||
anyBoolean() /* preserveWindows */, anyBoolean() /* notifyClients */);
|
||||
topActivity.setShowWhenLocked(true);
|
||||
|
||||
// Verify the top activity is occluded keyguard.
|
||||
assertEquals(topActivity, mStack.topRunningActivity());
|
||||
assertTrue(mStack.topActivityOccludesKeyguard());
|
||||
|
||||
final DisplayContent display = mActivity.mDisplayContent;
|
||||
doReturn(true).when(display).isSleeping();
|
||||
assertFalse(topActivity.shouldBeVisible());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that complete finish request for a show-when-locked activity must ensure the
|
||||
* keyguard occluded state being updated.
|
||||
|
||||
Reference in New Issue
Block a user