Loading media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.view.Surface; */ interface ITvInteractiveAppManager { List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList(int userId); List<AppLinkInfo> getAppLinkInfoList(int userId); void registerAppLinkInfo(String tiasId, in AppLinkInfo info, int userId); void unregisterAppLinkInfo(String tiasId, in AppLinkInfo info, int userId); void sendAppLinkCommand(String tiasId, in Bundle command, int userId); Loading media/java/android/media/tv/interactive/TvInteractiveAppManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -864,6 +864,24 @@ public final class TvInteractiveAppManager { } } /** * Returns a list of available app link information. * * <P>A package must declare its app link info in its manifest using meta-data tag, so the info * can be detected by the system. * * @return List of {@link AppLinkInfo} for each package that deslares its app link information. * @hide */ @NonNull public List<AppLinkInfo> getAppLinkInfoList() { try { return mService.getAppLinkInfoList(mUserId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Registers an Android application link info record which can be used to launch the specific * Android application by TV interactive App RTE. Loading media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java +40 −8 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { INTERACTIVE_APP_TYPE_HBBTV, INTERACTIVE_APP_TYPE_ATSC, INTERACTIVE_APP_TYPE_GINGA, INTERACTIVE_APP_TYPE_TARGETED_AD, INTERACTIVE_APP_TYPE_OTHER }) public @interface InteractiveAppType {} Loading @@ -66,10 +68,21 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { public static final int INTERACTIVE_APP_TYPE_ATSC = 0x2; /** Ginga interactive app type */ public static final int INTERACTIVE_APP_TYPE_GINGA = 0x4; /** * Targeted Advertisement interactive app type * @hide */ public static final int INTERACTIVE_APP_TYPE_TARGETED_AD = 0x8; /** * Other interactive app type * @hide */ public static final int INTERACTIVE_APP_TYPE_OTHER = 0x80000000; private final ResolveInfo mService; private final String mId; private int mTypes; private final List<String> mExtraTypes = new ArrayList<>(); /** * Constructs a TvInteractiveAppServiceInfo object. Loading Loading @@ -98,18 +111,21 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { mService = resolveInfo; mId = id; mTypes = toTypesFlag(types); toTypesFlag(types); } private TvInteractiveAppServiceInfo(ResolveInfo service, String id, int types) { private TvInteractiveAppServiceInfo( ResolveInfo service, String id, int types, List<String> extraTypes) { mService = service; mId = id; mTypes = types; mExtraTypes.addAll(extraTypes); } private TvInteractiveAppServiceInfo(@NonNull Parcel in) { mService = ResolveInfo.CREATOR.createFromParcel(in); mId = in.readString(); mTypes = in.readInt(); in.readStringList(mExtraTypes); } public static final @NonNull Creator<TvInteractiveAppServiceInfo> CREATOR = Loading @@ -135,6 +151,7 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { mService.writeToParcel(dest, flags); dest.writeString(mId); dest.writeInt(mTypes); dest.writeStringList(mExtraTypes); } /** Loading Loading @@ -171,6 +188,17 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { return mTypes; } /** * Gets extra supported interactive app types which are not listed. * * @see #getSupportedTypes() * @hide */ @NonNull public List<String> getExtraSupportedTypes() { return mExtraTypes; } private static String generateInteractiveAppServiceId(ComponentName name) { return name.flattenToShortString(); } Loading Loading @@ -219,23 +247,27 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { } } private static int toTypesFlag(List<String> types) { int flag = 0; private void toTypesFlag(List<String> types) { mTypes = 0; mExtraTypes.clear(); for (String type : types) { switch (type) { case "hbbtv": flag |= INTERACTIVE_APP_TYPE_HBBTV; mTypes |= INTERACTIVE_APP_TYPE_HBBTV; break; case "atsc": flag |= INTERACTIVE_APP_TYPE_ATSC; mTypes |= INTERACTIVE_APP_TYPE_ATSC; break; case "ginga": flag |= INTERACTIVE_APP_TYPE_GINGA; mTypes |= INTERACTIVE_APP_TYPE_GINGA; break; case "targeted_ad": mTypes |= INTERACTIVE_APP_TYPE_TARGETED_AD; default: mTypes |= INTERACTIVE_APP_TYPE_OTHER; mExtraTypes.add(type); break; } } return flag; } } services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java +69 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; Loading Loading @@ -86,6 +87,11 @@ import java.util.Set; public class TvInteractiveAppManagerService extends SystemService { private static final boolean DEBUG = false; private static final String TAG = "TvInteractiveAppManagerService"; private static final String METADATA_CLASS_NAME = "android.media.tv.interactive.AppLinkInfo.ClassName"; private static final String METADATA_URI = "android.media.tv.interactive.AppLinkInfo.Uri"; // A global lock. private final Object mLock = new Object(); private final Context mContext; Loading @@ -102,6 +108,8 @@ public class TvInteractiveAppManagerService extends SystemService { // TODO: remove mGetServiceListCalled if onBootPhrase work correctly @GuardedBy("mLock") private boolean mGetServiceListCalled = false; @GuardedBy("mLock") private boolean mGetAppLinkInfoListCalled = false; private final UserManager mUserManager; Loading @@ -120,6 +128,41 @@ public class TvInteractiveAppManagerService extends SystemService { mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); } @GuardedBy("mLock") private void buildAppLinkInfoLocked(int userId) { UserState userState = getOrCreateUserStateLocked(userId); if (DEBUG) { Slogf.d(TAG, "buildAppLinkInfoLocked"); } PackageManager pm = mContext.getPackageManager(); List<ApplicationInfo> appInfos = pm.getInstalledApplicationsAsUser( PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA), userId); List<AppLinkInfo> appLinkInfos = new ArrayList<>(); for (ApplicationInfo appInfo : appInfos) { AppLinkInfo info = buildAppLinkInfoLocked(appInfo); if (info != null) { appLinkInfos.add(info); } } // sort the list by package name Collections.sort(appLinkInfos, Comparator.comparing(AppLinkInfo::getComponentName)); userState.mAppLinkInfoList.clear(); userState.mAppLinkInfoList.addAll(appLinkInfos); } @GuardedBy("mLock") private AppLinkInfo buildAppLinkInfoLocked(ApplicationInfo appInfo) { if (appInfo.metaData == null || appInfo.packageName == null) { return null; } String className = appInfo.metaData.getString(METADATA_CLASS_NAME, null); String uri = appInfo.metaData.getString(METADATA_URI, null); if (className == null || uri == null) { return null; } return new AppLinkInfo(appInfo.packageName, className, uri); } @GuardedBy("mLock") private void buildTvInteractiveAppServiceListLocked(int userId, String[] updatedPackages) { UserState userState = getOrCreateUserStateLocked(userId); Loading Loading @@ -311,6 +354,7 @@ public class TvInteractiveAppManagerService extends SystemService { } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { synchronized (mLock) { buildTvInteractiveAppServiceListLocked(mCurrentUserId, null); buildAppLinkInfoLocked(mCurrentUserId); } } } Loading @@ -322,6 +366,7 @@ public class TvInteractiveAppManagerService extends SystemService { synchronized (mLock) { if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) { buildTvInteractiveAppServiceListLocked(userId, packages); buildAppLinkInfoLocked(userId); } } } Loading Loading @@ -428,6 +473,7 @@ public class TvInteractiveAppManagerService extends SystemService { mCurrentUserId = userId; buildTvInteractiveAppServiceListLocked(userId, null); buildAppLinkInfoLocked(userId); } } Loading Loading @@ -513,6 +559,7 @@ public class TvInteractiveAppManagerService extends SystemService { private void startProfileLocked(int userId) { mRunningProfiles.add(userId); buildTvInteractiveAppServiceListLocked(userId, null); buildAppLinkInfoLocked(userId); } @GuardedBy("mLock") Loading Loading @@ -667,6 +714,26 @@ public class TvInteractiveAppManagerService extends SystemService { } } @Override public List<AppLinkInfo> getAppLinkInfoList(int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), Binder.getCallingUid(), userId, "getAppLinkInfoList"); final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { if (!mGetAppLinkInfoListCalled) { buildAppLinkInfoLocked(userId); mGetAppLinkInfoListCalled = true; } UserState userState = getOrCreateUserStateLocked(resolvedUserId); List<AppLinkInfo> appLinkInfos = new ArrayList<>(userState.mAppLinkInfoList); return appLinkInfos; } } finally { Binder.restoreCallingIdentity(identity); } } @Override public void registerAppLinkInfo(String tiasId, AppLinkInfo appLinkInfo, int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), Loading Loading @@ -1996,6 +2063,8 @@ public class TvInteractiveAppManagerService extends SystemService { // A set of all TV Interactive App service packages. private final Set<String> mPackageSet = new HashSet<>(); // A list of all app link infos. private final List<AppLinkInfo> mAppLinkInfoList = new ArrayList<>(); // A list of callbacks. private final RemoteCallbackList<ITvInteractiveAppManagerCallback> mCallbacks = Loading Loading
media/java/android/media/tv/interactive/ITvInteractiveAppManager.aidl +1 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ import android.view.Surface; */ interface ITvInteractiveAppManager { List<TvInteractiveAppServiceInfo> getTvInteractiveAppServiceList(int userId); List<AppLinkInfo> getAppLinkInfoList(int userId); void registerAppLinkInfo(String tiasId, in AppLinkInfo info, int userId); void unregisterAppLinkInfo(String tiasId, in AppLinkInfo info, int userId); void sendAppLinkCommand(String tiasId, in Bundle command, int userId); Loading
media/java/android/media/tv/interactive/TvInteractiveAppManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -864,6 +864,24 @@ public final class TvInteractiveAppManager { } } /** * Returns a list of available app link information. * * <P>A package must declare its app link info in its manifest using meta-data tag, so the info * can be detected by the system. * * @return List of {@link AppLinkInfo} for each package that deslares its app link information. * @hide */ @NonNull public List<AppLinkInfo> getAppLinkInfoList() { try { return mService.getAppLinkInfoList(mUserId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Registers an Android application link info record which can be used to launch the specific * Android application by TV interactive App RTE. Loading
media/java/android/media/tv/interactive/TvInteractiveAppServiceInfo.java +40 −8 Original line number Diff line number Diff line Loading @@ -57,6 +57,8 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { INTERACTIVE_APP_TYPE_HBBTV, INTERACTIVE_APP_TYPE_ATSC, INTERACTIVE_APP_TYPE_GINGA, INTERACTIVE_APP_TYPE_TARGETED_AD, INTERACTIVE_APP_TYPE_OTHER }) public @interface InteractiveAppType {} Loading @@ -66,10 +68,21 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { public static final int INTERACTIVE_APP_TYPE_ATSC = 0x2; /** Ginga interactive app type */ public static final int INTERACTIVE_APP_TYPE_GINGA = 0x4; /** * Targeted Advertisement interactive app type * @hide */ public static final int INTERACTIVE_APP_TYPE_TARGETED_AD = 0x8; /** * Other interactive app type * @hide */ public static final int INTERACTIVE_APP_TYPE_OTHER = 0x80000000; private final ResolveInfo mService; private final String mId; private int mTypes; private final List<String> mExtraTypes = new ArrayList<>(); /** * Constructs a TvInteractiveAppServiceInfo object. Loading Loading @@ -98,18 +111,21 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { mService = resolveInfo; mId = id; mTypes = toTypesFlag(types); toTypesFlag(types); } private TvInteractiveAppServiceInfo(ResolveInfo service, String id, int types) { private TvInteractiveAppServiceInfo( ResolveInfo service, String id, int types, List<String> extraTypes) { mService = service; mId = id; mTypes = types; mExtraTypes.addAll(extraTypes); } private TvInteractiveAppServiceInfo(@NonNull Parcel in) { mService = ResolveInfo.CREATOR.createFromParcel(in); mId = in.readString(); mTypes = in.readInt(); in.readStringList(mExtraTypes); } public static final @NonNull Creator<TvInteractiveAppServiceInfo> CREATOR = Loading @@ -135,6 +151,7 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { mService.writeToParcel(dest, flags); dest.writeString(mId); dest.writeInt(mTypes); dest.writeStringList(mExtraTypes); } /** Loading Loading @@ -171,6 +188,17 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { return mTypes; } /** * Gets extra supported interactive app types which are not listed. * * @see #getSupportedTypes() * @hide */ @NonNull public List<String> getExtraSupportedTypes() { return mExtraTypes; } private static String generateInteractiveAppServiceId(ComponentName name) { return name.flattenToShortString(); } Loading Loading @@ -219,23 +247,27 @@ public final class TvInteractiveAppServiceInfo implements Parcelable { } } private static int toTypesFlag(List<String> types) { int flag = 0; private void toTypesFlag(List<String> types) { mTypes = 0; mExtraTypes.clear(); for (String type : types) { switch (type) { case "hbbtv": flag |= INTERACTIVE_APP_TYPE_HBBTV; mTypes |= INTERACTIVE_APP_TYPE_HBBTV; break; case "atsc": flag |= INTERACTIVE_APP_TYPE_ATSC; mTypes |= INTERACTIVE_APP_TYPE_ATSC; break; case "ginga": flag |= INTERACTIVE_APP_TYPE_GINGA; mTypes |= INTERACTIVE_APP_TYPE_GINGA; break; case "targeted_ad": mTypes |= INTERACTIVE_APP_TYPE_TARGETED_AD; default: mTypes |= INTERACTIVE_APP_TYPE_OTHER; mExtraTypes.add(type); break; } } return flag; } }
services/core/java/com/android/server/tv/interactive/TvInteractiveAppManagerService.java +69 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; Loading Loading @@ -86,6 +87,11 @@ import java.util.Set; public class TvInteractiveAppManagerService extends SystemService { private static final boolean DEBUG = false; private static final String TAG = "TvInteractiveAppManagerService"; private static final String METADATA_CLASS_NAME = "android.media.tv.interactive.AppLinkInfo.ClassName"; private static final String METADATA_URI = "android.media.tv.interactive.AppLinkInfo.Uri"; // A global lock. private final Object mLock = new Object(); private final Context mContext; Loading @@ -102,6 +108,8 @@ public class TvInteractiveAppManagerService extends SystemService { // TODO: remove mGetServiceListCalled if onBootPhrase work correctly @GuardedBy("mLock") private boolean mGetServiceListCalled = false; @GuardedBy("mLock") private boolean mGetAppLinkInfoListCalled = false; private final UserManager mUserManager; Loading @@ -120,6 +128,41 @@ public class TvInteractiveAppManagerService extends SystemService { mUserManager = (UserManager) getContext().getSystemService(Context.USER_SERVICE); } @GuardedBy("mLock") private void buildAppLinkInfoLocked(int userId) { UserState userState = getOrCreateUserStateLocked(userId); if (DEBUG) { Slogf.d(TAG, "buildAppLinkInfoLocked"); } PackageManager pm = mContext.getPackageManager(); List<ApplicationInfo> appInfos = pm.getInstalledApplicationsAsUser( PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA), userId); List<AppLinkInfo> appLinkInfos = new ArrayList<>(); for (ApplicationInfo appInfo : appInfos) { AppLinkInfo info = buildAppLinkInfoLocked(appInfo); if (info != null) { appLinkInfos.add(info); } } // sort the list by package name Collections.sort(appLinkInfos, Comparator.comparing(AppLinkInfo::getComponentName)); userState.mAppLinkInfoList.clear(); userState.mAppLinkInfoList.addAll(appLinkInfos); } @GuardedBy("mLock") private AppLinkInfo buildAppLinkInfoLocked(ApplicationInfo appInfo) { if (appInfo.metaData == null || appInfo.packageName == null) { return null; } String className = appInfo.metaData.getString(METADATA_CLASS_NAME, null); String uri = appInfo.metaData.getString(METADATA_URI, null); if (className == null || uri == null) { return null; } return new AppLinkInfo(appInfo.packageName, className, uri); } @GuardedBy("mLock") private void buildTvInteractiveAppServiceListLocked(int userId, String[] updatedPackages) { UserState userState = getOrCreateUserStateLocked(userId); Loading Loading @@ -311,6 +354,7 @@ public class TvInteractiveAppManagerService extends SystemService { } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { synchronized (mLock) { buildTvInteractiveAppServiceListLocked(mCurrentUserId, null); buildAppLinkInfoLocked(mCurrentUserId); } } } Loading @@ -322,6 +366,7 @@ public class TvInteractiveAppManagerService extends SystemService { synchronized (mLock) { if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) { buildTvInteractiveAppServiceListLocked(userId, packages); buildAppLinkInfoLocked(userId); } } } Loading Loading @@ -428,6 +473,7 @@ public class TvInteractiveAppManagerService extends SystemService { mCurrentUserId = userId; buildTvInteractiveAppServiceListLocked(userId, null); buildAppLinkInfoLocked(userId); } } Loading Loading @@ -513,6 +559,7 @@ public class TvInteractiveAppManagerService extends SystemService { private void startProfileLocked(int userId) { mRunningProfiles.add(userId); buildTvInteractiveAppServiceListLocked(userId, null); buildAppLinkInfoLocked(userId); } @GuardedBy("mLock") Loading Loading @@ -667,6 +714,26 @@ public class TvInteractiveAppManagerService extends SystemService { } } @Override public List<AppLinkInfo> getAppLinkInfoList(int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), Binder.getCallingUid(), userId, "getAppLinkInfoList"); final long identity = Binder.clearCallingIdentity(); try { synchronized (mLock) { if (!mGetAppLinkInfoListCalled) { buildAppLinkInfoLocked(userId); mGetAppLinkInfoListCalled = true; } UserState userState = getOrCreateUserStateLocked(resolvedUserId); List<AppLinkInfo> appLinkInfos = new ArrayList<>(userState.mAppLinkInfoList); return appLinkInfos; } } finally { Binder.restoreCallingIdentity(identity); } } @Override public void registerAppLinkInfo(String tiasId, AppLinkInfo appLinkInfo, int userId) { final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), Loading Loading @@ -1996,6 +2063,8 @@ public class TvInteractiveAppManagerService extends SystemService { // A set of all TV Interactive App service packages. private final Set<String> mPackageSet = new HashSet<>(); // A list of all app link infos. private final List<AppLinkInfo> mAppLinkInfoList = new ArrayList<>(); // A list of callbacks. private final RemoteCallbackList<ITvInteractiveAppManagerCallback> mCallbacks = Loading