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

Commit f5340028 authored by Shubang Lu's avatar Shubang Lu Committed by Android (Google) Code Review
Browse files

Merge "Add extra IApp types and AppLinkInfo APIs"

parents f8d597e8 3c3a362b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+18 −0
Original line number Diff line number Diff line
@@ -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.
+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;
@@ -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;
@@ -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;

@@ -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);
@@ -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);
            }
        }
    }
@@ -322,6 +366,7 @@ public class TvInteractiveAppManagerService extends SystemService {
                synchronized (mLock) {
                    if (mCurrentUserId == userId || mRunningProfiles.contains(userId)) {
                        buildTvInteractiveAppServiceListLocked(userId, packages);
                        buildAppLinkInfoLocked(userId);
                    }
                }
            }
@@ -428,6 +473,7 @@ public class TvInteractiveAppManagerService extends SystemService {

            mCurrentUserId = userId;
            buildTvInteractiveAppServiceListLocked(userId, null);
            buildAppLinkInfoLocked(userId);
        }
    }

@@ -513,6 +559,7 @@ public class TvInteractiveAppManagerService extends SystemService {
    private void startProfileLocked(int userId) {
        mRunningProfiles.add(userId);
        buildTvInteractiveAppServiceListLocked(userId, null);
        buildAppLinkInfoLocked(userId);
    }

    @GuardedBy("mLock")
@@ -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(),
@@ -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 =