summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Shubang Lu <shubang@google.com> 2025-03-21 17:41:49 -0700
committer Shubang Lu <shubang@google.com> 2025-03-21 23:54:22 -0700
commit96f794f41c1a894cb044677bcd527b4d6f787243 (patch)
tree03e6e3f919e49177df2165139c98b57d238ae180
parent256ba2367aee49bc89f36d394fdd569ed4fec14a (diff)
[MQ] Handle active profile listener
Test: CTS Bug: 405477207 Flag: android.media.tv.flags.media_quality_fw Change-Id: I0ae8fccdd0ddc41ac671d462e5bc221c973d400b
-rw-r--r--media/java/android/media/quality/ActiveProcessingPicture.java19
-rw-r--r--media/java/android/media/quality/MediaQualityManager.java29
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/IActiveProcessingPictureListener.aidl28
-rw-r--r--media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl2
-rw-r--r--services/core/java/com/android/server/media/quality/MediaQualityService.java124
5 files changed, 192 insertions, 10 deletions
diff --git a/media/java/android/media/quality/ActiveProcessingPicture.java b/media/java/android/media/quality/ActiveProcessingPicture.java
index e16ad62e23f2..15c2e47fe820 100644
--- a/media/java/android/media/quality/ActiveProcessingPicture.java
+++ b/media/java/android/media/quality/ActiveProcessingPicture.java
@@ -31,16 +31,26 @@ import androidx.annotation.NonNull;
public final class ActiveProcessingPicture implements Parcelable {
private final int mId;
private final String mProfileId;
+ private final boolean mForGlobal;
public ActiveProcessingPicture(int id, @NonNull String profileId) {
mId = id;
mProfileId = profileId;
+ mForGlobal = true;
+ }
+
+ /** @hide */
+ public ActiveProcessingPicture(int id, @NonNull String profileId, boolean forGlobal) {
+ mId = id;
+ mProfileId = profileId;
+ mForGlobal = forGlobal;
}
/** @hide */
ActiveProcessingPicture(Parcel in) {
mId = in.readInt();
mProfileId = in.readString();
+ mForGlobal = in.readBoolean();
}
@NonNull
@@ -73,6 +83,14 @@ public final class ActiveProcessingPicture implements Parcelable {
return mProfileId;
}
+ /**
+ * @hide
+ */
+ @NonNull
+ public boolean isForGlobal() {
+ return mForGlobal;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -82,5 +100,6 @@ public final class ActiveProcessingPicture implements Parcelable {
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mId);
dest.writeString(mProfileId);
+ dest.writeBoolean(mForGlobal);
}
}
diff --git a/media/java/android/media/quality/MediaQualityManager.java b/media/java/android/media/quality/MediaQualityManager.java
index 6ad7684b8701..3f0ba3100191 100644
--- a/media/java/android/media/quality/MediaQualityManager.java
+++ b/media/java/android/media/quality/MediaQualityManager.java
@@ -214,11 +214,31 @@ public final class MediaQualityManager {
}
};
+ IActiveProcessingPictureListener apListener = new IActiveProcessingPictureListener.Stub() {
+ @Override
+ public void onActiveProcessingPicturesChanged(List<ActiveProcessingPicture> aps) {
+ List<ActiveProcessingPicture> nonGlobal = new ArrayList<>();
+ for (ActiveProcessingPicture ap : aps) {
+ if (!ap.isForGlobal()) {
+ nonGlobal.add(ap);
+ }
+ }
+ for (ActiveProcessingPictureListenerRecord record : mApListenerRecords) {
+ if (record.mIsGlobal) {
+ record.postActiveProcessingPicturesChanged(aps);
+ } else {
+ record.postActiveProcessingPicturesChanged(nonGlobal);
+ }
+ }
+ }
+ };
+
try {
if (mService != null) {
mService.registerPictureProfileCallback(ppCallback);
mService.registerSoundProfileCallback(spCallback);
mService.registerAmbientBacklightCallback(abCallback);
+ mService.registerActiveProcessingPictureListener(apListener);
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1225,6 +1245,15 @@ public final class MediaQualityManager {
public Consumer<List<ActiveProcessingPicture>> getListener() {
return mListener;
}
+
+ public void postActiveProcessingPicturesChanged(List<ActiveProcessingPicture> aps) {
+ mExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ mListener.accept(aps);
+ }
+ });
+ }
}
/**
diff --git a/media/java/android/media/quality/aidl/android/media/quality/IActiveProcessingPictureListener.aidl b/media/java/android/media/quality/aidl/android/media/quality/IActiveProcessingPictureListener.aidl
new file mode 100644
index 000000000000..f7d19baac7a1
--- /dev/null
+++ b/media/java/android/media/quality/aidl/android/media/quality/IActiveProcessingPictureListener.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package android.media.quality;
+
+import android.media.quality.ActiveProcessingPicture;
+
+/**
+ * Interface to receive event from media quality service.
+ * @hide
+ */
+oneway interface IActiveProcessingPictureListener {
+ void onActiveProcessingPicturesChanged(in List<ActiveProcessingPicture> ap);
+}
diff --git a/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl b/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl
index 2ad5d9d3ed17..ff1bf0228474 100644
--- a/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl
+++ b/media/java/android/media/quality/aidl/android/media/quality/IMediaQualityManager.aidl
@@ -17,6 +17,7 @@
package android.media.quality;
import android.media.quality.AmbientBacklightSettings;
+import android.media.quality.IActiveProcessingPictureListener;
import android.media.quality.IAmbientBacklightCallback;
import android.media.quality.IPictureProfileCallback;
import android.media.quality.ISoundProfileCallback;
@@ -70,6 +71,7 @@ interface IMediaQualityManager {
void registerPictureProfileCallback(in IPictureProfileCallback cb);
void registerSoundProfileCallback(in ISoundProfileCallback cb);
void registerAmbientBacklightCallback(in IAmbientBacklightCallback cb);
+ void registerActiveProcessingPictureListener(in IActiveProcessingPictureListener l);
List<ParameterCapability> getParameterCapabilities(in List<String> names, int userId);
diff --git a/services/core/java/com/android/server/media/quality/MediaQualityService.java b/services/core/java/com/android/server/media/quality/MediaQualityService.java
index 4b8ba89b9336..a3d9c66c2668 100644
--- a/services/core/java/com/android/server/media/quality/MediaQualityService.java
+++ b/services/core/java/com/android/server/media/quality/MediaQualityService.java
@@ -42,9 +42,11 @@ import android.hardware.tv.mediaquality.SoundParameter;
import android.hardware.tv.mediaquality.SoundParameters;
import android.hardware.tv.mediaquality.StreamStatus;
import android.hardware.tv.mediaquality.VendorParamCapability;
+import android.media.quality.ActiveProcessingPicture;
import android.media.quality.AmbientBacklightEvent;
import android.media.quality.AmbientBacklightMetadata;
import android.media.quality.AmbientBacklightSettings;
+import android.media.quality.IActiveProcessingPictureListener;
import android.media.quality.IAmbientBacklightCallback;
import android.media.quality.IMediaQualityManager;
import android.media.quality.IPictureProfileCallback;
@@ -72,6 +74,8 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.SurfaceControlActivePicture;
+import android.view.SurfaceControlActivePictureListener;
import com.android.internal.annotations.GuardedBy;
import com.android.server.SystemService;
@@ -121,6 +125,7 @@ public class MediaQualityService extends SystemService {
private MqManagerNotifier mMqManagerNotifier;
private MqDatabaseUtils mMqDatabaseUtils;
private Handler mHandler;
+ private SurfaceControlActivePictureListener mSurfaceControlActivePictureListener;
// A global lock for picture profile objects.
private final Object mPictureProfileLock = new Object();
@@ -175,6 +180,14 @@ public class MediaQualityService extends SystemService {
}
Slogf.d(TAG, "Binder is not null");
+ mSurfaceControlActivePictureListener = new SurfaceControlActivePictureListener() {
+ @Override
+ public void onActivePicturesChanged(SurfaceControlActivePicture[] activePictures) {
+ handleOnActivePicturesChanged(activePictures);
+ }
+ };
+ mSurfaceControlActivePictureListener.startListening(); // TODO: stop listening
+
mMediaQuality = IMediaQuality.Stub.asInterface(binder);
if (mMediaQuality != null) {
try {
@@ -210,6 +223,54 @@ public class MediaQualityService extends SystemService {
publishBinderService(Context.MEDIA_QUALITY_SERVICE, new BinderService());
}
+ private void handleOnActivePicturesChanged(SurfaceControlActivePicture[] scActivePictures) {
+ if (DEBUG) {
+ Slog.d(TAG, "handleOnActivePicturesChanged");
+ }
+ synchronized (mPictureProfileLock) {
+ // TODO handle other users
+ UserState userState = getOrCreateUserState(UserHandle.USER_SYSTEM);
+ int n = userState.mActiveProcessingPictureCallbackList.beginBroadcast();
+ for (int i = 0; i < n; ++i) {
+ try {
+ IActiveProcessingPictureListener l = userState
+ .mActiveProcessingPictureCallbackList
+ .getBroadcastItem(i);
+ ActiveProcessingPictureListenerInfo info =
+ userState.mActiveProcessingPictureListenerMap.get(l);
+ if (info == null) {
+ continue;
+ }
+ int uid = info.mUid;
+ boolean hasGlobalPermission = mContext.checkPermission(
+ android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE,
+ info.mPid, uid)
+ == PackageManager.PERMISSION_GRANTED;
+ List<ActiveProcessingPicture> aps = new ArrayList<>();
+ for (SurfaceControlActivePicture scap : scActivePictures) {
+ if (!hasGlobalPermission && scap.getOwnerUid() != uid) {
+ // should not receive the event
+ continue;
+ }
+ String profileId = mPictureProfileTempIdMap.getValue(
+ scap.getPictureProfileHandle().getId());
+ if (profileId == null) {
+ continue;
+ }
+ aps.add(new ActiveProcessingPicture(
+ scap.getLayerId(), profileId, scap.getOwnerUid() != uid));
+
+ }
+
+ l.onActiveProcessingPicturesChanged(aps);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "failed to report added AD service to callback", e);
+ }
+ }
+ userState.mActiveProcessingPictureCallbackList.finishBroadcast();
+ }
+ }
+
private final class BinderService extends IMediaQualityManager.Stub {
@GuardedBy("mPictureProfileLock")
@@ -801,21 +862,21 @@ public class MediaQualityService extends SystemService {
}
private boolean hasGlobalPictureQualityServicePermission() {
- return mPackageManager.checkPermission(android.Manifest.permission
- .MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE,
- mContext.getPackageName()) == mPackageManager.PERMISSION_GRANTED;
+ return mContext.checkCallingPermission(
+ android.Manifest.permission.MANAGE_GLOBAL_PICTURE_QUALITY_SERVICE)
+ == PackageManager.PERMISSION_GRANTED;
}
private boolean hasGlobalSoundQualityServicePermission() {
- return mPackageManager.checkPermission(android.Manifest.permission
- .MANAGE_GLOBAL_SOUND_QUALITY_SERVICE,
- mContext.getPackageName()) == mPackageManager.PERMISSION_GRANTED;
+ return mContext.checkCallingPermission(
+ android.Manifest.permission.MANAGE_GLOBAL_SOUND_QUALITY_SERVICE)
+ == PackageManager.PERMISSION_GRANTED;
}
private boolean hasReadColorZonesPermission() {
- return mPackageManager.checkPermission(android.Manifest.permission
- .READ_COLOR_ZONES,
- mContext.getPackageName()) == mPackageManager.PERMISSION_GRANTED;
+ return mContext.checkCallingPermission(
+ android.Manifest.permission.READ_COLOR_ZONES)
+ == PackageManager.PERMISSION_GRANTED;
}
@Override
@@ -839,6 +900,18 @@ public class MediaQualityService extends SystemService {
}
@Override
+ public void registerActiveProcessingPictureListener(
+ final IActiveProcessingPictureListener l) {
+ int callingPid = Binder.getCallingPid();
+ int callingUid = Binder.getCallingUid();
+
+ UserState userState = getOrCreateUserState(Binder.getCallingUid());
+ String packageName = getPackageOfCallingUid();
+ userState.mActiveProcessingPictureListenerMap.put(l,
+ new ActiveProcessingPictureListenerInfo(callingUid, callingPid, packageName));
+ }
+
+ @Override
public void registerAmbientBacklightCallback(IAmbientBacklightCallback callback) {
if (DEBUG) {
Slogf.d(TAG, "registerAmbientBacklightCallback");
@@ -1245,6 +1318,20 @@ public class MediaQualityService extends SystemService {
}
}
+ private class ActiveProcessingPictureCallbackList extends
+ RemoteCallbackList<IActiveProcessingPictureListener> {
+ @Override
+ public void onCallbackDied(IActiveProcessingPictureListener l) {
+ synchronized (mPictureProfileLock) {
+ for (int i = 0; i < mUserStates.size(); i++) {
+ int userId = mUserStates.keyAt(i);
+ UserState userState = getOrCreateUserState(userId);
+ userState.mActiveProcessingPictureListenerMap.remove(l);
+ }
+ }
+ }
+ }
+
private final class UserState {
// A list of callbacks.
private final MediaQualityManagerPictureProfileCallbackList mPictureProfileCallbacks =
@@ -1253,18 +1340,35 @@ public class MediaQualityService extends SystemService {
private final MediaQualityManagerSoundProfileCallbackList mSoundProfileCallbacks =
new MediaQualityManagerSoundProfileCallbackList();
+ private final ActiveProcessingPictureCallbackList mActiveProcessingPictureCallbackList =
+ new ActiveProcessingPictureCallbackList();
+
private final Map<IPictureProfileCallback, Pair<Integer, Integer>>
mPictureProfileCallbackPidUidMap = new HashMap<>();
private final Map<ISoundProfileCallback, Pair<Integer, Integer>>
mSoundProfileCallbackPidUidMap = new HashMap<>();
+ private final Map<IActiveProcessingPictureListener, ActiveProcessingPictureListenerInfo>
+ mActiveProcessingPictureListenerMap = new HashMap<>();
+
private UserState(Context context, int userId) {
}
}
- @GuardedBy("mUserStateLock")
+ private final class ActiveProcessingPictureListenerInfo {
+ private int mUid;
+ private int mPid;
+ private String mPackageName;
+
+ ActiveProcessingPictureListenerInfo(int uid, int pid, String packageName) {
+ mUid = uid;
+ mPid = pid;
+ mPackageName = packageName;
+ }
+ }
+
private UserState getOrCreateUserState(int userId) {
UserState userState = getUserState(userId);
if (userState == null) {