diff options
5 files changed, 103 insertions, 1 deletions
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml index 1fe6ca7dc14f..9a55b80f37e2 100644 --- a/data/etc/privapp-permissions-platform.xml +++ b/data/etc/privapp-permissions-platform.xml @@ -592,6 +592,10 @@ applications that come with the platform <permission name="android.permission.INTERACT_ACROSS_USERS" /> </privapp-permissions> + <privapp-permissions package="com.android.providers.tv"> + <permission name="android.permission.INTERACT_ACROSS_USERS"/> + </privapp-permissions> + <privapp-permissions package="com.android.tv"> <permission name="android.permission.CHANGE_HDMI_CEC_ACTIVE_SOURCE"/> <permission name="android.permission.DVB_DEVICE"/> diff --git a/media/java/android/media/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl index be93abb15b41..87cb3e7ab73d 100644 --- a/media/java/android/media/tv/ITvInputManager.aidl +++ b/media/java/android/media/tv/ITvInputManager.aidl @@ -70,6 +70,7 @@ interface ITvInputManager { void releaseSession(in IBinder sessionToken, int userId); int getClientPid(in String sessionId); int getClientPriority(int useCase, in String sessionId); + int getClientUserId(in String sessionId); void setMainSession(in IBinder sessionToken, int userId); void setSurface(in IBinder sessionToken, in Surface surface, int userId); diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java index aed3e60e5d75..25b6bfac9b1a 100644 --- a/media/java/android/media/tv/TvInputManager.java +++ b/media/java/android/media/tv/TvInputManager.java @@ -760,6 +760,14 @@ public final class TvInputManager { * @hide */ public static final int UNKNOWN_CLIENT_PID = -1; + /** + * An unknown state of the client userId gets from the TvInputManager. Client gets this value + * when query through {@link #getClientUserId(String sessionId)} fails. + * + * @hide + */ + @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING) + public static final int UNKNOWN_CLIENT_USER_ID = -1; /** * Broadcast intent action when the user blocked content ratings change. For use with the @@ -2510,6 +2518,21 @@ public final class TvInputManager { }; /** + * Get a the client user id when creating the session with the session id provided. + * + * @param sessionId a String of session id that is used to query the client user id. + * @return the client pid when created the session. Returns {@link #UNKNOWN_CLIENT_USER_ID} + * if the call fails. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.TUNER_RESOURCE_ACCESS) + @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING) + public int getClientUserId(@NonNull String sessionId) { + return getClientUserIdInternal(sessionId); + } + + /** * Returns a priority for the given use case type and the client's foreground or background * status. * @@ -2599,6 +2622,18 @@ public final class TvInputManager { return clientPid; } + @FlaggedApi(Flags.FLAG_KIDS_MODE_TVDB_SHARING) + private int getClientUserIdInternal(String sessionId) { + Preconditions.checkNotNull(sessionId); + int clientUserId = UNKNOWN_CLIENT_USER_ID; + try { + clientUserId = mService.getClientUserId(sessionId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + return clientUserId; + } + private int getClientPriorityInternal(int useCase, String sessionId) { try { return mService.getClientPriority(useCase, sessionId); diff --git a/media/java/android/media/tv/flags/media_tv.aconfig b/media/java/android/media/tv/flags/media_tv.aconfig index 3196ba124d76..d6e9e4e4c355 100644 --- a/media/java/android/media/tv/flags/media_tv.aconfig +++ b/media/java/android/media/tv/flags/media_tv.aconfig @@ -31,4 +31,12 @@ flag { namespace: "media_tv" description: "Introduce ALWAYS_BOUND_TV_INPUT for TIS." bug: "332201346" +} + +flag { + name: "kids_mode_tvdb_sharing" + is_exported: true + namespace: "media_tv" + description: "Performance and Storage Optimization in Google TV Kids Mode." + bug: "288383796" }
\ No newline at end of file diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 6721893e0c60..c543b6d2af10 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -19,6 +19,7 @@ package com.android.server.tv; import static android.media.AudioManager.DEVICE_NONE; import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED; import static android.media.tv.TvInputManager.INPUT_STATE_CONNECTED_STANDBY; +import static android.media.tv.flags.Flags.kidsModeTvdbSharing; import android.annotation.NonNull; import android.annotation.Nullable; @@ -805,6 +806,19 @@ public final class TvInputManagerService extends SystemService { } } + private boolean isServiceSingleUser(ComponentName component) { + try { + ServiceInfo serviceInfo = getContext().getPackageManager() + .getServiceInfo(component, 0); + // Check if the single-user flag is present + return (serviceInfo.flags & ServiceInfo.FLAG_SINGLE_USER) != 0; + } catch (PackageManager.NameNotFoundException e) { + // Handle the case where the service is not found + Slog.e(TAG, "Service not found: " + component, e); + return false; + } + } + @GuardedBy("mLock") private void abortPendingCreateSessionRequestsLocked(ServiceState serviceState, String inputId, int userId) { @@ -2840,6 +2854,26 @@ public final class TvInputManagerService extends SystemService { } @Override + public int getClientUserId(String sessionId) { + ensureTunerResourceAccessPermission(); + int clientUserId = TvInputManager.UNKNOWN_CLIENT_USER_ID; + + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + try { + clientUserId = getClientUserIdLocked(sessionId); + } catch (ClientUserIdNotFoundException e) { + Slog.e(TAG, "error in getClientUserId", e); + } + } + } finally { + Binder.restoreCallingIdentity(identity); + } + return clientUserId; + } + + @Override public int getClientPriority(int useCase, String sessionId) { ensureTunerResourceAccessPermission(); final int callingPid = Binder.getCallingPid(); @@ -2924,6 +2958,16 @@ public final class TvInputManagerService extends SystemService { return mSessionIdToSessionStateMap.get(sessionId).callingPid; } + @GuardedBy("mLock") + private int getClientUserIdLocked(String sessionId) throws ClientUserIdNotFoundException { + SessionState sessionState = mSessionIdToSessionStateMap.get(sessionId); + if (sessionState == null) { + throw new ClientUserIdNotFoundException( + "Client UserId not found with sessionId " + sessionId); + } + return sessionState.userId; + } + private void ensureTunerResourceAccessPermission() { if (mContext.checkCallingPermission( android.Manifest.permission.TUNER_RESOURCE_ACCESS) @@ -3495,11 +3539,15 @@ public final class TvInputManagerService extends SystemService { "bindServiceAsUser(service=" + serviceState.component + ", userId=" + userId + ")"); } + int bindUserId = userId; + if (kidsModeTvdbSharing() && isServiceSingleUser(serviceState.component)) { + bindUserId = UserHandle.USER_SYSTEM; + } Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(serviceState.component); serviceState.bound = mContext.bindServiceAsUser(i, serviceState.connection, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, - new UserHandle(userId)); + new UserHandle(bindUserId)); if (!serviceState.bound) { Slog.e(TAG, "failed to bind " + serviceState.component + " for userId " + userId); mContext.unbindService(serviceState.connection); @@ -4700,4 +4748,10 @@ public final class TvInputManagerService extends SystemService { super(name); } } + + private static class ClientUserIdNotFoundException extends IllegalArgumentException { + ClientUserIdNotFoundException(String name) { + super(name); + } + } } |