diff options
38 files changed, 640 insertions, 377 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index 45e33ce4b6e9..e40c78c494aa 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -401,6 +401,7 @@ java_aconfig_library { min_sdk_version: "30", apex_available: [ "//apex_available:platform", + "com.android.tethering", "com.android.wifi", ], defaults: ["framework-minus-apex-aconfig-java-defaults"], diff --git a/core/api/current.txt b/core/api/current.txt index cfbf9e55c7dc..ca4b2fae2f99 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -98,6 +98,7 @@ package android { field public static final String DUMP = "android.permission.DUMP"; field public static final String ENFORCE_UPDATE_OWNERSHIP = "android.permission.ENFORCE_UPDATE_OWNERSHIP"; field public static final String EXECUTE_APP_ACTION = "android.permission.EXECUTE_APP_ACTION"; + field @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final String EXECUTE_APP_FUNCTIONS = "android.permission.EXECUTE_APP_FUNCTIONS"; field public static final String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR"; field public static final String FACTORY_TEST = "android.permission.FACTORY_TEST"; field public static final String FOREGROUND_SERVICE = "android.permission.FOREGROUND_SERVICE"; @@ -8892,8 +8893,8 @@ package android.app.appfunctions { } @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public final class AppFunctionManager { - method @RequiresPermission(anyOf={"android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED", "android.permission.EXECUTE_APP_FUNCTIONS"}, conditional=true) public void executeAppFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.concurrent.Executor, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.app.appfunctions.ExecuteAppFunctionResponse,android.app.appfunctions.AppFunctionException>); - method @RequiresPermission(anyOf={"android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED", "android.permission.EXECUTE_APP_FUNCTIONS"}, conditional=true) public void isAppFunctionEnabled(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,java.lang.Exception>); + method @RequiresPermission(anyOf={"android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED", android.Manifest.permission.EXECUTE_APP_FUNCTIONS}, conditional=true) public void executeAppFunction(@NonNull android.app.appfunctions.ExecuteAppFunctionRequest, @NonNull java.util.concurrent.Executor, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<android.app.appfunctions.ExecuteAppFunctionResponse,android.app.appfunctions.AppFunctionException>); + method @RequiresPermission(anyOf={"android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED", android.Manifest.permission.EXECUTE_APP_FUNCTIONS}, conditional=true) public void isAppFunctionEnabled(@NonNull String, @NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,java.lang.Exception>); method public void isAppFunctionEnabled(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Boolean,java.lang.Exception>); method public void setAppFunctionEnabled(@NonNull String, int, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,java.lang.Exception>); field public static final int APP_FUNCTION_STATE_DEFAULT = 0; // 0x0 diff --git a/core/api/system-current.txt b/core/api/system-current.txt index e1d8fb11efb3..0ec438562558 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -150,7 +150,6 @@ package android { field @FlaggedApi("com.android.window.flags.untrusted_embedding_any_app_permission") public static final String EMBED_ANY_APP_IN_UNTRUSTED_MODE = "android.permission.EMBED_ANY_APP_IN_UNTRUSTED_MODE"; field @FlaggedApi("android.content.pm.emergency_install_permission") public static final String EMERGENCY_INSTALL_PACKAGES = "android.permission.EMERGENCY_INSTALL_PACKAGES"; field public static final String ENTER_CAR_MODE_PRIORITIZED = "android.permission.ENTER_CAR_MODE_PRIORITIZED"; - field @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final String EXECUTE_APP_FUNCTIONS = "android.permission.EXECUTE_APP_FUNCTIONS"; field @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") public static final String EXECUTE_APP_FUNCTIONS_TRUSTED = "android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED"; field public static final String EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS = "android.permission.EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS"; field public static final String FORCE_BACK = "android.permission.FORCE_BACK"; diff --git a/core/java/android/app/supervision/SupervisionManager.java b/core/java/android/app/supervision/SupervisionManager.java index aee1cd9b4760..a5b58f968c27 100644 --- a/core/java/android/app/supervision/SupervisionManager.java +++ b/core/java/android/app/supervision/SupervisionManager.java @@ -16,8 +16,10 @@ package android.app.supervision; +import android.annotation.RequiresPermission; import android.annotation.SystemService; import android.annotation.UserHandleAware; +import android.annotation.UserIdInt; import android.compat.annotation.UnsupportedAppUsage; import android.content.Context; import android.os.RemoteException; @@ -32,9 +34,7 @@ public class SupervisionManager { private final Context mContext; private final ISupervisionManager mService; - /** - * @hide - */ + /** @hide */ @UnsupportedAppUsage public SupervisionManager(Context context, ISupervisionManager service) { mContext = context; @@ -48,8 +48,23 @@ public class SupervisionManager { */ @UserHandleAware public boolean isSupervisionEnabled() { + return isSupervisionEnabledForUser(mContext.getUserId()); + } + + /** + * Returns whether the device is supervised. + * + * <p>The caller must be from the same user as the target or hold the {@link + * android.Manifest.permission#INTERACT_ACROSS_USERS} permission. + * + * @hide + */ + @RequiresPermission( + value = android.Manifest.permission.INTERACT_ACROSS_USERS, + conditional = true) + public boolean isSupervisionEnabledForUser(@UserIdInt int userId) { try { - return mService.isSupervisionEnabledForUser(mContext.getUserId()); + return mService.isSupervisionEnabledForUser(userId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/os/IHintManager.aidl b/core/java/android/os/IHintManager.aidl index 56a089aff78a..4a14a8d0faf8 100644 --- a/core/java/android/os/IHintManager.aidl +++ b/core/java/android/os/IHintManager.aidl @@ -21,13 +21,11 @@ import android.os.CpuHeadroomParamsInternal; import android.os.GpuHeadroomParamsInternal; import android.os.IHintSession; import android.os.SessionCreationConfig; - -import android.hardware.power.ChannelConfig; import android.hardware.power.CpuHeadroomResult; +import android.hardware.power.ChannelConfig; import android.hardware.power.GpuHeadroomResult; import android.hardware.power.SessionConfig; import android.hardware.power.SessionTag; -import android.hardware.power.SupportInfo; /** {@hide} */ interface IHintManager { @@ -42,6 +40,11 @@ interface IHintManager { IHintSession createHintSessionWithConfig(in IBinder token, in SessionTag tag, in SessionCreationConfig creationConfig, out SessionConfig config); + /** + * Get preferred rate limit in nanoseconds. + */ + long getHintSessionPreferredRate(); + void setHintSessionThreads(in IHintSession hintSession, in int[] tids); int[] getHintSessionThreadIds(in IHintSession hintSession); @@ -58,28 +61,13 @@ interface IHintManager { long getGpuHeadroomMinIntervalMillis(); /** - * Used by the JNI to pass an interface to the SessionManager; - * for internal use only. + * Get Maximum number of graphics pipeline threads allowed per-app. */ - oneway void passSessionManagerBinder(in IBinder sessionManager); - - parcelable HintManagerClientData { - int powerHalVersion; - int maxGraphicsPipelineThreads; - long preferredRateNanos; - SupportInfo supportInfo; - } - - interface IHintManagerClient { - /** - * Returns FMQ channel information for the caller, which it associates to the callback binder lifespan. - */ - oneway void receiveChannelConfig(in ChannelConfig config); - } + int getMaxGraphicsPipelineThreadsCount(); /** - * Set up an ADPF client, receiving a remote client binder interface and - * passing back a bundle of support and configuration information. + * Used by the JNI to pass an interface to the SessionManager; + * for internal use only. */ - HintManagerClientData registerClient(in IHintManagerClient client); + oneway void passSessionManagerBinder(in IBinder sessionManager); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index c14854023b39..cf0e90fb43ce 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -13710,6 +13710,14 @@ public final class Settings { "render_shadows_in_compositor"; /** + * Policy to be used for the display shade when connected to an external display. + * @hide + */ + @Readable + public static final String DEVELOPMENT_SHADE_DISPLAY_AWARENESS = + "shade_display_awareness"; + + /** * Path to the WindowManager display settings file. If unset, the default file path will * be used. * diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 82cad8b3a477..4a948dd91fb0 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -8307,20 +8307,21 @@ android:featureFlag="android.app.appfunctions.flags.enable_app_function_manager" android:protectionLevel="signature" /> - <!-- @SystemApi Allows a trusted application to perform actions on behalf of users inside of + <!-- Allows a trusted application to perform actions on behalf of users inside of applications with privacy guarantees from the system. <p>This permission is currently only granted to system packages in the {@link android.app.role.SYSTEM_UI_INTELLIGENCE} role which complies with privacy requirements outlined in the Android CDD section "9.8.6 Content Capture". <p>Apps are not able to opt-out from caller having this permission. <p>Protection level: internal|role + @SystemApi @hide - @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") --> + @FlaggedApi(android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER) --> <permission android:name="android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED" android:featureFlag="android.app.appfunctions.flags.enable_app_function_manager" android:protectionLevel="internal|role" /> - <!-- @SystemApi Allows an application to perform actions on behalf of users inside of + <!-- Allows an application to perform actions on behalf of users inside of applications. <p>This permission is currently only granted to preinstalled / system apps having the {@link android.app.role.ASSISTANT} role. @@ -8328,8 +8329,7 @@ limiting to only callers with {@link android.permission.EXECUTE_APP_FUNCTIONS_TRUSTED} instead. <p>Protection level: internal|role - @hide - @FlaggedApi("android.app.appfunctions.flags.enable_app_function_manager") --> + @FlaggedApi(android.app.appfunctions.flags.Flags.FLAG_ENABLE_APP_FUNCTION_MANAGER) --> <permission android:name="android.permission.EXECUTE_APP_FUNCTIONS" android:featureFlag="android.app.appfunctions.flags.enable_app_function_manager" android:protectionLevel="internal|role" /> diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java index 248efde4902c..bbb03e77c8c9 100644 --- a/media/java/android/media/MediaRoute2Info.java +++ b/media/java/android/media/MediaRoute2Info.java @@ -934,6 +934,15 @@ public final class MediaRoute2Info implements Parcelable { } /** + * Returns whether this route supports {@link #FLAG_ROUTING_TYPE_REMOTE remote routing}. + * + * @hide + */ + public boolean supportsRemoteRouting() { + return (mRoutingTypeFlags & MediaRoute2Info.FLAG_ROUTING_TYPE_REMOTE) != 0; + } + + /** * Returns true if the route info has all of the required field. * A route is valid if and only if it is obtained from * {@link com.android.server.media.MediaRouterService}. diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp index 9257901bcd1f..0db99ffd208a 100644 --- a/native/android/performance_hint.cpp +++ b/native/android/performance_hint.cpp @@ -22,7 +22,6 @@ #include <aidl/android/hardware/power/SessionHint.h> #include <aidl/android/hardware/power/SessionMode.h> #include <aidl/android/hardware/power/SessionTag.h> -#include <aidl/android/hardware/power/SupportInfo.h> #include <aidl/android/hardware/power/WorkDuration.h> #include <aidl/android/hardware/power/WorkDurationFixedV1.h> #include <aidl/android/os/IHintManager.h> @@ -149,36 +148,10 @@ private: std::future<bool> mChannelCreationFinished; }; -class SupportInfoWrapper { -public: - SupportInfoWrapper(hal::SupportInfo& info); - bool isSessionModeSupported(hal::SessionMode mode); - bool isSessionHintSupported(hal::SessionHint hint); - -private: - template <class T> - bool getEnumSupportFromBitfield(T& enumValue, int64_t& supportBitfield) { - // extract the bit corresponding to the enum by shifting the bitfield - // over that much and cutting off any extra values - return (supportBitfield >> static_cast<int>(enumValue)) % 2; - } - hal::SupportInfo mSupportInfo; -}; - -class HintManagerClient : public IHintManager::BnHintManagerClient { -public: - // Currently a no-op that exists for FMQ init to call in the future - ndk::ScopedAStatus receiveChannelConfig(const hal::ChannelConfig&) { - return ndk::ScopedAStatus::ok(); - } -}; - struct APerformanceHintManager { public: static APerformanceHintManager* getInstance(); - APerformanceHintManager(std::shared_ptr<IHintManager>& service, - IHintManager::HintManagerClientData&& clientData, - std::shared_ptr<HintManagerClient> callbackClient); + APerformanceHintManager(std::shared_ptr<IHintManager>& service, int64_t preferredRateNanos); APerformanceHintManager() = delete; ~APerformanceHintManager(); @@ -196,21 +169,29 @@ public: FMQWrapper& getFMQWrapper(); bool canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) REQUIRES(sHintMutex); void initJava(JNIEnv* _Nonnull env); + ndk::ScopedAIBinder_Weak x; template <class T> static void layersFromNativeSurfaces(ANativeWindow** windows, int numWindows, ASurfaceControl** controls, int numSurfaceControls, std::vector<T>& out); - ndk::SpAIBinder& getToken(); - SupportInfoWrapper& getSupportInfo(); private: + // Necessary to create an empty binder object + static void* tokenStubOnCreate(void*) { + return nullptr; + } + static void tokenStubOnDestroy(void*) {} + static binder_status_t tokenStubOnTransact(AIBinder*, transaction_code_t, const AParcel*, + AParcel*) { + return STATUS_OK; + } + static APerformanceHintManager* create(std::shared_ptr<IHintManager> iHintManager); std::shared_ptr<IHintManager> mHintManager; - std::shared_ptr<HintManagerClient> mCallbackClient; - IHintManager::HintManagerClientData mClientData; - SupportInfoWrapper mSupportInfoWrapper; ndk::SpAIBinder mToken; + const int64_t mPreferredRateNanos; + std::optional<int32_t> mMaxGraphicsPipelineThreadsCount; FMQWrapper mFMQWrapper; double mHintBudget = kMaxLoadHintsPerInterval; int64_t mLastBudgetReplenish = 0; @@ -292,27 +273,14 @@ static FMQWrapper& getFMQ() { return APerformanceHintManager::getInstance()->getFMQWrapper(); } -// ===================================== SupportInfoWrapper implementation - -SupportInfoWrapper::SupportInfoWrapper(hal::SupportInfo& info) : mSupportInfo(info) {} - -bool SupportInfoWrapper::isSessionHintSupported(hal::SessionHint hint) { - return getEnumSupportFromBitfield(hint, mSupportInfo.sessionHints); -} - -bool SupportInfoWrapper::isSessionModeSupported(hal::SessionMode mode) { - return getEnumSupportFromBitfield(mode, mSupportInfo.sessionModes); -} - // ===================================== APerformanceHintManager implementation APerformanceHintManager::APerformanceHintManager(std::shared_ptr<IHintManager>& manager, - IHintManager::HintManagerClientData&& clientData, - std::shared_ptr<HintManagerClient> callbackClient) - : mHintManager(std::move(manager)), - mCallbackClient(callbackClient), - mClientData(clientData), - mSupportInfoWrapper(clientData.supportInfo), - mToken(callbackClient->asBinder()) { + int64_t preferredRateNanos) + : mHintManager(std::move(manager)), mPreferredRateNanos(preferredRateNanos) { + static AIBinder_Class* tokenBinderClass = + AIBinder_Class_define("phm_token", tokenStubOnCreate, tokenStubOnDestroy, + tokenStubOnTransact); + mToken = ndk::SpAIBinder(AIBinder_new(tokenBinderClass, nullptr)); if (mFMQWrapper.isSupported()) { mFMQWrapper.setToken(mToken); mFMQWrapper.startChannel(mHintManager.get()); @@ -347,17 +315,16 @@ APerformanceHintManager* APerformanceHintManager::create(std::shared_ptr<IHintMa ALOGE("%s: PerformanceHint service is not ready ", __FUNCTION__); return nullptr; } - std::shared_ptr<HintManagerClient> client = ndk::SharedRefBase::make<HintManagerClient>(); - IHintManager::HintManagerClientData clientData; - ndk::ScopedAStatus ret = manager->registerClient(client, &clientData); + int64_t preferredRateNanos = -1L; + ndk::ScopedAStatus ret = manager->getHintSessionPreferredRate(&preferredRateNanos); if (!ret.isOk()) { - ALOGE("%s: PerformanceHint is not supported. %s", __FUNCTION__, ret.getMessage()); + ALOGE("%s: PerformanceHint cannot get preferred rate. %s", __FUNCTION__, ret.getMessage()); return nullptr; } - if (clientData.preferredRateNanos <= 0) { - clientData.preferredRateNanos = -1L; + if (preferredRateNanos <= 0) { + preferredRateNanos = -1L; } - return new APerformanceHintManager(manager, std::move(clientData), client); + return new APerformanceHintManager(manager, preferredRateNanos); } bool APerformanceHintManager::canSendLoadHints(std::vector<hal::SessionHint>& hints, int64_t now) { @@ -422,9 +389,7 @@ APerformanceHintSession* APerformanceHintManager::createSessionUsingConfig( ALOGE("%s: PerformanceHint cannot create session. %s", __FUNCTION__, ret.getMessage()); return nullptr; } - - auto out = new APerformanceHintSession(mHintManager, std::move(session), - mClientData.preferredRateNanos, + auto out = new APerformanceHintSession(mHintManager, std::move(session), mPreferredRateNanos, sessionCreationConfig->targetWorkDurationNanos, isJava, sessionConfig.id == -1 ? std::nullopt @@ -451,11 +416,24 @@ APerformanceHintSession* APerformanceHintManager::getSessionFromJava(JNIEnv* env } int64_t APerformanceHintManager::getPreferredRateNanos() const { - return mClientData.preferredRateNanos; + return mPreferredRateNanos; } int32_t APerformanceHintManager::getMaxGraphicsPipelineThreadsCount() { - return mClientData.maxGraphicsPipelineThreads; + if (!mMaxGraphicsPipelineThreadsCount.has_value()) { + int32_t threadsCount = -1; + ndk::ScopedAStatus ret = mHintManager->getMaxGraphicsPipelineThreadsCount(&threadsCount); + if (!ret.isOk()) { + ALOGE("%s: PerformanceHint cannot get max graphics pipeline threads count. %s", + __FUNCTION__, ret.getMessage()); + return -1; + } + if (threadsCount <= 0) { + threadsCount = -1; + } + mMaxGraphicsPipelineThreadsCount.emplace(threadsCount); + } + return mMaxGraphicsPipelineThreadsCount.value(); } FMQWrapper& APerformanceHintManager::getFMQWrapper() { @@ -472,14 +450,6 @@ void APerformanceHintManager::initJava(JNIEnv* _Nonnull env) { mJavaInitialized = true; } -ndk::SpAIBinder& APerformanceHintManager::getToken() { - return mToken; -} - -SupportInfoWrapper& APerformanceHintManager::getSupportInfo() { - return mSupportInfoWrapper; -} - // ===================================== APerformanceHintSession implementation constexpr int kNumEnums = enum_size<hal::SessionHint>(); diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp index e3c10f63abb4..c166e738ffb2 100644 --- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp +++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp @@ -56,6 +56,9 @@ public: const SessionCreationConfig& creationConfig, hal::SessionConfig* config, std::shared_ptr<IHintSession>* _aidl_return), (override)); + MOCK_METHOD(ScopedAStatus, getHintSessionPreferredRate, (int64_t * _aidl_return), (override)); + MOCK_METHOD(ScopedAStatus, getMaxGraphicsPipelineThreadsCount, (int32_t* _aidl_return), + (override)); MOCK_METHOD(ScopedAStatus, setHintSessionThreads, (const std::shared_ptr<IHintSession>& hintSession, const ::std::vector<int32_t>& tids), @@ -81,11 +84,6 @@ public: MOCK_METHOD(ScopedAStatus, getGpuHeadroomMinIntervalMillis, (int64_t* _aidl_return), (override)); MOCK_METHOD(ScopedAStatus, passSessionManagerBinder, (const SpAIBinder& sessionManager)); - MOCK_METHOD(ScopedAStatus, registerClient, - (const std::shared_ptr<::aidl::android::os::IHintManager::IHintManagerClient>& - clientDataIn, - ::aidl::android::os::IHintManager::HintManagerClientData* _aidl_return), - (override)); MOCK_METHOD(SpAIBinder, asBinder, (), (override)); MOCK_METHOD(bool, isRemote, (), (override)); }; @@ -127,9 +125,10 @@ public: APerformanceHintManager* createManager() { APerformanceHint_setUseFMQForTesting(mUsingFMQ); - ON_CALL(*mMockIHintManager, registerClient(_, _)) - .WillByDefault( - DoAll(SetArgPointee<1>(mClientData), [] { return ScopedAStatus::ok(); })); + ON_CALL(*mMockIHintManager, getHintSessionPreferredRate(_)) + .WillByDefault(DoAll(SetArgPointee<0>(123L), [] { return ScopedAStatus::ok(); })); + ON_CALL(*mMockIHintManager, getMaxGraphicsPipelineThreadsCount(_)) + .WillByDefault(DoAll(SetArgPointee<0>(5), [] { return ScopedAStatus::ok(); })); return APerformanceHint_getManager(); } @@ -239,20 +238,6 @@ public: int kMockQueueSize = 20; bool mUsingFMQ = false; - IHintManager::HintManagerClientData mClientData{ - .powerHalVersion = 6, - .maxGraphicsPipelineThreads = 5, - .preferredRateNanos = 123L, - .supportInfo{ - .usesSessions = true, - .boosts = 0, - .modes = 0, - .sessionHints = -1, - .sessionModes = -1, - .sessionTags = -1, - }, - }; - int32_t mMaxLoadHintsPerInterval; int64_t mLoadHintInterval; @@ -271,6 +256,12 @@ bool equalsWithoutTimestamp(hal::WorkDuration lhs, hal::WorkDuration rhs) { lhs.gpuDurationNanos == rhs.gpuDurationNanos && lhs.durationNanos == rhs.durationNanos; } +TEST_F(PerformanceHintTest, TestGetPreferredUpdateRateNanos) { + APerformanceHintManager* manager = createManager(); + int64_t preferredUpdateRateNanos = APerformanceHint_getPreferredUpdateRateNanos(manager); + EXPECT_EQ(123L, preferredUpdateRateNanos); +} + TEST_F(PerformanceHintTest, TestSession) { APerformanceHintManager* manager = createManager(); APerformanceHintSession* session = createSession(manager); diff --git a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/SettingsSpinnerPreference.java b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/SettingsSpinnerPreference.java index 63fe1b509751..e173c5e996df 100644 --- a/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/SettingsSpinnerPreference.java +++ b/packages/SettingsLib/SettingsSpinner/src/com/android/settingslib/widget/SettingsSpinnerPreference.java @@ -25,13 +25,15 @@ import android.widget.Spinner; import androidx.preference.Preference; import androidx.preference.Preference.OnPreferenceClickListener; import androidx.preference.PreferenceViewHolder; + import com.android.settingslib.widget.spinner.R; /** * This preference uses Spinner & SettingsSpinnerAdapter which provide default layouts for * both view and drop down view of the Spinner. */ -public class SettingsSpinnerPreference extends Preference implements OnPreferenceClickListener { +public class SettingsSpinnerPreference extends Preference + implements OnPreferenceClickListener, GroupSectionDividerMixin { private SettingsSpinnerAdapter mAdapter; private AdapterView.OnItemSelectedListener mListener; diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml index 5a4d3ce5661b..63c8929ef652 100644 --- a/packages/SettingsLib/res/values/arrays.xml +++ b/packages/SettingsLib/res/values/arrays.xml @@ -667,4 +667,25 @@ <item>3</item> </string-array> + <!-- Options for showing shade on external display for developers --> + <string-array name="shade_display_awareness_entries" > + <item>Device display only (Default)</item> + <item>External display</item> + <item>Focus-based</item> + </string-array> + + <!-- Options for showing shade on external display for developers --> + <string-array name="shade_display_awareness_summaries" > + <item>Show shade on device display only </item> + <item>Show device on single external display</item> + <item>Show device on last focused display</item> + </string-array> + + <!-- Values for showing shade on external display for developers --> + <string-array name="shade_display_awareness_values" > + <item>device-display</item> + <item>external-display</item> + <item>focus-based</item> + </string-array> + </resources> diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index eaf155df4785..e1929b725a58 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -990,6 +990,9 @@ <!-- UI debug setting: simulate secondary display devices using overlays [CHAR LIMIT=45] --> <string name="overlay_display_devices_title">Simulate secondary displays</string> + <!-- UI debug setting: shade display awareness title [CHAR LIMIT=45] --> + <string name="shade_display_awareness_title">Shade display position</string> + <!-- Preference category for application debugging development settings. [CHAR LIMIT=25] --> <string name="debug_applications_category">Apps</string> diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 9004488c2e12..c88a7fd834d6 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -182,6 +182,7 @@ public class SettingsBackupTest { Settings.Global.DEVELOPMENT_FORCE_RTL, Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, + Settings.Global.DEVELOPMENT_SHADE_DISPLAY_AWARENESS, Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH, Settings.Global.DEVICE_DEMO_MODE, Settings.Global.DEVICE_IDLE_CONSTANTS, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt index 5fb9416cf35b..e4f4df386583 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt @@ -37,6 +37,7 @@ import com.android.systemui.notifications.ui.composable.SnoozeableHeadsUpNotific import com.android.systemui.qs.ui.composable.QuickSettings import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.Default +import com.android.systemui.scene.shared.model.Overlays import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.scene.ui.viewmodel.GoneUserActionsViewModel import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView @@ -70,18 +71,22 @@ constructor( @Composable override fun SceneScope.Content(modifier: Modifier) { - val isIdle by remember { - derivedStateOf { layoutState.transitionState is TransitionState.Idle } + val isIdleAndNotOccluded by remember { + derivedStateOf { + layoutState.transitionState is TransitionState.Idle && + Overlays.NotificationsShade !in layoutState.transitionState.currentOverlays + } } - LaunchedEffect(isIdle) { + LaunchedEffect(isIdleAndNotOccluded) { // Wait for being Idle on this Scene, otherwise LaunchedEffect would fire too soon, // and another transition could override the NSSL stack bounds. - if (isIdle) { + if (isIdleAndNotOccluded) { // Reset the stack bounds to avoid caching these values from the previous Scenes, // and not to confuse the StackScrollAlgorithm when it displays a HUN over GONE. notificationStackScrolLView.get().apply { - setStackTop(0f) + // use -headsUpInset to allow HUN translation outside bounds for snoozing + setStackTop(-getHeadsUpInset().toFloat()) setStackCutoff(0f) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt index c5bef99f9307..ef68b4de5291 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/NotificationScrollViewBinder.kt @@ -109,11 +109,6 @@ constructor( } } launch { - viewModel.shouldResetStackTop - .filter { it } - .collectTraced { view.setStackTop(-(view.getHeadsUpInset().toFloat())) } - } - launch { viewModel.shouldCloseGuts .filter { it } .collectTraced { view.closeGutsOnSceneTouch() } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt index 56b335648138..1bb205cbcb61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationScrollViewModel.kt @@ -192,12 +192,6 @@ constructor( /** Whether we should close any open notification guts. */ val shouldCloseGuts: Flow<Boolean> = stackAppearanceInteractor.shouldCloseGuts - val shouldResetStackTop: Flow<Boolean> = - sceneInteractor.transitionState - .mapNotNull { state -> state is Idle && state.currentScene == Scenes.Gone } - .distinctUntilChanged() - .dumpWhileCollecting("shouldResetStackTop") - /** Whether the Notification Stack is visibly on the lockscreen scene. */ val isShowingStackOnLockscreen: Flow<Boolean> = sceneInteractor.transitionState diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index f42641ece09b..aadf6f61956c 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -2840,7 +2840,6 @@ public class OomAdjuster { return true; } } - capability |= PROCESS_CAPABILITY_CPU_TIME; } // Not doing bind OOM management, so treat // this guy more like a started service. @@ -3089,7 +3088,6 @@ public class OomAdjuster { return true; } } - capability |= PROCESS_CAPABILITY_CPU_TIME; } } if (cr.hasFlag(Context.BIND_TREAT_LIKE_ACTIVITY)) { @@ -4243,6 +4241,11 @@ public class OomAdjuster { != client.getSetCapability()) { // The connection might elevate the importance of the service's capabilities. needDryRun = true; + } else if (Flags.useCpuTimeCapability() + && (client.getSetCapability() & ~app.getSetCapability() + & PROCESS_CAPABILITY_CPU_TIME) != 0) { + // The connection might grant PROCESS_CAPABILITY_CPU_TIME to the service. + needDryRun = true; } else if (Flags.unfreezeBindPolicyFix() && cr.hasFlag(Context.BIND_WAIVE_PRIORITY | Context.BIND_ALLOW_OOM_MANAGEMENT)) { @@ -4290,6 +4293,10 @@ public class OomAdjuster { && client.mOptRecord.shouldNotFreeze()) { // Process has shouldNotFreeze and it could have gotten it from the client. return true; + } else if (Flags.useCpuTimeCapability() + && (client.getSetCapability() & app.getSetCapability() + & PROCESS_CAPABILITY_CPU_TIME) != 0) { + return true; } return false; } @@ -4309,6 +4316,11 @@ public class OomAdjuster { && client.mOptRecord.shouldNotFreeze() && !app.mOptRecord.shouldNotFreeze()) { needDryRun = true; + } else if (Flags.useCpuTimeCapability() + && (client.getSetCapability() & ~app.getSetCapability() + & PROCESS_CAPABILITY_CPU_TIME) != 0) { + // The connection might grant PROCESS_CAPABILITY_CPU_TIME to the provider. + needDryRun = true; } if (needDryRun) { @@ -4335,6 +4347,10 @@ public class OomAdjuster { && client.mOptRecord.shouldNotFreeze()) { // Process has shouldNotFreeze and it could have gotten it from the client. return true; + } else if (Flags.useCpuTimeCapability() + && (client.getSetCapability() & app.getSetCapability() + & PROCESS_CAPABILITY_CPU_TIME) != 0) { + return true; } return false; diff --git a/services/core/java/com/android/server/display/BrightnessRangeController.java b/services/core/java/com/android/server/display/BrightnessRangeController.java index 83b0801ce87f..50d650855b05 100644 --- a/services/core/java/com/android/server/display/BrightnessRangeController.java +++ b/services/core/java/com/android/server/display/BrightnessRangeController.java @@ -37,7 +37,6 @@ class BrightnessRangeController { private final HdrClamper mHdrClamper; private final Runnable mModeChangeCallback; - private final boolean mUseNbmController; private final boolean mUseHdrClamper; @@ -62,11 +61,8 @@ class BrightnessRangeController { mHdrClamper = hdrClamper; mNormalBrightnessModeController = normalBrightnessModeController; mUseHdrClamper = flags.isHdrClamperEnabled() && !flags.useNewHdrBrightnessModifier(); - mUseNbmController = flags.isNbmControllerEnabled(); - if (mUseNbmController) { - mNormalBrightnessModeController.resetNbmData( - displayDeviceConfig.getLuxThrottlingData()); - } + mNormalBrightnessModeController.resetNbmData( + displayDeviceConfig.getLuxThrottlingData()); if (flags.useNewHdrBrightnessModifier()) { // HDR boost is handled by HdrBrightnessModifier and should be disabled in HbmController mHbmController.disableHdrBoost(); @@ -76,7 +72,6 @@ class BrightnessRangeController { void dump(PrintWriter pw) { pw.println("BrightnessRangeController:"); - pw.println(" mUseNormalBrightnessController=" + mUseNbmController); pw.println(" mUseHdrClamper=" + mUseHdrClamper); mHbmController.dump(pw); mNormalBrightnessModeController.dump(pw); @@ -138,9 +133,7 @@ class BrightnessRangeController { float getCurrentBrightnessMax() { // nbmController might adjust maxBrightness only if device does not support HBM or // hbm is currently not allowed - if (mUseNbmController - && (!mHbmController.deviceSupportsHbm() - || !mHbmController.isHbmCurrentlyAllowed())) { + if (!mHbmController.deviceSupportsHbm() || !mHbmController.isHbmCurrentlyAllowed()) { return Math.min(mHbmController.getCurrentBrightnessMax(), mNormalBrightnessModeController.getCurrentBrightnessMax()); } @@ -173,16 +166,12 @@ class BrightnessRangeController { } private void applyChanges(BooleanSupplier nbmChangesFunc, Runnable hbmChangesFunc) { - if (mUseNbmController) { - boolean nbmTransitionChanged = nbmChangesFunc.getAsBoolean(); - hbmChangesFunc.run(); - // if nbm transition changed - trigger callback - // HighBrightnessModeController handles sending changes itself - if (nbmTransitionChanged) { - mModeChangeCallback.run(); - } - } else { - hbmChangesFunc.run(); + boolean nbmTransitionChanged = nbmChangesFunc.getAsBoolean(); + hbmChangesFunc.run(); + // if nbm transition changed - trigger callback + // HighBrightnessModeController handles sending changes itself + if (nbmTransitionChanged) { + mModeChangeCallback.run(); } } diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java index 7892639fc8ed..52e64905c984 100644 --- a/services/core/java/com/android/server/display/color/ColorDisplayService.java +++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java @@ -168,8 +168,7 @@ public final class ColorDisplayService extends SystemService { new NightDisplayTintController(); private final TintController mGlobalSaturationTintController = new GlobalSaturationTintController(); - private final ReduceBrightColorsTintController mReduceBrightColorsTintController = - new ReduceBrightColorsTintController(); + private final ReduceBrightColorsTintController mReduceBrightColorsTintController; @VisibleForTesting final Handler mHandler; @@ -201,7 +200,13 @@ public final class ColorDisplayService extends SystemService { private boolean mEvenDimmerActivated; public ColorDisplayService(Context context) { + this(context, new ReduceBrightColorsTintController()); + } + + @VisibleForTesting + public ColorDisplayService(Context context, ReduceBrightColorsTintController rbcController) { super(context); + mReduceBrightColorsTintController = rbcController; mHandler = new TintHandler(DisplayThread.get().getLooper()); mVisibleBackgroundUsersEnabled = isVisibleBackgroundUsersEnabled(); mUserManager = UserManagerService.getInstance(); @@ -571,27 +576,37 @@ public final class ColorDisplayService extends SystemService { return mColorModeCompositionColorSpaces.get(mode, Display.COLOR_MODE_INVALID); } - private void onDisplayColorModeChanged(int mode) { + @VisibleForTesting + void onDisplayColorModeChanged(int mode) { if (mode == NOT_SET) { return; } + mReduceBrightColorsTintController.cancelAnimator(); mNightDisplayTintController.cancelAnimator(); mDisplayWhiteBalanceTintController.cancelAnimator(); + final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); + if (mNightDisplayTintController.isAvailable(getContext())) { - final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); mNightDisplayTintController.setUp(getContext(), dtm.needsLinearColorMatrix(mode)); mNightDisplayTintController .setMatrix(mNightDisplayTintController.getColorTemperatureSetting()); } + if (mReduceBrightColorsTintController.isAvailable(getContext())) { + // Different color modes may require different coefficients to be loaded for RBC. + // Re-set up RBC so that it can recalculate its transform matrix with new values. + mReduceBrightColorsTintController.setUp(getContext(), dtm.needsLinearColorMatrix(mode)); + onReduceBrightColorsStrengthLevelChanged(); // Trigger matrix recalc + updates + } + // dtm.setColorMode() needs to be called before // updateDisplayWhiteBalanceStatus(), this is because the latter calls // DisplayTransformManager.needsLinearColorMatrix(), therefore it is dependent // on the state of DisplayTransformManager. - final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); dtm.setColorMode(mode, mNightDisplayTintController.getMatrix(), + mReduceBrightColorsTintController.getMatrix(), getCompositionColorSpace(mode)); if (mDisplayWhiteBalanceTintController.isAvailable(getContext())) { diff --git a/services/core/java/com/android/server/display/color/DisplayTransformManager.java b/services/core/java/com/android/server/display/color/DisplayTransformManager.java index a76c427bec0e..cb7b1773e47e 100644 --- a/services/core/java/com/android/server/display/color/DisplayTransformManager.java +++ b/services/core/java/com/android/server/display/color/DisplayTransformManager.java @@ -265,7 +265,7 @@ public class DisplayTransformManager { /** * Sets color mode and updates night display transform values. */ - public boolean setColorMode(int colorMode, float[] nightDisplayMatrix, + public boolean setColorMode(int colorMode, float[] nightDisplayMatrix, float[] rbcMatrix, int compositionColorMode) { if (colorMode == ColorDisplayManager.COLOR_MODE_NATURAL) { applySaturation(COLOR_SATURATION_NATURAL); @@ -285,7 +285,11 @@ public class DisplayTransformManager { setDisplayColor(colorMode, compositionColorMode); } + // These are close to the setDisplayColor() call to reduce delay between + // setting these matrixes and updating the color mode. Without this proximity + // of calls, updates to color mode can result in flicker. setColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY, nightDisplayMatrix); + setColorMatrix(LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS, rbcMatrix); updateConfiguration(); diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java index 78bd41bd2e11..85b6bbb40b91 100644 --- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java +++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java @@ -46,10 +46,6 @@ public class DisplayManagerFlags { Flags.FLAG_ENABLE_CONNECTED_DISPLAY_MANAGEMENT, Flags::enableConnectedDisplayManagement); - private final FlagState mNbmControllerFlagState = new FlagState( - Flags.FLAG_ENABLE_NBM_CONTROLLER, - Flags::enableNbmController); - private final FlagState mHdrClamperFlagState = new FlagState( Flags.FLAG_ENABLE_HDR_CLAMPER, Flags::enableHdrClamper); @@ -282,11 +278,6 @@ public class DisplayManagerFlags { return mConnectedDisplayManagementFlagState.isEnabled(); } - /** Returns whether NBM Controller is enabled or not. */ - public boolean isNbmControllerEnabled() { - return mNbmControllerFlagState.isEnabled(); - } - /** Returns whether hdr clamper is enabled on not. */ public boolean isHdrClamperEnabled() { return mHdrClamperFlagState.isEnabled(); @@ -595,7 +586,6 @@ public class DisplayManagerFlags { pw.println(" " + mExternalDisplayLimitModeState); pw.println(" " + mDisplayTopology); pw.println(" " + mHdrClamperFlagState); - pw.println(" " + mNbmControllerFlagState); pw.println(" " + mPowerThrottlingClamperFlagState); pw.println(" " + mEvenDimmerFlagState); pw.println(" " + mSmallAreaDetectionFlagState); diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig index 123b7dfbf843..3358f723709c 100644 --- a/services/core/java/com/android/server/display/feature/display_flags.aconfig +++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig @@ -37,14 +37,6 @@ flag { } flag { - name: "enable_nbm_controller" - namespace: "display_manager" - description: "Feature flag for Normal Brightness Mode Controller" - bug: "299527549" - is_fixed_read_only: true -} - -flag { name: "enable_hdr_clamper" namespace: "display_manager" description: "Feature flag for HDR Clamper" diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java index d8c35358102d..f09be2c15ee0 100644 --- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java +++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java @@ -289,7 +289,9 @@ final class MediaRoute2ProviderServiceProxy extends MediaRoute2Provider { // doesn't have any registered discovery preference, we should still be able to route their // system media. boolean bindDueToSystemMediaRoutingSupport = - mIsManagerScanning && mSupportsSystemMediaRouting; + mLastDiscoveryPreference != null + && mLastDiscoveryPreference.shouldPerformActiveScan() + && mSupportsSystemMediaRouting; if (!getSessionInfos().isEmpty() || bindDueToManagerScan || bindDueToSystemMediaRoutingSupport) { diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java index e18ed410c045..58deffcbd4ba 100644 --- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java +++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java @@ -848,7 +848,7 @@ class MediaRouter2ServiceImpl { UserRecord userRecord = getOrCreateUserRecordLocked(userId); List<RoutingSessionInfo> sessionInfos; if (hasSystemRoutingPermissions) { - if (setDeviceRouteSelected) { + if (setDeviceRouteSelected && !Flags.enableMirroringInMediaRouter2()) { // Return a fake system session that shows the device route as selected and // available bluetooth routes as transferable. return userRecord.mHandler.getSystemProvider() @@ -2733,6 +2733,15 @@ class MediaRouter2ServiceImpl { newRoutes = Collections.emptySet(); } + if (Flags.enableMirroringInMediaRouter2() + && provider instanceof MediaRoute2ProviderServiceProxy proxyProvider) { + // We notify the system provider of service updates, so that it can update the + // system routing session by adding them as transferable routes. And we remove those + // that don't support remote routing. + mSystemProvider.updateSystemMediaRoutesFromProxy(proxyProvider); + newRoutes.removeIf(it -> !it.supportsRemoteRouting()); + } + // Add new routes to the maps. ArrayList<MediaRoute2Info> addedRoutes = new ArrayList<>(); boolean hasAddedOrModifiedRoutes = false; diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java index 8dfba39dcfd8..b93846bf9ee7 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java @@ -73,6 +73,10 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { // For apps without MODIFYING_AUDIO_ROUTING permission. // This should be the currently selected route. MediaRoute2Info mDefaultRoute; + + @GuardedBy("mLock") + RoutingSessionInfo mSystemSessionInfo; + RoutingSessionInfo mDefaultSessionInfo; private final AudioManagerBroadcastReceiver mAudioReceiver = @@ -180,7 +184,10 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { if (TextUtils.equals(routeOriginalId, mSelectedRouteId)) { RoutingSessionInfo currentSessionInfo; synchronized (mLock) { - currentSessionInfo = mSessionInfos.get(0); + currentSessionInfo = + Flags.enableMirroringInMediaRouter2() + ? mSystemSessionInfo + : mSessionInfos.get(0); } mCallback.onSessionCreated(this, requestId, currentSessionInfo); return; @@ -354,7 +361,10 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } if (Flags.enableBuiltInSpeakerRouteSuitabilityStatuses()) { - RoutingSessionInfo oldSessionInfo = mSessionInfos.get(0); + var oldSessionInfo = + Flags.enableMirroringInMediaRouter2() + ? mSystemSessionInfo + : mSessionInfos.get(0); builder.setTransferReason(oldSessionInfo.getTransferReason()) .setTransferInitiator(oldSessionInfo.getTransferInitiatorUserHandle(), oldSessionInfo.getTransferInitiatorPackageName()); @@ -364,6 +374,31 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } } + /** + * Notifies the system provider of a {@link MediaRoute2ProviderServiceProxy} update. + * + * <p>To be overridden so as to generate system media routes for {@link + * MediaRoute2ProviderService} routes that {@link MediaRoute2Info#supportsSystemMediaRouting() + * support system media routing}). + * + * @param serviceProxy The proxy of the service that updated its state. + */ + public void updateSystemMediaRoutesFromProxy(MediaRoute2ProviderServiceProxy serviceProxy) { + // Do nothing. This implementation doesn't support MR2ProviderService system media routes. + // The subclass overrides this method to implement app-managed system media routing (aka + // mirroring). + } + + /** + * Called when the system provider state changes. + * + * <p>To be overridden by {@link SystemMediaRoute2Provider2}, so that app-provided system media + * routing routes are added before setting the provider state. + */ + public void onSystemProviderRoutesChanged(MediaRoute2ProviderInfo providerInfo) { + setProviderState(providerInfo); + } + protected void updateProviderState() { MediaRoute2ProviderInfo.Builder builder = new MediaRoute2ProviderInfo.Builder(); @@ -373,7 +408,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { for (MediaRoute2Info route : deviceRoutes) { builder.addRoute(route); } - setProviderState(builder.build()); + if (!Flags.enableMirroringInMediaRouter2()) { + setProviderState(builder.build()); + } } else { builder.addRoute(mDeviceRouteController.getSelectedRoute()); } @@ -382,7 +419,7 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { builder.addRoute(route); } MediaRoute2ProviderInfo providerInfo = builder.build(); - setProviderState(providerInfo); + onSystemProviderRoutesChanged(providerInfo); if (DEBUG) { Slog.d(TAG, "Updating system provider info : " + providerInfo); } @@ -393,8 +430,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { */ boolean updateSessionInfosIfNeeded() { synchronized (mLock) { - RoutingSessionInfo oldSessionInfo = mSessionInfos.isEmpty() ? null : mSessionInfos.get( - 0); + RoutingSessionInfo oldSessionInfo; + if (Flags.enableMirroringInMediaRouter2()) { + oldSessionInfo = mSystemSessionInfo; + } else { + oldSessionInfo = mSessionInfos.isEmpty() ? null : mSessionInfos.get(0); + } RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder( SYSTEM_SESSION_ID, "" /* clientPackageName */) @@ -483,8 +524,8 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { if (DEBUG) { Slog.d(TAG, "Updating system routing session info : " + newSessionInfo); } - mSessionInfos.clear(); - mSessionInfos.add(newSessionInfo); + mSystemSessionInfo = newSessionInfo; + onSystemSessionInfoUpdated(); mDefaultSessionInfo = new RoutingSessionInfo.Builder( SYSTEM_SESSION_ID, "" /* clientPackageName */) @@ -501,6 +542,12 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { } } + @GuardedBy("mLock") + protected void onSystemSessionInfoUpdated() { + mSessionInfos.clear(); + mSessionInfos.add(mSystemSessionInfo); + } + @GuardedBy("mRequestLock") private void reportPendingSessionRequestResultLockedIfNeeded( RoutingSessionInfo newSessionInfo) { @@ -587,6 +634,9 @@ class SystemMediaRoute2Provider extends MediaRoute2Provider { RoutingSessionInfo sessionInfo; synchronized (mLock) { sessionInfo = mSessionInfos.get(0); + if (sessionInfo == null) { + return; + } } mCallback.onSessionUpdated(this, sessionInfo); diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java index 85b30ad8cadb..7dc30ab66fd2 100644 --- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java +++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider2.java @@ -16,11 +16,26 @@ package com.android.server.media; +import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO; + +import android.annotation.Nullable; import android.content.ComponentName; import android.content.Context; +import android.media.MediaRoute2Info; +import android.media.MediaRoute2ProviderInfo; import android.media.MediaRoute2ProviderService; +import android.media.RoutingSessionInfo; import android.os.Looper; import android.os.UserHandle; +import android.util.ArraySet; + +import com.android.internal.annotations.GuardedBy; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; /** * Extends {@link SystemMediaRoute2Provider} by adding system routes provided by {@link @@ -30,6 +45,15 @@ import android.os.UserHandle; */ /* package */ class SystemMediaRoute2Provider2 extends SystemMediaRoute2Provider { + private static final String ROUTE_ID_PREFIX_SYSTEM = "SYSTEM"; + private static final String ROUTE_ID_SYSTEM_SEPARATOR = "."; + + @GuardedBy("mLock") + private MediaRoute2ProviderInfo mLastSystemProviderInfo; + + @GuardedBy("mLock") + private final Map<String, ProviderProxyRecord> mProxyRecords = new HashMap<>(); + private static final ComponentName COMPONENT_NAME = new ComponentName( SystemMediaRoute2Provider2.class.getPackage().getName(), @@ -46,4 +70,117 @@ import android.os.UserHandle; private SystemMediaRoute2Provider2(Context context, UserHandle user, Looper looper) { super(context, COMPONENT_NAME, user, looper); } + + @Override + protected void onSystemSessionInfoUpdated() { + updateSessionInfo(); + } + + @Override + public void updateSystemMediaRoutesFromProxy(MediaRoute2ProviderServiceProxy serviceProxy) { + var proxyRecord = ProviderProxyRecord.createFor(serviceProxy); + synchronized (mLock) { + if (proxyRecord == null) { + mProxyRecords.remove(serviceProxy.mUniqueId); + } else { + mProxyRecords.put(serviceProxy.mUniqueId, proxyRecord); + } + setProviderState(buildProviderInfo()); + } + updateSessionInfo(); + notifyProviderState(); + notifySessionInfoUpdated(); + } + + @Override + public void onSystemProviderRoutesChanged(MediaRoute2ProviderInfo providerInfo) { + synchronized (mLock) { + mLastSystemProviderInfo = providerInfo; + setProviderState(buildProviderInfo()); + } + updateSessionInfo(); + notifySessionInfoUpdated(); + } + + /** + * Updates the {@link #mSessionInfos} by expanding the {@link SystemMediaRoute2Provider} session + * with information from the {@link MediaRoute2ProviderService provider services}. + */ + private void updateSessionInfo() { + synchronized (mLock) { + var systemSessionInfo = mSystemSessionInfo; + if (systemSessionInfo == null) { + // The system session info hasn't been initialized yet. Do nothing. + return; + } + var builder = new RoutingSessionInfo.Builder(systemSessionInfo); + mProxyRecords.values().stream() + .flatMap(ProviderProxyRecord::getRoutesStream) + .map(MediaRoute2Info::getId) + .forEach(builder::addTransferableRoute); + mSessionInfos.clear(); + mSessionInfos.add(builder.build()); + } + } + + /** + * Returns a new a provider info that includes all routes from the system provider {@link + * SystemMediaRoute2Provider}, along with system routes from {@link MediaRoute2ProviderService + * provider services}. + */ + @GuardedBy("mLock") + private MediaRoute2ProviderInfo buildProviderInfo() { + MediaRoute2ProviderInfo.Builder builder = + new MediaRoute2ProviderInfo.Builder(mLastSystemProviderInfo); + mProxyRecords.values().stream() + .flatMap(ProviderProxyRecord::getRoutesStream) + .forEach(builder::addRoute); + return builder.build(); + } + + /** + * Holds information about {@link MediaRoute2ProviderService provider services} registered in + * the system. + * + * @param mProxy The corresponding {@link MediaRoute2ProviderServiceProxy}. + * @param mSystemMediaRoutes The last snapshot of routes from the service that support system + * media routing, as defined by {@link MediaRoute2Info#supportsSystemMediaRouting()}. + */ + private record ProviderProxyRecord( + MediaRoute2ProviderServiceProxy mProxy, + Collection<MediaRoute2Info> mSystemMediaRoutes) { + + /** Returns a stream representation of the {@link #mSystemMediaRoutes}. */ + public Stream<MediaRoute2Info> getRoutesStream() { + return mSystemMediaRoutes.stream(); + } + + /** + * Returns a new instance, or null if the given {@code serviceProxy} doesn't have an + * associated {@link MediaRoute2ProviderInfo}. + */ + @Nullable + public static ProviderProxyRecord createFor(MediaRoute2ProviderServiceProxy serviceProxy) { + MediaRoute2ProviderInfo providerInfo = serviceProxy.getProviderInfo(); + if (providerInfo == null) { + return null; + } + ArraySet<MediaRoute2Info> routes = new ArraySet<>(); + providerInfo.getRoutes().stream() + .filter(MediaRoute2Info::supportsSystemMediaRouting) + .forEach( + route -> { + String id = + ROUTE_ID_PREFIX_SYSTEM + + route.getProviderId() + + ROUTE_ID_SYSTEM_SEPARATOR + + route.getOriginalId(); + routes.add( + new MediaRoute2Info.Builder(id, route.getName()) + .addFeature(FEATURE_LIVE_AUDIO) + .build()); + }); + return new ProviderProxyRecord(serviceProxy, Collections.unmodifiableSet(routes)); + } + } } diff --git a/services/core/java/com/android/server/power/hint/HintManagerService.java b/services/core/java/com/android/server/power/hint/HintManagerService.java index 51e0195f13fc..7c7504dccf94 100644 --- a/services/core/java/com/android/server/power/hint/HintManagerService.java +++ b/services/core/java/com/android/server/power/hint/HintManagerService.java @@ -297,11 +297,7 @@ public final class HintManagerService extends SystemService { mPowerHalVersion = 0; mUsesFmq = false; if (mPowerHal != null) { - try { - mSupportInfo = getSupportInfo(); - } catch (RemoteException e) { - throw new IllegalStateException("Could not contact PowerHAL!", e); - } + mSupportInfo = getSupportInfo(); } mDefaultCpuHeadroomCalculationWindowMillis = new CpuHeadroomParamsInternal().calculationWindowMillis; @@ -319,7 +315,7 @@ public final class HintManagerService extends SystemService { } } - SupportInfo getSupportInfo() throws RemoteException { + SupportInfo getSupportInfo() { try { mPowerHalVersion = mPowerHal.getInterfaceVersion(); if (mPowerHalVersion >= 6) { @@ -330,40 +326,9 @@ public final class HintManagerService extends SystemService { } SupportInfo supportInfo = new SupportInfo(); - supportInfo.usesSessions = isHintSessionSupported(); - // Global boosts & modes aren't currently relevant for HMS clients - supportInfo.boosts = 0; - supportInfo.modes = 0; - supportInfo.sessionHints = 0; - supportInfo.sessionModes = 0; - supportInfo.sessionTags = 0; - supportInfo.headroom = new SupportInfo.HeadroomSupportInfo(); supportInfo.headroom.isCpuSupported = false; supportInfo.headroom.isGpuSupported = false; - if (isHintSessionSupported()) { - if (mPowerHalVersion == 4) { - // Assume we support the V4 hints & modes unless specified - // otherwise; this is to avoid breaking backwards compat - // since we historically just assumed they were. - supportInfo.sessionHints = 31; // first 5 bits are ones - } - if (mPowerHalVersion == 5) { - // Assume we support the V5 hints & modes unless specified - // otherwise; this is to avoid breaking backwards compat - // since we historically just assumed they were. - - // Hal V5 has 8 modes, all of which it assumes are supported, - // so we represent that by having the first 8 bits set - supportInfo.sessionHints = 255; // first 8 bits are ones - // Hal V5 has 1 mode which it assumes is supported, so we - // represent that by having the first bit set - supportInfo.sessionModes = 1; - // Hal V5 has 5 tags, all of which it assumes are supported, - // so we represent that by having the first 5 bits set - supportInfo.sessionTags = 31; - } - } return supportInfo; } @@ -1264,7 +1229,7 @@ public final class HintManagerService extends SystemService { @SessionTag int tag, SessionCreationConfig creationConfig, SessionConfig config) { if (!isHintSessionSupported()) { - throw new UnsupportedOperationException("PowerHintSessions are not supported!"); + throw new UnsupportedOperationException("PowerHAL is not supported!"); } java.util.Objects.requireNonNull(token); @@ -1460,6 +1425,12 @@ public final class HintManagerService extends SystemService { removeChannelItem(callingTgid, callingUid); }; + @Override + public long getHintSessionPreferredRate() { + return mHintSessionPreferredRate; + } + + @Override public int getMaxGraphicsPipelineThreadsCount() { return MAX_GRAPHICS_PIPELINE_THREADS_COUNT; } @@ -1649,16 +1620,6 @@ public final class HintManagerService extends SystemService { mSessionManager = ISessionManager.Stub.asInterface(sessionManager); } - public IHintManager.HintManagerClientData - registerClient(@NonNull IHintManager.IHintManagerClient clientBinder) { - IHintManager.HintManagerClientData out = new IHintManager.HintManagerClientData(); - out.preferredRateNanos = mHintSessionPreferredRate; - out.maxGraphicsPipelineThreads = getMaxGraphicsPipelineThreadsCount(); - out.powerHalVersion = mPowerHalVersion; - out.supportInfo = mSupportInfo; - return out; - } - @Override public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) { @@ -1666,7 +1627,7 @@ public final class HintManagerService extends SystemService { } pw.println("HintSessionPreferredRate: " + mHintSessionPreferredRate); pw.println("MaxGraphicsPipelineThreadsCount: " + MAX_GRAPHICS_PIPELINE_THREADS_COUNT); - pw.println("Hint Session Support: " + isHintSessionSupported()); + pw.println("HAL Support: " + isHintSessionSupported()); pw.println("Active Sessions:"); synchronized (mLock) { for (int i = 0; i < mActiveSessions.size(); i++) { diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 24a6f118ad04..4bcba13448e9 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -258,16 +258,13 @@ class InsetsPolicy { * We also need to exclude certain types of insets source for client within specific windowing * modes. * - * @param attrs the LayoutParams of the target - * @param windowingMode the windowing mode of the target - * @param isAlwaysOnTop is the target always on top + * @param target the target on which the policy is applied * @param state the input inset state containing all the sources * @return The state stripped of the necessary information. */ - InsetsState enforceInsetsPolicyForTarget(WindowManager.LayoutParams attrs, - @WindowConfiguration.WindowingMode int windowingMode, boolean isAlwaysOnTop, - InsetsState state) { + InsetsState enforceInsetsPolicyForTarget(WindowState target, InsetsState state) { final InsetsState originalState = state; + final WindowManager.LayoutParams attrs = target.getAttrs(); // The caller should not receive the visible insets provided by itself. if (attrs.type == TYPE_INPUT_METHOD) { @@ -316,12 +313,17 @@ class InsetsPolicy { } } + final @WindowConfiguration.WindowingMode int windowingMode = target.getWindowingMode(); if (WindowConfiguration.isFloating(windowingMode) - || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && isAlwaysOnTop)) { + || (windowingMode == WINDOWING_MODE_MULTI_WINDOW && target.isAlwaysOnTop())) { // Keep frames, caption, and IME. int types = WindowInsets.Type.captionBar(); if (windowingMode != WINDOWING_MODE_PINNED) { - types |= WindowInsets.Type.ime(); + if (!Flags.refactorInsetsController() || (mDisplayContent != null + && target == mDisplayContent.getImeInputTarget() + && (WindowInsets.Type.ime() & target.getRequestedVisibleTypes()) != 0)) { + types |= WindowInsets.Type.ime(); + } } final InsetsState newState = new InsetsState(); newState.set(state, types); diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 90bf053dfbef..68b4b6f0ae91 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -1631,8 +1631,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } final InsetsState rawInsetsState = mFrozenInsetsState != null ? mFrozenInsetsState : getMergedInsetsState(); - final InsetsState insetsStateForWindow = insetsPolicy.enforceInsetsPolicyForTarget( - mAttrs, getWindowingMode(), isAlwaysOnTop(), rawInsetsState); + final InsetsState insetsStateForWindow = insetsPolicy.enforceInsetsPolicyForTarget(this, + rawInsetsState); return insetsPolicy.adjustInsetsForWindow(this, insetsStateForWindow, includeTransient); } @@ -3303,7 +3303,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP // just kill it. And if it is a window of foreground activity, the activity can be // restarted automatically if needed. Slog.w(TAG, "Exception thrown during dispatchAppVisibility " + this, e); - if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid) { + if (android.os.Process.getUidForPid(mSession.mPid) == mSession.mUid + && android.os.Process.getThreadGroupLeader(mSession.mPid) == mSession.mPid) { android.os.Process.killProcess(mSession.mPid); } } diff --git a/services/supervision/java/com/android/server/supervision/SupervisionService.java b/services/supervision/java/com/android/server/supervision/SupervisionService.java index 0ccaa6043f5f..073ee31ddd60 100644 --- a/services/supervision/java/com/android/server/supervision/SupervisionService.java +++ b/services/supervision/java/com/android/server/supervision/SupervisionService.java @@ -16,6 +16,11 @@ package com.android.server.supervision; +import static android.Manifest.permission.INTERACT_ACROSS_USERS; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +import static com.android.internal.util.Preconditions.checkCallAuthorization; + import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; @@ -31,6 +36,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.UserInfo; +import android.os.Binder; import android.os.PersistableBundle; import android.os.RemoteException; import android.os.ResultReceiver; @@ -78,6 +84,9 @@ public class SupervisionService extends ISupervisionManager.Stub { @Override public boolean isSupervisionEnabledForUser(@UserIdInt int userId) { + if (UserHandle.getUserId(Binder.getCallingUid()) != userId) { + enforcePermission(INTERACT_ACROSS_USERS); + } synchronized (getLockObject()) { return getUserDataLocked(userId).supervisionEnabled; } @@ -151,7 +160,8 @@ public class SupervisionService extends ISupervisionManager.Stub { /** Returns whether the supervision app has profile owner status. */ private boolean isProfileOwner(@UserIdInt int userId) { - ComponentName profileOwner = mDpmInternal.getProfileOwnerAsUser(userId); + ComponentName profileOwner = + mDpmInternal != null ? mDpmInternal.getProfileOwnerAsUser(userId) : null; return profileOwner != null && isSupervisionAppPackage(profileOwner.getPackageName()); } @@ -161,6 +171,12 @@ public class SupervisionService extends ISupervisionManager.Stub { mContext.getResources().getString(R.string.config_systemSupervision)); } + /** Enforces that the caller has the given permission. */ + private void enforcePermission(String permission) { + checkCallAuthorization( + mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED); + } + public static class Lifecycle extends SystemService { private final SupervisionService mSupervisionService; diff --git a/services/tests/displayservicetests/src/com/android/server/display/BrightnessRangeControllerTest.kt b/services/tests/displayservicetests/src/com/android/server/display/BrightnessRangeControllerTest.kt index f589a2c9385c..7db6ea0bf86d 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/BrightnessRangeControllerTest.kt +++ b/services/tests/displayservicetests/src/com/android/server/display/BrightnessRangeControllerTest.kt @@ -60,12 +60,6 @@ class BrightnessRangeControllerTest { } @Test - fun testMaxBrightness_HbmDisabledAndNotAllowed() { - val controller = createController(nbmEnabled = false, hbmAllowed = false) - assertThat(controller.currentBrightnessMax).isEqualTo(MAX_BRIGHTNESS) - } - - @Test fun testMaxBrightness_transitionPointLessThanCurrentNbmLimit() { val controller = createController( hbmAllowed = false, @@ -76,13 +70,11 @@ class BrightnessRangeControllerTest { } private fun createController( - nbmEnabled: Boolean = true, hbmSupported: Boolean = true, hbmAllowed: Boolean = true, hbmMaxBrightness: Float = MAX_BRIGHTNESS, nbmMaxBrightness: Float = NORMAL_BRIGHTNESS_LOW ): BrightnessRangeController { - whenever(mockFlags.isNbmControllerEnabled).thenReturn(nbmEnabled) whenever(mockHbmController.deviceSupportsHbm()).thenReturn(hbmSupported) whenever(mockHbmController.isHbmCurrentlyAllowed).thenReturn(hbmAllowed) whenever(mockHbmController.currentBrightnessMax).thenReturn(hbmMaxBrightness) diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java index 8ca39194de3b..a4dfecb8ed96 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayPowerControllerTest.java @@ -2626,8 +2626,8 @@ public final class DisplayPowerControllerTest { mock(ScreenOffBrightnessSensorController.class); final HighBrightnessModeController hbmController = mock(HighBrightnessModeController.class); final HdrClamper hdrClamper = mock(HdrClamper.class); - final NormalBrightnessModeController normalBrightnessModeController = mock( - NormalBrightnessModeController.class); + final NormalBrightnessModeController normalBrightnessModeController = + new NormalBrightnessModeController(); BrightnessClamperController clamperController = mock(BrightnessClamperController.class); when(hbmController.getCurrentBrightnessMax()).thenReturn(PowerManager.BRIGHTNESS_MAX); diff --git a/services/tests/displayservicetests/src/com/android/server/display/color/ColorDisplayServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/color/ColorDisplayServiceTest.java index f391e409a717..4e81b3530b62 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/color/ColorDisplayServiceTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/color/ColorDisplayServiceTest.java @@ -20,10 +20,13 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -89,6 +92,7 @@ public class ColorDisplayServiceTest { private ColorDisplayService.BinderService mBinderService; private Resources mResourcesSpy; + private ReduceBrightColorsTintController mRbcSpy; private static final int[] MINIMAL_COLOR_MODES = new int[] { ColorDisplayManager.COLOR_MODE_NATURAL, @@ -135,7 +139,8 @@ public class ColorDisplayServiceTest { mLocalServiceKeeperRule.overrideLocalService( DisplayManagerInternal.class, mDisplayManagerInternal); - mCds = new ColorDisplayService(mContext); + mRbcSpy = Mockito.spy(new ReduceBrightColorsTintController()); + mCds = new ColorDisplayService(mContext, mRbcSpy); mBinderService = mCds.new BinderService(); mLocalServiceKeeperRule.overrideLocalService( ColorDisplayService.ColorDisplayServiceInternal.class, @@ -1106,7 +1111,8 @@ public class ColorDisplayServiceTest { setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL); startService(); verify(mDisplayTransformManager).setColorMode( - eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), eq(Display.COLOR_MODE_INVALID)); + eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), any(), + eq(Display.COLOR_MODE_INVALID)); } @Test @@ -1124,7 +1130,8 @@ public class ColorDisplayServiceTest { setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL); startService(); verify(mDisplayTransformManager).setColorMode( - eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), eq(Display.COLOR_MODE_INVALID)); + eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), any(), + eq(Display.COLOR_MODE_INVALID)); } @Test @@ -1140,7 +1147,8 @@ public class ColorDisplayServiceTest { setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL); startService(); verify(mDisplayTransformManager).setColorMode( - eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), eq(Display.COLOR_MODE_SRGB)); + eq(ColorDisplayManager.COLOR_MODE_NATURAL), any(), any(), + eq(Display.COLOR_MODE_SRGB)); } @Test @@ -1156,7 +1164,8 @@ public class ColorDisplayServiceTest { setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED); startService(); verify(mDisplayTransformManager).setColorMode( - eq(ColorDisplayManager.COLOR_MODE_BOOSTED), any(), eq(Display.COLOR_MODE_INVALID)); + eq(ColorDisplayManager.COLOR_MODE_BOOSTED), any(), any(), + eq(Display.COLOR_MODE_INVALID)); } @Test @@ -1164,10 +1173,27 @@ public class ColorDisplayServiceTest { when(mResourcesSpy.getIntArray(R.array.config_availableColorModes)) .thenReturn(new int[] {}); startService(); - verify(mDisplayTransformManager, never()).setColorMode(anyInt(), any(), anyInt()); + verify(mDisplayTransformManager, never()).setColorMode(anyInt(), any(), any(), anyInt()); assertThat(mBinderService.getColorMode()).isEqualTo(-1); } + @Test + public void ensureColorModeChangeTriggersRbcReload() { + // should set up RBC once at startup + startService(); + reset(mRbcSpy); + + // Make sure RBC is enabled and available for this test + doReturn(true).when(mRbcSpy).isAvailable(mContext); + + // When Color Mode changes, RBC needs to re-setup + // onDisplayColorModeChanged cancels animations, and should be called in handler thread + mCds.mHandler.runWithScissors( + () -> mCds.onDisplayColorModeChanged(ColorDisplayManager.COLOR_MODE_NATURAL), + 1000); + verify(mRbcSpy, times(1)).setUp(eq(mContext), anyBoolean()); + } + /** * Configures Night display to use a custom schedule. * diff --git a/services/tests/displayservicetests/src/com/android/server/display/color/DisplayTransformManagerTest.java b/services/tests/displayservicetests/src/com/android/server/display/color/DisplayTransformManagerTest.java index 27f87aae35bb..a7ef5e0afc0e 100644 --- a/services/tests/displayservicetests/src/com/android/server/display/color/DisplayTransformManagerTest.java +++ b/services/tests/displayservicetests/src/com/android/server/display/color/DisplayTransformManagerTest.java @@ -19,6 +19,7 @@ package com.android.server.display.color; import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyString; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; +import static com.android.server.display.color.DisplayTransformManager.LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS; import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE; import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_DISPLAY_COLOR; import static com.android.server.display.color.DisplayTransformManager.PERSISTENT_PROPERTY_SATURATION; @@ -51,12 +52,14 @@ public class DisplayTransformManagerTest { private MockitoSession mSession; private DisplayTransformManager mDtm; private float[] mNightDisplayMatrix; + private float[] mRbcMatrix; private HashMap<String, String> mSystemProperties; @Before public void setUp() { mDtm = new DisplayTransformManager(); mNightDisplayMatrix = mDtm.getColorMatrix(LEVEL_COLOR_MATRIX_NIGHT_DISPLAY); + mRbcMatrix = mDtm.getColorMatrix(LEVEL_COLOR_MATRIX_REDUCE_BRIGHT_COLORS); mSession = ExtendedMockito.mockitoSession() .initMocks(this) @@ -81,7 +84,8 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_natural() { - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, -1); + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, mRbcMatrix, + Display.COLOR_MODE_INVALID); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo("0" /* managed */); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -90,7 +94,8 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_boosted() { - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED, mNightDisplayMatrix, -1); + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_BOOSTED, mNightDisplayMatrix, mRbcMatrix, + Display.COLOR_MODE_INVALID); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo("0" /* managed */); @@ -100,7 +105,8 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_saturated() { - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED, mNightDisplayMatrix, -1); + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_SATURATED, mNightDisplayMatrix, mRbcMatrix, + Display.COLOR_MODE_INVALID); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo("1" /* unmanaged */); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -109,7 +115,8 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_automatic() { - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC, mNightDisplayMatrix, -1); + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_AUTOMATIC, mNightDisplayMatrix, mRbcMatrix, + Display.COLOR_MODE_INVALID); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo("2" /* enhanced */); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -118,7 +125,7 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_vendor() { - mDtm.setColorMode(0x100, mNightDisplayMatrix, -1); + mDtm.setColorMode(0x100, mNightDisplayMatrix, mRbcMatrix, Display.COLOR_MODE_INVALID); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo(Integer.toString(0x100) /* pass-through */); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -127,7 +134,7 @@ public class DisplayTransformManagerTest { @Test public void setColorMode_outOfBounds() { - mDtm.setColorMode(0x50, mNightDisplayMatrix, -1); + mDtm.setColorMode(0x50, mNightDisplayMatrix, mRbcMatrix, Display.COLOR_MODE_INVALID); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_DISPLAY_COLOR)) .isEqualTo(null); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_SATURATION)) @@ -141,7 +148,7 @@ public class DisplayTransformManagerTest { // Start with a known state, which we expect to remain unmodified SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE, magicPropertyValue); - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, mRbcMatrix, Display.COLOR_MODE_INVALID); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE)) .isEqualTo(magicPropertyValue); @@ -155,7 +162,7 @@ public class DisplayTransformManagerTest { // Start with a known state, which we expect to get modified SystemProperties.set(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE, magicPropertyValue); - mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, + mDtm.setColorMode(ColorDisplayManager.COLOR_MODE_NATURAL, mNightDisplayMatrix, mRbcMatrix, testPropertyValue); assertThat(mSystemProperties.get(PERSISTENT_PROPERTY_COMPOSITION_COLOR_MODE)) .isEqualTo(Integer.toString(testPropertyValue)); diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index 1efe4707fc11..9e96800ca2e9 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -18,6 +18,7 @@ package com.android.server.am; import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL; import static android.app.ActivityManager.PROCESS_CAPABILITY_BFSL; +import static android.app.ActivityManager.PROCESS_CAPABILITY_CPU_TIME; import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP; import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; @@ -40,6 +41,7 @@ import static android.app.ActivityManager.PROCESS_STATE_TOP_SLEEPING; import static android.app.ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_ACTIVITY; import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_NONE; +import static android.app.ActivityManagerInternal.OOM_ADJ_REASON_SHORT_FGS_TIMEOUT; import static android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE; import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; @@ -283,6 +285,15 @@ public class MockingOomAdjusterTests { } } + private static void assertNoCpuTime(ProcessRecord app) { + assertEquals(0, app.mState.getSetCapability() & PROCESS_CAPABILITY_CPU_TIME); + } + + private static void assertCpuTime(ProcessRecord app) { + assertEquals(PROCESS_CAPABILITY_CPU_TIME, + app.mState.getSetCapability() & PROCESS_CAPABILITY_CPU_TIME); + } + private static void assertBfsl(ProcessRecord app) { assertEquals(PROCESS_CAPABILITY_BFSL, app.mState.getSetCapability() & PROCESS_CAPABILITY_BFSL); @@ -661,6 +672,7 @@ public class MockingOomAdjusterTests { // SHORT_SERVICE, timed out already. s = ServiceRecord.newEmptyInstanceForTest(mService); s.appInfo = new ApplicationInfo(); + mProcessStateController.setStartRequested(s, true); s.isForeground = true; s.foregroundServiceType = FOREGROUND_SERVICE_TYPE_SHORT_SERVICE; @@ -687,6 +699,51 @@ public class MockingOomAdjusterTests { @SuppressWarnings("GuardedBy") @Test + @EnableFlags(Flags.FLAG_USE_CPU_TIME_CAPABILITY) + public void testUpdateOomAdjFreezeState_bindingFromShortFgs() { + // Setting up a started short FGS within app1. + final ServiceRecord s = ServiceRecord.newEmptyInstanceForTest(mService); + s.appInfo = new ApplicationInfo(); + mProcessStateController.setStartRequested(s, true); + s.isForeground = true; + s.foregroundServiceType = FOREGROUND_SERVICE_TYPE_SHORT_SERVICE; + mProcessStateController.setShortFgsInfo(s, SystemClock.uptimeMillis()); + + final ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, + MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true)); + mProcessStateController.setHostProcess(s, app); + mProcessStateController.setHasForegroundServices(app.mServices, true, + FOREGROUND_SERVICE_TYPE_SHORT_SERVICE, /* hasNoneType=*/false); + mProcessStateController.startService(app.mServices, s); + app.mState.setLastTopTime(SystemClock.uptimeMillis() + - mService.mConstants.TOP_TO_FGS_GRACE_DURATION); + + final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID, + MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false)); + // App1 with short service binds to app2 + bindService(app2, app, null, null, 0, mock(IBinder.class)); + + setProcessesToLru(app, app2); + updateOomAdj(app); + + assertCpuTime(app); + assertCpuTime(app2); + + // Timeout the short FGS. + mProcessStateController.setShortFgsInfo(s, SystemClock.uptimeMillis() + - mService.mConstants.mShortFgsTimeoutDuration + - mService.mConstants.mShortFgsProcStateExtraWaitDuration); + mService.mServices.onShortFgsProcstateTimeout(s); + // mService is a mock, but this verifies that the timeout would trigger an update. + verify(mService).updateOomAdjLocked(app, OOM_ADJ_REASON_SHORT_FGS_TIMEOUT); + updateOomAdj(app); + + assertNoCpuTime(app); + assertNoCpuTime(app2); + } + + @SuppressWarnings("GuardedBy") + @Test public void testUpdateOomAdj_DoOne_OverlayUi() { ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID, MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, true)); @@ -3142,11 +3199,19 @@ public class MockingOomAdjusterTests { assertEquals(true, app.getUidRecord().isSetAllowListed()); assertFreezeState(app, false); assertFreezeState(app2, false); + if (Flags.useCpuTimeCapability()) { + assertCpuTime(app); + assertCpuTime(app2); + } mProcessStateController.setUidTempAllowlistStateLSP(MOCKAPP_UID, false); assertEquals(false, app.getUidRecord().isSetAllowListed()); assertFreezeState(app, true); assertFreezeState(app2, true); + if (Flags.useCpuTimeCapability()) { + assertNoCpuTime(app); + assertNoCpuTime(app2); + } } @SuppressWarnings("GuardedBy") @@ -3171,6 +3236,11 @@ public class MockingOomAdjusterTests { assertFreezeState(app, false); assertFreezeState(app2, false); assertFreezeState(app3, false); + if (Flags.useCpuTimeCapability()) { + assertCpuTime(app); + assertCpuTime(app2); + assertCpuTime(app3); + } // Remove app1 from allowlist. mProcessStateController.setUidTempAllowlistStateLSP(MOCKAPP_UID, false); @@ -3179,6 +3249,11 @@ public class MockingOomAdjusterTests { assertFreezeState(app, true); assertFreezeState(app2, false); assertFreezeState(app3, false); + if (Flags.useCpuTimeCapability()) { + assertNoCpuTime(app); + assertCpuTime(app2); + assertCpuTime(app3); + } // Now remove app2 from allowlist. mProcessStateController.setUidTempAllowlistStateLSP(MOCKAPP2_UID, false); @@ -3187,6 +3262,11 @@ public class MockingOomAdjusterTests { assertFreezeState(app, true); assertFreezeState(app2, true); assertFreezeState(app3, true); + if (Flags.useCpuTimeCapability()) { + assertNoCpuTime(app); + assertNoCpuTime(app2); + assertNoCpuTime(app3); + } } @SuppressWarnings("GuardedBy") diff --git a/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java b/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java index 2988c77703b7..7e052dcba3fd 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/ServiceBindingOomAdjPolicyTest.java @@ -16,6 +16,7 @@ package com.android.server.am; +import static android.app.ActivityManager.PROCESS_CAPABILITY_CPU_TIME; import static android.app.ActivityManager.PROCESS_CAPABILITY_FOREGROUND_MICROPHONE; import static android.app.ActivityManager.PROCESS_CAPABILITY_NONE; import static android.app.ActivityManager.PROCESS_STATE_CACHED_EMPTY; @@ -64,6 +65,8 @@ import android.content.pm.ServiceInfo; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.RequiresFlagsDisabled; import android.platform.test.annotations.RequiresFlagsEnabled; @@ -326,6 +329,7 @@ public final class ServiceBindingOomAdjPolicyTest { @Test @RequiresFlagsEnabled(com.android.server.am.Flags.FLAG_UNFREEZE_BIND_POLICY_FIX) + @DisableFlags(Flags.FLAG_USE_CPU_TIME_CAPABILITY) public void testServiceDistinctBindingOomAdjShouldNotFreeze() throws Exception { // Enable the flags. mSetFlagsRule.enableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY); @@ -418,6 +422,7 @@ public final class ServiceBindingOomAdjPolicyTest { @Test @RequiresFlagsEnabled(com.android.server.am.Flags.FLAG_UNFREEZE_BIND_POLICY_FIX) + @DisableFlags(Flags.FLAG_USE_CPU_TIME_CAPABILITY) public void testServiceDistinctBindingOomAdjAllowOomManagement() throws Exception { // Enable the flags. mSetFlagsRule.enableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY); @@ -497,6 +502,7 @@ public final class ServiceBindingOomAdjPolicyTest { @Test @RequiresFlagsEnabled(com.android.server.am.Flags.FLAG_UNFREEZE_BIND_POLICY_FIX) + @DisableFlags(Flags.FLAG_USE_CPU_TIME_CAPABILITY) public void testServiceDistinctBindingOomAdjWaivePriority_propagateUnfreeze() throws Exception { // Enable the flags. mSetFlagsRule.enableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY); @@ -574,6 +580,50 @@ public final class ServiceBindingOomAdjPolicyTest { } @Test + @RequiresFlagsEnabled({ + Flags.FLAG_UNFREEZE_BIND_POLICY_FIX, + Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY + }) + @EnableFlags(Flags.FLAG_USE_CPU_TIME_CAPABILITY) + public void testServiceDistinctBindingOomAdj_propagateCpuTimeCapability() throws Exception { + // Note that PROCESS_CAPABILITY_CPU_TIME is special and should be propagated even when + // BIND_INCLUDE_CAPABILITIES is not present. + performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID, + PROCESS_STATE_HOME, HOME_APP_ADJ, PROCESS_CAPABILITY_CPU_TIME, TEST_APP1_NAME, + this::setHomeProcess, + TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_FOREGROUND_SERVICE, + PERCEPTIBLE_APP_ADJ, PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME, + this::setHasForegroundServices, + BIND_AUTO_CREATE, + atLeastOnce(), atLeastOnce()); + + // BIND_WAIVE_PRIORITY should not affect propagation of capability CPU_TIME + performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID, + PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, PROCESS_CAPABILITY_CPU_TIME, + TEST_APP1_NAME, + this::setHasForegroundServices, + TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME, HOME_APP_ADJ, + PROCESS_CAPABILITY_NONE, TEST_APP2_NAME, TEST_SERVICE2_NAME, + this::setHomeProcess, + BIND_AUTO_CREATE | BIND_WAIVE_PRIORITY, + atLeastOnce(), atLeastOnce()); + + // If both process have the capability, the bind should not need an update but the unbind + // is not safe to skip. + // Note that this check can fail on future changes that are not related to + // PROCESS_CAPABILITY_CPU_TIME and trigger updates but this is important to ensure + // efficiency of OomAdjuster. + performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID, + PROCESS_STATE_HOME, HOME_APP_ADJ, PROCESS_CAPABILITY_CPU_TIME, TEST_APP1_NAME, + this::setHomeProcess, + TEST_APP2_PID, TEST_APP2_UID, PROCESS_STATE_HOME, HOME_APP_ADJ, + PROCESS_CAPABILITY_CPU_TIME, TEST_APP2_NAME, TEST_SERVICE2_NAME, + this::setHomeProcess, + BIND_AUTO_CREATE, + never(), atLeastOnce()); + } + + @Test @RequiresFlagsDisabled(com.android.server.am.Flags.FLAG_UNFREEZE_BIND_POLICY_FIX) public void testServiceDistinctBindingOomAdjWaivePriority() throws Exception { // Enable the flags. @@ -624,6 +674,9 @@ public final class ServiceBindingOomAdjPolicyTest { // Enable the flags. mSetFlagsRule.enableFlags(Flags.FLAG_SERVICE_BINDING_OOM_ADJ_POLICY); + // Note that some capabilities like PROCESS_CAPABILITY_CPU_TIME are special and propagated + // regardless of BIND_INCLUDE_CAPABILITIES. We don't test for them here. + // Verify that there should be 0 oom adj update // because we didn't specify the "BIND_INCLUDE_CAPABILITIES" performTestServiceDistinctBindingOomAdj(TEST_APP1_PID, TEST_APP1_UID, diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java index 428e438443cd..5c73fd33f46f 100644 --- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java +++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java @@ -64,7 +64,6 @@ import android.os.Binder; import android.os.CpuHeadroomParamsInternal; import android.os.GpuHeadroomParamsInternal; import android.os.IBinder; -import android.os.IHintManager; import android.os.IHintSession; import android.os.PerformanceHintManager; import android.os.Process; @@ -155,8 +154,6 @@ public class HintManagerServiceTest { private ActivityManagerInternal mAmInternalMock; @Mock private PackageManager mMockPackageManager; - @Mock - private IHintManager.IHintManagerClient mClientCallback; @Rule public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); @@ -174,23 +171,6 @@ public class HintManagerServiceTest { }; } - private SupportInfo makeDefaultSupportInfo() { - mSupportInfo = new SupportInfo(); - mSupportInfo.usesSessions = true; - // By default, mark everything as fully supported - mSupportInfo.sessionHints = -1; - mSupportInfo.sessionModes = -1; - mSupportInfo.modes = -1; - mSupportInfo.boosts = -1; - mSupportInfo.sessionTags = -1; - mSupportInfo.headroom = new SupportInfo.HeadroomSupportInfo(); - mSupportInfo.headroom.isCpuSupported = true; - mSupportInfo.headroom.cpuMinIntervalMillis = 2000; - mSupportInfo.headroom.isGpuSupported = true; - mSupportInfo.headroom.gpuMinIntervalMillis = 2000; - return mSupportInfo; - } - @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); @@ -201,7 +181,12 @@ public class HintManagerServiceTest { mConfig.eventFlagDescriptor = new MQDescriptor<Byte, Byte>(); ApplicationInfo applicationInfo = new ApplicationInfo(); applicationInfo.category = ApplicationInfo.CATEGORY_GAME; - mSupportInfo = makeDefaultSupportInfo(); + mSupportInfo = new SupportInfo(); + mSupportInfo.headroom = new SupportInfo.HeadroomSupportInfo(); + mSupportInfo.headroom.isCpuSupported = true; + mSupportInfo.headroom.cpuMinIntervalMillis = 2000; + mSupportInfo.headroom.isGpuSupported = true; + mSupportInfo.headroom.gpuMinIntervalMillis = 2000; when(mContext.getPackageManager()).thenReturn(mMockPackageManager); when(mMockPackageManager.getNameForUid(anyInt())).thenReturn(TEST_APP_NAME); when(mMockPackageManager.getApplicationInfo(eq(TEST_APP_NAME), anyInt())) @@ -230,7 +215,6 @@ public class HintManagerServiceTest { when(mIPowerMock.getInterfaceVersion()).thenReturn(6); when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo); when(mIPowerMock.getSessionChannel(anyInt(), anyInt())).thenReturn(mConfig); - when(mIPowerMock.getSupportInfo()).thenReturn(mSupportInfo); LocalServices.removeServiceForTest(ActivityManagerInternal.class); LocalServices.addService(ActivityManagerInternal.class, mAmInternalMock); } @@ -425,11 +409,8 @@ public class HintManagerServiceTest { HintManagerService service = createService(); IBinder token = new Binder(); - IHintManager.HintManagerClientData data = service.getBinderServiceInstance() - .registerClient(mClientCallback); - - final int threadCount = data.maxGraphicsPipelineThreads; - + final int threadCount = + service.getBinderServiceInstance().getMaxGraphicsPipelineThreadsCount(); long sessionPtr1 = 1111L; long sessionId1 = 11111L; CountDownLatch stopLatch1 = new CountDownLatch(1); @@ -1466,67 +1447,4 @@ public class HintManagerServiceTest { verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams1)); verify(mIPowerMock, times(1)).getGpuHeadroom(eq(halParams2)); } - - @Test - public void testRegisteringClient() throws Exception { - HintManagerService service = createService(); - IHintManager.HintManagerClientData data = service.getBinderServiceInstance() - .registerClient(mClientCallback); - assertNotNull(data); - assertEquals(data.supportInfo, mSupportInfo); - } - - @Test - public void testRegisteringClientOnV4() throws Exception { - when(mIPowerMock.getInterfaceVersion()).thenReturn(4); - HintManagerService service = createService(); - IHintManager.HintManagerClientData data = service.getBinderServiceInstance() - .registerClient(mClientCallback); - assertNotNull(data); - assertEquals(data.supportInfo.usesSessions, true); - assertEquals(data.supportInfo.boosts, 0); - assertEquals(data.supportInfo.modes, 0); - assertEquals(data.supportInfo.sessionHints, 31); - assertEquals(data.supportInfo.sessionModes, 0); - assertEquals(data.supportInfo.sessionTags, 0); - assertEquals(data.powerHalVersion, 4); - assertEquals(data.preferredRateNanos, DEFAULT_HINT_PREFERRED_RATE); - } - - @Test - public void testRegisteringClientOnV5() throws Exception { - when(mIPowerMock.getInterfaceVersion()).thenReturn(5); - HintManagerService service = createService(); - IHintManager.HintManagerClientData data = service.getBinderServiceInstance() - .registerClient(mClientCallback); - assertNotNull(data); - assertEquals(data.supportInfo.usesSessions, true); - assertEquals(data.supportInfo.boosts, 0); - assertEquals(data.supportInfo.modes, 0); - assertEquals(data.supportInfo.sessionHints, 255); - assertEquals(data.supportInfo.sessionModes, 1); - assertEquals(data.supportInfo.sessionTags, 31); - assertEquals(data.powerHalVersion, 5); - assertEquals(data.preferredRateNanos, DEFAULT_HINT_PREFERRED_RATE); - } - - @Test - public void testSettingUpOldClientWhenUnsupported() throws Exception { - when(mIPowerMock.getInterfaceVersion()).thenReturn(5); - // Mock unsupported to modify the default support behavior - when(mNativeWrapperMock.halGetHintSessionPreferredRate()) - .thenReturn(-1L); - HintManagerService service = createService(); - IHintManager.HintManagerClientData data = service.getBinderServiceInstance() - .registerClient(mClientCallback); - assertNotNull(data); - assertEquals(data.supportInfo.usesSessions, false); - assertEquals(data.supportInfo.boosts, 0); - assertEquals(data.supportInfo.modes, 0); - assertEquals(data.supportInfo.sessionHints, 0); - assertEquals(data.supportInfo.sessionModes, 0); - assertEquals(data.supportInfo.sessionTags, 0); - assertEquals(data.powerHalVersion, 5); - assertEquals(data.preferredRateNanos, -1); - } } |