1 /* 2 * Copyright 2019 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 com.android.car.media.testmediaapp; 18 19 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_ACTION_ABORTED; 20 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_APP_ERROR; 21 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED; 22 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_CONCURRENT_STREAM_LIMIT; 23 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_CONTENT_ALREADY_PLAYING; 24 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_END_OF_QUEUE; 25 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_NOT_AVAILABLE_IN_REGION; 26 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_NOT_SUPPORTED; 27 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_PARENTAL_CONTROL_RESTRICTED; 28 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED; 29 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_SKIP_LIMIT_REACHED; 30 import static android.support.v4.media.session.PlaybackStateCompat.ERROR_CODE_UNKNOWN_ERROR; 31 import static android.support.v4.media.session.PlaybackStateCompat.STATE_BUFFERING; 32 import static android.support.v4.media.session.PlaybackStateCompat.STATE_CONNECTING; 33 import static android.support.v4.media.session.PlaybackStateCompat.STATE_ERROR; 34 import static android.support.v4.media.session.PlaybackStateCompat.STATE_FAST_FORWARDING; 35 import static android.support.v4.media.session.PlaybackStateCompat.STATE_NONE; 36 import static android.support.v4.media.session.PlaybackStateCompat.STATE_PAUSED; 37 import static android.support.v4.media.session.PlaybackStateCompat.STATE_PLAYING; 38 import static android.support.v4.media.session.PlaybackStateCompat.STATE_REWINDING; 39 import static android.support.v4.media.session.PlaybackStateCompat.STATE_SKIPPING_TO_NEXT; 40 import static android.support.v4.media.session.PlaybackStateCompat.STATE_SKIPPING_TO_PREVIOUS; 41 import static android.support.v4.media.session.PlaybackStateCompat.STATE_SKIPPING_TO_QUEUE_ITEM; 42 import static android.support.v4.media.session.PlaybackStateCompat.STATE_STOPPED; 43 44 import android.support.v4.media.session.PlaybackStateCompat.State; 45 import android.util.Log; 46 47 /** 48 * Contains the info needed to generate a new playback state. 49 */ 50 public class TmaMediaEvent { 51 52 private static final String TAG = "TmaMediaEvent"; 53 54 public static final TmaMediaEvent INSTANT_PLAYBACK = 55 new TmaMediaEvent(EventState.PLAYING, StateErrorCode.UNKNOWN_ERROR, null, null, 56 ResolutionIntent.NONE, Action.NONE, 0, null, null); 57 58 /** The name of each entry is the value used in the json file. */ 59 public enum EventState { 60 NONE (STATE_NONE), 61 STOPPED (STATE_STOPPED), 62 PAUSED (STATE_PAUSED), 63 PLAYING (STATE_PLAYING), 64 FAST_FORWARDING (STATE_FAST_FORWARDING), 65 REWINDING (STATE_REWINDING), 66 BUFFERING (STATE_BUFFERING), 67 ERROR (STATE_ERROR), 68 CONNECTING (STATE_CONNECTING), 69 SKIPPING_TO_PREVIOUS (STATE_SKIPPING_TO_PREVIOUS), 70 SKIPPING_TO_NEXT (STATE_SKIPPING_TO_NEXT), 71 SKIPPING_TO_QUEUE_ITEM (STATE_SKIPPING_TO_QUEUE_ITEM); 72 73 @State final int mValue; 74 EventState(@tate int value)75 EventState(@State int value) { 76 mValue = value; 77 } 78 } 79 80 /** The name of each entry is the value used in the json file. */ 81 public enum StateErrorCode { 82 UNKNOWN_ERROR (ERROR_CODE_UNKNOWN_ERROR), 83 APP_ERROR (ERROR_CODE_APP_ERROR), 84 NOT_SUPPORTED (ERROR_CODE_NOT_SUPPORTED), 85 AUTHENTICATION_EXPIRED (ERROR_CODE_AUTHENTICATION_EXPIRED), 86 PREMIUM_ACCOUNT_REQUIRED (ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED), 87 CONCURRENT_STREAM_LIMIT (ERROR_CODE_CONCURRENT_STREAM_LIMIT), 88 PARENTAL_CONTROL_RESTRICTED (ERROR_CODE_PARENTAL_CONTROL_RESTRICTED), 89 NOT_AVAILABLE_IN_REGION (ERROR_CODE_NOT_AVAILABLE_IN_REGION), 90 CONTENT_ALREADY_PLAYING (ERROR_CODE_CONTENT_ALREADY_PLAYING), 91 SKIP_LIMIT_REACHED (ERROR_CODE_SKIP_LIMIT_REACHED), 92 ACTION_ABORTED (ERROR_CODE_ACTION_ABORTED), 93 END_OF_QUEUE (ERROR_CODE_END_OF_QUEUE); 94 95 @State final int mValue; 96 StateErrorCode(@tate int value)97 StateErrorCode(@State int value) { 98 mValue = value; 99 } 100 } 101 102 /** The name of each entry is the value used in the json file. */ 103 public enum ResolutionIntent { 104 NONE, 105 PREFS 106 } 107 108 /** The name of each entry is the value used in the json file. */ 109 public enum Action { 110 NONE, 111 RESET_METADATA 112 } 113 114 final EventState mState; 115 final StateErrorCode mErrorCode; 116 final String mErrorMessage; 117 final String mActionLabel; 118 final ResolutionIntent mResolutionIntent; 119 final Action mAction; 120 /** How long to wait before sending the event to the app. */ 121 final int mPostDelayMs; 122 private final String mExceptionClass; 123 final String mMediaItemIdToToggle; 124 TmaMediaEvent(EventState state, StateErrorCode errorCode, String errorMessage, String actionLabel, ResolutionIntent resolutionIntent, Action action, int postDelayMs, String exceptionClass, String mediaItemIdToToggle)125 public TmaMediaEvent(EventState state, StateErrorCode errorCode, String errorMessage, 126 String actionLabel, ResolutionIntent resolutionIntent, Action action, int postDelayMs, 127 String exceptionClass, String mediaItemIdToToggle) { 128 mState = state; 129 mErrorCode = errorCode; 130 mErrorMessage = errorMessage; 131 mActionLabel = actionLabel; 132 mResolutionIntent = resolutionIntent; 133 mAction = action; 134 mPostDelayMs = postDelayMs; 135 mExceptionClass = exceptionClass; 136 mMediaItemIdToToggle = mediaItemIdToToggle; 137 } 138 premiumAccountRequired()139 boolean premiumAccountRequired() { 140 return mState == EventState.ERROR && mErrorCode == StateErrorCode.PREMIUM_ACCOUNT_REQUIRED; 141 } 142 maybeThrow()143 void maybeThrow() { 144 if (mExceptionClass != null) { 145 RuntimeException exception = null; 146 try { 147 Class aClass = Class.forName(mExceptionClass); 148 exception = (RuntimeException) aClass.newInstance(); 149 } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { 150 Log.e(TAG, "Class error for " + mExceptionClass + " : " + e); 151 } 152 153 if (exception != null) throw exception; 154 } 155 } 156 157 @Override toString()158 public String toString() { 159 return "TmaMediaEvent{" + 160 "mState=" + mState + 161 ", mErrorCode=" + mErrorCode + 162 ", mErrorMessage='" + mErrorMessage + '\'' + 163 ", mActionLabel='" + mActionLabel + '\'' + 164 ", mResolutionIntent=" + mResolutionIntent + 165 ", mAction=" + mAction + 166 ", mPostDelayMs=" + mPostDelayMs + 167 ", mExceptionClass=" + mExceptionClass + 168 '}'; 169 } 170 } 171