script-astra/Android/Sdk/sources/android-35/android/media/tv/interactive/TvInteractiveAppServiceInfo.java
localadmin 4380f00a78 init
2025-01-20 18:15:20 +03:00

280 lines
9.8 KiB
Java

/*
* Copyright 2021 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.interactive;
import android.annotation.IntDef;
import android.annotation.NonNull;
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.TypedArray;
import android.content.res.XmlResourceParser;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
/**
* This class is used to specify meta information of a TV interactive app.
*/
public final class TvInteractiveAppServiceInfo implements Parcelable {
private static final boolean DEBUG = false;
private static final String TAG = "TvInteractiveAppServiceInfo";
private static final String XML_START_TAG_NAME = "tv-interactive-app";
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "INTERACTIVE_APP_TYPE_" }, value = {
INTERACTIVE_APP_TYPE_HBBTV,
INTERACTIVE_APP_TYPE_ATSC,
INTERACTIVE_APP_TYPE_GINGA,
INTERACTIVE_APP_TYPE_TARGETED_AD,
INTERACTIVE_APP_TYPE_OTHER
})
public @interface InteractiveAppType {}
/** HbbTV interactive app type */
public static final int INTERACTIVE_APP_TYPE_HBBTV = 0x1;
/** ATSC interactive app type */
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 */
public static final int INTERACTIVE_APP_TYPE_TARGETED_AD = 0x8;
/** Other interactive app type */
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.
*
* @param context the application context
* @param component the component name of the TvInteractiveAppService
*/
public TvInteractiveAppServiceInfo(@NonNull Context context, @NonNull ComponentName component) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null.");
}
Intent intent =
new Intent(TvInteractiveAppService.SERVICE_INTERFACE).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 = generateInteractiveAppServiceId(componentName);
List<String> types = new ArrayList<>();
parseServiceMetadata(resolveInfo, context, types);
mService = resolveInfo;
mId = id;
toTypesFlag(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 =
new Creator<TvInteractiveAppServiceInfo>() {
@Override
public TvInteractiveAppServiceInfo createFromParcel(Parcel in) {
return new TvInteractiveAppServiceInfo(in);
}
@Override
public TvInteractiveAppServiceInfo[] newArray(int size) {
return new TvInteractiveAppServiceInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
mService.writeToParcel(dest, flags);
dest.writeString(mId);
dest.writeInt(mTypes);
dest.writeStringList(mExtraTypes);
}
/**
* Returns a unique ID for this TV interactive app service. The ID is generated from the package
* and class name implementing the TV interactive app service.
*/
@NonNull
public String getId() {
return mId;
}
/**
* Returns the component of the TV Interactive App service.
* @hide
*/
public ComponentName getComponent() {
return new ComponentName(mService.serviceInfo.packageName, mService.serviceInfo.name);
}
/**
* Returns the information of the service that implements this TV Interactive App service.
*/
@Nullable
public ServiceInfo getServiceInfo() {
return mService.serviceInfo;
}
/**
* Gets supported interactive app types.
*
* <p>The supported interactive app types is in a bit map format. For example:
* <pre><code>
* int types = tvInteractiveAppInfo.getSupportedTypes();
* if (types & TvInteractiveAppInfo.INTERACTIVE_APP_TYPE_HBBTV != 0) {
* // HbbTV type is supported. Do something...
* }
* if (types & TvInteractiveAppInfo.INTERACTIVE_APP_TYPE_ATSC == 0) {
* // ATSC type is not supported. Do something...
* }
* </code></pre>
*
* @return An int bit map representing supported types.
*/
@InteractiveAppType
@NonNull
public int getSupportedTypes() {
return mTypes;
}
/**
* Gets custom supported interactive app types which are not listed.
*
* @see #getSupportedTypes()
*/
@NonNull
public List<String> getCustomSupportedTypes() {
return mExtraTypes;
}
private static String generateInteractiveAppServiceId(ComponentName name) {
return name.flattenToShortString();
}
private static void parseServiceMetadata(
ResolveInfo resolveInfo, Context context, List<String> types) {
ServiceInfo si = resolveInfo.serviceInfo;
PackageManager pm = context.getPackageManager();
try (XmlResourceParser parser =
si.loadXmlMetaData(pm, TvInteractiveAppService.SERVICE_META_DATA)) {
if (parser == null) {
throw new IllegalStateException(
"No " + TvInteractiveAppService.SERVICE_META_DATA
+ " meta-data found for " + si.name);
}
Resources res = pm.getResourcesForApplication(si.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 " + si.name);
}
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.TvInteractiveAppService);
CharSequence[] textArr = sa.getTextArray(
com.android.internal.R.styleable.TvInteractiveAppService_supportedTypes);
for (CharSequence cs : textArr) {
types.add(cs.toString().toLowerCase());
}
sa.recycle();
} catch (IOException | XmlPullParserException e) {
throw new IllegalStateException(
"Failed reading meta-data for " + si.packageName, e);
} catch (PackageManager.NameNotFoundException e) {
throw new IllegalStateException("No resources found for " + si.packageName, e);
}
}
private void toTypesFlag(List<String> types) {
mTypes = 0;
mExtraTypes.clear();
for (String type : types) {
switch (type) {
case "hbbtv":
mTypes |= INTERACTIVE_APP_TYPE_HBBTV;
break;
case "atsc":
mTypes |= INTERACTIVE_APP_TYPE_ATSC;
break;
case "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;
}
}
}
}