Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c3a362b authored by shubang's avatar shubang Committed by Shubang Lu
Browse files

Add extra IApp types and AppLinkInfo APIs

Bug: 264717550
Bug: 264717547
Test: mmm
Change-Id: Ia92bff53ea69b6e8a4ff3aca1a8bfbeda316ebac
parent a43dbaae
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+18 −0
Original line number Diff line number Diff line
@@ -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.
+40 −8
Original line number Diff line number Diff line
@@ -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;
    }
}
+69 −0
Original line number Diff line number Diff line
@@ -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 =