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