diff options
Diffstat (limited to 'media')
7 files changed, 154 insertions, 12 deletions
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java index e57148fe5a6a..3af36a404c30 100644 --- a/media/java/android/media/MediaRouter2.java +++ b/media/java/android/media/MediaRouter2.java @@ -281,7 +281,7 @@ public final class MediaRouter2 { /* executor */ null, /* onInstanceInvalidatedListener */ null); } catch (IllegalArgumentException ex) { - Log.e(TAG, "Package " + clientPackageName + " not found. Ignoring."); + Log.e(TAG, "Failed to create proxy router for package '" + clientPackageName + "'", ex); return null; } } diff --git a/media/java/android/media/flags/projection.aconfig b/media/java/android/media/flags/projection.aconfig index fa1349c61c4c..6d4f0b4f47d5 100644 --- a/media/java/android/media/flags/projection.aconfig +++ b/media/java/android/media/flags/projection.aconfig @@ -29,3 +29,13 @@ flag { is_exported: true } +flag { + namespace: "media_projection" + name: "show_stop_dialog_post_call_end" + description: "Shows a stop dialog for MediaProjection sessions that started during call and remain active after a call ends" + bug: "390343524" + metadata { + purpose: PURPOSE_BUGFIX + } + is_exported: true +} diff --git a/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl b/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl index e46d34e81483..3baf4d7efd65 100644 --- a/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl +++ b/media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl @@ -18,6 +18,7 @@ package android.media.projection; import android.media.projection.MediaProjectionInfo; import android.view.ContentRecordingSession; +import android.media.projection.MediaProjectionEvent; /** {@hide} */ oneway interface IMediaProjectionWatcherCallback { @@ -35,4 +36,19 @@ oneway interface IMediaProjectionWatcherCallback { in MediaProjectionInfo info, in @nullable ContentRecordingSession session ); + + /** + * Called when a specific {@link MediaProjectionEvent} occurs during the media projection session. + * + * @param event contains the event type, which describes the nature/context of the event. + * @param info optional {@link MediaProjectionInfo} containing details about the media + projection host. + * @param session the recording session for the current media projection. Can be + * {@code null} when the recording will stop. + */ + void onMediaProjectionEvent( + in MediaProjectionEvent event, + in @nullable MediaProjectionInfo info, + in @nullable ContentRecordingSession session + ); } diff --git a/media/java/android/media/projection/MediaProjectionEvent.aidl b/media/java/android/media/projection/MediaProjectionEvent.aidl new file mode 100644 index 000000000000..34359900ce81 --- /dev/null +++ b/media/java/android/media/projection/MediaProjectionEvent.aidl @@ -0,0 +1,3 @@ +package android.media.projection; + +parcelable MediaProjectionEvent;
\ No newline at end of file diff --git a/media/java/android/media/projection/MediaProjectionEvent.java b/media/java/android/media/projection/MediaProjectionEvent.java new file mode 100644 index 000000000000..6922560c8abe --- /dev/null +++ b/media/java/android/media/projection/MediaProjectionEvent.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2025 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, + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.media.projection; + +import android.annotation.IntDef; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.Objects; + +/** @hide */ +public final class MediaProjectionEvent implements Parcelable { + + /** + * Represents various media projection events. + */ + @IntDef({PROJECTION_STARTED_DURING_CALL_AND_ACTIVE_POST_CALL}) + @Retention(RetentionPolicy.SOURCE) + public @interface EventType {} + + /** Event type for when a call ends but the session is still active. */ + public static final int PROJECTION_STARTED_DURING_CALL_AND_ACTIVE_POST_CALL = 0; + + private final @EventType int mEventType; + private final long mTimestampMillis; + + public MediaProjectionEvent(@EventType int eventType, long timestampMillis) { + mEventType = eventType; + mTimestampMillis = timestampMillis; + } + + private MediaProjectionEvent(Parcel in) { + mEventType = in.readInt(); + mTimestampMillis = in.readLong(); + } + + public @EventType int getEventType() { + return mEventType; + } + + public long getTimestampMillis() { + return mTimestampMillis; + } + + @Override + public boolean equals(Object o) { + if (o instanceof MediaProjectionEvent other) { + return mEventType == other.mEventType && mTimestampMillis == other.mTimestampMillis; + } + return false; + } + + @Override + public int hashCode() { + return Objects.hash(mEventType, mTimestampMillis); + } + + @Override + public String toString() { + return "MediaProjectionEvent{mEventType=" + mEventType + ", mTimestampMillis=" + + mTimestampMillis + "}"; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + out.writeInt(mEventType); + out.writeLong(mTimestampMillis); + } + + public static final Parcelable.Creator<MediaProjectionEvent> CREATOR = + new Parcelable.Creator<>() { + @Override + public MediaProjectionEvent createFromParcel(Parcel in) { + return new MediaProjectionEvent(in); + } + + @Override + public MediaProjectionEvent[] newArray(int size) { + return new MediaProjectionEvent[size]; + } + }; +} diff --git a/media/java/android/media/projection/MediaProjectionManager.java b/media/java/android/media/projection/MediaProjectionManager.java index 9cc2cca441a4..9036bf385d96 100644 --- a/media/java/android/media/projection/MediaProjectionManager.java +++ b/media/java/android/media/projection/MediaProjectionManager.java @@ -363,6 +363,19 @@ public final class MediaProjectionManager { @Nullable ContentRecordingSession session ) { } + + /** + * Called when a specific {@link MediaProjectionEvent} occurs during the media projection + * session. + * + * @param event the media projection event details. + * @param info optional details about the media projection host. + * @param session optional associated recording session details. + */ + public void onMediaProjectionEvent( + final MediaProjectionEvent event, + @Nullable MediaProjectionInfo info, + @Nullable final ContentRecordingSession session) {} } /** @hide */ @@ -405,5 +418,13 @@ public final class MediaProjectionManager { ) { mHandler.post(() -> mCallback.onRecordingSessionSet(info, session)); } + + @Override + public void onMediaProjectionEvent( + final MediaProjectionEvent event, + @Nullable MediaProjectionInfo info, + @Nullable final ContentRecordingSession session) { + mHandler.post(() -> mCallback.onMediaProjectionEvent(event, info, session)); + } } } diff --git a/media/java/android/media/quality/MediaQualityManager.java b/media/java/android/media/quality/MediaQualityManager.java index b7269256a449..0d6d32a22dae 100644 --- a/media/java/android/media/quality/MediaQualityManager.java +++ b/media/java/android/media/quality/MediaQualityManager.java @@ -51,7 +51,6 @@ import java.util.function.Consumer; @FlaggedApi(Flags.FLAG_MEDIA_QUALITY_FW) @SystemService(Context.MEDIA_QUALITY_SERVICE) public final class MediaQualityManager { - // TODO: unhide the APIs for api review private static final String TAG = "MediaQualityManager"; private final IMediaQualityManager mService; @@ -123,7 +122,6 @@ public final class MediaQualityManager { public void onPictureProfileAdded(String profileId, PictureProfile profile) { synchronized (mPpLock) { for (PictureProfileCallbackRecord record : mPpCallbackRecords) { - // TODO: filter callback record record.postPictureProfileAdded(profileId, profile); } } @@ -132,7 +130,6 @@ public final class MediaQualityManager { public void onPictureProfileUpdated(String profileId, PictureProfile profile) { synchronized (mPpLock) { for (PictureProfileCallbackRecord record : mPpCallbackRecords) { - // TODO: filter callback record record.postPictureProfileUpdated(profileId, profile); } } @@ -141,7 +138,6 @@ public final class MediaQualityManager { public void onPictureProfileRemoved(String profileId, PictureProfile profile) { synchronized (mPpLock) { for (PictureProfileCallbackRecord record : mPpCallbackRecords) { - // TODO: filter callback record record.postPictureProfileRemoved(profileId, profile); } } @@ -151,7 +147,6 @@ public final class MediaQualityManager { String profileId, List<ParameterCapability> caps) { synchronized (mPpLock) { for (PictureProfileCallbackRecord record : mPpCallbackRecords) { - // TODO: filter callback record record.postParameterCapabilitiesChanged(profileId, caps); } } @@ -160,7 +155,6 @@ public final class MediaQualityManager { public void onError(String profileId, int err) { synchronized (mPpLock) { for (PictureProfileCallbackRecord record : mPpCallbackRecords) { - // TODO: filter callback record record.postError(profileId, err); } } @@ -171,7 +165,6 @@ public final class MediaQualityManager { public void onSoundProfileAdded(String profileId, SoundProfile profile) { synchronized (mSpLock) { for (SoundProfileCallbackRecord record : mSpCallbackRecords) { - // TODO: filter callback record record.postSoundProfileAdded(profileId, profile); } } @@ -180,7 +173,6 @@ public final class MediaQualityManager { public void onSoundProfileUpdated(String profileId, SoundProfile profile) { synchronized (mSpLock) { for (SoundProfileCallbackRecord record : mSpCallbackRecords) { - // TODO: filter callback record record.postSoundProfileUpdated(profileId, profile); } } @@ -189,7 +181,6 @@ public final class MediaQualityManager { public void onSoundProfileRemoved(String profileId, SoundProfile profile) { synchronized (mSpLock) { for (SoundProfileCallbackRecord record : mSpCallbackRecords) { - // TODO: filter callback record record.postSoundProfileRemoved(profileId, profile); } } @@ -199,7 +190,6 @@ public final class MediaQualityManager { String profileId, List<ParameterCapability> caps) { synchronized (mSpLock) { for (SoundProfileCallbackRecord record : mSpCallbackRecords) { - // TODO: filter callback record record.postParameterCapabilitiesChanged(profileId, caps); } } @@ -208,7 +198,6 @@ public final class MediaQualityManager { public void onError(String profileId, int err) { synchronized (mSpLock) { for (SoundProfileCallbackRecord record : mSpCallbackRecords) { - // TODO: filter callback record record.postError(profileId, err); } } |