diff options
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) { |