Add extra IApp types and AppLinkInfo APIs

Bug: 264717550
Bug: 264717547
Test: mmm
Change-Id: Ia92bff53ea69b6e8a4ff3aca1a8bfbeda316ebac
This commit is contained in:
shubang
2023-01-06 17:50:36 -08:00
committed by Shubang Lu
parent a43dbaae9b
commit 3c3a362b5a
4 changed files with 128 additions and 8 deletions

View File

@@ -36,6 +36,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);

View File

@@ -848,6 +848,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.

View File

@@ -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 {}
@@ -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.
@@ -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 =
@@ -135,6 +151,7 @@ public final class TvInteractiveAppServiceInfo implements Parcelable {
mService.writeToParcel(dest, flags);
dest.writeString(mId);
dest.writeInt(mTypes);
dest.writeStringList(mExtraTypes);
}
/**
@@ -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();
}
@@ -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;
}
}

View File

@@ -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;
@@ -85,6 +86,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;
@@ -101,6 +107,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;
@@ -119,6 +127,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);
@@ -310,6 +353,7 @@ public class TvInteractiveAppManagerService extends SystemService {
} else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
buildTvInteractiveAppServiceListLocked(mCurrentUserId, null);
buildAppLinkInfoLocked(mCurrentUserId);
}
}
}
@@ -321,6 +365,7 @@ public class TvInteractiveAppManagerService extends SystemService {
synchronized (mLock) {
if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) {
buildTvInteractiveAppServiceListLocked(userId, packages);
buildAppLinkInfoLocked(userId);
}
}
}
@@ -427,6 +472,7 @@ public class TvInteractiveAppManagerService extends SystemService {
mCurrentUserId = userId;
buildTvInteractiveAppServiceListLocked(userId, null);
buildAppLinkInfoLocked(userId);
}
}
@@ -512,6 +558,7 @@ public class TvInteractiveAppManagerService extends SystemService {
private void startProfileLocked(int userId) {
mRunningProfiles.add(userId);
buildTvInteractiveAppServiceListLocked(userId, null);
buildAppLinkInfoLocked(userId);
}
@GuardedBy("mLock")
@@ -666,6 +713,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(),
@@ -1883,6 +1950,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 =