From f2c597df8914da7fefcb2b08eea0f61e436ef47d Mon Sep 17 00:00:00 2001 From: Yixiao Luo Date: Wed, 14 Dec 2022 18:57:27 -0800 Subject: [PATCH] Add API to register AttributionSource of TV App to TIS test: mmm bug: 183922416 Change-Id: Ie537e5ce61bda84ba40d4a60aa4de45217f32aa5 --- core/api/current.txt | 2 ++ .../android/media/tv/ITvInputManager.aidl | 3 +- .../android/media/tv/ITvInputService.aidl | 3 +- .../media/tv/ITvInputSessionWrapper.java | 1 - .../java/android/media/tv/TvInputManager.java | 26 +++++++------- .../java/android/media/tv/TvInputService.java | 34 +++++++++++++++---- media/java/android/media/tv/TvView.java | 26 ++++++++++++-- .../server/tv/TvInputManagerService.java | 18 +++++----- 8 files changed, 79 insertions(+), 34 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index a0c132f980dc..8a2ce85519f2 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -25915,6 +25915,7 @@ package android.media.tv { method @Nullable public android.media.tv.TvInputService.RecordingSession onCreateRecordingSession(@NonNull String, @NonNull String); method @Nullable public abstract android.media.tv.TvInputService.Session onCreateSession(@NonNull String); method @Nullable public android.media.tv.TvInputService.Session onCreateSession(@NonNull String, @NonNull String); + method @Nullable public android.media.tv.TvInputService.Session onCreateSession(@NonNull String, @NonNull String, @NonNull android.content.AttributionSource); field public static final int PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND = 100; // 0x64 field public static final int PRIORITY_HINT_USE_CASE_TYPE_LIVE = 400; // 0x190 field public static final int PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK = 300; // 0x12c @@ -26075,6 +26076,7 @@ package android.media.tv { method public String getSelectedTrack(int); method public java.util.List getTracks(int); method public boolean onUnhandledInputEvent(android.view.InputEvent); + method public void overrideTvAppAttributionSource(@NonNull android.content.AttributionSource); method public void reset(); method public void selectTrack(int, String); method public void sendAppPrivateCommand(@NonNull String, android.os.Bundle); diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl index 2a33ee6a6b4d..1d2198ee740f 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -16,6 +16,7 @@ package android.media.tv; +import android.content.AttributionSource; import android.content.ComponentName; import android.content.Intent; import android.graphics.Rect; @@ -62,7 +63,7 @@ interface ITvInputManager { void addBlockedRating(in String rating, int userId); void removeBlockedRating(in String rating, int userId); - void createSession(in ITvInputClient client, in String inputId, boolean isRecordingSession, + void createSession(in ITvInputClient client, in String inputId, in AttributionSource tvAppAttributionSource, boolean isRecordingSession, int seq, int userId); void releaseSession(in IBinder sessionToken, int userId); int getClientPid(in String sessionId); diff --git a/media/java/android/media/tv/ITvInputService.aidl b/media/java/android/media/tv/ITvInputService.aidl index 64a23a2323f6..be73c0cdf43a 100755 --- a/media/java/android/media/tv/ITvInputService.aidl +++ b/media/java/android/media/tv/ITvInputService.aidl @@ -16,6 +16,7 @@ package android.media.tv; +import android.content.AttributionSource; import android.hardware.hdmi.HdmiDeviceInfo; import android.media.tv.ITvInputServiceCallback; import android.media.tv.ITvInputSessionCallback; @@ -30,7 +31,7 @@ interface ITvInputService { oneway void registerCallback(in ITvInputServiceCallback callback); oneway void unregisterCallback(in ITvInputServiceCallback callback); oneway void createSession(in InputChannel channel, in ITvInputSessionCallback callback, - in String inputId, in String sessionId); + in String inputId, in String sessionId, in AttributionSource tvAppAttributionSource); oneway void createRecordingSession(in ITvInputSessionCallback callback, in String inputId, in String sessionId); List getAvailableExtensionInterfaceNames(); diff --git a/media/java/android/media/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java index 8911f6c7d4be..6c1099082ef7 100644 --- a/media/java/android/media/tv/ITvInputSessionWrapper.java +++ b/media/java/android/media/tv/ITvInputSessionWrapper.java @@ -30,7 +30,6 @@ import android.view.InputChannel; import android.view.InputEvent; import android.view.InputEventReceiver; import android.view.Surface; - import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index 149c2f471a4c..819cd0c8c58c 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -25,6 +25,7 @@ import android.annotation.RequiresPermission; import android.annotation.SystemApi; import android.annotation.SystemService; import android.annotation.TestApi; +import android.content.AttributionSource; import android.content.Context; import android.content.Intent; import android.graphics.Rect; @@ -53,9 +54,7 @@ import android.view.InputEventSender; import android.view.KeyEvent; import android.view.Surface; import android.view.View; - import com.android.internal.util.Preconditions; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -1835,13 +1834,15 @@ public final class TvInputManager { * of the given TV input. * * @param inputId The ID of the TV input. + * @param tvAppAttributionSource The Attribution Source of the TV App. * @param callback A callback used to receive the created session. * @param handler A {@link Handler} that the session creation will be delivered to. * @hide */ - public void createSession(@NonNull String inputId, @NonNull final SessionCallback callback, - @NonNull Handler handler) { - createSessionInternal(inputId, false, callback, handler); + public void createSession(@NonNull String inputId, + @NonNull AttributionSource tvAppAttributionSource, + @NonNull final SessionCallback callback, @NonNull Handler handler) { + createSessionInternal(inputId, tvAppAttributionSource, false, callback, handler); } /** @@ -1866,7 +1867,7 @@ public final class TvInputManager { * @param useCase the use case type of the client. * {@see TvInputService#PriorityHintUseCaseType}. * @param sessionId the unique id of the session owned by the client. - * {@see TvInputService#onCreateSession(String, String)}. + * {@see TvInputService#onCreateSession(String, String, AttributionSource)}. * * @return the use case priority value for the given use case type and the client's foreground * or background status. @@ -1917,11 +1918,11 @@ public final class TvInputManager { */ public void createRecordingSession(@NonNull String inputId, @NonNull final SessionCallback callback, @NonNull Handler handler) { - createSessionInternal(inputId, true, callback, handler); + createSessionInternal(inputId, null, true, callback, handler); } - private void createSessionInternal(String inputId, boolean isRecordingSession, - SessionCallback callback, Handler handler) { + private void createSessionInternal(String inputId, AttributionSource tvAppAttributionSource, + boolean isRecordingSession, SessionCallback callback, Handler handler) { Preconditions.checkNotNull(inputId); Preconditions.checkNotNull(callback); Preconditions.checkNotNull(handler); @@ -1930,7 +1931,8 @@ public final class TvInputManager { int seq = mNextSeq++; mSessionCallbackRecordMap.put(seq, record); try { - mService.createSession(mClient, inputId, isRecordingSession, seq, mUserId); + mService.createSession( + mClient, inputId, tvAppAttributionSource, isRecordingSession, seq, mUserId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -2101,8 +2103,8 @@ public final class TvInputManager { * @param deviceId The device ID to acquire Hardware for. * @param info The TV input which will use the acquired Hardware. * @param tvInputSessionId a String returned to TIS when the session was created. - * {@see TvInputService#onCreateSession(String, String)}. If null, the client will be - * treated as a background app. + * {@see TvInputService#onCreateSession(String, String, AttributionSource)}. If null, the + * client will be treated as a background app. * @param priorityHint The use case of the client. {@see TvInputService#PriorityHintUseCaseType} * @param executor the executor on which the listener would be invoked. * @param callback A callback to receive updates on Hardware. diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java index 70acf25afc51..f3e5d14eec7a 100755 --- a/media/java/android/media/tv/TvInputService.java +++ b/media/java/android/media/tv/TvInputService.java @@ -26,6 +26,7 @@ import android.annotation.SystemApi; import android.app.ActivityManager; import android.app.Service; import android.compat.annotation.UnsupportedAppUsage; +import android.content.AttributionSource; import android.content.Context; import android.content.Intent; import android.graphics.PixelFormat; @@ -57,10 +58,8 @@ import android.view.ViewRootImpl; import android.view.WindowManager; import android.view.accessibility.CaptioningManager; import android.widget.FrameLayout; - import com.android.internal.os.SomeArgs; import com.android.internal.util.Preconditions; - import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; @@ -171,7 +170,7 @@ public abstract class TvInputService extends Service { @Override public void createSession(InputChannel channel, ITvInputSessionCallback cb, - String inputId, String sessionId) { + String inputId, String sessionId, AttributionSource tvAppAttributionSource) { if (channel == null) { Log.w(TAG, "Creating session without input channel"); } @@ -183,6 +182,7 @@ public abstract class TvInputService extends Service { args.arg2 = cb; args.arg3 = inputId; args.arg4 = sessionId; + args.arg5 = tvAppAttributionSource; mServiceHandler.obtainMessage(ServiceHandler.DO_CREATE_SESSION, args).sendToTarget(); } @@ -369,6 +369,24 @@ public abstract class TvInputService extends Service { return onCreateSession(inputId); } + /** + * Returns a concrete implementation of {@link Session}. + * + *

For any apps that needs sessionId to request tuner resources from TunerResourceManager and + * needs to specify custom AttributionSource to AudioTrack, it needs to override this method to + * get the sessionId and AttrubutionSource passed. When no overriding, this method calls {@link + * #onCreateSession(String, String)} defaultly. + * + * @param inputId The ID of the TV input associated with the session. + * @param sessionId the unique sessionId created by TIF when session is created. + * @param tvAppAttributionSource The Attribution Source of the TV App. + */ + @Nullable + public Session onCreateSession(@NonNull String inputId, @NonNull String sessionId, + @NonNull AttributionSource tvAppAttributionSource) { + return onCreateSession(inputId, sessionId); + } + /** * Returns a concrete implementation of {@link RecordingSession}. * @@ -1107,7 +1125,7 @@ public abstract class TvInputService extends Service { public abstract void onSetStreamVolume(@FloatRange(from = 0.0, to = 1.0) float volume); /** - * called when broadcast info is requested. + * Called when broadcast info is requested. * * @param request broadcast info request */ @@ -1115,7 +1133,7 @@ public abstract class TvInputService extends Service { } /** - * called when broadcast info is removed. + * Called when broadcast info is removed. */ public void onRemoveBroadcastInfo(int requestId) { } @@ -2444,8 +2462,10 @@ public abstract class TvInputService extends Service { ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg2; String inputId = (String) args.arg3; String sessionId = (String) args.arg4; + AttributionSource tvAppAttributionSource = (AttributionSource) args.arg5; args.recycle(); - Session sessionImpl = onCreateSession(inputId, sessionId); + Session sessionImpl = + onCreateSession(inputId, sessionId, tvAppAttributionSource); if (sessionImpl == null) { try { // Failed to create a session. @@ -2481,7 +2501,7 @@ public abstract class TvInputService extends Service { proxySession.mServiceHandler = mServiceHandler; TvInputManager manager = (TvInputManager) getSystemService( Context.TV_INPUT_SERVICE); - manager.createSession(hardwareInputId, + manager.createSession(hardwareInputId, tvAppAttributionSource, proxySession.mHardwareSessionCallback, mServiceHandler); } else { SomeArgs someArgs = SomeArgs.obtain(); diff --git a/media/java/android/media/tv/TvView.java b/media/java/android/media/tv/TvView.java index ff3d06c5bd69..de9acc3d797f 100644 --- a/media/java/android/media/tv/TvView.java +++ b/media/java/android/media/tv/TvView.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.content.AttributionSource; import android.content.Context; import android.content.pm.PackageManager; import android.content.res.Resources; @@ -51,7 +52,6 @@ import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.ViewRootImpl; - import java.lang.ref.WeakReference; import java.util.ArrayDeque; import java.util.List; @@ -111,6 +111,7 @@ public class TvView extends ViewGroup { private int mSurfaceViewTop; private int mSurfaceViewBottom; private TimeShiftPositionCallback mTimeShiftPositionCallback; + private AttributionSource mTvAppAttributionSource; private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() { @Override @@ -185,6 +186,7 @@ public class TvView extends ViewGroup { mDefStyleAttr = defStyleAttr; resetSurfaceView(); mTvInputManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE); + mTvAppAttributionSource = getContext().getAttributionSource(); } /** @@ -303,6 +305,22 @@ public class TvView extends ViewGroup { mSession.setStreamVolume(volume); } + /** + * Override default attribution source of TV App. + * + *

An attribution source of TV App is used to attribute work to TV Input Service. + * The default attribution source is created by {@link Context#getAttributionSource()}. + * Call this method before calling {@link #tune(String, Uri, Bundle)} or {@link + * #timeShiftPlay(String, Uri)} to override the default attribution source. + * + * @param tvAppAttributionSource The attribution source of the TV App. + */ + public void overrideTvAppAttributionSource(@NonNull AttributionSource tvAppAttributionSource) { + if (tvAppAttributionSource != null) { + mTvAppAttributionSource = tvAppAttributionSource; + } + } + /** * Tunes to a given channel. * @@ -355,7 +373,8 @@ public class TvView extends ViewGroup { // is obsolete and should ignore it. mSessionCallback = new MySessionCallback(inputId, channelUri, params); if (mTvInputManager != null) { - mTvInputManager.createSession(inputId, mSessionCallback, mHandler); + mTvInputManager.createSession( + inputId, mTvAppAttributionSource, mSessionCallback, mHandler); } } } @@ -526,7 +545,8 @@ public class TvView extends ViewGroup { resetInternal(); mSessionCallback = new MySessionCallback(inputId, recordedProgramUri); if (mTvInputManager != null) { - mTvInputManager.createSession(inputId, mSessionCallback, mHandler); + mTvInputManager.createSession( + inputId, mTvAppAttributionSource, mSessionCallback, mHandler); } } } diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index b95d3726af07..8bc7bcce4958 100755 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -24,6 +24,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.ActivityManager; +import android.content.AttributionSource; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -90,7 +91,6 @@ import android.util.Slog; import android.util.SparseArray; import android.view.InputChannel; import android.view.Surface; - import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; @@ -101,9 +101,7 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.IndentingPrintWriter; import com.android.server.IoThread; import com.android.server.SystemService; - import dalvik.annotation.optimization.NeverCompile; - import java.io.File; import java.io.FileDescriptor; import java.io.FileNotFoundException; @@ -813,7 +811,7 @@ public final class TvInputManagerService extends SystemService { @GuardedBy("mLock") private boolean createSessionInternalLocked(ITvInputService service, IBinder sessionToken, - int userId) { + int userId, AttributionSource tvAppAttributionSource) { UserState userState = getOrCreateUserStateLocked(userId); SessionState sessionState = userState.sessionStateMap.get(sessionToken); if (DEBUG) { @@ -832,8 +830,8 @@ public final class TvInputManagerService extends SystemService { service.createRecordingSession( callback, sessionState.inputId, sessionState.sessionId); } else { - service.createSession( - channels[1], callback, sessionState.inputId, sessionState.sessionId); + service.createSession(channels[1], callback, sessionState.inputId, + sessionState.sessionId, tvAppAttributionSource); } } catch (RemoteException e) { Slog.e(TAG, "error in createSession", e); @@ -1485,7 +1483,8 @@ public final class TvInputManagerService extends SystemService { @Override public void createSession(final ITvInputClient client, final String inputId, - boolean isRecordingSession, int seq, int userId) { + AttributionSource tvAppAttributionSource, boolean isRecordingSession, int seq, + int userId) { final int callingUid = Binder.getCallingUid(); final int callingPid = Binder.getCallingPid(); final int resolvedUserId = resolveCallingUserId(callingPid, callingUid, @@ -1556,7 +1555,7 @@ public final class TvInputManagerService extends SystemService { if (serviceState.service != null) { if (!createSessionInternalLocked(serviceState.service, sessionToken, - resolvedUserId)) { + resolvedUserId, tvAppAttributionSource)) { removeSessionStateLocked(sessionToken, resolvedUserId); } } else { @@ -3113,7 +3112,8 @@ public final class TvInputManagerService extends SystemService { // And create sessions, if any. for (IBinder sessionToken : serviceState.sessionTokens) { - if (!createSessionInternalLocked(serviceState.service, sessionToken, mUserId)) { + if (!createSessionInternalLocked( + serviceState.service, sessionToken, mUserId, null)) { tokensToBeRemoved.add(sessionToken); } }