1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 package com.android.tv.common.compat; 17 18 import android.content.Context; 19 import android.content.pm.PackageManager; 20 import android.content.pm.ServiceInfo; 21 import android.media.tv.TvInputInfo; 22 import android.media.tv.TvInputService; 23 import android.support.annotation.VisibleForTesting; 24 import android.util.Log; 25 26 import java.util.Collections; 27 import java.util.HashMap; 28 import java.util.Map; 29 30 import org.xmlpull.v1.XmlPullParser; 31 32 /** 33 * TIF Compatibility for {@link TvInputInfo}. 34 */ 35 public class TvInputInfoCompat { 36 private static final String TAG = "TvInputInfoCompat"; 37 private static final String ATTRIBUTE_NAMESPACE_ANDROID = 38 "http://schemas.android.com/apk/res/android"; 39 private static final String TV_INPUT_XML_START_TAG_NAME = "tv-input"; 40 private static final String TV_INPUT_EXTRA_XML_START_TAG_NAME = "extra"; 41 private static final String ATTRIBUTE_NAME = "name"; 42 private static final String ATTRIBUTE_VALUE = "value"; 43 private static final String ATTRIBUTE_NAME_AUDIO_ONLY = 44 "com.android.tv.common.compat.tvinputinfocompat.audioOnly"; 45 46 private final Context mContext; 47 private final TvInputInfo mTvInputInfo; 48 private boolean mAudioOnly; 49 private boolean mAudioAttributeInit = false; 50 TvInputInfoCompat(Context context, TvInputInfo tvInputInfo)51 public TvInputInfoCompat(Context context, TvInputInfo tvInputInfo) { 52 mContext = context; 53 mTvInputInfo = tvInputInfo; 54 } 55 getTvInputInfo()56 public TvInputInfo getTvInputInfo() { 57 return mTvInputInfo; 58 } 59 isAudioOnly()60 public boolean isAudioOnly() { 61 // TODO(b/112938832): use tvInputInfo.isAudioOnly() when SDK is updated 62 if (!mAudioAttributeInit) { 63 mAudioOnly = Boolean.parseBoolean(getExtras().get(ATTRIBUTE_NAME_AUDIO_ONLY)); 64 mAudioAttributeInit = true; 65 } 66 return mAudioOnly; 67 } 68 getType()69 public int getType() { 70 return mTvInputInfo.getType(); 71 } 72 73 @VisibleForTesting getExtras()74 public Map<String, String> getExtras() { 75 ServiceInfo si = mTvInputInfo.getServiceInfo(); 76 77 try { 78 XmlPullParser parser = getXmlResourceParser(); 79 int type; 80 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT 81 && type != XmlPullParser.START_TAG) { 82 } 83 84 if (!TV_INPUT_XML_START_TAG_NAME.equals(parser.getName())) { 85 Log.w(TAG, "Meta-data does not start with " + TV_INPUT_XML_START_TAG_NAME 86 + " tag for " + si.name); 87 return Collections.emptyMap(); 88 } 89 // <tv-input> start tag found 90 Map<String, String> extras = new HashMap<>(); 91 while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) { 92 if (type == XmlPullParser.END_TAG 93 && TV_INPUT_XML_START_TAG_NAME.equals(parser.getName())) { 94 // </tv-input> end tag found 95 return extras; 96 } 97 if (type == XmlPullParser.START_TAG 98 && TV_INPUT_EXTRA_XML_START_TAG_NAME.equals(parser.getName())) { 99 String extraName = 100 parser.getAttributeValue(ATTRIBUTE_NAMESPACE_ANDROID, ATTRIBUTE_NAME); 101 String extraValue = 102 parser.getAttributeValue(ATTRIBUTE_NAMESPACE_ANDROID, ATTRIBUTE_VALUE); 103 if (extraName != null && extraValue != null) { 104 extras.put(extraName, extraValue); 105 } 106 } 107 } 108 109 } catch (Exception e) { 110 Log.e(TAG, "Failed to get extras of " + mTvInputInfo.getId() , e); 111 } 112 return Collections.emptyMap(); 113 } 114 115 @VisibleForTesting getXmlResourceParser()116 XmlPullParser getXmlResourceParser() { 117 ServiceInfo si = mTvInputInfo.getServiceInfo(); 118 PackageManager pm = mContext.getPackageManager(); 119 return si.loadXmlMetaData(pm, TvInputService.SERVICE_META_DATA); 120 } 121 } 122