1/* 2 * Copyright (C) 2013 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 17package android.support.v7.media; 18 19import android.app.PendingIntent; 20import android.os.Bundle; 21import android.os.SystemClock; 22import android.support.v4.util.TimeUtils; 23 24/** 25 * Describes the playback status of a media session. 26 * <p> 27 * This class is part of the remote playback protocol described by the 28 * {@link MediaControlIntent MediaControlIntent} class. 29 * </p><p> 30 * When a media session is created, it is initially in the 31 * {@link #SESSION_STATE_ACTIVE active} state. When the media session ends 32 * normally, it transitions to the {@link #SESSION_STATE_ENDED ended} state. 33 * If the media session is invalidated due to another session forcibly taking 34 * control of the route, then it transitions to the 35 * {@link #SESSION_STATE_INVALIDATED invalidated} state. 36 * Refer to the documentation of each state for an explanation of its meaning. 37 * </p><p> 38 * To monitor session status, the application should supply a {@link PendingIntent} to use as the 39 * {@link MediaControlIntent#EXTRA_SESSION_STATUS_UPDATE_RECEIVER session status update receiver} 40 * for a given {@link MediaControlIntent#ACTION_START_SESSION session start request}. 41 * </p><p> 42 * This object is immutable once created using a {@link Builder} instance. 43 * </p> 44 */ 45public final class MediaSessionStatus { 46 private static final String KEY_TIMESTAMP = "timestamp"; 47 private static final String KEY_SESSION_STATE = "sessionState"; 48 private static final String KEY_QUEUE_PAUSED = "queuePaused"; 49 private static final String KEY_EXTRAS = "extras"; 50 51 private final Bundle mBundle; 52 53 /** 54 * Session state: Active. 55 * <p> 56 * Indicates that the media session is active and in control of the route. 57 * </p> 58 */ 59 public static final int SESSION_STATE_ACTIVE = 0; 60 61 /** 62 * Session state: Ended. 63 * <p> 64 * Indicates that the media session was ended normally using the 65 * {@link MediaControlIntent#ACTION_END_SESSION end session} action. 66 * </p><p> 67 * A terminated media session cannot be used anymore. To play more media, the 68 * application must start a new session. 69 * </p> 70 */ 71 public static final int SESSION_STATE_ENDED = 1; 72 73 /** 74 * Session state: Invalidated. 75 * <p> 76 * Indicates that the media session was invalidated involuntarily due to 77 * another session taking control of the route. 78 * </p><p> 79 * An invalidated media session cannot be used anymore. To play more media, the 80 * application must start a new session. 81 * </p> 82 */ 83 public static final int SESSION_STATE_INVALIDATED = 2; 84 85 private MediaSessionStatus(Bundle bundle) { 86 mBundle = bundle; 87 } 88 89 /** 90 * Gets the timestamp associated with the status information in 91 * milliseconds since boot in the {@link SystemClock#elapsedRealtime} time base. 92 * 93 * @return The status timestamp in the {@link SystemClock#elapsedRealtime()} time base. 94 */ 95 public long getTimestamp() { 96 return mBundle.getLong(KEY_TIMESTAMP); 97 } 98 99 /** 100 * Gets the session state. 101 * 102 * @return The session state. One of {@link #SESSION_STATE_ACTIVE}, 103 * {@link #SESSION_STATE_ENDED}, or {@link #SESSION_STATE_INVALIDATED}. 104 */ 105 public int getSessionState() { 106 return mBundle.getInt(KEY_SESSION_STATE, SESSION_STATE_INVALIDATED); 107 } 108 109 /** 110 * Returns true if the session's queue is paused. 111 * 112 * @return True if the session's queue is paused. 113 */ 114 public boolean isQueuePaused() { 115 return mBundle.getBoolean(KEY_QUEUE_PAUSED); 116 } 117 118 /** 119 * Gets a bundle of extras for this status object. 120 * The extras will be ignored by the media router but they may be used 121 * by applications. 122 */ 123 public Bundle getExtras() { 124 return mBundle.getBundle(KEY_EXTRAS); 125 } 126 127 @Override 128 public String toString() { 129 StringBuilder result = new StringBuilder(); 130 result.append("MediaSessionStatus{ "); 131 result.append("timestamp="); 132 TimeUtils.formatDuration(SystemClock.elapsedRealtime() - getTimestamp(), result); 133 result.append(" ms ago"); 134 result.append(", sessionState=").append(sessionStateToString(getSessionState())); 135 result.append(", queuePaused=").append(isQueuePaused()); 136 result.append(", extras=").append(getExtras()); 137 result.append(" }"); 138 return result.toString(); 139 } 140 141 private static String sessionStateToString(int sessionState) { 142 switch (sessionState) { 143 case SESSION_STATE_ACTIVE: 144 return "active"; 145 case SESSION_STATE_ENDED: 146 return "ended"; 147 case SESSION_STATE_INVALIDATED: 148 return "invalidated"; 149 } 150 return Integer.toString(sessionState); 151 } 152 153 /** 154 * Converts this object to a bundle for serialization. 155 * 156 * @return The contents of the object represented as a bundle. 157 */ 158 public Bundle asBundle() { 159 return mBundle; 160 } 161 162 /** 163 * Creates an instance from a bundle. 164 * 165 * @param bundle The bundle, or null if none. 166 * @return The new instance, or null if the bundle was null. 167 */ 168 public static MediaSessionStatus fromBundle(Bundle bundle) { 169 return bundle != null ? new MediaSessionStatus(bundle) : null; 170 } 171 172 /** 173 * Builder for {@link MediaSessionStatus media session status objects}. 174 */ 175 public static final class Builder { 176 private final Bundle mBundle; 177 178 /** 179 * Creates a media session status builder using the current time as the 180 * reference timestamp. 181 * 182 * @param sessionState The session state. 183 */ 184 public Builder(int sessionState) { 185 mBundle = new Bundle(); 186 setTimestamp(SystemClock.elapsedRealtime()); 187 setSessionState(sessionState); 188 } 189 190 /** 191 * Creates a media session status builder whose initial contents are 192 * copied from an existing status. 193 */ 194 public Builder(MediaSessionStatus status) { 195 if (status == null) { 196 throw new IllegalArgumentException("status must not be null"); 197 } 198 199 mBundle = new Bundle(status.mBundle); 200 } 201 202 /** 203 * Sets the timestamp associated with the status information in 204 * milliseconds since boot in the {@link SystemClock#elapsedRealtime} time base. 205 */ 206 public Builder setTimestamp(long elapsedRealtimeTimestamp) { 207 mBundle.putLong(KEY_TIMESTAMP, elapsedRealtimeTimestamp); 208 return this; 209 } 210 211 /** 212 * Sets the session state. 213 */ 214 public Builder setSessionState(int sessionState) { 215 mBundle.putInt(KEY_SESSION_STATE, sessionState); 216 return this; 217 } 218 219 /** 220 * Sets whether the queue is paused. 221 */ 222 public Builder setQueuePaused(boolean queuePaused) { 223 mBundle.putBoolean(KEY_QUEUE_PAUSED, queuePaused); 224 return this; 225 } 226 227 /** 228 * Sets a bundle of extras for this status object. 229 * The extras will be ignored by the media router but they may be used 230 * by applications. 231 */ 232 public Builder setExtras(Bundle extras) { 233 mBundle.putBundle(KEY_EXTRAS, extras); 234 return this; 235 } 236 237 /** 238 * Builds the {@link MediaSessionStatus media session status object}. 239 */ 240 public MediaSessionStatus build() { 241 return new MediaSessionStatus(mBundle); 242 } 243 } 244} 245