1 /*
2  * Copyright 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 
17 package android.media;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Bundle;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.text.TextUtils;
25 
26 import java.util.Objects;
27 
28 /**
29  * This API is not generally intended for third party application developers.
30  * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
31  * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
32  * Library</a> for consistent behavior across all devices.
33  * <p>
34  * Define a command that a {@link MediaController2} can send to a {@link MediaSession2}.
35  * <p>
36  * If {@link #getCommandCode()} isn't {@link #COMMAND_CODE_CUSTOM}), it's predefined command.
37  * If {@link #getCommandCode()} is {@link #COMMAND_CODE_CUSTOM}), it's custom command and
38  * {@link #getCustomAction()} shouldn't be {@code null}.
39  * <p>
40  * Refer to the
41  * <a href="{@docRoot}reference/androidx/media2/SessionCommand2.html">AndroidX SessionCommand</a>
42  * class for the list of valid commands.
43  */
44 public final class Session2Command implements Parcelable {
45     /**
46      * Command code for the custom command which can be defined by string action in the
47      * {@link Session2Command}.
48      */
49     public static final int COMMAND_CODE_CUSTOM = 0;
50 
51     public static final @android.annotation.NonNull Parcelable.Creator<Session2Command> CREATOR =
52             new Parcelable.Creator<Session2Command>() {
53                 @Override
54                 public Session2Command createFromParcel(Parcel in) {
55                     return new Session2Command(in);
56                 }
57 
58                 @Override
59                 public Session2Command[] newArray(int size) {
60                     return new Session2Command[size];
61                 }
62             };
63 
64     private final int mCommandCode;
65     // Nonnull if it's custom command
66     private final String mCustomAction;
67     private final Bundle mCustomExtras;
68 
69     /**
70      * Constructor for creating a command predefined in AndroidX media2.
71      *
72      * @param commandCode A command code for a command predefined in AndroidX media2.
73      */
Session2Command(int commandCode)74     public Session2Command(int commandCode) {
75         if (commandCode == COMMAND_CODE_CUSTOM) {
76             throw new IllegalArgumentException("commandCode shouldn't be COMMAND_CODE_CUSTOM");
77         }
78         mCommandCode = commandCode;
79         mCustomAction = null;
80         mCustomExtras = null;
81     }
82 
83     /**
84      * Constructor for creating a custom command.
85      *
86      * @param action The action of this custom command.
87      * @param extras An extra bundle for this custom command.
88      */
Session2Command(@onNull String action, @Nullable Bundle extras)89     public Session2Command(@NonNull String action, @Nullable Bundle extras) {
90         if (action == null) {
91             throw new IllegalArgumentException("action shouldn't be null");
92         }
93         mCommandCode = COMMAND_CODE_CUSTOM;
94         mCustomAction = action;
95         mCustomExtras = extras;
96     }
97 
98     /**
99      * Used by parcelable creator.
100      */
101     @SuppressWarnings("WeakerAccess") /* synthetic access */
Session2Command(Parcel in)102     Session2Command(Parcel in) {
103         mCommandCode = in.readInt();
104         mCustomAction = in.readString();
105         mCustomExtras = in.readBundle();
106     }
107 
108     /**
109      * Gets the command code of a predefined command.
110      * This will return {@link #COMMAND_CODE_CUSTOM} for a custom command.
111      */
getCommandCode()112     public int getCommandCode() {
113         return mCommandCode;
114     }
115 
116     /**
117      * Gets the action of a custom command.
118      * This will return {@code null} for a predefined command.
119      */
120     @Nullable
getCustomAction()121     public String getCustomAction() {
122         return mCustomAction;
123     }
124 
125     /**
126      * Gets the extra bundle of a custom command.
127      * This will return {@code null} for a predefined command.
128      */
129     @Nullable
getCustomExtras()130     public Bundle getCustomExtras() {
131         return mCustomExtras;
132     }
133 
134     @Override
describeContents()135     public int describeContents() {
136         return 0;
137     }
138 
139     @Override
writeToParcel(@onNull Parcel dest, int flags)140     public void writeToParcel(@NonNull Parcel dest, int flags) {
141         if (dest == null) {
142             throw new IllegalArgumentException("parcel shouldn't be null");
143         }
144         dest.writeInt(mCommandCode);
145         dest.writeString(mCustomAction);
146         dest.writeBundle(mCustomExtras);
147     }
148 
149     @Override
equals(@ullable Object obj)150     public boolean equals(@Nullable Object obj) {
151         if (!(obj instanceof Session2Command)) {
152             return false;
153         }
154         Session2Command other = (Session2Command) obj;
155         return mCommandCode == other.mCommandCode
156                 && TextUtils.equals(mCustomAction, other.mCustomAction);
157     }
158 
159     @Override
hashCode()160     public int hashCode() {
161         return Objects.hash(mCustomAction, mCommandCode);
162     }
163 
164     /**
165      * This API is not generally intended for third party application developers.
166      * Use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a>
167      * <a href="{@docRoot}reference/androidx/media2/session/package-summary.html">Media2 session
168      * Library</a> for consistent behavior across all devices.
169      * <p>
170      * Contains the result of {@link Session2Command}.
171      */
172     public static final class Result {
173         private final int mResultCode;
174         private final Bundle mResultData;
175 
176         /**
177          * Result code representing that the command is skipped or canceled. For an example, a seek
178          * command can be skipped if it is followed by another seek command.
179          */
180         public static final int RESULT_INFO_SKIPPED = 1;
181 
182         /**
183          * Result code representing that the command is successfully completed.
184          */
185         public static final int RESULT_SUCCESS = 0;
186 
187         /**
188          * Result code represents that call is ended with an unknown error.
189          */
190         public static final int RESULT_ERROR_UNKNOWN_ERROR = -1;
191 
192         /**
193          * Constructor of {@link Result}.
194          *
195          * @param resultCode result code
196          * @param resultData result data
197          */
Result(int resultCode, @Nullable Bundle resultData)198         public Result(int resultCode, @Nullable Bundle resultData) {
199             mResultCode = resultCode;
200             mResultData = resultData;
201         }
202 
203         /**
204          * Returns the result code.
205          */
getResultCode()206         public int getResultCode() {
207             return mResultCode;
208         }
209 
210         /**
211          * Returns the result data.
212          */
213         @Nullable
getResultData()214         public Bundle getResultData() {
215             return mResultData;
216         }
217     }
218 }
219