diff options
44 files changed, 508 insertions, 195 deletions
diff --git a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java index 4b4fb9623ba0..0585825cc98b 100644 --- a/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java +++ b/apex/jobscheduler/framework/java/android/os/PowerWhitelistManager.java @@ -24,6 +24,8 @@ import android.annotation.SystemService; import android.annotation.TestApi; import android.content.Context; +import libcore.util.EmptyArray; + import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Collections; @@ -100,6 +102,28 @@ public class PowerWhitelistManager { } /** + * Get a list of app IDs of app that are whitelisted. This does not include temporarily + * whitelisted apps. + * + * @param includingIdle Set to true if the app should be whitelisted from device idle as well + * as other power save restrictions + * @hide + */ + @NonNull + public int[] getWhitelistedAppIds(boolean includingIdle) { + try { + if (includingIdle) { + return mService.getAppIdWhitelist(); + } else { + return mService.getAppIdWhitelistExceptIdle(); + } + } catch (RemoteException e) { + e.rethrowFromSystemServer(); + return EmptyArray.INT; + } + } + + /** * Add an app to the temporary whitelist for a short amount of time. * * @param packageName The package to add to the temp whitelist diff --git a/core/java/android/app/UiModeManager.java b/core/java/android/app/UiModeManager.java index 24873b86e32b..7c6eff143724 100644 --- a/core/java/android/app/UiModeManager.java +++ b/core/java/android/app/UiModeManager.java @@ -72,19 +72,26 @@ public class UiModeManager { * also monitor this Intent in order to be informed of mode changes or * prevent the normal car UI from being displayed by setting the result * of the broadcast to {@link Activity#RESULT_CANCELED}. + * <p> + * This intent is broadcast when {@link #getCurrentModeType()} transitions to + * {@link Configuration#UI_MODE_TYPE_CAR} from some other ui mode. */ public static String ACTION_ENTER_CAR_MODE = "android.app.action.ENTER_CAR_MODE"; /** - * Broadcast sent when the device's UI has switched to car mode, either by being placed in a car - * dock or explicit action of the user. + * Broadcast sent when an app has entered car mode using either {@link #enableCarMode(int)} or + * {@link #enableCarMode(int, int)}. + * <p> + * Unlike {@link #ACTION_ENTER_CAR_MODE}, which is only sent when the global car mode state + * (i.e. {@link #getCurrentModeType()}) transitions to {@link Configuration#UI_MODE_TYPE_CAR}, + * this intent is sent any time an app declares it has entered car mode. Thus, this intent is + * intended for use by a component which needs to know not only when the global car mode state + * changed, but also when the highest priority app declaring car mode has changed. * <p> - * In addition to the behavior for {@link #ACTION_ENTER_CAR_MODE}, this broadcast includes the - * package name of the app which requested to enter car mode in the - * {@link #EXTRA_CALLING_PACKAGE}. If an app requested to enter car mode using - * {@link #enableCarMode(int, int)} and specified a priority this will be specified in the + * This broadcast includes the package name of the app which requested to enter car mode in + * {@link #EXTRA_CALLING_PACKAGE}. The priority the app entered car mode at is specified in * {@link #EXTRA_PRIORITY}. - * + * <p> * This is primarily intended to be received by other components of the Android OS. * <p> * Receiver requires permission: {@link android.Manifest.permission.HANDLE_CAR_MODE_CHANGES} @@ -98,17 +105,25 @@ public class UiModeManager { * Broadcast sent when the device's UI has switch away from car mode back * to normal mode. Typically used by a car mode app, to dismiss itself * when the user exits car mode. + * <p> + * This intent is broadcast when {@link #getCurrentModeType()} transitions from + * {@link Configuration#UI_MODE_TYPE_CAR} to some other ui mode. */ public static String ACTION_EXIT_CAR_MODE = "android.app.action.EXIT_CAR_MODE"; /** - * Broadcast sent when the device's UI has switched away from car mode back to normal mode. - * Typically used by a car mode app, to dismiss itself when the user exits car mode. + * Broadcast sent when an app has exited car mode using {@link #disableCarMode(int)}. + * <p> + * Unlike {@link #ACTION_EXIT_CAR_MODE}, which is only sent when the global car mode state + * (i.e. {@link #getCurrentModeType()}) transitions to a non-car mode state such as + * {@link Configuration#UI_MODE_TYPE_NORMAL}, this intent is sent any time an app declares it + * has exited car mode. Thus, this intent is intended for use by a component which needs to + * know not only when the global car mode state changed, but also when the highest priority app + * declaring car mode has changed. * <p> - * In addition to the behavior for {@link #ACTION_EXIT_CAR_MODE}, this broadcast includes the - * package name of the app which requested to exit car mode in {@link #EXTRA_CALLING_PACKAGE}. - * If an app requested to enter car mode using {@link #enableCarMode(int, int)} and specified a - * priority this will be specified in the {@link #EXTRA_PRIORITY} when exiting car mode. + * This broadcast includes the package name of the app which requested to exit car mode in + * {@link #EXTRA_CALLING_PACKAGE}. The priority the app originally entered car mode at is + * specified in {@link #EXTRA_PRIORITY}. * <p> * If {@link #DISABLE_CAR_MODE_ALL_PRIORITIES} is used when disabling car mode (i.e. this is * initiated by the user via the persistent car mode notification), this broadcast is sent once @@ -260,9 +275,7 @@ public class UiModeManager { * An app may request to enter car mode when the system is already in car mode. The app may * specify a "priority" when entering car mode. The device will remain in car mode * (i.e. {@link #getCurrentModeType()} is {@link Configuration#UI_MODE_TYPE_CAR}) as long as - * there is a priority level at which car mode have been enabled. For example assume app A - * enters car mode at priority level 100, and then app B enters car mode at the default priority - * (0). If app A exits car mode, the device will remain in car mode until app B exits car mode. + * there is a priority level at which car mode have been enabled. * <p> * Specifying a priority level when entering car mode is important in cases where multiple apps * on a device implement a car-mode {@link android.telecom.InCallService} (see @@ -275,18 +288,28 @@ public class UiModeManager { * correct conditions exist for that app to be in car mode. The device maker should ensure that * where multiple apps exist on the device which can potentially enter car mode, appropriate * priorities are used to ensure that calls delivered by the - * {@link android.telecom.InCallService} API are delivered to the highest priority app. - * If app A and app B can both potentially enable car mode, and it is desired that app B is the - * one which should receive call information, the priority for app B should be higher than the - * one for app A. + * {@link android.telecom.InCallService} API are sent to the highest priority app given the + * desired behavior of the car mode experience on the device. + * <p> + * If app A and app B both meet their own criteria to enable car mode, and it is desired that + * app B should be the one which should receive call information in that scenario, the priority + * for app B should be higher than the one for app A. The higher priority of app B compared to + * A means it will be bound to during calls and app A will not. When app B no longer meets its + * criteria for providing a car mode experience it uses {@link #disableCarMode(int)} to disable + * car mode at its priority level. The system will then unbind from app B and bind to app A as + * it has the next highest priority. * <p> - * When an app uses a priority to enable car mode, they can disable car mode at the specified + * When an app enables car mode at a certain priority, it can disable car mode at the specified * priority level using {@link #disableCarMode(int)}. An app may only enable car mode at a * single priority. * <p> - * Public apps are assumed to enter/exit car mode at {@link #DEFAULT_PRIORITY}. + * Public apps are assumed to enter/exit car mode at the lowest priority, + * {@link #DEFAULT_PRIORITY}. * - * @param priority The declared priority for the caller. + * @param priority The declared priority for the caller, where {@link #DEFAULT_PRIORITY} (0) is + * the lowest priority and higher numbers represent a higher priority. + * The priorities apps declare when entering car mode is determined by the + * device manufacturer based on the desired car mode experience. * @param flags Car mode flags. * @hide */ @@ -331,11 +354,11 @@ public class UiModeManager { /** * The default priority used for entering car mode. * <p> - * Callers of the {@link UiModeManager#enableCarMode(int)} priority will be assigned the - * default priority. + * Callers of the {@link #enableCarMode(int)} priority will be assigned the default priority. + * This is considered the lowest possible priority for enabling car mode. * <p> * System apps can specify a priority other than the default priority when using - * {@link UiModeManager#enableCarMode(int, int)} to enable car mode. + * {@link #enableCarMode(int, int)} to enable car mode. * @hide */ @SystemApi diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java index 40754dff5ea0..b4f21593165f 100644 --- a/core/java/android/content/pm/parsing/ParsingPackageUtils.java +++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java @@ -1795,6 +1795,7 @@ public class ParsingPackageUtils { // Default false .setAllowTaskReparenting(bool(false, R.styleable.AndroidManifestApplication_allowTaskReparenting, sa)) .setCantSaveState(bool(false, R.styleable.AndroidManifestApplication_cantSaveState, sa)) + .setCrossProfile(bool(false, R.styleable.AndroidManifestApplication_crossProfile, sa)) .setDebuggable(bool(false, R.styleable.AndroidManifestApplication_debuggable, sa)) .setDefaultToDeviceProtectedStorage(bool(false, R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage, sa)) .setDirectBootAware(bool(false, R.styleable.AndroidManifestApplication_directBootAware, sa)) diff --git a/core/java/android/os/incremental/IncrementalFileStorages.java b/core/java/android/os/incremental/IncrementalFileStorages.java index 3f8c0fedc7a6..ab224a2c0b51 100644 --- a/core/java/android/os/incremental/IncrementalFileStorages.java +++ b/core/java/android/os/incremental/IncrementalFileStorages.java @@ -101,8 +101,7 @@ public final class IncrementalFileStorages { } catch (IOException e) { // TODO(b/146080380): add incremental-specific error code throw new IOException( - "Failed to add file to IncFS: " + file.getName() + ", reason: " - + e.getMessage(), e.getCause()); + "Failed to add file to IncFS: " + file.getName() + ", reason: ", e); } } else { throw new IOException("Unknown file location: " + file.getLocation()); @@ -117,6 +116,7 @@ public final class IncrementalFileStorages { return result; } catch (IOException e) { + Slog.e(TAG, "Failed to initialize Incremental file storages. Cleaning up...", e); if (result != null) { result.cleanUp(); } diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java index dea495bf9327..bf31bc206278 100644 --- a/core/java/android/os/incremental/IncrementalStorage.java +++ b/core/java/android/os/incremental/IncrementalStorage.java @@ -424,14 +424,18 @@ public final class IncrementalStorage { */ private static IncrementalSignature parseV4Signature(@Nullable byte[] v4signatureBytes) throws IOException { - if (v4signatureBytes == null) { + if (v4signatureBytes == null || v4signatureBytes.length == 0) { return null; } final V4Signature signature; try (DataInputStream input = new DataInputStream( new ByteArrayInputStream(v4signatureBytes))) { - signature = V4Signature.readFrom(input); + try { + signature = V4Signature.readFrom(input); + } catch (IOException e) { + throw new IOException("Failed to read v4 signature:", e); + } } if (!signature.isVersionSupported()) { diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java index 58c73b568553..bbd739941422 100644 --- a/media/java/android/media/MediaMuxer.java +++ b/media/java/android/media/MediaMuxer.java @@ -654,6 +654,13 @@ final public class MediaMuxer { * the right tracks. Also, it needs to make sure the samples for each track * are written in chronological order (e.g. in the order they are provided * by the encoder.)</p> + * <p> For MPEG4 media format, the duration of the last sample in a track can be set by passing + * an additional empty buffer(bufferInfo.size = 0) with MediaCodec.BUFFER_FLAG_END_OF_STREAM + * flag and a suitable presentation timestamp set in bufferInfo parameter as the last sample of + * that track. This last sample's presentation timestamp shall be a sum of the presentation + * timestamp and the duration preferred for the original last sample. If no explicit + * END_OF_STREAM sample was passed, then the duration of the last sample would be the same as + * that of the sample before that.</p> * @param byteBuf The encoded sample. * @param trackIndex The track index for this sample. * @param bufferInfo The buffer information related to this sample. diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h index 8c98ac992f75..15b39f2df891 100644 --- a/media/jni/soundpool/StreamManager.h +++ b/media/jni/soundpool/StreamManager.h @@ -52,6 +52,12 @@ public: JavaThread(JavaThread &&) = delete; // uses "this" ptr, not moveable. + ~JavaThread() { + join(); // manually block until the future is ready as std::future + // destructor doesn't block unless it comes from std::async + // and it is the last reference to shared state. + } + void join() const { mFuture.wait(); } @@ -64,8 +70,9 @@ private: static int staticFunction(void *data) { JavaThread *jt = static_cast<JavaThread *>(data); jt->mF(); - jt->mIsClosed = true; jt->mPromise.set_value(); + jt->mIsClosed = true; // publicly inform that we are closed + // after we have accessed all variables. return 0; } diff --git a/packages/SettingsProvider/res/values-as/strings.xml b/packages/SettingsProvider/res/values-as/strings.xml index 5235e3c1a9db..89b7c1e95482 100644 --- a/packages/SettingsProvider/res/values-as/strings.xml +++ b/packages/SettingsProvider/res/values-as/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"ছেটিংছসমূহৰ সঞ্চয়াগাৰ"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"হটস্পটৰ ছেটিংসমূহ সলনি হৈছে"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"সবিশেষ চাবলৈ টিপক"</string> </resources> diff --git a/packages/SettingsProvider/res/values-bn/strings.xml b/packages/SettingsProvider/res/values-bn/strings.xml index c785cd8fce9e..b2eaa2f9ec5c 100644 --- a/packages/SettingsProvider/res/values-bn/strings.xml +++ b/packages/SettingsProvider/res/values-bn/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"সেটিংস স্টোরেজ"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"হটস্পট সেটিংসে পরিবর্তন করা হয়েছে"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"বিশদে জানতে ট্যাপ করুন"</string> </resources> diff --git a/packages/SettingsProvider/res/values-de/strings.xml b/packages/SettingsProvider/res/values-de/strings.xml index a46993697569..b006ac936755 100644 --- a/packages/SettingsProvider/res/values-de/strings.xml +++ b/packages/SettingsProvider/res/values-de/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"Einstellungsspeicher"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot-Einstellungen wurden geändert"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Für Details tippen"</string> </resources> diff --git a/packages/SettingsProvider/res/values-es/strings.xml b/packages/SettingsProvider/res/values-es/strings.xml index 3f1fa61ab088..a3d3469b4cfe 100644 --- a/packages/SettingsProvider/res/values-es/strings.xml +++ b/packages/SettingsProvider/res/values-es/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"Almacenamiento de configuración"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"Se han cambiado los ajustes del punto de acceso"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toca para ver información detallada"</string> </resources> diff --git a/packages/SettingsProvider/res/values-gu/strings.xml b/packages/SettingsProvider/res/values-gu/strings.xml index 074675f76319..1f91f71be546 100644 --- a/packages/SettingsProvider/res/values-gu/strings.xml +++ b/packages/SettingsProvider/res/values-gu/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"સેટિંગ્સ સંગ્રહ"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"હૉટસ્પૉટ સેટિંગ બદલાઈ ગઈ છે"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"વિગતો જોવા માટે ટૅપ કરો"</string> </resources> diff --git a/packages/SettingsProvider/res/values-kn/strings.xml b/packages/SettingsProvider/res/values-kn/strings.xml index 0b0000d5e865..400b358e7c9b 100644 --- a/packages/SettingsProvider/res/values-kn/strings.xml +++ b/packages/SettingsProvider/res/values-kn/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"ಸೆಟ್ಟಿಂಗ್ಗಳ ಸಂಗ್ರಹಣೆ"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"ಹಾಟ್ಸ್ಪಾಟ್ ಸೆಟ್ಟಿಂಗ್ಗಳು ಬದಲಾಗಿವೆ"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ವಿವರಗಳನ್ನು ನೋಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> </resources> diff --git a/packages/SettingsProvider/res/values-ml/strings.xml b/packages/SettingsProvider/res/values-ml/strings.xml index 54a05fbc55e8..8df8ce4e02c8 100644 --- a/packages/SettingsProvider/res/values-ml/strings.xml +++ b/packages/SettingsProvider/res/values-ml/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"സംഭരണ ക്രമീകരണം"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"ഹോട്ട്സ്പോട്ട് ക്രമീകരണം മാറിയിരിക്കുന്നു"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"വിശദാംശങ്ങൾ കാണാൻ ടാപ്പ് ചെയ്യുക"</string> </resources> diff --git a/packages/SettingsProvider/res/values-mr/strings.xml b/packages/SettingsProvider/res/values-mr/strings.xml index 0e80f704218e..51b8b194df15 100644 --- a/packages/SettingsProvider/res/values-mr/strings.xml +++ b/packages/SettingsProvider/res/values-mr/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"सेटिंग्ज संचयन"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"हॉटस्पॉट सेटिंग्ज बदलल्या आहेत"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"तपशील पाहण्यासाठी टॅप करा"</string> </resources> diff --git a/packages/SettingsProvider/res/values-ne/strings.xml b/packages/SettingsProvider/res/values-ne/strings.xml index bb04b6ba8dd0..a0e3465a32ff 100644 --- a/packages/SettingsProvider/res/values-ne/strings.xml +++ b/packages/SettingsProvider/res/values-ne/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"सेटिङहरू भण्डारण"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"हटस्पटका सेटिङ परिवर्तन गरिएका छन्"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"विवरणहरू हेर्न ट्याप गर्नुहोस्"</string> </resources> diff --git a/packages/SettingsProvider/res/values-or/strings.xml b/packages/SettingsProvider/res/values-or/strings.xml index 4b73a555d4f8..486d8ffaa500 100644 --- a/packages/SettingsProvider/res/values-or/strings.xml +++ b/packages/SettingsProvider/res/values-or/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"ସେଟିଙ୍ଗ ଷ୍ଟୋରେଜ୍"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"ହଟସ୍ପଟ୍ ସେଟିଂସ୍ ବଦଳାଯାଇଛି"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ବିବରଣୀ ଦେଖିବାକୁ ଟାପ୍ କରନ୍ତୁ"</string> </resources> diff --git a/packages/SettingsProvider/res/values-pa/strings.xml b/packages/SettingsProvider/res/values-pa/strings.xml index 5af8d6a7cdb9..1c9a985677eb 100644 --- a/packages/SettingsProvider/res/values-pa/strings.xml +++ b/packages/SettingsProvider/res/values-pa/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"ਸੈਟਿੰਗਾਂ ਸਟੋਰੇਜ"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"ਹੌਟਸਪੌਟ ਸੈਟਿੰਗਾਂ ਬਦਲ ਗਈਆਂ ਹਨ"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ਵੇਰਵੇ ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string> </resources> diff --git a/packages/SettingsProvider/res/values-te/strings.xml b/packages/SettingsProvider/res/values-te/strings.xml index b1955ed54de9..fa2191f56477 100644 --- a/packages/SettingsProvider/res/values-te/strings.xml +++ b/packages/SettingsProvider/res/values-te/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"సెట్టింగ్ల నిల్వ"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"హాట్స్పాట్ సెట్టింగ్లు మార్చబడ్డాయి"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"వివరాలను చూడటానికి ట్యాప్ చేయండి"</string> </resources> diff --git a/packages/SettingsProvider/res/values-ur/strings.xml b/packages/SettingsProvider/res/values-ur/strings.xml index 2ce44b1bbfc4..5a1b0f985bb6 100644 --- a/packages/SettingsProvider/res/values-ur/strings.xml +++ b/packages/SettingsProvider/res/values-ur/strings.xml @@ -20,8 +20,6 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="app_label" msgid="4567566098528588863">"ترتیبات کا اسٹوریج"</string> - <!-- no translation found for wifi_softap_config_change (5688373762357941645) --> - <skip /> - <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) --> - <skip /> + <string name="wifi_softap_config_change" msgid="5688373762357941645">"ہاٹ اسپاٹ کی ترتیبات تبدیل ہو گئیں"</string> + <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"تفصیلات دیکھنے کے لیے تھپتھپائیں"</string> </resources> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index ef7f167652f2..241c512a856c 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -204,6 +204,7 @@ <!-- Permission needed to run network tests in CTS --> <uses-permission android:name="android.permission.MANAGE_TEST_NETWORKS" /> + <uses-permission android:name="android.permission.NETWORK_STACK" /> <!-- Permission needed to test tcp keepalive offload. --> <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" /> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java index 44cec966ba55..14903cd7bb27 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifPipeline.java @@ -16,6 +16,7 @@ package com.android.systemui.statusbar.notification.collection; +import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; @@ -63,7 +64,7 @@ import javax.inject.Singleton; * 6. Top-level entries are assigned sections by NotifSections ({@link #setSections}) * 7. Top-level entries within the same section are sorted by NotifComparators * ({@link #setComparators}) - * 8. Pre-render filters are fired on each notification ({@link #addPreRenderFilter}) + * 8. Finalize filters are fired on each notification ({@link #addFinalizeFilter}) * 9. OnBeforeRenderListListeners are fired ({@link #addOnBeforeRenderListListener}) * 9. The list is handed off to the view layer to be rendered */ @@ -169,14 +170,22 @@ public class NotifPipeline implements CommonNotifCollection { } /** + * Called after notifs have been filtered once, grouped, and sorted but before the final + * filtering. + */ + public void addOnBeforeFinalizeFilterListener(OnBeforeFinalizeFilterListener listener) { + mShadeListBuilder.addOnBeforeFinalizeFilterListener(listener); + } + + /** * Registers a filter with the pipeline to filter right before rendering the list (after * pre-group filtering, grouping, promoting and sorting occurs). Filters are * called on each notification in the order that they were registered. If any filter returns * true, the notification is removed from the pipeline (and no other filters are called on that * notif). */ - public void addPreRenderFilter(NotifFilter filter) { - mShadeListBuilder.addPreRenderFilter(filter); + public void addFinalizeFilter(NotifFilter filter) { + mShadeListBuilder.addFinalizeFilter(filter); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java index 76311207fe6f..5b73b1aa7388 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java @@ -18,11 +18,11 @@ package com.android.systemui.statusbar.notification.collection; import static com.android.systemui.statusbar.notification.collection.GroupEntry.ROOT_ENTRY; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_BUILD_STARTED; +import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZE_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_FINALIZING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_GROUPING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_IDLE; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_GROUP_FILTERING; -import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_PRE_RENDER_FILTERING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_RESETTING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_SORTING; import static com.android.systemui.statusbar.notification.collection.listbuilder.PipelineState.STATE_TRANSFORMING; @@ -36,6 +36,7 @@ import androidx.annotation.NonNull; import com.android.systemui.Dumpable; import com.android.systemui.dump.DumpManager; +import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; @@ -82,7 +83,7 @@ public class ShadeListBuilder implements Dumpable { private final List<NotifFilter> mNotifPreGroupFilters = new ArrayList<>(); private final List<NotifPromoter> mNotifPromoters = new ArrayList<>(); - private final List<NotifFilter> mNotifPreRenderFilters = new ArrayList<>(); + private final List<NotifFilter> mNotifFinalizeFilters = new ArrayList<>(); private final List<NotifComparator> mNotifComparators = new ArrayList<>(); private final List<NotifSection> mNotifSections = new ArrayList<>(); @@ -90,6 +91,8 @@ public class ShadeListBuilder implements Dumpable { new ArrayList<>(); private final List<OnBeforeSortListener> mOnBeforeSortListeners = new ArrayList<>(); + private final List<OnBeforeFinalizeFilterListener> mOnBeforeFinalizeFilterListeners = + new ArrayList<>(); private final List<OnBeforeRenderListListener> mOnBeforeRenderListListeners = new ArrayList<>(); @Nullable private OnRenderListListener mOnRenderListListener; @@ -142,6 +145,13 @@ public class ShadeListBuilder implements Dumpable { mOnBeforeSortListeners.add(listener); } + void addOnBeforeFinalizeFilterListener(OnBeforeFinalizeFilterListener listener) { + Assert.isMainThread(); + + mPipelineState.requireState(STATE_IDLE); + mOnBeforeFinalizeFilterListeners.add(listener); + } + void addOnBeforeRenderListListener(OnBeforeRenderListListener listener) { Assert.isMainThread(); @@ -157,12 +167,12 @@ public class ShadeListBuilder implements Dumpable { filter.setInvalidationListener(this::onPreGroupFilterInvalidated); } - void addPreRenderFilter(NotifFilter filter) { + void addFinalizeFilter(NotifFilter filter) { Assert.isMainThread(); mPipelineState.requireState(STATE_IDLE); - mNotifPreRenderFilters.add(filter); - filter.setInvalidationListener(this::onPreRenderFilterInvalidated); + mNotifFinalizeFilters.add(filter); + filter.setInvalidationListener(this::onFinalizeFilterInvalidated); } void addPromoter(NotifPromoter promoter) { @@ -237,12 +247,12 @@ public class ShadeListBuilder implements Dumpable { rebuildListIfBefore(STATE_SORTING); } - private void onPreRenderFilterInvalidated(NotifFilter filter) { + private void onFinalizeFilterInvalidated(NotifFilter filter) { Assert.isMainThread(); - mLogger.logPreRenderFilterInvalidated(filter.getName(), mPipelineState.getState()); + mLogger.logFinalizeFilterInvalidated(filter.getName(), mPipelineState.getState()); - rebuildListIfBefore(STATE_PRE_RENDER_FILTERING); + rebuildListIfBefore(STATE_FINALIZE_FILTERING); } private void onNotifComparatorInvalidated(NotifComparator comparator) { @@ -298,8 +308,9 @@ public class ShadeListBuilder implements Dumpable { // Step 6: Filter out entries after pre-group filtering, grouping, promoting and sorting // Now filters can see grouping information to determine whether to filter or not. - mPipelineState.incrementTo(STATE_PRE_RENDER_FILTERING); - filterNotifs(mNotifList, mNewNotifList, mNotifPreRenderFilters); + dispatchOnBeforeFinalizeFilter(mReadOnlyNotifList); + mPipelineState.incrementTo(STATE_FINALIZE_FILTERING); + filterNotifs(mNotifList, mNewNotifList, mNotifFinalizeFilters); applyNewNotifList(); pruneIncompleteGroups(mNotifList); @@ -772,6 +783,12 @@ public class ShadeListBuilder implements Dumpable { } } + private void dispatchOnBeforeFinalizeFilter(List<ListEntry> entries) { + for (int i = 0; i < mOnBeforeFinalizeFilterListeners.size(); i++) { + mOnBeforeFinalizeFilterListeners.get(i).onBeforeFinalizeFilter(entries); + } + } + private void dispatchOnBeforeRenderList(List<ListEntry> entries) { for (int i = 0; i < mOnBeforeRenderListListeners.size(); i++) { mOnBeforeRenderListListeners.get(i).onBeforeRenderList(entries); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java index 8b2a07d00378..370de838b903 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java @@ -77,7 +77,7 @@ public class BubbleCoordinator implements Coordinator { public void attach(NotifPipeline pipeline) { mNotifPipeline = pipeline; mNotifPipeline.addNotificationDismissInterceptor(mDismissInterceptor); - mNotifPipeline.addPreRenderFilter(mNotifFilter); + mNotifPipeline.addFinalizeFilter(mNotifFilter); mBubbleController.addNotifCallback(mNotifCallback); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java index a26ee5450d60..aaf71f58cb5c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java @@ -87,7 +87,7 @@ public class KeyguardCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { setupInvalidateNotifListCallbacks(); - pipeline.addPreRenderFilter(mNotifFilter); + pipeline.addFinalizeFilter(mNotifFilter); } private final NotifFilter mNotifFilter = new NotifFilter(TAG) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java index 1c8fdac4c51b..ebecf181b808 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java @@ -16,31 +16,39 @@ package com.android.systemui.statusbar.notification.collection.coordinator; +import android.annotation.IntDef; import android.os.RemoteException; import android.service.notification.StatusBarNotification; +import android.util.ArrayMap; import com.android.internal.statusbar.IStatusBarService; +import com.android.systemui.statusbar.notification.collection.GroupEntry; +import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder; import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater; +import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager; -import java.util.ArrayList; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; +import java.util.Map; +import java.util.Objects; import javax.inject.Inject; import javax.inject.Singleton; /** - * Kicks off notification inflation and view rebinding when a notification is added or updated. + * Kicks off core notification inflation and view rebinding when a notification is added or updated. * Aborts inflation when a notification is removed. * - * If a notification is not done inflating, this coordinator will filter the notification out - * from the {@link ShadeListBuilder}. + * If a notification was uninflated, this coordinator will filter the notification out from the + * {@link ShadeListBuilder} until it is inflated. */ @Singleton public class PreparationCoordinator implements Coordinator { @@ -49,7 +57,7 @@ public class PreparationCoordinator implements Coordinator { private final PreparationCoordinatorLogger mLogger; private final NotifInflater mNotifInflater; private final NotifInflationErrorManager mNotifErrorManager; - private final List<NotificationEntry> mPendingNotifications = new ArrayList<>(); + private final Map<NotificationEntry, Integer> mInflationStates = new ArrayMap<>(); private final IStatusBarService mStatusBarService; @Inject @@ -69,27 +77,44 @@ public class PreparationCoordinator implements Coordinator { @Override public void attach(NotifPipeline pipeline) { pipeline.addCollectionListener(mNotifCollectionListener); - pipeline.addPreRenderFilter(mNotifInflationErrorFilter); - pipeline.addPreRenderFilter(mNotifInflatingFilter); + // Inflate after grouping/sorting since that affects what views to inflate. + pipeline.addOnBeforeFinalizeFilterListener(mOnBeforeFinalizeFilterListener); + pipeline.addFinalizeFilter(mNotifInflationErrorFilter); + pipeline.addFinalizeFilter(mNotifInflatingFilter); } private final NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() { + @Override - public void onEntryAdded(NotificationEntry entry) { - inflateEntry(entry, "entryAdded"); + public void onEntryInit(NotificationEntry entry) { + mInflationStates.put(entry, STATE_UNINFLATED); } @Override public void onEntryUpdated(NotificationEntry entry) { - rebind(entry, "entryUpdated"); + @InflationState int state = getInflationState(entry); + if (state == STATE_INFLATED) { + mInflationStates.put(entry, STATE_INFLATED_INVALID); + } else if (state == STATE_ERROR) { + // Updated so maybe it won't error out now. + mInflationStates.put(entry, STATE_UNINFLATED); + } } @Override public void onEntryRemoved(NotificationEntry entry, int reason) { abortInflation(entry, "entryRemoved reason=" + reason); } + + @Override + public void onEntryCleanUp(NotificationEntry entry) { + mInflationStates.remove(entry); + } }; + private final OnBeforeFinalizeFilterListener mOnBeforeFinalizeFilterListener = + entries -> inflateAllRequiredViews(entries); + private final NotifFilter mNotifInflationErrorFilter = new NotifFilter( TAG + "InflationError") { /** @@ -97,10 +122,7 @@ public class PreparationCoordinator implements Coordinator { */ @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { - if (mNotifErrorManager.hasInflationError(entry)) { - return true; - } - return false; + return getInflationState(entry) == STATE_ERROR; } }; @@ -110,7 +132,8 @@ public class PreparationCoordinator implements Coordinator { */ @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { - return mPendingNotifications.contains(entry); + @InflationState int state = getInflationState(entry); + return (state != STATE_INFLATED) && (state != STATE_INFLATED_INVALID); } }; @@ -119,7 +142,7 @@ public class PreparationCoordinator implements Coordinator { @Override public void onInflationFinished(NotificationEntry entry) { mLogger.logNotifInflated(entry.getKey()); - mPendingNotifications.remove(entry); + mInflationStates.put(entry, STATE_INFLATED); mNotifInflatingFilter.invalidateList(); } }; @@ -128,7 +151,7 @@ public class PreparationCoordinator implements Coordinator { new NotifInflationErrorManager.NotifInflationErrorListener() { @Override public void onNotifInflationError(NotificationEntry entry, Exception e) { - mPendingNotifications.remove(entry); + mInflationStates.put(entry, STATE_ERROR); try { final StatusBarNotification sbn = entry.getSbn(); // report notification inflation errors back up @@ -152,9 +175,41 @@ public class PreparationCoordinator implements Coordinator { } }; + private void inflateAllRequiredViews(List<ListEntry> entries) { + for (int i = 0, size = entries.size(); i < size; i++) { + ListEntry entry = entries.get(i); + if (entry instanceof GroupEntry) { + GroupEntry groupEntry = (GroupEntry) entry; + inflateNotifRequiredViews(groupEntry.getSummary()); + List<NotificationEntry> children = groupEntry.getChildren(); + for (int j = 0, groupSize = children.size(); j < groupSize; j++) { + inflateNotifRequiredViews(children.get(j)); + } + } else { + NotificationEntry notifEntry = (NotificationEntry) entry; + inflateNotifRequiredViews(notifEntry); + } + } + } + + private void inflateNotifRequiredViews(NotificationEntry entry) { + @InflationState int state = mInflationStates.get(entry); + switch (state) { + case STATE_UNINFLATED: + inflateEntry(entry, "entryAdded"); + break; + case STATE_INFLATED_INVALID: + rebind(entry, "entryUpdated"); + break; + case STATE_INFLATED: + case STATE_ERROR: + default: + // Nothing to do. + } + } + private void inflateEntry(NotificationEntry entry, String reason) { abortInflation(entry, reason); - mPendingNotifications.add(entry); mNotifInflater.inflateViews(entry); } @@ -165,6 +220,32 @@ public class PreparationCoordinator implements Coordinator { private void abortInflation(NotificationEntry entry, String reason) { mLogger.logInflationAborted(entry.getKey(), reason); entry.abortTask(); - mPendingNotifications.remove(entry); } + + private @InflationState int getInflationState(NotificationEntry entry) { + Integer stateObj = mInflationStates.get(entry); + Objects.requireNonNull(stateObj, + "Asking state of a notification preparation coordinator doesn't know about"); + return stateObj; + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"STATE_"}, + value = {STATE_UNINFLATED, STATE_INFLATED_INVALID, STATE_INFLATED, STATE_ERROR}) + @interface InflationState {} + + /** The notification has never been inflated before. */ + private static final int STATE_UNINFLATED = 0; + + /** The notification is inflated. */ + private static final int STATE_INFLATED = 1; + + /** + * The notification is inflated, but its content may be out-of-date since the notification has + * been updated. + */ + private static final int STATE_INFLATED_INVALID = 2; + + /** The notification errored out while inflating */ + private static final int STATE_ERROR = -1; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java new file mode 100644 index 000000000000..086661ea219b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/OnBeforeFinalizeFilterListener.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2020 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 com.android.systemui.statusbar.notification.collection.listbuilder; + +import com.android.systemui.statusbar.notification.collection.ListEntry; +import com.android.systemui.statusbar.notification.collection.NotifPipeline; + +import java.util.List; + +/** See {@link NotifPipeline#addOnBeforeFinalizeFilterListener(OnBeforeFinalizeFilterListener)} */ +public interface OnBeforeFinalizeFilterListener { + /** + * Called after the notif list has been filtered, grouped, and sorted but before they are + * filtered one last time before rendering. + * + * @param entries The current list of top-level entries. Note that this is a live view into the + * current list and will change whenever the pipeline is rerun. + */ + void onBeforeFinalizeFilter(List<ListEntry> entries); +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java index 1897ba2319ac..f1f7d632b6f8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/PipelineState.java @@ -82,7 +82,7 @@ public class PipelineState { public static final int STATE_GROUPING = 4; public static final int STATE_TRANSFORMING = 5; public static final int STATE_SORTING = 6; - public static final int STATE_PRE_RENDER_FILTERING = 7; + public static final int STATE_FINALIZE_FILTERING = 7; public static final int STATE_FINALIZING = 8; @IntDef(prefix = { "STATE_" }, value = { @@ -93,7 +93,7 @@ public class PipelineState { STATE_GROUPING, STATE_TRANSFORMING, STATE_SORTING, - STATE_PRE_RENDER_FILTERING, + STATE_FINALIZE_FILTERING, STATE_FINALIZING, }) @Retention(RetentionPolicy.SOURCE) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt index 6e15043973f7..763547ce1638 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/ShadeListBuilderLogger.kt @@ -87,12 +87,12 @@ class ShadeListBuilderLogger @Inject constructor( }) } - fun logPreRenderFilterInvalidated(name: String, pipelineState: Int) { + fun logFinalizeFilterInvalidated(name: String, pipelineState: Int) { buffer.log(TAG, DEBUG, { str1 = name int1 = pipelineState }, { - """Pre-render NotifFilter "$str1" invalidated; pipeline state is $int1""" + """Finalize NotifFilter "$str1" invalidated; pipeline state is $int1""" }) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java index 8f575cdd8918..9edb5fc89d8f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifFilter.java @@ -21,7 +21,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; /** * Pluggable for participating in notif filtering. - * See {@link NotifPipeline#addPreGroupFilter} and {@link NotifPipeline#addPreRenderFilter}. + * See {@link NotifPipeline#addPreGroupFilter} and {@link NotifPipeline#addFinalizeFilter}. */ public abstract class NotifFilter extends Pluggable<NotifFilter> { protected NotifFilter(String name) { @@ -37,7 +37,7 @@ public abstract class NotifFilter extends Pluggable<NotifFilter> { * @param entry The entry in question. * If this filter is registered via {@link NotifPipeline#addPreGroupFilter}, * this entry will not have any grouping nor sorting information. - * If this filter is registered via {@link NotifPipeline#addPreRenderFilter}, + * If this filter is registered via {@link NotifPipeline#addFinalizeFilter}, * this entry will have grouping and sorting information. * @param now A timestamp in SystemClock.uptimeMillis that represents "now" for the purposes of * pipeline execution. This value will be the same for all pluggable calls made diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt index a3e59e52abe5..fd92ad026312 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt @@ -97,19 +97,25 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { @Test fun testBindService() { manager.bindService() + executor.runAllReady() assertTrue(mContext.isBound(componentName)) } @Test fun testUnbindService() { manager.bindService() + executor.runAllReady() + manager.unbindService() + executor.runAllReady() + assertFalse(mContext.isBound(componentName)) } @Test fun testMaybeBindAndLoad() { manager.maybeBindAndLoad(subscriberService) + executor.runAllReady() verify(service).load(subscriberService) @@ -119,14 +125,17 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { @Test fun testMaybeUnbind_bindingAndCallback() { manager.maybeBindAndLoad(subscriberService) + executor.runAllReady() manager.unbindService() + executor.runAllReady() assertFalse(mContext.isBound(componentName)) } @Test fun testMaybeBindAndLoad_timeout() { manager.maybeBindAndLoad(subscriberService) + executor.runAllReady() executor.advanceClockToLast() executor.runAllReady() @@ -138,6 +147,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { fun testMaybeBindAndSubscribe() { val list = listOf("TEST_ID") manager.maybeBindAndSubscribe(list) + executor.runAllReady() assertTrue(mContext.isBound(componentName)) verify(service).subscribe(list, subscriberService) @@ -148,6 +158,7 @@ class ControlsProviderLifecycleManagerTest : SysuiTestCase() { val controlId = "TEST_ID" val action = ControlAction.ERROR_ACTION manager.maybeBindAndSendAction(controlId, action) + executor.runAllReady() assertTrue(mContext.isBound(componentName)) verify(service).action(eq(controlId), capture(wrapperCaptor), diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java index 546fce851fd1..d7c72799e180 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java @@ -42,6 +42,7 @@ import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; import com.android.systemui.statusbar.notification.collection.ShadeListBuilder.OnRenderListListener; +import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeSortListener; import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeTransformGroupsListener; @@ -84,6 +85,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { @Mock private NotifCollection mNotifCollection; @Spy private OnBeforeTransformGroupsListener mOnBeforeTransformGroupsListener; @Spy private OnBeforeSortListener mOnBeforeSortListener; + @Spy private OnBeforeFinalizeFilterListener mOnBeforeFinalizeFilterListener; @Spy private OnBeforeRenderListListener mOnBeforeRenderListListener; @Spy private OnRenderListListener mOnRenderListListener = list -> mBuiltList = list; @@ -387,7 +389,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { NotifFilter preGroupFilter = spy(new PackageFilter(PACKAGE_2)); NotifFilter preRenderFilter = spy(new PackageFilter(PACKAGE_2)); mListBuilder.addPreGroupFilter(preGroupFilter); - mListBuilder.addPreRenderFilter(preRenderFilter); + mListBuilder.addFinalizeFilter(preRenderFilter); // WHEN the pipeline is kicked off on a list of notifs addNotif(0, PACKAGE_1); @@ -423,7 +425,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { public void testPreRenderNotifsAreFiltered() { // GIVEN a NotifFilter that filters out a specific package NotifFilter filter1 = spy(new PackageFilter(PACKAGE_2)); - mListBuilder.addPreRenderFilter(filter1); + mListBuilder.addFinalizeFilter(filter1); // WHEN the pipeline is kicked off on a list of notifs addNotif(0, PACKAGE_1); @@ -454,7 +456,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { final String filterTag = "FILTER_ME"; // GIVEN a NotifFilter that filters out notifications with a tag NotifFilter filter1 = spy(new NotifFilterWithTag(filterTag)); - mListBuilder.addPreRenderFilter(filter1); + mListBuilder.addFinalizeFilter(filter1); // WHEN the pipeline is kicked off on a list of notifs addGroupChildWithTag(0, PACKAGE_2, GROUP_1, filterTag); @@ -742,8 +744,9 @@ public class ShadeListBuilderTest extends SysuiTestCase { mListBuilder.addOnBeforeSortListener(mOnBeforeSortListener); mListBuilder.setComparators(Collections.singletonList(comparator)); mListBuilder.setSections(Arrays.asList(section)); + mListBuilder.addOnBeforeFinalizeFilterListener(mOnBeforeFinalizeFilterListener); + mListBuilder.addFinalizeFilter(preRenderFilter); mListBuilder.addOnBeforeRenderListListener(mOnBeforeRenderListListener); - mListBuilder.addPreRenderFilter(preRenderFilter); // WHEN a few new notifs are added addNotif(0, PACKAGE_1); @@ -763,6 +766,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { mOnBeforeSortListener, section, comparator, + mOnBeforeFinalizeFilterListener, preRenderFilter, mOnBeforeRenderListListener, mOnRenderListListener); @@ -777,6 +781,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { inOrder.verify(section, atLeastOnce()).isInSection(any(ListEntry.class)); inOrder.verify(comparator, atLeastOnce()) .compare(any(ListEntry.class), any(ListEntry.class)); + inOrder.verify(mOnBeforeFinalizeFilterListener).onBeforeFinalizeFilter(anyList()); inOrder.verify(preRenderFilter, atLeastOnce()) .shouldFilterOut(any(NotificationEntry.class), anyLong()); inOrder.verify(mOnBeforeRenderListListener).onBeforeRenderList(anyList()); @@ -1075,7 +1080,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { // GIVEN a PreRenderNotifFilter that gets invalidated during the finalizing stage NotifFilter filter = new PackageFilter(PACKAGE_5); OnBeforeRenderListListener listener = (list) -> filter.invalidateList(); - mListBuilder.addPreRenderFilter(filter); + mListBuilder.addFinalizeFilter(filter); mListBuilder.addOnBeforeRenderListListener(listener); // WHEN we try to run the pipeline and the PreRenderFilter is invalidated @@ -1090,7 +1095,7 @@ public class ShadeListBuilderTest extends SysuiTestCase { // GIVEN a PreRenderFilter that gets invalidated during the grouping stage NotifFilter filter = new PackageFilter(PACKAGE_5); OnBeforeTransformGroupsListener listener = (list) -> filter.invalidateList(); - mListBuilder.addPreRenderFilter(filter); + mListBuilder.addFinalizeFilter(filter); mListBuilder.addOnBeforeTransformGroupsListener(listener); // WHEN we try to run the pipeline and the filter is invalidated diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java index 5866d90f62bf..c4f3a1611afc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinatorTest.java @@ -88,7 +88,7 @@ public class KeyguardCoordinatorTest extends SysuiTestCase { ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class); mKeyguardCoordinator.attach(mNotifPipeline); - verify(mNotifPipeline, times(1)).addPreRenderFilter(filterCaptor.capture()); + verify(mNotifPipeline, times(1)).addFinalizeFilter(filterCaptor.capture()); mKeyguardFilter = filterCaptor.getValue(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java index 61a4fbe3526c..792b4d5c707c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java @@ -16,8 +16,8 @@ package com.android.systemui.statusbar.notification.collection.coordinator; -import static junit.framework.Assert.assertTrue; - +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; @@ -35,13 +35,16 @@ import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; +import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeFinalizeFilterListener; import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; +import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener; import com.android.systemui.statusbar.notification.row.NotifInflationErrorManager; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -54,14 +57,22 @@ public class PreparationCoordinatorTest extends SysuiTestCase { private static final String TEST_MESSAGE = "TEST_MESSAGE"; private PreparationCoordinator mCoordinator; + private NotifCollectionListener mCollectionListener; + private OnBeforeFinalizeFilterListener mBeforeFilterListener; + private NotifFilter mUninflatedFilter; private NotifFilter mInflationErrorFilter; + private NotifInflaterImpl.InflationCallback mCallback; private NotifInflationErrorManager mErrorManager; private NotificationEntry mEntry; private Exception mInflationError; - @Mock - private NotifPipeline mNotifPipeline; + @Captor private ArgumentCaptor<NotifCollectionListener> mCollectionListenerCaptor; + @Captor private ArgumentCaptor<OnBeforeFinalizeFilterListener> mBeforeFilterListenerCaptor; + @Captor private ArgumentCaptor<NotifInflaterImpl.InflationCallback> mCallbackCaptor; + + @Mock private NotifPipeline mNotifPipeline; @Mock private IStatusBarService mService; + @Mock private NotifInflaterImpl mNotifInflater; @Before public void setUp() { @@ -73,15 +84,28 @@ public class PreparationCoordinatorTest extends SysuiTestCase { mCoordinator = new PreparationCoordinator( mock(PreparationCoordinatorLogger.class), - mock(NotifInflaterImpl.class), + mNotifInflater, mErrorManager, mService); ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class); mCoordinator.attach(mNotifPipeline); - verify(mNotifPipeline, times(2)).addPreRenderFilter(filterCaptor.capture()); + verify(mNotifPipeline, times(2)).addFinalizeFilter(filterCaptor.capture()); List<NotifFilter> filters = filterCaptor.getAllValues(); mInflationErrorFilter = filters.get(0); + mUninflatedFilter = filters.get(1); + + verify(mNotifPipeline).addCollectionListener(mCollectionListenerCaptor.capture()); + mCollectionListener = mCollectionListenerCaptor.getValue(); + + verify(mNotifPipeline).addOnBeforeFinalizeFilterListener( + mBeforeFilterListenerCaptor.capture()); + mBeforeFilterListener = mBeforeFilterListenerCaptor.getValue(); + + verify(mNotifInflater).setInflationCallback(mCallbackCaptor.capture()); + mCallback = mCallbackCaptor.getValue(); + + mCollectionListener.onEntryInit(mEntry); } @Test @@ -108,4 +132,42 @@ public class PreparationCoordinatorTest extends SysuiTestCase { // THEN we filter it from the notification list. assertTrue(mInflationErrorFilter.shouldFilterOut(mEntry, 0)); } + + @Test + public void testInflatesNewNotification() { + // WHEN there is a new notification + mCollectionListener.onEntryAdded(mEntry); + mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); + + // THEN we inflate it + verify(mNotifInflater).inflateViews(mEntry); + + // THEN we filter it out until it's done inflating. + assertTrue(mUninflatedFilter.shouldFilterOut(mEntry, 0)); + } + + @Test + public void testRebindsInflatedNotificationsOnUpdate() { + // GIVEN an inflated notification + mCallback.onInflationFinished(mEntry); + + // WHEN notification is updated + mCollectionListener.onEntryUpdated(mEntry); + mBeforeFilterListener.onBeforeFinalizeFilter(List.of(mEntry)); + + // THEN we rebind it + verify(mNotifInflater).rebindViews(mEntry); + + // THEN we do not filter it because it's not the first inflation. + assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0)); + } + + @Test + public void testDoesntFilterInflatedNotifs() { + // WHEN a notification is inflated + mCallback.onInflationFinished(mEntry); + + // THEN it isn't filtered from shade list + assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0)); + } } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 7d970ed2c62c..f14a7e906c5d 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -2459,18 +2459,24 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return; } - if (!isSameViewEntered - && (flags & FLAG_MANUAL_REQUEST) == 0 - && mAugmentedAutofillableIds != null - && mAugmentedAutofillableIds.contains(id)) { - // View was already reported when server could not handle a response, but it - // triggered augmented autofill - - if (sDebug) Slog.d(TAG, "updateLocked(" + id + "): augmented-autofillable"); - - // ...then trigger the augmented autofill UI - triggerAugmentedAutofillLocked(); - return; + if ((flags & FLAG_MANUAL_REQUEST) == 0) { + // Not a manual request + if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains( + id)) { + // Regular autofill handled the view and returned null response, but it + // triggered augmented autofill + if (!isSameViewEntered) { + if (sDebug) Slog.d(TAG, "trigger augmented autofill."); + triggerAugmentedAutofillLocked(); + } else { + if (sDebug) Slog.d(TAG, "skip augmented autofill for same view."); + } + return; + } else if (mForAugmentedAutofillOnly && isSameViewEntered) { + // Regular autofill is disabled. + if (sDebug) Slog.d(TAG, "skip augmented autofill for same view."); + return; + } } if (requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags)) { diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java index 3148a6205871..cea3251d26a1 100644 --- a/services/core/java/com/android/server/PinnerService.java +++ b/services/core/java/com/android/server/PinnerService.java @@ -103,7 +103,7 @@ public final class PinnerService extends SystemService { private static boolean PROP_PIN_CAMERA = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT, "pin_camera", - SystemProperties.getBoolean("pinner.pin_camera", false)); + SystemProperties.getBoolean("pinner.pin_camera", true)); // Pin using pinlist.meta when pinning apps. private static boolean PROP_PIN_PINLIST = SystemProperties.getBoolean( "pinner.use_pinlist", true); diff --git a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java index 351dd6ed3d3d..dabf88670639 100644 --- a/services/core/java/com/android/server/locksettings/RebootEscrowManager.java +++ b/services/core/java/com/android/server/locksettings/RebootEscrowManager.java @@ -181,15 +181,13 @@ class RebootEscrowManager { } private void onEscrowRestoreComplete(boolean success) { - int previousBootCount = mStorage.getInt(REBOOT_ESCROW_ARMED_KEY, 0, USER_SYSTEM); + int previousBootCount = mStorage.getInt(REBOOT_ESCROW_ARMED_KEY, -1, USER_SYSTEM); mStorage.removeKey(REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM); int bootCountDelta = mInjector.getBootCount() - previousBootCount; - if (bootCountDelta > BOOT_COUNT_TOLERANCE) { - return; + if (success || (previousBootCount != -1 && bootCountDelta <= BOOT_COUNT_TOLERANCE)) { + mInjector.reportMetric(success); } - - mInjector.reportMetric(success); } private RebootEscrowKey getAndClearRebootEscrowKey() { diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index b6933623c559..0b1c91f4e2f5 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -171,7 +171,6 @@ import android.os.Environment; import android.os.Handler; import android.os.HandlerExecutor; import android.os.HandlerThread; -import android.os.IDeviceIdleController; import android.os.INetworkManagementService; import android.os.Message; import android.os.MessageQueue.IdleHandler; @@ -180,11 +179,11 @@ import android.os.PowerManager; import android.os.PowerManager.ServiceType; import android.os.PowerManagerInternal; import android.os.PowerSaveState; +import android.os.PowerWhitelistManager; import android.os.Process; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; -import android.os.ServiceManager; import android.os.ShellCallback; import android.os.SystemClock; import android.os.SystemProperties; @@ -411,7 +410,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private IConnectivityManager mConnManager; private PowerManagerInternal mPowerManagerInternal; - private IDeviceIdleController mDeviceIdleController; + private PowerWhitelistManager mPowerWhitelistManager; /** Current cached value of the current Battery Saver mode's setting for restrict background. */ @GuardedBy("mUidRulesFirstLock") @@ -618,8 +617,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mContext = Objects.requireNonNull(context, "missing context"); mActivityManager = Objects.requireNonNull(activityManager, "missing activityManager"); mNetworkManager = Objects.requireNonNull(networkManagement, "missing networkManagement"); - mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService( - Context.DEVICE_IDLE_CONTROLLER)); + mPowerWhitelistManager = mContext.getSystemService(PowerWhitelistManager.class); mClock = Objects.requireNonNull(clock, "missing Clock"); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mCarrierConfigManager = mContext.getSystemService(CarrierConfigManager.class); @@ -651,23 +649,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } @GuardedBy("mUidRulesFirstLock") - void updatePowerSaveWhitelistUL() { - try { - int[] whitelist = mDeviceIdleController.getAppIdWhitelistExceptIdle(); - mPowerSaveWhitelistExceptIdleAppIds.clear(); - if (whitelist != null) { - for (int uid : whitelist) { - mPowerSaveWhitelistExceptIdleAppIds.put(uid, true); - } - } - whitelist = mDeviceIdleController.getAppIdWhitelist(); - mPowerSaveWhitelistAppIds.clear(); - if (whitelist != null) { - for (int uid : whitelist) { - mPowerSaveWhitelistAppIds.put(uid, true); - } - } - } catch (RemoteException e) { + private void updatePowerSaveWhitelistUL() { + int[] whitelist = mPowerWhitelistManager.getWhitelistedAppIds(/* includingIdle */ false); + mPowerSaveWhitelistExceptIdleAppIds.clear(); + for (int uid : whitelist) { + mPowerSaveWhitelistExceptIdleAppIds.put(uid, true); + } + + whitelist = mPowerWhitelistManager.getWhitelistedAppIds(/* includingIdle */ true); + mPowerSaveWhitelistAppIds.clear(); + for (int uid : whitelist) { + mPowerSaveWhitelistAppIds.put(uid, true); } } diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp index f445aa810753..0487028e7cbc 100644 --- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp +++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp @@ -16,22 +16,17 @@ #define ATRACE_TAG ATRACE_TAG_ADB #define LOG_TAG "PackageManagerShellCommandDataLoader-jni" -#include <android-base/logging.h> - #include <android-base/file.h> +#include <android-base/logging.h> #include <android-base/stringprintf.h> #include <android-base/unique_fd.h> +#include <core_jni_helpers.h> #include <cutils/trace.h> +#include <endian.h> +#include <nativehelper/JNIHelp.h> #include <sys/eventfd.h> #include <sys/poll.h> -#include <nativehelper/JNIHelp.h> - -#include <core_jni_helpers.h> -#include <endian.h> - -#include "dataloader.h" - #include <charconv> #include <chrono> #include <span> @@ -40,6 +35,8 @@ #include <unordered_map> #include <unordered_set> +#include "dataloader.h" + namespace android { namespace { @@ -681,7 +678,7 @@ private: auto& writeFd = writeFds[fileIdx]; if (writeFd < 0) { - writeFd = this->mIfs->openWrite(fileId); + writeFd.reset(this->mIfs->openWrite(fileId)); if (writeFd < 0) { ALOGE("Failed to open file %d for writing (%d). Aboring.", header.fileIdx, -writeFd); diff --git a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java index 1cf8525eecdd..4127fece17bd 100644 --- a/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java +++ b/services/tests/servicestests/src/com/android/server/locksettings/RebootEscrowManagerTests.java @@ -293,9 +293,8 @@ public class RebootEscrowManagerTests { verify(mRebootEscrow, never()).storeKey(any()); - ArgumentCaptor<byte[]> keyByteCaptor = ArgumentCaptor.forClass(byte[].class); assertTrue(mService.armRebootEscrowIfNeeded()); - verify(mRebootEscrow).storeKey(keyByteCaptor.capture()); + verify(mRebootEscrow).storeKey(any()); assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID)); assertFalse(mStorage.hasRebootEscrow(NONSECURE_SECONDARY_USER_ID)); @@ -303,13 +302,72 @@ public class RebootEscrowManagerTests { // pretend reboot happens here when(mInjected.getBootCount()).thenReturn(10); - when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue()); + when(mRebootEscrow.retrieveKey()).thenReturn(new byte[32]); mService.loadRebootEscrowDataIfAvailable(); verify(mRebootEscrow).retrieveKey(); verify(mInjected, never()).reportMetric(anyBoolean()); } + @Test + public void loadRebootEscrowDataIfAvailable_ManualReboot_Failure_NoMetrics() throws Exception { + when(mInjected.getBootCount()).thenReturn(0); + + RebootEscrowListener mockListener = mock(RebootEscrowListener.class); + mService.setRebootEscrowListener(mockListener); + mService.prepareRebootEscrow(); + + clearInvocations(mRebootEscrow); + mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN); + verify(mockListener).onPreparedForReboot(eq(true)); + + verify(mRebootEscrow, never()).storeKey(any()); + + assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID)); + assertFalse(mStorage.hasRebootEscrow(NONSECURE_SECONDARY_USER_ID)); + + // pretend reboot happens here + + when(mInjected.getBootCount()).thenReturn(10); + when(mRebootEscrow.retrieveKey()).thenReturn(new byte[32]); + + mService.loadRebootEscrowDataIfAvailable(); + verify(mInjected, never()).reportMetric(anyBoolean()); + } + + @Test + public void loadRebootEscrowDataIfAvailable_OTAFromBeforeArmedStatus_SuccessMetrics() + throws Exception { + when(mInjected.getBootCount()).thenReturn(0); + + RebootEscrowListener mockListener = mock(RebootEscrowListener.class); + mService.setRebootEscrowListener(mockListener); + mService.prepareRebootEscrow(); + + clearInvocations(mRebootEscrow); + mService.callToRebootEscrowIfNeeded(PRIMARY_USER_ID, FAKE_SP_VERSION, FAKE_AUTH_TOKEN); + verify(mockListener).onPreparedForReboot(eq(true)); + + verify(mRebootEscrow, never()).storeKey(any()); + + ArgumentCaptor<byte[]> keyByteCaptor = ArgumentCaptor.forClass(byte[].class); + assertTrue(mService.armRebootEscrowIfNeeded()); + verify(mRebootEscrow).storeKey(keyByteCaptor.capture()); + + assertTrue(mStorage.hasRebootEscrow(PRIMARY_USER_ID)); + assertFalse(mStorage.hasRebootEscrow(NONSECURE_SECONDARY_USER_ID)); + + // Delete key to simulate old version that didn't have it. + mStorage.removeKey(RebootEscrowManager.REBOOT_ESCROW_ARMED_KEY, USER_SYSTEM); + + // pretend reboot happens here + + when(mInjected.getBootCount()).thenReturn(10); + when(mRebootEscrow.retrieveKey()).thenAnswer(invocation -> keyByteCaptor.getValue()); + + mService.loadRebootEscrowDataIfAvailable(); + verify(mInjected).reportMetric(eq(true)); + } @Test public void loadRebootEscrowDataIfAvailable_RestoreUnsuccessful_Failure() throws Exception { diff --git a/tests/ApkVerityTest/Android.bp b/tests/ApkVerityTest/Android.bp index c8d1ce1e7837..248206817740 100644 --- a/tests/ApkVerityTest/Android.bp +++ b/tests/ApkVerityTest/Android.bp @@ -16,7 +16,7 @@ java_test_host { name: "ApkVerityTest", srcs: ["src/**/*.java"], libs: ["tradefed", "compatibility-tradefed", "compatibility-host-util"], - test_suites: ["general-tests"], + test_suites: ["general-tests", "vts-core"], target_required: [ "block_device_writer_module", ], diff --git a/tests/ApkVerityTest/block_device_writer/Android.bp b/tests/ApkVerityTest/block_device_writer/Android.bp index 78850c534596..65cb3643259b 100644 --- a/tests/ApkVerityTest/block_device_writer/Android.bp +++ b/tests/ApkVerityTest/block_device_writer/Android.bp @@ -47,6 +47,6 @@ cc_test { }, }, - test_suites: ["general-tests", "pts"], + test_suites: ["general-tests", "pts", "vts-core"], gtest: false, } diff --git a/tests/RollbackTest/MultiUserRollbackTest.xml b/tests/RollbackTest/MultiUserRollbackTest.xml index 41cec461c377..ba86c3ff6777 100644 --- a/tests/RollbackTest/MultiUserRollbackTest.xml +++ b/tests/RollbackTest/MultiUserRollbackTest.xml @@ -15,9 +15,6 @@ --> <configuration description="Runs rollback tests for multiple users"> <option name="test-suite-tag" value="MultiUserRollbackTest" /> - <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"> - <option name="run-command" value="pm uninstall com.android.cts.install.lib.testapp.A" /> - </target_preparer> <test class="com.android.tradefed.testtype.HostTest" > <option name="class" value="com.android.tests.rollback.host.MultiUserRollbackTest" /> </test> diff --git a/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java b/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java index e616ac46830f..4c29e72ec713 100644 --- a/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java +++ b/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java @@ -40,15 +40,20 @@ public class MultiUserRollbackTest extends BaseHostJUnit4Test { private static final long SWITCH_USER_COMPLETED_NUMBER_OF_POLLS = 60; private static final long SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS = 1000; + private void cleanUp() throws Exception { + getDevice().executeShellCommand("pm rollback-app com.android.cts.install.lib.testapp.A"); + getDevice().executeShellCommand("pm uninstall com.android.cts.install.lib.testapp.A"); + } @After public void tearDown() throws Exception { - getDevice().executeShellCommand("pm uninstall com.android.cts.install.lib.testapp.A"); + cleanUp(); removeSecondaryUserIfNecessary(); } @Before public void setup() throws Exception { + cleanUp(); mOriginalUserId = getDevice().getCurrentUser(); createAndStartSecondaryUser(); // TODO(b/149733368): Remove the '-g' workaround when the bug is fixed. |