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