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

Commit 032a57a7 authored by Shubang Lu's avatar Shubang Lu
Browse files

CSAI: add TvAdServiceInfo

Bug: 309866029
Test: mmm
Change-Id: Ibf49a99604d499a7d34df63841fb878be3b33801
parent 10614f64
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.tv.ad;

parcelable TvAdServiceInfo;
+194 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2023 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.media.tv.ad;

import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Xml;

import androidx.annotation.NonNull;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * This class is used to specify meta information of a TV AD service.
 * @hide
 */
public final class TvAdServiceInfo implements Parcelable {
    private static final boolean DEBUG = false;
    private static final String TAG = "TvAdServiceInfo";

    private static final String XML_START_TAG_NAME = "tv-ad-service";

    private final ResolveInfo mService;
    private final String mId;
    private final List<String> mTypes = new ArrayList<>();

    /**
     * Constructs a TvAdServiceInfo object.
     *
     * @param context the application context
     * @param component the component name of the TvAdService
     */
    public TvAdServiceInfo(@NonNull Context context, @NonNull ComponentName component) {
        if (context == null) {
            throw new IllegalArgumentException("context cannot be null.");
        }
        // TODO: use a constant
        Intent intent = new Intent("android.media.tv.ad.TvAdService").setComponent(component);
        ResolveInfo resolveInfo = context.getPackageManager().resolveService(
                intent, PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
        if (resolveInfo == null) {
            throw new IllegalArgumentException("Invalid component. Can't find the service.");
        }

        ComponentName componentName = new ComponentName(resolveInfo.serviceInfo.packageName,
                resolveInfo.serviceInfo.name);
        String id;
        id = generateAdServiceId(componentName);
        List<String> types = new ArrayList<>();
        parseServiceMetadata(resolveInfo, context, types);

        mService = resolveInfo;
        mId = id;
    }

    private TvAdServiceInfo(ResolveInfo service, String id, List<String> types) {
        mService = service;
        mId = id;
        mTypes.addAll(types);
    }

    private TvAdServiceInfo(@NonNull Parcel in) {
        mService = ResolveInfo.CREATOR.createFromParcel(in);
        mId = in.readString();
        in.readStringList(mTypes);
    }

    public static final Creator<TvAdServiceInfo> CREATOR = new Creator<TvAdServiceInfo>() {
        @Override
        public TvAdServiceInfo createFromParcel(Parcel in) {
            return new TvAdServiceInfo(in);
        }

        @Override
        public TvAdServiceInfo[] newArray(int size) {
            return new TvAdServiceInfo[size];
        }
    };

    /**
     * Returns a unique ID for this TV AD service. The ID is generated from the package and class
     * name implementing the TV AD service.
     */
    @NonNull
    public String getId() {
        return mId;
    }

    /**
     * Returns the component of the TV AD service.
     * @hide
     */
    public ComponentName getComponent() {
        return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
    }

    /**
     * Returns the information of the service that implements this AD service.
     */
    @Nullable
    public ServiceInfo getServiceInfo() {
        return mService.serviceInfo;
    }

    /**
     * Gets supported TV AD types.
     */
    @NonNull
    public List<String> getSupportedTypes() {
        return mTypes;
    }

    private static String generateAdServiceId(ComponentName name) {
        return name.flattenToShortString();
    }

    private static void parseServiceMetadata(
            ResolveInfo resolveInfo, Context context, List<String> types) {
        ServiceInfo serviceInfo = resolveInfo.serviceInfo;
        PackageManager pm = context.getPackageManager();
        // TODO: use constant for the metadata
        try (XmlResourceParser parser =
                     serviceInfo.loadXmlMetaData(pm, "android.media.tv.ad.service")) {
            if (parser == null) {
                throw new IllegalStateException(
                        "No " + "android.media.tv.ad.service"
                                + " meta-data found for " + serviceInfo.name);
            }

            Resources resources = pm.getResourcesForApplication(serviceInfo.applicationInfo);
            AttributeSet attrs = Xml.asAttributeSet(parser);

            int type;
            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                    && type != XmlPullParser.START_TAG) {
                // move to the START_TAG
            }

            String nodeName = parser.getName();
            if (!XML_START_TAG_NAME.equals(nodeName)) {
                throw new IllegalStateException("Meta-data does not start with "
                        + XML_START_TAG_NAME + " tag for " + serviceInfo.name);
            }

            // TODO: parse attributes
        } catch (IOException | XmlPullParserException e) {
            throw new IllegalStateException(
                    "Failed reading meta-data for " + serviceInfo.packageName, e);
        } catch (PackageManager.NameNotFoundException e) {
            throw new IllegalStateException("No resources found for " + serviceInfo.packageName, e);
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(@NonNull Parcel dest, int flags) {
        mService.writeToParcel(dest, flags);
        dest.writeString(mId);
        dest.writeStringList(mTypes);
    }
}