diff options
35 files changed, 393 insertions, 145 deletions
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl index f72288c670d9..9a7a949e3cd2 100644 --- a/core/java/android/content/pm/IPackageInstallerSession.aidl +++ b/core/java/android/content/pm/IPackageInstallerSession.aidl @@ -55,4 +55,5 @@ interface IPackageInstallerSession { int getParentSessionId(); boolean isStaged(); + int getInstallFlags(); } diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index 3f8aedb31ea9..4030708d6a53 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -1432,6 +1432,18 @@ public class PackageInstaller { } /** + * @return Session's {@link SessionParams#installFlags}. + * @hide + */ + public int getInstallFlags() { + try { + return mSession.getInstallFlags(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * @return the session ID of the multi-package session that this belongs to or * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session. */ diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl index 539fd4adb0a0..e1ccc4fb740b 100644 --- a/core/java/android/nfc/INfcTag.aidl +++ b/core/java/android/nfc/INfcTag.aidl @@ -45,4 +45,7 @@ interface INfcTag boolean canMakeReadOnly(int ndefType); int getMaxTransceiveLength(int technology); boolean getExtendedLengthApdusSupported(); + + void setTagUpToDate(long cookie); + boolean isTagUpToDate(long cookie); } diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java index 398ec63a931b..731d1ba78299 100644 --- a/core/java/android/nfc/Tag.java +++ b/core/java/android/nfc/Tag.java @@ -34,6 +34,7 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; +import android.os.SystemClock; import java.io.IOException; import java.util.Arrays; @@ -121,6 +122,7 @@ public final class Tag implements Parcelable { final INfcTag mTagService; // interface to NFC service, will be null if mock tag int mConnectedTechnology; + long mCookie; /** * Hidden constructor to be used by NFC service and internal classes. @@ -140,6 +142,17 @@ public final class Tag implements Parcelable { mTagService = tagService; mConnectedTechnology = -1; + mCookie = SystemClock.elapsedRealtime(); + + if (tagService == null) { + return; + } + + try { + tagService.setTagUpToDate(mCookie); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } } /** @@ -361,6 +374,22 @@ public final class Tag implements Parcelable { /** @hide */ @UnsupportedAppUsage public INfcTag getTagService() { + if (mTagService == null) { + return null; + } + + try { + if (!mTagService.isTagUpToDate(mCookie)) { + String id_str = ""; + for (int i = 0; i < mId.length; i++) { + id_str = id_str + String.format("%02X ", mId[i]); + } + String msg = "Permission Denial: Tag ( ID: " + id_str + ") is out of date"; + throw new SecurityException(msg); + } + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } return mTagService; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f1eb783726db..0b19f4f44653 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3390,6 +3390,12 @@ public final class ViewRootImpl implements ViewParent, mReportNextDraw = false; pendingDrawFinished(); } + + // Make sure the consumer is not waiting if the view root was just made invisible. + if (mBLASTDrawConsumer != null) { + mBLASTDrawConsumer.accept(null); + mBLASTDrawConsumer = null; + } } } diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index 037359946393..fcfa7d751a91 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -1344,7 +1344,7 @@ <string name="sms_short_code_confirm_deny" msgid="1356917469323768230">"Cancel"</string> <string name="sms_short_code_remember_choice" msgid="1374526438647744862">"Remember my choice"</string> <string name="sms_short_code_remember_undo_instruction" msgid="2620984439143080410">"You can change this later in Settings > Apps"</string> - <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"Always Allow*"</string> + <string name="sms_short_code_confirm_always_allow" msgid="2223014893129755950">"Always allow"</string> <string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"Never Allow"</string> <string name="sim_removed_title" msgid="5387212933992546283">"SIM card removed"</string> <string name="sim_removed_message" msgid="9051174064474904617">"The mobile network will be unavailable until you restart with a valid SIM card inserted."</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 4638307bab6f..51396e3c4694 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -2009,7 +2009,7 @@ <string name="demo_restarting_message" msgid="1160053183701746766">"Mereset perangkat..."</string> <string name="suspended_widget_accessibility" msgid="6331451091851326101">"<xliff:g id="LABEL">%1$s</xliff:g> dinonaktifkan"</string> <string name="conference_call" msgid="5731633152336490471">"Konferensi Telepon"</string> - <string name="tooltip_popup_title" msgid="7863719020269945722">"Keterangan alat"</string> + <string name="tooltip_popup_title" msgid="7863719020269945722">"Tooltip"</string> <string name="app_category_game" msgid="4534216074910244790">"Game"</string> <string name="app_category_audio" msgid="8296029904794676222">"Musik & Audio"</string> <string name="app_category_video" msgid="2590183854839565814">"Film & Video"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 3602d2ddcb0b..b436409bcb59 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -389,7 +389,7 @@ <string name="permlab_systemAlertWindow" msgid="5757218350944719065">"Апликацијава може да се појави врз други апликации"</string> <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"Апликацијава може да се појави врз други апликации или делови од екранот. Тоа може да го попречи нормалното користење на апликацијата и да го смени начинот на кој се појавуваат другите апликации."</string> <string name="permlab_runInBackground" msgid="541863968571682785">"извршување во заднина"</string> - <string name="permdesc_runInBackground" msgid="4344539472115495141">"Апликацијава може да се извршува во заднина. Тоа може побрзо да ја троши батеријата."</string> + <string name="permdesc_runInBackground" msgid="4344539472115495141">"Апликацијава може да работи во заднина. Тоа може побрзо да ја троши батеријата."</string> <string name="permlab_useDataInBackground" msgid="783415807623038947">"користење мобилен интернет во заднина"</string> <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"Апликацијава може да користи мобилен интернет во заднина. Тоа може да го зголеми користењето мобилен интернет."</string> <string name="permlab_persistentActivity" msgid="464970041740567970">"направи апликацијата постојано да биде активна"</string> diff --git a/data/etc/car/com.android.carsystemui.xml b/data/etc/car/com.android.carsystemui.xml index a267d5650782..6c9103cb0f4f 100644 --- a/data/etc/car/com.android.carsystemui.xml +++ b/data/etc/car/com.android.carsystemui.xml @@ -24,5 +24,6 @@ <permission name="android.car.permission.CONTROL_CAR_CLIMATE"/> <permission name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"/> <permission name="android.car.permission.MONITOR_CAR_EVS_STATUS"/> + <permission name="android.car.permission.CONTROL_CAR_APP_LAUNCH"/> </privapp-permissions> </permissions> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 2c494c01fa4b..24edc1ce555c 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -693,7 +693,7 @@ <string name="instant_apps_message_with_help" msgid="1816952263531203932">"Sovellus avattiin ilman asennusta. Katso lisätietoja napauttamalla."</string> <string name="app_info" msgid="5153758994129963243">"Sovelluksen tiedot"</string> <string name="go_to_web" msgid="636673528981366511">"Siirry selaimeen"</string> - <string name="mobile_data" msgid="4564407557775397216">"Mobiilitiedonsiirto"</string> + <string name="mobile_data" msgid="4564407557775397216">"Mobiilidata"</string> <string name="mobile_data_text_format" msgid="6806501540022589786">"<xliff:g id="ID_1">%1$s</xliff:g> – <xliff:g id="ID_2">%2$s</xliff:g>"</string> <string name="mobile_carrier_text_format" msgid="8912204177152950766">"<xliff:g id="CARRIER_NAME">%1$s</xliff:g>, <xliff:g id="MOBILE_DATA_TYPE">%2$s</xliff:g>"</string> <string name="wifi_is_off" msgid="5389597396308001471">"Wi-Fi on pois päältä"</string> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index e1afd3fe6a30..4a7d7089d712 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -78,6 +78,18 @@ <!-- Checkbox label for USB device dialogs with warning text for USB device dialogs. [CHAR LIMIT=200]--> <string name="usb_device_permission_prompt_warn">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device.</string> + <!-- USB audio device permission dialog title. [CHAR LIMIT=200]--> + <string name="usb_audio_device_permission_prompt_title">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?</string> + + <!-- USB audio device confirm dialog title. [CHAR LIMIT=200]--> + <string name="usb_audio_device_confirm_prompt_title">Open <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to handle <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?</string> + + <!-- Checkbox label for USB audio device dialogs with warning text for USB audio device dialogs. [CHAR LIMIT=NONE]--> + <string name="usb_audio_device_prompt_warn">This app has not been granted record permission but could capture audio through this USB device. Using <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms.</string> + + <!-- Prompt for the USB audio device permission dialog [CHAR LIMIT=NONE] --> + <string name="usb_audio_device_prompt">Using <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms.</string> + <!-- Prompt for the USB accessory permission dialog [CHAR LIMIT=80] --> <string name="usb_accessory_permission_prompt">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_accessory" example="USB Dock">%2$s</xliff:g>?</string> diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index e9f288d51317..9b52746800a8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -112,6 +112,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.DozeParameters; @@ -324,6 +325,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, // the properties of the keyguard private final KeyguardUpdateMonitor mUpdateMonitor; + private final Lazy<NotificationShadeWindowController> mNotificationShadeWindowControllerLazy; /** * Last SIM state reported by the telephony system. @@ -846,7 +848,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, KeyguardStateController keyguardStateController, Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationControllerLazy, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, - Lazy<NotificationShadeDepthController> notificationShadeDepthController) { + Lazy<NotificationShadeDepthController> notificationShadeDepthController, + Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy) { super(context); mFalsingCollector = falsingCollector; mLockPatternUtils = lockPatternUtils; @@ -862,6 +865,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, mKeyguardDisplayManager = keyguardDisplayManager; dumpManager.registerDumpable(getClass().getName(), this); mDeviceConfig = deviceConfig; + mNotificationShadeWindowControllerLazy = notificationShadeWindowControllerLazy; mShowHomeOverLockscreen = mDeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN, @@ -1889,10 +1893,13 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, Trace.beginSection( "KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM"); StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj; - handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration, - params.mApps, params.mWallpapers, params.mNonApps, - params.mFinishedCallback); - mFalsingCollector.onSuccessfulUnlock(); + mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams( + () -> { + handleStartKeyguardExitAnimation(params.startTime, + params.fadeoutDuration, params.mApps, params.mWallpapers, + params.mNonApps, params.mFinishedCallback); + mFalsingCollector.onSuccessfulUnlock(); + }); Trace.endSection(); break; case CANCEL_KEYGUARD_EXIT_ANIM: @@ -2190,10 +2197,12 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, mKeyguardGoingAwayRunnable.run(); } else { // TODO(bc-unlock): Fill parameters - handleStartKeyguardExitAnimation( - SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(), - mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */, - null /* nonApps */, null /* finishedCallback */); + mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams(() -> { + handleStartKeyguardExitAnimation( + SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(), + mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */, + null /* nonApps */, null /* finishedCallback */); + }); } } Trace.endSection(); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index cae9feeb62eb..88dcf6d35075 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -42,6 +42,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardLiftController; @@ -97,7 +98,8 @@ public class KeyguardModule { KeyguardStateController keyguardStateController, Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, - Lazy<NotificationShadeDepthController> notificationShadeDepthController) { + Lazy<NotificationShadeDepthController> notificationShadeDepthController, + Lazy<NotificationShadeWindowController> notificationShadeWindowController) { return new KeyguardViewMediator( context, falsingCollector, @@ -120,7 +122,8 @@ public class KeyguardModule { keyguardStateController, keyguardUnlockAnimationController, unlockedScreenOffAnimationController, - notificationShadeDepthController + notificationShadeDepthController, + notificationShadeWindowController ); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java index 6ea79af8b9ad..65ff5583e7d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar; import android.view.ViewGroup; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; @@ -188,6 +189,14 @@ public interface NotificationShadeWindowController extends RemoteInputController default void setLightRevealScrimOpaque(boolean opaque) {} /** + * Defer any application of window {@link WindowManager.LayoutParams} until {@code scope} is + * fully applied. + */ + default void batchApplyWindowLayoutParams(@NonNull Runnable scope) { + scope.run(); + } + + /** * Custom listener to pipe data back to plugins about whether or not the status bar would be * collapsed if not for the plugin. * TODO: Find cleaner way to do this. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 33c4109b3426..3ba66bff66bb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -145,6 +145,7 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.RemoteInputController; @@ -664,7 +665,9 @@ public class NotificationPanelViewController extends PanelViewController { NotificationLockscreenUserManager notificationLockscreenUserManager, NotificationEntryManager notificationEntryManager, KeyguardStateController keyguardStateController, - StatusBarStateController statusBarStateController, DozeLog dozeLog, + StatusBarStateController statusBarStateController, + NotificationShadeWindowController notificationShadeWindowController, + DozeLog dozeLog, DozeParameters dozeParameters, CommandQueue commandQueue, VibratorHelper vibratorHelper, LatencyTracker latencyTracker, PowerManager powerManager, AccessibilityManager accessibilityManager, @DisplayId int displayId, @@ -716,6 +719,7 @@ public class NotificationPanelViewController extends PanelViewController { dozeLog, keyguardStateController, (SysuiStatusBarStateController) statusBarStateController, + notificationShadeWindowController, vibratorHelper, statusBarKeyguardViewManager, latencyTracker, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java index 030a8951943d..8c76a1bf4f83 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -107,6 +107,12 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW private final SysuiColorExtractor mColorExtractor; private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private float mFaceAuthDisplayBrightness = LayoutParams.BRIGHTNESS_OVERRIDE_NONE; + /** + * Layout params would be aggregated and dispatched all at once if this is > 0. + * + * @see #batchApplyWindowLayoutParams(Runnable) + */ + private int mDeferWindowLayoutParams; @Inject public NotificationShadeWindowControllerImpl(Context context, WindowManager windowManager, @@ -433,6 +439,20 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } } + private void applyWindowLayoutParams() { + if (mDeferWindowLayoutParams == 0 && mLp != null && mLp.copyFrom(mLpChanged) != 0) { + mWindowManager.updateViewLayout(mNotificationShadeView, mLp); + } + } + + @Override + public void batchApplyWindowLayoutParams(Runnable scope) { + mDeferWindowLayoutParams++; + scope.run(); + mDeferWindowLayoutParams--; + applyWindowLayoutParams(); + } + private void apply(State state) { applyKeyguardFlags(state); applyFocusableFlag(state); @@ -447,9 +467,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW applyHasTopUi(state); applyNotTouchable(state); applyStatusBarColorSpaceAgnosticFlag(state); - if (mLp != null && mLp.copyFrom(mLpChanged) != 0) { - mWindowManager.updateViewLayout(mNotificationShadeView, mLp); - } + applyWindowLayoutParams(); + if (mHasTopUi != mHasTopUiChanged) { whitelistIpcs(() -> { try { @@ -722,6 +741,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW pw.println(TAG + ":"); pw.println(" mKeyguardMaxRefreshRate=" + mKeyguardMaxRefreshRate); pw.println(" mKeyguardPreferredRefreshRate=" + mKeyguardPreferredRefreshRate); + pw.println(" mDeferWindowLayoutParams=" + mDeferWindowLayoutParams); pw.println(mCurrentState); if (mNotificationShadeView != null && mNotificationShadeView.getViewRootImpl() != null) { mNotificationShadeView.getViewRootImpl().dump(" ", pw); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 2bf16fc9e52c..040820e90790 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -54,6 +54,7 @@ import com.android.systemui.animation.Interpolators; import com.android.systemui.classifier.Classifier; import com.android.systemui.doze.DozeLog; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; @@ -177,6 +178,7 @@ public abstract class PanelViewController { private boolean mExpandLatencyTracking; private final PanelView mView; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + private final NotificationShadeWindowController mNotificationShadeWindowController; protected final Resources mResources; protected final KeyguardStateController mKeyguardStateController; protected final SysuiStatusBarStateController mStatusBarStateController; @@ -215,6 +217,7 @@ public abstract class PanelViewController { DozeLog dozeLog, KeyguardStateController keyguardStateController, SysuiStatusBarStateController statusBarStateController, + NotificationShadeWindowController notificationShadeWindowController, VibratorHelper vibratorHelper, StatusBarKeyguardViewManager statusBarKeyguardViewManager, LatencyTracker latencyTracker, @@ -247,6 +250,7 @@ public abstract class PanelViewController { mResources = mView.getResources(); mKeyguardStateController = keyguardStateController; mStatusBarStateController = statusBarStateController; + mNotificationShadeWindowController = notificationShadeWindowController; mFlingAnimationUtils = flingAnimationUtilsBuilder .reset() .setMaxLengthSeconds(0.6f) @@ -743,34 +747,36 @@ public abstract class PanelViewController { if (isNaN(h)) { Log.wtf(TAG, "ExpandedHeight set to NaN"); } - if (mExpandLatencyTracking && h != 0f) { - DejankUtils.postAfterTraversal( - () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL)); - mExpandLatencyTracking = false; - } - float maxPanelHeight = getMaxPanelHeight(); - if (mHeightAnimator == null) { - if (mTracking) { - float overExpansionPixels = Math.max(0, h - maxPanelHeight); - setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */); + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + if (mExpandLatencyTracking && h != 0f) { + DejankUtils.postAfterTraversal( + () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL)); + mExpandLatencyTracking = false; + } + float maxPanelHeight = getMaxPanelHeight(); + if (mHeightAnimator == null) { + if (mTracking) { + float overExpansionPixels = Math.max(0, h - maxPanelHeight); + setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */); + } + mExpandedHeight = Math.min(h, maxPanelHeight); + } else { + mExpandedHeight = h; } - mExpandedHeight = Math.min(h, maxPanelHeight); - } else { - mExpandedHeight = h; - } - // If we are closing the panel and we are almost there due to a slow decelerating - // interpolator, abort the animation. - if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) { - mExpandedHeight = 0f; - if (mHeightAnimator != null) { - mHeightAnimator.end(); + // If we are closing the panel and we are almost there due to a slow decelerating + // interpolator, abort the animation. + if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) { + mExpandedHeight = 0f; + if (mHeightAnimator != null) { + mHeightAnimator.end(); + } } - } - mExpandedFraction = Math.min(1f, - maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); - onHeightUpdated(mExpandedHeight); - updatePanelExpansionAndVisibility(); + mExpandedFraction = Math.min(1f, + maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); + onHeightUpdated(mExpandedHeight); + updatePanelExpansionAndVisibility(); + }); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 071c8c9117ec..0eefc9404825 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -2937,9 +2937,8 @@ public class StatusBar extends SystemUI implements // turned off fully. boolean keyguardForDozing = mDozeServiceHost.getDozingRequested() && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard)); - boolean isWakingAndOccluded = isOccluded() && isWaking(); boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested() - || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded; + || keyguardForDozing) && !wakeAndUnlocking; if (keyguardForDozing) { updatePanelExpansionForKeyguard(); } @@ -3560,26 +3559,29 @@ public class StatusBar extends SystemUI implements public void onStartedWakingUp() { String tag = "StatusBar#onStartedWakingUp"; DejankUtils.startDetectingBlockingIpcs(tag); - mDeviceInteractive = true; - mWakeUpCoordinator.setWakingUp(true); - if (!mKeyguardBypassController.getBypassEnabled()) { - mHeadsUpManager.releaseAllImmediately(); - } - updateVisibleToUser(); - updateIsKeyguard(); - mDozeServiceHost.stopDozing(); - // This is intentionally below the stopDozing call above, since it avoids that we're - // unnecessarily animating the wakeUp transition. Animations should only be enabled - // once we fully woke up. - updateRevealEffect(true /* wakingUp */); - updateNotificationPanelTouchState(); - - // If we are waking up during the screen off animation, we should undo making the - // expanded visible (we did that so the LightRevealScrim would be visible). - if (mUnlockedScreenOffAnimationController.isScreenOffLightRevealAnimationPlaying()) { - makeExpandedInvisible(); - } + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + mDeviceInteractive = true; + mWakeUpCoordinator.setWakingUp(true); + if (!mKeyguardBypassController.getBypassEnabled()) { + mHeadsUpManager.releaseAllImmediately(); + } + updateVisibleToUser(); + updateIsKeyguard(); + mDozeServiceHost.stopDozing(); + // This is intentionally below the stopDozing call above, since it avoids that we're + // unnecessarily animating the wakeUp transition. Animations should only be enabled + // once we fully woke up. + updateRevealEffect(true /* wakingUp */); + updateNotificationPanelTouchState(); + + // If we are waking up during the screen off animation, we should undo making the + // expanded visible (we did that so the LightRevealScrim would be visible). + if (mUnlockedScreenOffAnimationController + .isScreenOffLightRevealAnimationPlaying()) { + makeExpandedInvisible(); + } + }); DejankUtils.stopDetectingBlockingIpcs(tag); } @@ -3717,10 +3719,6 @@ public class StatusBar extends SystemUI implements == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP; } - boolean isWaking() { - return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING; - } - public void notifyBiometricAuthModeChanged() { mDozeServiceHost.updateDozing(); updateScrimController(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt index 12258136c011..67985b95dda4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallController.kt @@ -21,7 +21,7 @@ import android.app.IActivityManager import android.app.IUidObserver import android.app.Notification import android.app.Notification.CallStyle.CALL_TYPE_ONGOING -import android.content.Intent +import android.app.PendingIntent import android.util.Log import android.view.View import androidx.annotation.VisibleForTesting @@ -98,7 +98,7 @@ class OngoingCallController @Inject constructor( val newOngoingCallInfo = CallNotificationInfo( entry.sbn.key, entry.sbn.notification.`when`, - entry.sbn.notification.contentIntent?.intent, + entry.sbn.notification.contentIntent, entry.sbn.uid, entry.sbn.notification.extras.getInt( Notification.EXTRA_CALL_TYPE, -1) == CALL_TYPE_ONGOING, @@ -230,7 +230,6 @@ class OngoingCallController @Inject constructor( logger.logChipClicked() activityStarter.postStartActivityDismissingKeyguard( intent, - 0, ActivityLaunchAnimator.Controller.fromView( backgroundView, InteractionJankMonitor.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP) @@ -351,7 +350,7 @@ class OngoingCallController @Inject constructor( private data class CallNotificationInfo( val key: String, val callStartTime: Long, - val intent: Intent?, + val intent: PendingIntent?, val uid: Int, /** True if the call is currently ongoing (as opposed to incoming, screening, etc.). */ val isOngoing: Boolean, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 6d8645e44fb0..086cb1ab68fb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -51,6 +51,7 @@ import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.dump.DumpManager; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; @@ -64,9 +65,6 @@ import com.android.systemui.util.DeviceConfigProxyFake; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; -import java.util.Optional; -import java.util.function.Function; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -75,6 +73,11 @@ import org.mockito.ArgumentMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Optional; +import java.util.function.Function; + +import dagger.Lazy; + @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @SmallTest @@ -103,6 +106,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; private @Mock UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private @Mock IKeyguardDrawnCallback mKeyguardDrawnCallback; + private @Mock Lazy<NotificationShadeWindowController> mNotificationShadeWindowControllerLazy; private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake(); private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -144,7 +148,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mKeyguardStateController, () -> mKeyguardUnlockAnimationController, mUnlockedScreenOffAnimationController, - () -> mNotificationShadeDepthController); + () -> mNotificationShadeDepthController, + mNotificationShadeWindowControllerLazy); mViewMediator.start(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 13989d3f0ebe..5eaa60a6f157 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -23,7 +23,6 @@ import static com.android.keyguard.KeyguardClockSwitch.SMALL; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED; -import static com.android.systemui.statusbar.notification.ViewGroupFadeHelper.reset; import static com.google.common.truth.Truth.assertThat; @@ -107,6 +106,7 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.StatusBarStateControllerImpl; @@ -305,6 +305,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { @Mock private NotificationsQSContainerController mNotificationsQSContainerController; @Mock + private NotificationShadeWindowController mNotificationShadeWindowController; + @Mock private FeatureFlags mFeatureFlags; private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty(); private SysuiStatusBarStateController mStatusBarStateController; @@ -402,8 +404,10 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean())) .thenReturn(mKeyguardBottomArea); when(mNotificationRemoteInputManager.isRemoteInputActive()).thenReturn(false); - - reset(mView); + doAnswer(invocation -> { + ((Runnable) invocation.getArgument(0)).run(); + return null; + }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any()); mNotificationPanelViewController = new NotificationPanelViewController(mView, mResources, @@ -412,8 +416,9 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController, mFalsingManager, new FalsingCollectorFake(), mNotificationLockscreenUserManager, mNotificationEntryManager, - mKeyguardStateController, mStatusBarStateController, mDozeLog, - mDozeParameters, mCommandQueue, mVibratorHelper, + mKeyguardStateController, mStatusBarStateController, + mNotificationShadeWindowController, + mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper, mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor, mMetricsLogger, mActivityManager, mConfigurationController, () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java index 90b8a74d88be..cb468108880a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -225,4 +226,17 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) != 0).isTrue(); assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue(); } + + @Test + public void batchApplyWindowLayoutParams_doesNotDispatchEvents() { + mNotificationShadeWindowController.setForceDozeBrightness(true); + verify(mWindowManager).updateViewLayout(any(), any()); + + clearInvocations(mWindowManager); + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + mNotificationShadeWindowController.setForceDozeBrightness(false); + verify(mWindowManager, never()).updateViewLayout(any(), any()); + }); + verify(mWindowManager).updateViewLayout(any(), any()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 20575ae504ad..2709e436a663 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -351,6 +351,10 @@ public class StatusBarTest extends SysuiTestCase { when(mStatusBarComponentFactory.create()).thenReturn(mStatusBarComponent); when(mStatusBarComponent.getNotificationShadeWindowViewController()).thenReturn( mNotificationShadeWindowViewController); + doAnswer(invocation -> { + ((Runnable) invocation.getArgument(0)).run(); + return null; + }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any()); mShadeController = new ShadeControllerImpl(mCommandQueue, mStatusBarStateController, mNotificationShadeWindowController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt index b385b7d62cff..45c6be936eb9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ongoingcall/OngoingCallControllerTest.kt @@ -22,7 +22,6 @@ import android.app.IUidObserver import android.app.Notification import android.app.PendingIntent import android.app.Person -import android.content.Intent import android.service.notification.NotificationListenerService.REASON_USER_STOPPED import android.testing.AndroidTestingRunner import android.testing.TestableLooper @@ -429,6 +428,19 @@ class OngoingCallControllerTest : SysuiTestCase() { .isEqualTo(OngoingCallLogger.OngoingCallEvents.ONGOING_CALL_CLICKED.id) } + /** Regression test for b/212467440. */ + @Test + fun chipClicked_activityStarterTriggeredWithUnmodifiedIntent() { + val notifEntry = createOngoingCallNotifEntry() + val pendingIntent = notifEntry.sbn.notification.contentIntent + notifCollectionListener.onEntryUpdated(notifEntry) + + chipView.performClick() + + // Ensure that the sysui didn't modify the notification's intent -- see b/212467440. + verify(mockActivityStarter).postStartActivityDismissingKeyguard(eq(pendingIntent), any()) + } + @Test fun notifyChipVisibilityChanged_visibleEventLogged() { controller.notifyChipVisibilityChanged(true) @@ -570,7 +582,6 @@ class OngoingCallControllerTest : SysuiTestCase() { notificationEntryBuilder.modifyNotification(context).setContentIntent(null) } else { val contentIntent = mock(PendingIntent::class.java) - `when`(contentIntent.intent).thenReturn(mock(Intent::class.java)) notificationEntryBuilder.modifyNotification(context).setContentIntent(contentIntent) } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 330d2ddc0a94..ed7448140581 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -13804,14 +13804,26 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } - if (!Build.IS_DEBUGGABLE) { - int match = mContext.getPackageManager().checkSignatures( - ii.targetPackage, ii.packageName); - if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) { + int match = mContext.getPackageManager().checkSignatures( + ii.targetPackage, ii.packageName); + if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) { + if (Build.IS_DEBUGGABLE) { + String message = "Instrumentation test " + ii.packageName + + " doesn't have a signature matching the target " + + ii.targetPackage + + ", which would not be allowed on the production Android builds"; + if (callingUid != Process.ROOT_UID) { + Slog.e(TAG, message + + ". THIS WILL BE DISALLOWED ON FUTURE ANDROID VERSIONS" + + " unless from a rooted ADB shell."); + } else { + Slog.w(TAG, message); + } + } else { String msg = "Permission Denial: starting instrumentation " + className + " from pid=" + Binder.getCallingPid() - + ", uid=" + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + " not allowed because package " + ii.packageName + " does not have a signature matching the target " + ii.targetPackage; diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index d0e445749698..3ddcf17d0a47 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -126,6 +126,7 @@ import android.system.StructStat; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.EventLog; import android.util.ExceptionUtils; import android.util.MathUtils; import android.util.Slog; @@ -3097,6 +3098,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { if (mResolvedBaseFile == null) { mResolvedBaseFile = new File(appInfo.getBaseCodePath()); inheritFileLocked(mResolvedBaseFile); + } else if ((params.installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) { + EventLog.writeEvent(0x534e4554, "219044664"); + + // Installing base.apk. Make sure the app is restarted. + params.setDontKillApp(false); } // Inherit splits if not overridden. @@ -3743,6 +3749,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { } @Override + public int getInstallFlags() { + return params.installFlags; + } + + @Override public DataLoaderParamsParcel getDataLoaderParams() { mContext.enforceCallingOrSelfPermission(Manifest.permission.USE_INSTALLER_V2, null); return params.dataLoaderParams != null ? params.dataLoaderParams.getData() : null; diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java index ee0e5ba916b9..e3dcfd0c89c0 100644 --- a/services/core/java/com/android/server/slice/SliceManagerService.java +++ b/services/core/java/com/android/server/slice/SliceManagerService.java @@ -247,6 +247,8 @@ public class SliceManagerService extends ISliceManager.Stub { if (autoGrantPermissions != null && callingPkg != null) { // Need to own the Uri to call in with permissions to grant. enforceOwner(callingPkg, uri, userId); + // b/208232850: Needs to verify caller before granting slice access + verifyCaller(callingPkg); for (String perm : autoGrantPermissions) { if (mContext.checkPermission(perm, pid, uid) == PERMISSION_GRANTED) { int providerUser = ContentProvider.getUserIdFromUri(uri, userId); diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 6fda72e1267b..eddb5e977fa2 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -59,8 +59,8 @@ import android.content.pm.UserInfo; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; import android.graphics.Color; +import android.graphics.ImageDecoder; import android.graphics.Rect; import android.graphics.RectF; import android.hardware.display.DisplayManager; @@ -193,6 +193,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub static final String WALLPAPER_LOCK_ORIG = "wallpaper_lock_orig"; static final String WALLPAPER_LOCK_CROP = "wallpaper_lock"; static final String WALLPAPER_INFO = "wallpaper_info.xml"; + private static final String RECORD_FILE = "decode_record"; + private static final String RECORD_LOCK_FILE = "decode_lock_record"; // All the various per-user state files we need to be aware of private static final String[] sPerUserFiles = new String[] { @@ -674,8 +676,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } if (DEBUG) { - // This is just a quick estimation, may be smaller than it is. - long estimateSize = options.outWidth * options.outHeight * 4; + long estimateSize = (long) options.outWidth * options.outHeight * 4; Slog.v(TAG, "Null crop of new wallpaper, estimate size=" + estimateSize + ", success=" + success); } @@ -684,9 +685,6 @@ public class WallpaperManagerService extends IWallpaperManager.Stub FileOutputStream f = null; BufferedOutputStream bos = null; try { - BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance( - wallpaper.wallpaperFile.getAbsolutePath(), false); - // This actually downsamples only by powers of two, but that's okay; we do // a proper scaling blit later. This is to minimize transient RAM use. // We calculate the largest power-of-two under the actual ratio rather than @@ -740,8 +738,24 @@ public class WallpaperManagerService extends IWallpaperManager.Stub Slog.v(TAG, " maxTextureSize=" + GLHelper.getMaxTextureSize()); } - Bitmap cropped = decoder.decodeRegion(cropHint, options); - decoder.recycle(); + //Create a record file and will delete if ImageDecoder work well. + final String recordName = + (wallpaper.wallpaperFile.getName().equals(WALLPAPER) + ? RECORD_FILE : RECORD_LOCK_FILE); + final File record = new File(getWallpaperDir(wallpaper.userId), recordName); + record.createNewFile(); + Slog.v(TAG, "record path =" + record.getPath() + + ", record name =" + record.getName()); + + final ImageDecoder.Source srcData = + ImageDecoder.createSource(wallpaper.wallpaperFile); + final int sampleSize = scale; + Bitmap cropped = ImageDecoder.decodeBitmap(srcData, (decoder, info, src) -> { + decoder.setTargetSampleSize(sampleSize); + decoder.setCrop(estimateCrop); + }); + + record.delete(); if (cropped == null) { Slog.e(TAG, "Could not decode new wallpaper"); @@ -1779,6 +1793,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub new UserSwitchObserver() { @Override public void onUserSwitching(int newUserId, IRemoteCallback reply) { + errorCheck(newUserId); switchUser(newUserId, reply); } }, TAG); @@ -1816,6 +1831,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub @Override public void onBootPhase(int phase) { + // If someone set too large jpg file as wallpaper, system_server may be killed by lmk in + // generateCrop(), so we create a file in generateCrop() before ImageDecoder starts working + // and delete this file after ImageDecoder finishing. If the specific file exists, that + // means ImageDecoder can't handle the original wallpaper file, in order to avoid + // system_server restart again and again and rescue party will trigger factory reset, + // so we reset default wallpaper in case system_server is trapped into a restart loop. + errorCheck(UserHandle.USER_SYSTEM); + if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) { systemReady(); } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { @@ -1823,6 +1846,38 @@ public class WallpaperManagerService extends IWallpaperManager.Stub } } + private static final HashMap<Integer, String> sWallpaperType = new HashMap<Integer, String>() { + { + put(FLAG_SYSTEM, RECORD_FILE); + put(FLAG_LOCK, RECORD_LOCK_FILE); + } + }; + + private void errorCheck(int userID) { + sWallpaperType.forEach((type, filename) -> { + final File record = new File(getWallpaperDir(userID), filename); + if (record.exists()) { + Slog.w(TAG, "User:" + userID + ", wallpaper tyep = " + type + + ", wallpaper fail detect!! reset to default wallpaper"); + clearWallpaperData(userID, type); + record.delete(); + } + }); + } + + private void clearWallpaperData(int userID, int wallpaperType) { + final WallpaperData wallpaper = new WallpaperData(userID, getWallpaperDir(userID), + (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_ORIG : WALLPAPER, + (wallpaperType == FLAG_LOCK) ? WALLPAPER_LOCK_CROP : WALLPAPER_CROP); + if (wallpaper.sourceExists()) { + wallpaper.wallpaperFile.delete(); + } + if (wallpaper.cropExists()) { + wallpaper.cropFile.delete(); + } + + } + @Override public void onUnlockUser(final int userId) { TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG); diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java index badb1f5a0a12..4708d0026931 100644 --- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java +++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java @@ -97,7 +97,7 @@ class EnsureActivitiesVisibleHelper { // activities are actually behind other fullscreen activities, but still required // to be visible (such as performing Recents animation). final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind - && mTaskFragment.isTopActivityFocusable() + && mTaskFragment.canBeResumed(starting) && (starting == null || !starting.isDescendantOf(mTaskFragment)); ArrayList<TaskFragment> adjacentTaskFragments = null; diff --git a/services/core/java/com/android/server/wm/MirrorActiveUids.java b/services/core/java/com/android/server/wm/MirrorActiveUids.java index 4e7f1d4cca18..b9aa9599babe 100644 --- a/services/core/java/com/android/server/wm/MirrorActiveUids.java +++ b/services/core/java/com/android/server/wm/MirrorActiveUids.java @@ -19,7 +19,7 @@ package com.android.server.wm; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import android.app.ActivityManager.ProcessState; -import android.util.SparseArray; +import android.util.SparseIntArray; import java.io.PrintWriter; @@ -29,15 +29,14 @@ import java.io.PrintWriter; * adjustment) or getting state from window manager (background start check). */ class MirrorActiveUids { - private final SparseArray<UidRecord> mUidStates = new SparseArray<>(); + /** Uid -> process state. */ + private final SparseIntArray mUidStates = new SparseIntArray(); + + /** Uid -> number of non-app visible windows belong to the uid. */ + private final SparseIntArray mNumNonAppVisibleWindowMap = new SparseIntArray(); synchronized void onUidActive(int uid, int procState) { - UidRecord r = mUidStates.get(uid); - if (r == null) { - r = new UidRecord(); - mUidStates.put(uid, r); - } - r.mProcState = procState; + mUidStates.put(uid, procState); } synchronized void onUidInactive(int uid) { @@ -45,22 +44,28 @@ class MirrorActiveUids { } synchronized void onUidProcStateChanged(int uid, int procState) { - final UidRecord r = mUidStates.get(uid); - if (r != null) { - r.mProcState = procState; + final int index = mUidStates.indexOfKey(uid); + if (index >= 0) { + mUidStates.setValueAt(index, procState); } } synchronized @ProcessState int getUidState(int uid) { - final UidRecord r = mUidStates.get(uid); - return r != null ? r.mProcState : PROCESS_STATE_NONEXISTENT; + return mUidStates.get(uid, PROCESS_STATE_NONEXISTENT); } /** Called when the surface of non-application (exclude toast) window is shown or hidden. */ synchronized void onNonAppSurfaceVisibilityChanged(int uid, boolean visible) { - final UidRecord r = mUidStates.get(uid); - if (r != null) { - r.mNumNonAppVisibleWindow += visible ? 1 : -1; + final int index = mNumNonAppVisibleWindowMap.indexOfKey(uid); + if (index >= 0) { + final int num = mNumNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1); + if (num > 0) { + mNumNonAppVisibleWindowMap.setValueAt(index, num); + } else { + mNumNonAppVisibleWindowMap.removeAt(index); + } + } else if (visible) { + mNumNonAppVisibleWindowMap.append(uid, 1); } } @@ -70,23 +75,15 @@ class MirrorActiveUids { * {@link VisibleActivityProcessTracker}. */ synchronized boolean hasNonAppVisibleWindow(int uid) { - final UidRecord r = mUidStates.get(uid); - return r != null && r.mNumNonAppVisibleWindow > 0; + return mNumNonAppVisibleWindowMap.get(uid) > 0; } synchronized void dump(PrintWriter pw, String prefix) { - pw.print(prefix + "NumNonAppVisibleWindowByUid:["); - for (int i = mUidStates.size() - 1; i >= 0; i--) { - final UidRecord r = mUidStates.valueAt(i); - if (r.mNumNonAppVisibleWindow > 0) { - pw.print(" " + mUidStates.keyAt(i) + ":" + r.mNumNonAppVisibleWindow); - } + pw.print(prefix + "NumNonAppVisibleWindowUidMap:["); + for (int i = mNumNonAppVisibleWindowMap.size() - 1; i >= 0; i--) { + pw.print(" " + mNumNonAppVisibleWindowMap.keyAt(i) + ":" + + mNumNonAppVisibleWindowMap.valueAt(i)); } pw.println("]"); } - - private static final class UidRecord { - @ProcessState int mProcState; - int mNumNonAppVisibleWindow; - } } diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index fbc8f73b53b0..9cd37b305dc6 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -1979,7 +1979,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent> try { if (mTaskSupervisor.realStartActivityLocked(r, app, - top == r && r.isFocusable() /*andResume*/, true /*checkConfig*/)) { + top == r && r.getTask().canBeResumed(r) /*andResume*/, + true /*checkConfig*/)) { mTmpBoolean = true; } } catch (RemoteException e) { @@ -3623,11 +3624,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return new ArrayList<>(); } } else { + final RecentTasks recentTasks = mWindowManager.mAtmService.getRecentTasks(); + final int recentsComponentUid = recentTasks != null + ? recentTasks.getRecentsComponentUid() + : -1; final ArrayList<ActivityRecord> activities = new ArrayList<>(); - forAllRootTasks(rootTask -> { - if (!dumpVisibleRootTasksOnly || rootTask.shouldBeVisible(null)) { - activities.addAll(rootTask.getDumpActivitiesLocked(name)); + forAllLeafTasks(task -> { + final boolean isRecents = (task.effectiveUid == recentsComponentUid); + if (!dumpVisibleRootTasksOnly || task.shouldBeVisible(null) || isRecents) { + activities.addAll(task.getDumpActivitiesLocked(name)); } + return false; }); return activities; } diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 5af9147cd56f..c63780c3dd57 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -70,6 +70,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.os.Debug; @@ -3563,7 +3564,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< private void setTaskBackgroundColor(@ColorInt int backgroundColor) { TaskDisplayArea taskDisplayArea = getTaskDisplayArea(); - if (taskDisplayArea != null) { + if (taskDisplayArea != null && backgroundColor != Color.TRANSPARENT) { taskDisplayArea.setBackgroundColor(backgroundColor); // Atomic counter to make sure the clearColor callback is only called one. diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index a94fd074ff2e..2d8410bd12d2 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -513,9 +513,14 @@ public class WindowManagerShellCommand extends ShellCommand { try (ZipOutputStream out = new ZipOutputStream(getRawOutputStream())) { ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>(); synchronized (mInternal.mGlobalLock) { + final RecentTasks recentTasks = mInternal.mAtmService.getRecentTasks(); + final int recentsComponentUid = recentTasks != null + ? recentTasks.getRecentsComponentUid() + : -1; // Request dump from all windows parallelly before writing to disk. mInternal.mRoot.forAllWindows(w -> { - if (w.isVisible()) { + final boolean isRecents = (w.mSession.mUid == recentsComponentUid); + if (w.isVisible() || isRecents) { ByteTransferPipe pipe = null; try { pipe = new ByteTransferPipe(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index b89d116f4fe4..0fbcfd3a3ba1 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8465,20 +8465,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { admin.getPackageName(), userId, "set-device-owner"); Slogf.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId); + } - if (setProfileOwnerOnCurrentUserIfNecessary - && mInjector.userManagerIsHeadlessSystemUserMode()) { - int currentForegroundUser = getCurrentForegroundUserId(); - Slogf.i(LOG_TAG, "setDeviceOwner(): setting " + admin - + " as profile owner on user " + currentForegroundUser); - // Sets profile owner on current foreground user since - // the human user will complete the DO setup workflow from there. - manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin, - /* managedUser= */ currentForegroundUser, /* adminExtras= */ null, - /* showDisclaimer= */ false); + if (setProfileOwnerOnCurrentUserIfNecessary + && mInjector.userManagerIsHeadlessSystemUserMode()) { + int currentForegroundUser; + synchronized (getLockObject()) { + currentForegroundUser = getCurrentForegroundUserId(); } - return true; + Slogf.i(LOG_TAG, "setDeviceOwner(): setting " + admin + + " as profile owner on user " + currentForegroundUser); + // Sets profile owner on current foreground user since + // the human user will complete the DO setup workflow from there. + manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin, + /* managedUser= */ currentForegroundUser, /* adminExtras= */ null, + /* showDisclaimer= */ false); } + return true; } @Override diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index e6ad68aafaec..7d501356d469 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -800,7 +800,6 @@ public class WindowStateTests extends WindowTestsBase { @Test public void testHasActiveVisibleWindow() { final int uid = ActivityBuilder.DEFAULT_FAKE_UID; - mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */); final WindowState app = createWindow(null, TYPE_APPLICATION, "app", uid); app.mActivityRecord.setVisible(false); @@ -828,6 +827,11 @@ public class WindowStateTests extends WindowTestsBase { // Make the application overlay window visible. It should be a valid active visible window. overlay.onSurfaceShownChanged(true); assertTrue(mAtm.hasActiveVisibleWindow(uid)); + + // The number of windows should be independent of the existence of uid state. + mAtm.mActiveUids.onUidInactive(uid); + mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */); + assertTrue(mAtm.mActiveUids.hasNonAppVisibleWindow(uid)); } @UseTestDisplay(addWindows = W_ACTIVITY) |