1 /* 2 * Copyright 2020 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 17 package android.media.tv; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.net.Uri; 24 import android.os.Parcel; 25 import android.os.Parcelable; 26 import android.text.TextUtils; 27 import android.util.Log; 28 import android.view.Surface; 29 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 import java.util.Objects; 33 34 35 /** 36 * Contains information about a {@link TvInputService.Session} that is currently tuned to a channel 37 * or pass-through input. 38 * @hide 39 */ 40 @SystemApi 41 public final class TunedInfo implements Parcelable { 42 static final String TAG = "TunedInfo"; 43 44 /** 45 * App tag for {@link #getAppTag()}: the corresponding application of the channel is the same as 46 * the caller. 47 * <p>{@link #getAppType()} returns {@link #APP_TYPE_SELF} if and only if the app tag is 48 * {@link #APP_TAG_SELF}. 49 */ 50 public static final int APP_TAG_SELF = 0; 51 /** 52 * App tag for {@link #getAppType()}: the corresponding application of the channel is the same 53 * as the caller. 54 * <p>{@link #getAppType()} returns {@link #APP_TYPE_SELF} if and only if the app tag is 55 * {@link #APP_TAG_SELF}. 56 */ 57 public static final int APP_TYPE_SELF = 1; 58 /** 59 * App tag for {@link #getAppType()}: the corresponding app of the channel is a system 60 * application. 61 */ 62 public static final int APP_TYPE_SYSTEM = 2; 63 /** 64 * App tag for {@link #getAppType()}: the corresponding app of the channel is not a system 65 * application. 66 */ 67 public static final int APP_TYPE_NON_SYSTEM = 3; 68 69 /** @hide */ 70 @IntDef(prefix = "APP_TYPE_", value = {APP_TYPE_SELF, APP_TYPE_SYSTEM, APP_TYPE_NON_SYSTEM}) 71 @Retention(RetentionPolicy.SOURCE) 72 public @interface AppType {} 73 74 public static final @NonNull Parcelable.Creator<TunedInfo> CREATOR = 75 new Parcelable.Creator<TunedInfo>() { 76 @Override 77 public TunedInfo createFromParcel(Parcel source) { 78 try { 79 return new TunedInfo(source); 80 } catch (Exception e) { 81 Log.e(TAG, "Exception creating TunedInfo from parcel", e); 82 return null; 83 } 84 } 85 86 @Override 87 public TunedInfo[] newArray(int size) { 88 return new TunedInfo[size]; 89 } 90 }; 91 92 93 private final String mInputId; 94 @Nullable private final Uri mChannelUri; 95 private final boolean mIsRecordingSession; 96 private final boolean mIsVisible; 97 private final boolean mIsMainSession; 98 @AppType private final int mAppType; 99 private final int mAppTag; 100 101 /** @hide */ TunedInfo( String inputId, @Nullable Uri channelUri, boolean isRecordingSession, boolean isVisible, boolean isMainSession, @AppType int appType, int appTag)102 public TunedInfo( 103 String inputId, @Nullable Uri channelUri, boolean isRecordingSession, 104 boolean isVisible, boolean isMainSession, @AppType int appType, int appTag) { 105 mInputId = inputId; 106 mChannelUri = channelUri; 107 mIsRecordingSession = isRecordingSession; 108 mIsVisible = isVisible; 109 mIsMainSession = isMainSession; 110 mAppType = appType; 111 mAppTag = appTag; 112 } 113 114 TunedInfo(Parcel source)115 private TunedInfo(Parcel source) { 116 mInputId = source.readString(); 117 String uriString = source.readString(); 118 mChannelUri = uriString == null ? null : Uri.parse(uriString); 119 mIsRecordingSession = (source.readInt() == 1); 120 mIsVisible = (source.readInt() == 1); 121 mIsMainSession = (source.readInt() == 1); 122 mAppType = source.readInt(); 123 mAppTag = source.readInt(); 124 } 125 126 /** 127 * Returns the TV input ID of the channel. 128 */ 129 @NonNull getInputId()130 public String getInputId() { 131 return mInputId; 132 } 133 134 /** 135 * Returns the channel URI of the channel. 136 * <p>Returns {@code null} if it's a passthrough input or the permission is not granted. 137 */ 138 @Nullable getChannelUri()139 public Uri getChannelUri() { 140 return mChannelUri; 141 } 142 143 /** 144 * Returns {@code true} if the channel session is a recording session. 145 * @see TvInputService.RecordingSession 146 */ isRecordingSession()147 public boolean isRecordingSession() { 148 return mIsRecordingSession; 149 } 150 151 /** 152 * Returns {@code true} if the corresponding session is visible. 153 * <p>The system checks whether the {@link Surface} of the session is {@code null} or not. When 154 * it becomes invisible, the surface is destroyed and set to null. 155 * @see TvInputService.Session#onSetSurface(Surface) 156 * @see android.view.SurfaceView#notifySurfaceDestroyed 157 */ isVisible()158 public boolean isVisible() { 159 return mIsVisible; 160 } 161 162 /** 163 * Returns {@code true} if the corresponding session is set as main session. 164 * @see TvView#setMain 165 * @see TvInputService.Session#onSetMain 166 */ isMainSession()167 public boolean isMainSession() { 168 return mIsMainSession; 169 } 170 171 /** 172 * Returns the app tag. 173 * <p>App tag is used to differentiate one app from another. 174 * {@link #APP_TAG_SELF} is for current app. 175 */ getAppTag()176 public int getAppTag() { 177 return mAppTag; 178 } 179 180 /** 181 * Returns the app type. 182 */ 183 @AppType getAppType()184 public int getAppType() { 185 return mAppType; 186 } 187 188 @Override describeContents()189 public int describeContents() { 190 return 0; 191 } 192 193 @Override writeToParcel(@onNull Parcel dest, int flags)194 public void writeToParcel(@NonNull Parcel dest, int flags) { 195 dest.writeString(mInputId); 196 String uriString = mChannelUri == null ? null : mChannelUri.toString(); 197 dest.writeString(uriString); 198 dest.writeInt(mIsRecordingSession ? 1 : 0); 199 dest.writeInt(mIsVisible ? 1 : 0); 200 dest.writeInt(mIsMainSession ? 1 : 0); 201 dest.writeInt(mAppType); 202 dest.writeInt(mAppTag); 203 } 204 205 @Override toString()206 public String toString() { 207 return "inputID=" + mInputId 208 + ";channelUri=" + mChannelUri 209 + ";isRecording=" + mIsRecordingSession 210 + ";isVisible=" + mIsVisible 211 + ";isMainSession=" + mIsMainSession 212 + ";appType=" + mAppType 213 + ";appTag=" + mAppTag; 214 } 215 216 @Override equals(Object o)217 public boolean equals(Object o) { 218 if (!(o instanceof TunedInfo)) { 219 return false; 220 } 221 222 TunedInfo other = (TunedInfo) o; 223 224 return TextUtils.equals(mInputId, other.getInputId()) 225 && Objects.equals(mChannelUri, other.mChannelUri) 226 && mIsRecordingSession == other.mIsRecordingSession 227 && mIsVisible == other.mIsVisible 228 && mIsMainSession == other.mIsMainSession 229 && mAppType == other.mAppType 230 && mAppTag == other.mAppTag; 231 } 232 233 @Override hashCode()234 public int hashCode() { 235 return Objects.hash( 236 mInputId, mChannelUri, mIsRecordingSession, mIsVisible, mIsMainSession, mAppType, 237 mAppTag); 238 } 239 } 240