1e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo/* 2e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Copyright (C) 2015 The Android Open Source Project 3e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 4e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Licensed under the Apache License, Version 2.0 (the "License"); 5e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * you may not use this file except in compliance with the License. 6e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * You may obtain a copy of the License at 7e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 8e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * http://www.apache.org/licenses/LICENSE-2.0 9e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 10e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Unless required by applicable law or agreed to in writing, software 11e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * distributed under the License is distributed on an "AS IS" BASIS, 12e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * See the License for the specific language governing permissions and 14e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * limitations under the License. 15e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 16e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seopackage android.support.v4.media; 17e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 18e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.content.ComponentName; 19e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.content.Context; 20e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.content.Intent; 21e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.content.ServiceConnection; 227a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Limimport android.os.Binder; 23a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Limimport android.os.Build; 24e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.Bundle; 25e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.Handler; 26e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.IBinder; 273f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Limimport android.os.Message; 283f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Limimport android.os.Messenger; 29e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.Parcel; 30e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.Parcelable; 31e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.RemoteException; 32e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.annotation.IntDef; 33e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.annotation.NonNull; 34e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.annotation.Nullable; 3582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Limimport android.support.v4.app.BundleCompat; 362490f437a4111d64520f891b2c81685f8fae323cJae Seoimport android.support.v4.media.session.MediaControllerCompat; 37e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.v4.media.session.MediaSessionCompat; 38ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Limimport android.support.v4.os.BuildCompat; 39e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.v4.os.ResultReceiver; 40e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.v4.util.ArrayMap; 41e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.text.TextUtils; 42e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.util.Log; 43e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 44e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport java.lang.annotation.Retention; 45e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport java.lang.annotation.RetentionPolicy; 4616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Limimport java.lang.ref.WeakReference; 476b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Limimport java.util.ArrayList; 48ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Limimport java.util.Collections; 49e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport java.util.List; 5082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Limimport java.util.Map; 51e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 5282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Limimport static android.support.v4.media.MediaBrowserProtocol.*; 5382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 54e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo/** 55096f2531cb790bc1106377d2da344614a3b88d39Jae Seo * Browses media content offered by a {@link MediaBrowserServiceCompat}. 56e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 57e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * This object is not thread-safe. All calls should happen on the thread on which the browser 58e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * was constructed. 59e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 60e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 61096f2531cb790bc1106377d2da344614a3b88d39Jae Seopublic final class MediaBrowserCompat { 6282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim private static final String TAG = "MediaBrowserCompat"; 637a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 643f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim 6582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 6682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Used as an int extra field to denote the page number to subscribe. 6782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * The value of {@code EXTRA_PAGE} should be greater than or equal to 1. 6882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 6982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @see android.service.media.MediaBrowserService.BrowserRoot 7082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @see #EXTRA_PAGE_SIZE 7182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 7282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public static final String EXTRA_PAGE = "android.media.browse.extra.PAGE"; 7382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 7482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 7582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Used as an int extra field to denote the number of media items in a page. 7682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * The value of {@code EXTRA_PAGE_SIZE} should be greater than or equal to 1. 7782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 7882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @see android.service.media.MediaBrowserService.BrowserRoot 7982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @see #EXTRA_PAGE 8082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 8182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public static final String EXTRA_PAGE_SIZE = "android.media.browse.extra.PAGE_SIZE"; 8282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 836b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim private final MediaBrowserImpl mImpl; 84e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 85e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 86e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Creates a media browser for the specified media browse service. 87e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 88e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param context The context. 89e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param serviceComponent The component name of the media browse service. 90e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param callback The connection callback. 91e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param rootHints An optional bundle of service-specific arguments to send 92e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * to the media browse service when connecting and retrieving the root id 9382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * for browsing, or null if none. The contents of this bundle may affect 94e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * the information returned when browsing. 9526e88318c8f69f62f41591b0df0720cc48b4ce11Jae Seo * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_RECENT 9626e88318c8f69f62f41591b0df0720cc48b4ce11Jae Seo * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_OFFLINE 9726e88318c8f69f62f41591b0df0720cc48b4ce11Jae Seo * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_SUGGESTED 98e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 99096f2531cb790bc1106377d2da344614a3b88d39Jae Seo public MediaBrowserCompat(Context context, ComponentName serviceComponent, 100e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo ConnectionCallback callback, Bundle rootHints) { 101ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (Build.VERSION.SDK_INT >= 24 || BuildCompat.isAtLeastN()) { 10201b922eddadab50910ce289921001a63855e1f8eSungsoo Lim mImpl = new MediaBrowserImplApi24(context, serviceComponent, callback, rootHints); 10301b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } else if (Build.VERSION.SDK_INT >= 23) { 10482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mImpl = new MediaBrowserImplApi23(context, serviceComponent, callback, rootHints); 105a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim } else if (Build.VERSION.SDK_INT >= 21) { 1066b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim mImpl = new MediaBrowserImplApi21(context, serviceComponent, callback, rootHints); 1076b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } else { 10899f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim mImpl = new MediaBrowserImplBase(context, serviceComponent, callback, rootHints); 1096b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 110e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 111e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 112e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 113e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Connects to the media browse service. 114e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 115e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * The connection callback specified in the constructor will be invoked 116e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * when the connection completes or fails. 117e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 118e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 119e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void connect() { 120e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mImpl.connect(); 121e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 122e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 123e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 124e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Disconnects from the media browse service. 125e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * After this, no more callbacks will be received. 126e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 127e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void disconnect() { 128e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mImpl.disconnect(); 129e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 130e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 131e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 132e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns whether the browser is connected to the service. 133e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 134e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public boolean isConnected() { 135e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.isConnected(); 136e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 137e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 138e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 139e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets the service component that the media browser is connected to. 140e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 141e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull 142e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo ComponentName getServiceComponent() { 143e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.getServiceComponent(); 144e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 145e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 146e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 147e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets the root id. 148e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 149e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Note that the root id may become invalid or change when when the 150e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * browser is disconnected. 151e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 152e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 153e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @throws IllegalStateException if not connected. 154e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 155e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull String getRoot() { 156e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.getRoot(); 157e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 158e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 159e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 160e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets any extras for the media service. 161e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 162e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @throws IllegalStateException if not connected. 163e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 164e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @Nullable 165e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo Bundle getExtras() { 166e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.getExtras(); 167e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 168e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 169e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 170e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets the media session token associated with the media browser. 171e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 172e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Note that the session token may become invalid or change when when the 173e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * browser is disconnected. 174e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 175e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 176e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @return The session token for the browser, never null. 177e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 178e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @throws IllegalStateException if not connected. 179e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 180a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim public @NonNull MediaSessionCompat.Token getSessionToken() { 181e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.getSessionToken(); 182e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 183e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 184e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 185e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Queries for information about the media items that are contained within 186e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * the specified id and subscribes to receive updates when they change. 187e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 188e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * The list of subscriptions is maintained even when not connected and is 18982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * restored after the reconnection. It is ok to subscribe while not connected 190e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * but the results will not be returned until the connection completes. 191e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 192e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 193e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * If the id is already subscribed with a different callback then the new 194e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * callback will replace the previous one and the child data will be 195e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * reloaded. 196e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 197e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 198e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param parentId The id of the parent media item whose list of children 199e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * will be subscribed. 200e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param callback The callback to receive the list of children. 201e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 202e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void subscribe(@NonNull String parentId, @NonNull SubscriptionCallback callback) { 2037a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // Check arguments. 2047a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (TextUtils.isEmpty(parentId)) { 2057a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("parentId is empty"); 2067a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 2077a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callback == null) { 2087a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("callback is null"); 2097a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 21082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mImpl.subscribe(parentId, null, callback); 21182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 21282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 21382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 21482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Queries with service-specific arguments for information about the media items 21582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * that are contained within the specified id and subscribes to receive updates 21682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * when they change. 21782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * <p> 21882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * The list of subscriptions is maintained even when not connected and is 21982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * restored after the reconnection. It is ok to subscribe while not connected 22082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * but the results will not be returned until the connection completes. 22182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * </p> 22282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * <p> 22382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * If the id is already subscribed with a different callback then the new 22482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * callback will replace the previous one and the child data will be 22582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * reloaded. 22682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * </p> 22782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 22882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param parentId The id of the parent media item whose list of children 22982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * will be subscribed. 23082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param options A bundle of service-specific arguments to send to the media 23182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * browse service. The contents of this bundle may affect the 23282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * information returned when browsing. 23382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param callback The callback to receive the list of children. 23482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 23582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void subscribe(@NonNull String parentId, @NonNull Bundle options, 23682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim @NonNull SubscriptionCallback callback) { 2377a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // Check arguments. 2387a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (TextUtils.isEmpty(parentId)) { 2397a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("parentId is empty"); 2407a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 2417a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callback == null) { 2427a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("callback is null"); 2437a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 24482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (options == null) { 24582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim throw new IllegalArgumentException("options are null"); 24682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 24782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mImpl.subscribe(parentId, options, callback); 248e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 249e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 250e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 251e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Unsubscribes for changes to the children of the specified media id. 252e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 253e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * The query callback will no longer be invoked for results associated with 254e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * this id once this method returns. 255e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 256e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 257e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param parentId The id of the parent media item whose list of children 25882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * will be unsubscribed. 259e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 260e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void unsubscribe(@NonNull String parentId) { 2617a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // Check arguments. 2627a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (TextUtils.isEmpty(parentId)) { 2637a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("parentId is empty"); 2647a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 26582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mImpl.unsubscribe(parentId, null); 26682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 26782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 26882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 26982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Unsubscribes for changes to the children of the specified media id. 27082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * <p> 27182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * The query callback will no longer be invoked for results associated with 27282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * this id once this method returns. 27382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * </p> 27482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 27582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param parentId The id of the parent media item whose list of children 27682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * will be unsubscribed. 2777a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim * @param callback A callback sent to the media browse service to subscribe. 27882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 2797a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim public void unsubscribe(@NonNull String parentId, @NonNull SubscriptionCallback callback) { 2807a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // Check arguments. 2817a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (TextUtils.isEmpty(parentId)) { 2827a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("parentId is empty"); 2837a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 2847a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callback == null) { 2857a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("callback is null"); 28682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 2877a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mImpl.unsubscribe(parentId, callback); 288e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 289e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 290e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 291e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Retrieves a specific {@link MediaItem} from the connected service. Not 292e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * all services may support this, so falling back to subscribing to the 293e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * parent's id should be used when unavailable. 294e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 295e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param mediaId The id of the item to retrieve. 296e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param cb The callback to receive the result on. 297e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 298e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb) { 299e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mImpl.getItem(mediaId, cb); 300e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 301e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 30223471681e408dfe4e44975e13e7575ab5a04bc8cJae Seo /** 30323471681e408dfe4e44975e13e7575ab5a04bc8cJae Seo * A class with information on a single media item for use in browsing media. 30423471681e408dfe4e44975e13e7575ab5a04bc8cJae Seo */ 305e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static class MediaItem implements Parcelable { 306e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo private final int mFlags; 307e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo private final MediaDescriptionCompat mDescription; 308e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 309e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** @hide */ 310e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Retention(RetentionPolicy.SOURCE) 311e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @IntDef(flag=true, value = { FLAG_BROWSABLE, FLAG_PLAYABLE }) 312e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @interface Flags { } 313e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 314e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 315e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Flag: Indicates that the item has children of its own. 316e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 317e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static final int FLAG_BROWSABLE = 1 << 0; 318e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 319e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 320e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Flag: Indicates that the item is playable. 321e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 322e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * The id of this item may be passed to 3232490f437a4111d64520f891b2c81685f8fae323cJae Seo * {@link MediaControllerCompat.TransportControls#playFromMediaId(String, Bundle)} 324e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * to start playing it. 325e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 326e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 327e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static final int FLAG_PLAYABLE = 1 << 1; 328e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 329e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 330e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Create a new MediaItem for use in browsing media. 331e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param description The description of the media, which must include a 332e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * media id. 333e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param flags The flags for this item. 334e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 335e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public MediaItem(@NonNull MediaDescriptionCompat description, @Flags int flags) { 336e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo if (description == null) { 337e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo throw new IllegalArgumentException("description cannot be null"); 338e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 339e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo if (TextUtils.isEmpty(description.getMediaId())) { 340e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo throw new IllegalArgumentException("description must have a non-empty media id"); 341e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 342e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mFlags = flags; 343e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mDescription = description; 344e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 345e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 346e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 347e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Private constructor. 348e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 349e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo private MediaItem(Parcel in) { 350e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mFlags = in.readInt(); 351e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mDescription = MediaDescriptionCompat.CREATOR.createFromParcel(in); 352e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 353e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 354e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 355e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public int describeContents() { 356e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return 0; 357e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 358e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 359e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 360e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void writeToParcel(Parcel out, int flags) { 361e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo out.writeInt(mFlags); 362e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mDescription.writeToParcel(out, flags); 363e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 364e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 365e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 366e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public String toString() { 367e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo final StringBuilder sb = new StringBuilder("MediaItem{"); 368e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo sb.append("mFlags=").append(mFlags); 369e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo sb.append(", mDescription=").append(mDescription); 370e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo sb.append('}'); 371e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return sb.toString(); 372e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 373e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 374e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static final Parcelable.Creator<MediaItem> CREATOR = 375e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo new Parcelable.Creator<MediaItem>() { 376e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 377e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public MediaItem createFromParcel(Parcel in) { 378e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return new MediaItem(in); 379e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 380e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 381e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 382e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public MediaItem[] newArray(int size) { 383e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return new MediaItem[size]; 384e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 385e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo }; 386e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 387e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 388e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets the flags of the item. 389e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 390e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @Flags int getFlags() { 391e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return mFlags; 392e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 393e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 394e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 395e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns whether this item is browsable. 396e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @see #FLAG_BROWSABLE 397e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 398e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public boolean isBrowsable() { 399e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return (mFlags & FLAG_BROWSABLE) != 0; 400e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 401e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 402e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 403e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns whether this item is playable. 404e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @see #FLAG_PLAYABLE 405e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 406e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public boolean isPlayable() { 407e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return (mFlags & FLAG_PLAYABLE) != 0; 408e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 409e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 410e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 411e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns the description of the media. 412e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 413e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull MediaDescriptionCompat getDescription() { 414e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return mDescription; 415e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 416e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 417e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 418e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns the media id for this item. 419e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 420e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull String getMediaId() { 421e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return mDescription.getMediaId(); 422e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 423e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 424e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 425e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 426e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Callbacks for connection related events. 427e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 428e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static class ConnectionCallback { 4296b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim final Object mConnectionCallbackObj; 43016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private ConnectionCallbackInternal mConnectionCallbackInternal; 4316b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 4326b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public ConnectionCallback() { 433a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim if (Build.VERSION.SDK_INT >= 21) { 4346b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim mConnectionCallbackObj = 4356b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim MediaBrowserCompatApi21.createConnectionCallback(new StubApi21()); 4366b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } else { 4376b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim mConnectionCallbackObj = null; 4386b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4396b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4406b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 441e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 442096f2531cb790bc1106377d2da344614a3b88d39Jae Seo * Invoked after {@link MediaBrowserCompat#connect()} when the request has successfully 443096f2531cb790bc1106377d2da344614a3b88d39Jae Seo * completed. 444e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 445e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onConnected() { 446e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 447e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 448e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 449e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Invoked when the client is disconnected from the media browser. 450e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 451e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onConnectionSuspended() { 452e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 453e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 454e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 455e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Invoked when the connection to the media browser failed. 456e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 457e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onConnectionFailed() { 458e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 4596b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 46016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void setInternalConnectionCallback(ConnectionCallbackInternal connectionCallbackInternal) { 46116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mConnectionCallbackInternal = connectionCallbackInternal; 46216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 46316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 46416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim interface ConnectionCallbackInternal { 46516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onConnected(); 46616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onConnectionSuspended(); 46716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onConnectionFailed(); 46816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4696b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 4706b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim private class StubApi21 implements MediaBrowserCompatApi21.ConnectionCallback { 4716b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 4726b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void onConnected() { 47316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mConnectionCallbackInternal != null) { 47416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mConnectionCallbackInternal.onConnected(); 47516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4766b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ConnectionCallback.this.onConnected(); 4776b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4786b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 4796b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 4806b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void onConnectionSuspended() { 48116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mConnectionCallbackInternal != null) { 48216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mConnectionCallbackInternal.onConnectionSuspended(); 48316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4846b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ConnectionCallback.this.onConnectionSuspended(); 4856b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4866b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 4876b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 4886b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void onConnectionFailed() { 48916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mConnectionCallbackInternal != null) { 49016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mConnectionCallbackInternal.onConnectionFailed(); 49116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4926b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ConnectionCallback.this.onConnectionFailed(); 4936b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4946b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 495e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 496e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 497e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 498e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Callbacks for subscription related events. 499e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 500e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static abstract class SubscriptionCallback { 50116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final Object mSubscriptionCallbackObj; 5027a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim private final IBinder mToken; 503ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim private WeakReference<Subscription> mSubscriptionRef; 50416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 5057a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim public SubscriptionCallback() { 506ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (Build.VERSION.SDK_INT >= 24 || BuildCompat.isAtLeastN()) { 50701b922eddadab50910ce289921001a63855e1f8eSungsoo Lim mSubscriptionCallbackObj = 50801b922eddadab50910ce289921001a63855e1f8eSungsoo Lim MediaBrowserCompatApi24.createSubscriptionCallback(new StubApi24()); 5097a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mToken = null; 5107a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } else if (Build.VERSION.SDK_INT >= 21) { 51101b922eddadab50910ce289921001a63855e1f8eSungsoo Lim mSubscriptionCallbackObj = 51201b922eddadab50910ce289921001a63855e1f8eSungsoo Lim MediaBrowserCompatApi21.createSubscriptionCallback(new StubApi21()); 5137a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mToken = new Binder(); 5147a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } else { 5157a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mSubscriptionCallbackObj = null; 5167a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mToken = new Binder(); 51701b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 5186b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 5196b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 520e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 521e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Called when the list of children is loaded or updated. 522e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 523e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param parentId The media id of the parent media item. 524ae6d147640b8a868d2edff8ebac8d2a6bb03c594Sungsoo Lim * @param children The children which were loaded, or null if the id is invalid. 525e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 526ae6d147640b8a868d2edff8ebac8d2a6bb03c594Sungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children) { 527e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 528e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 529e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 53082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Called when the list of children is loaded or updated. 53182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 53282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param parentId The media id of the parent media item. 53382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param children The children which were loaded, or null if the id is invalid. 53482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param options A bundle of service-specific arguments to send to the media 53582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * browse service. The contents of this bundle may affect the 53682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * information returned when browsing. 53782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 53882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children, 53982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim @NonNull Bundle options) { 54082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 54182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 54282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 543e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Called when the id doesn't exist or other errors in subscribing. 544e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 545096f2531cb790bc1106377d2da344614a3b88d39Jae Seo * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} 546e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * called, because some errors may heal themselves. 547e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 548e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 54916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param parentId The media id of the parent media item whose children could not be loaded. 550e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 551e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onError(@NonNull String parentId) { 552e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 5536b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 55482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 55582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Called when the id doesn't exist or other errors in subscribing. 55682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * <p> 55782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} 55882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * called, because some errors may heal themselves. 55982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * </p> 56082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 56182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param parentId The media id of the parent media item whose children could 56282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * not be loaded. 56382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param options A bundle of service-specific arguments sent to the media 56482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * browse service. 56582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 56682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void onError(@NonNull String parentId, @NonNull Bundle options) { 56782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 56882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 569ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim private void setSubscription(Subscription subscription) { 570ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim mSubscriptionRef = new WeakReference(subscription); 571ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 572ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim 5736b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim private class StubApi21 implements MediaBrowserCompatApi21.SubscriptionCallback { 5746b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 57582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<Parcel> children) { 57664f99cb02f21f6a708b1f404b5e0ee6144f3af5bSungsoo Lim Subscription sub = mSubscriptionRef == null ? null : mSubscriptionRef.get(); 577ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (sub == null) { 578ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim SubscriptionCallback.this.onChildrenLoaded( 579ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim parentId, parcelListToItemList(children)); 580ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } else { 581ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim List<MediaBrowserCompat.MediaItem> itemList = parcelListToItemList(children); 582ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim final List<SubscriptionCallback> callbacks = sub.getCallbacks(); 583ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim final List<Bundle> optionsList = sub.getOptionsList(); 584ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim for (int i = 0; i < callbacks.size(); ++i) { 585ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim Bundle options = optionsList.get(i); 586ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (options == null) { 587ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim SubscriptionCallback.this.onChildrenLoaded(parentId, itemList); 588ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } else { 589ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim SubscriptionCallback.this.onChildrenLoaded( 590ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim parentId, applyOptions(itemList, options), options); 591ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 592ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 593ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 5946b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 5956b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 5966b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 5976b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void onError(@NonNull String parentId) { 5987a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim SubscriptionCallback.this.onError(parentId); 5996b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 600a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim 601a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim List<MediaBrowserCompat.MediaItem> parcelListToItemList( 602a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim List<Parcel> parcelList) { 603a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim if (parcelList == null) { 604a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim return null; 605a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim } 606a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim List<MediaBrowserCompat.MediaItem> items = new ArrayList<>(); 607a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim for (Parcel parcel : parcelList) { 608a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim parcel.setDataPosition(0); 609a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim items.add(MediaBrowserCompat.MediaItem.CREATOR.createFromParcel(parcel)); 610a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim parcel.recycle(); 611a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim } 612a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim return items; 613a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim } 614ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim 615ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim List<MediaBrowserCompat.MediaItem> applyOptions(List<MediaBrowserCompat.MediaItem> list, 616ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim final Bundle options) { 617ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (list == null) { 618ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim return null; 619ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 620ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim int page = options.getInt(MediaBrowserCompat.EXTRA_PAGE, -1); 621ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim int pageSize = options.getInt(MediaBrowserCompat.EXTRA_PAGE_SIZE, -1); 622ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (page == -1 && pageSize == -1) { 623ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim return list; 624ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 625ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim int fromIndex = pageSize * page; 626ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim int toIndex = fromIndex + pageSize; 627ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (page < 0 || pageSize < 1 || fromIndex >= list.size()) { 628ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim return Collections.EMPTY_LIST; 629ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 630ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (toIndex > list.size()) { 631ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim toIndex = list.size(); 632ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 633ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim return list.subList(fromIndex, toIndex); 634ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim } 635ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim 6366b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 63701b922eddadab50910ce289921001a63855e1f8eSungsoo Lim 63801b922eddadab50910ce289921001a63855e1f8eSungsoo Lim private class StubApi24 extends StubApi21 63901b922eddadab50910ce289921001a63855e1f8eSungsoo Lim implements MediaBrowserCompatApi24.SubscriptionCallback { 64001b922eddadab50910ce289921001a63855e1f8eSungsoo Lim @Override 6417a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<Parcel> children, 64201b922eddadab50910ce289921001a63855e1f8eSungsoo Lim @NonNull Bundle options) { 6437a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim SubscriptionCallback.this.onChildrenLoaded( 6447a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim parentId, parcelListToItemList(children), options); 64501b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 64601b922eddadab50910ce289921001a63855e1f8eSungsoo Lim 64701b922eddadab50910ce289921001a63855e1f8eSungsoo Lim @Override 64801b922eddadab50910ce289921001a63855e1f8eSungsoo Lim public void onError(@NonNull String parentId, @NonNull Bundle options) { 6497a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim SubscriptionCallback.this.onError(parentId, options); 65001b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 65101b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 652e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 653e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 654e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 655e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Callback for receiving the result of {@link #getItem}. 656e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 657e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static abstract class ItemCallback { 65882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim final Object mItemCallbackObj; 65982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 66082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public ItemCallback() { 661a7a03ae00cf642cb470e04c9a2164bad35627dbfSungsoo Lim if (Build.VERSION.SDK_INT >= 23) { 66282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mItemCallbackObj = MediaBrowserCompatApi23.createItemCallback(new StubApi23()); 66382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } else { 66482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mItemCallbackObj = null; 66582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 66682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 66782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 668e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 669e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Called when the item has been returned by the browser service. 670e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 671e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param item The item that was returned or null if it doesn't exist. 672e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 673e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onItemLoaded(MediaItem item) { 674e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 675e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 676e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 677e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Called when the item doesn't exist or there was an error retrieving it. 678e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 679e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param itemId The media id of the media item which could not be loaded. 680e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 681e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onError(@NonNull String itemId) { 682e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 68382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 68482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim private class StubApi23 implements MediaBrowserCompatApi23.ItemCallback { 68582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 68682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void onItemLoaded(Parcel itemParcel) { 68782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim itemParcel.setDataPosition(0); 68882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim MediaItem item = MediaBrowserCompat.MediaItem.CREATOR.createFromParcel(itemParcel); 68982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim itemParcel.recycle(); 69082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim ItemCallback.this.onItemLoaded(item); 69182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 69282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 69382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 69482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void onError(@NonNull String itemId) { 69582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim ItemCallback.this.onError(itemId); 69682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 69782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 698e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 699e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 7006b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim interface MediaBrowserImpl { 7016b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim void connect(); 7026b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim void disconnect(); 7036b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim boolean isConnected(); 7046b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ComponentName getServiceComponent(); 7056b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @NonNull String getRoot(); 7066b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Nullable Bundle getExtras(); 7076b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @NonNull MediaSessionCompat.Token getSessionToken(); 70882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim void subscribe(@NonNull String parentId, Bundle options, 70982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim @NonNull SubscriptionCallback callback); 7107a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim void unsubscribe(@NonNull String parentId, SubscriptionCallback callback); 7116b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb); 7126b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 7136b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 71416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim interface MediaBrowserServiceCallbackImpl { 71516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onServiceConnected(Messenger callback, String root, MediaSessionCompat.Token session, 71616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle extra); 71716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onConnectionFailed(Messenger callback); 71816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onLoadChildren(Messenger callback, String parentId, List list, Bundle options); 71916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 72016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 72199f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim static class MediaBrowserImplBase 72216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim implements MediaBrowserImpl, MediaBrowserServiceCallbackImpl { 723e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final int CONNECT_STATE_DISCONNECTED = 0; 724e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final int CONNECT_STATE_CONNECTING = 1; 725e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final int CONNECT_STATE_CONNECTED = 2; 726e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final int CONNECT_STATE_SUSPENDED = 3; 727e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 728e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private final Context mContext; 729e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private final ComponentName mServiceComponent; 730e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private final ConnectionCallback mCallback; 731e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private final Bundle mRootHints; 73216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final CallbackHandler mHandler = new CallbackHandler(this); 73382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim private final ArrayMap<String, Subscription> mSubscriptions = new ArrayMap<>(); 734e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 735e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private int mState = CONNECT_STATE_DISCONNECTED; 736e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private MediaServiceConnection mServiceConnection; 7373f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim private ServiceBinderWrapper mServiceBinderWrapper; 7383f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim private Messenger mCallbacksMessenger; 739e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private String mRootId; 740e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private MediaSessionCompat.Token mMediaSessionToken; 741e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private Bundle mExtras; 742e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 74399f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim public MediaBrowserImplBase(Context context, ComponentName serviceComponent, 744e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake ConnectionCallback callback, Bundle rootHints) { 745e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (context == null) { 746e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("context must not be null"); 747e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 748e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (serviceComponent == null) { 749e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("service component must not be null"); 750e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 751e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (callback == null) { 752e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("connection callback must not be null"); 753e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 754e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mContext = context; 755e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mServiceComponent = serviceComponent; 756e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mCallback = callback; 757fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim mRootHints = rootHints == null ? null : new Bundle(rootHints); 758e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 759e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 7607a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 761e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void connect() { 762e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mState != CONNECT_STATE_DISCONNECTED) { 763e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalStateException("connect() called while not disconnected (state=" 764e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + getStateLabel(mState) + ")"); 765e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 766e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // TODO: remove this extra check. 7677a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 768e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mServiceConnection != null) { 769e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new RuntimeException("mServiceConnection should be null. Instead it is " 770e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + mServiceConnection); 771e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 772e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 7733f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mServiceBinderWrapper != null) { 7743f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim throw new RuntimeException("mServiceBinderWrapper should be null. Instead it is " 7753f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + mServiceBinderWrapper); 776e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 7773f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mCallbacksMessenger != null) { 7783f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim throw new RuntimeException("mCallbacksMessenger should be null. Instead it is " 7793f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + mCallbacksMessenger); 780e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 781e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 782e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mState = CONNECT_STATE_CONNECTING; 783e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 784e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake final Intent intent = new Intent(MediaBrowserServiceCompat.SERVICE_INTERFACE); 785e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake intent.setComponent(mServiceComponent); 786e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 787e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake final ServiceConnection thisConnection = mServiceConnection = 788e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake new MediaServiceConnection(); 789e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 790e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake boolean bound = false; 791e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo try { 792e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); 793e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } catch (Exception ex) { 794e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.e(TAG, "Failed binding to service " + mServiceComponent); 795e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 796e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 797e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!bound) { 79882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // Tell them that it didn't work. We are already on the main thread, 79982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // but we don't want to do callbacks inside of connect(). So post it, 80082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // and then check that we are on the same ServiceConnection. We know 801e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // we won't also get an onServiceConnected or onServiceDisconnected, 802e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // so we won't be doing double callbacks. 803e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mHandler.post(new Runnable() { 804e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 805e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void run() { 806e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Ensure that nobody else came in or tried to connect again. 807e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (thisConnection == mServiceConnection) { 808e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake forceCloseConnection(); 809e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mCallback.onConnectionFailed(); 810e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 811e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 812e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake }); 813e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 814e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 8157a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 816e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, "connect..."); 817e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo dump(); 818e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 819e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 820e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 8217a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 822e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void disconnect() { 823e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // It's ok to call this any state, because allowing this lets apps not have 82482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // to check isConnected() unnecessarily. They won't appreciate the extra 82582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // assertions for this. We do everything we can here to go back to a sane state. 8263f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mCallbacksMessenger != null) { 827e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake try { 82816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.disconnect(mCallbacksMessenger); 829e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } catch (RemoteException ex) { 83082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // We are disconnecting anyway. Log, just for posterity but it's not 831e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // a big problem. 832e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.w(TAG, "RemoteException during connect for " + mServiceComponent); 833e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 834e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 835e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake forceCloseConnection(); 836e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 8377a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 838e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, "disconnect..."); 839e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake dump(); 840e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 841e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 842e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 843e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake /** 84482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Null out the variables and unbind from the service. This doesn't include 845e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * calling disconnect on the service, because we only try to do that in the 846e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * clean shutdown cases. 847e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * <p> 848e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * Everywhere that calls this EXCEPT for disconnect() should follow it with 84982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * a call to mCallback.onConnectionFailed(). Disconnect doesn't do that callback 850e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * for a clean shutdown, but everywhere else is a dirty shutdown and should 851e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * notify the app. 852e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake */ 853e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private void forceCloseConnection() { 854e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mServiceConnection != null) { 855e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mContext.unbindService(mServiceConnection); 856e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 857e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mState = CONNECT_STATE_DISCONNECTED; 858e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mServiceConnection = null; 8593f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mServiceBinderWrapper = null; 8603f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mCallbacksMessenger = null; 86199f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim mHandler.setCallbacksMessenger(null); 862e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mRootId = null; 863e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mMediaSessionToken = null; 864e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 865e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 8667a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 867e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public boolean isConnected() { 868e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mState == CONNECT_STATE_CONNECTED; 869e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 870e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 8717a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 8727a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim public @NonNull ComponentName getServiceComponent() { 873e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!isConnected()) { 874e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalStateException("getServiceComponent() called while not connected" + 875e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake " (state=" + mState + ")"); 876e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 877e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mServiceComponent; 878e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 879e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 8807a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 881e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public @NonNull String getRoot() { 882e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!isConnected()) { 883dfed7fbde83fb36b1993582317a27c5247af958cDongwon Kang throw new IllegalStateException("getRoot() called while not connected" 884e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + "(state=" + getStateLabel(mState) + ")"); 885e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 886e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mRootId; 887e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 888e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 8897a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 8907a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim public @Nullable Bundle getExtras() { 891e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!isConnected()) { 892e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalStateException("getExtras() called while not connected (state=" 893e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + getStateLabel(mState) + ")"); 894e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 895e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mExtras; 896e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 897e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 8987a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 899e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public @NonNull MediaSessionCompat.Token getSessionToken() { 900e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!isConnected()) { 901e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalStateException("getSessionToken() called while not connected" 902e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + "(state=" + mState + ")"); 903e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 904e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mMediaSessionToken; 905e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 906e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 9077a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 90882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void subscribe(@NonNull String parentId, Bundle options, 90982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim @NonNull SubscriptionCallback callback) { 910e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Update or create the subscription. 911e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Subscription sub = mSubscriptions.get(parentId); 91282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (sub == null) { 91382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim sub = new Subscription(); 914e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mSubscriptions.put(parentId, sub); 915e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 91658302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim sub.putCallback(options, callback); 917e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 91882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // If we are connected, tell the service that we are watching. If we aren't 919e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // connected, the service will be told when we connect. 920e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mState == CONNECT_STATE_CONNECTED) { 921e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake try { 9227a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mServiceBinderWrapper.addSubscription(parentId, callback.mToken, options, 9237a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mCallbacksMessenger); 92416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } catch (RemoteException e) { 92582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 926e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // automatically reregister. So nothing to do here. 927e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, "addSubscription failed with RemoteException parentId=" + parentId); 928e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 929e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 930e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 931e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 9327a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 9337a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim public void unsubscribe(@NonNull String parentId, SubscriptionCallback callback) { 93482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim Subscription sub = mSubscriptions.get(parentId); 9357a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (sub == null) { 9367a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim return; 9377a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 938e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 939e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Tell the service if necessary. 9407a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim try { 9417a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callback == null) { 9427a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (mState == CONNECT_STATE_CONNECTED) { 9437a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mServiceBinderWrapper.removeSubscription(parentId, null, 9447a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mCallbacksMessenger); 9457a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 9467a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } else { 9477a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim final List<SubscriptionCallback> callbacks = sub.getCallbacks(); 9487a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim final List<Bundle> optionsList = sub.getOptionsList(); 9497a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim for (int i = callbacks.size() - 1; i >= 0; --i) { 9507a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callbacks.get(i) == callback) { 9517a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (mState == CONNECT_STATE_CONNECTED) { 9527a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mServiceBinderWrapper.removeSubscription( 9537a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim parentId, callback.mToken, mCallbacksMessenger); 9547a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 9557a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim callbacks.remove(i); 9567a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim optionsList.remove(i); 9577a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 9587a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 959e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 9607a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } catch (RemoteException ex) { 9617a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 9627a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // automatically reregister. So nothing to do here. 9637a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim Log.d(TAG, "removeSubscription failed with RemoteException parentId=" + parentId); 964e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 9657a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim 9667a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (sub.isEmpty() || callback == null) { 96782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mSubscriptions.remove(parentId); 96882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 969e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 970e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 9717a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 972d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim public void getItem(@NonNull final String mediaId, @NonNull final ItemCallback cb) { 973e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (TextUtils.isEmpty(mediaId)) { 9747a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("mediaId is empty"); 975e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 976e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (cb == null) { 9777a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("cb is null"); 978e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 979e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mState != CONNECT_STATE_CONNECTED) { 980e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.i(TAG, "Not connected, unable to retrieve the MediaItem."); 981e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mHandler.post(new Runnable() { 982e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 983e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void run() { 984e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake cb.onError(mediaId); 985e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 986e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake }); 987e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return; 988e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 989d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim ResultReceiver receiver = new ItemReceiver(mediaId, cb, mHandler); 990e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake try { 991fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim mServiceBinderWrapper.getMediaItem(mediaId, receiver, mCallbacksMessenger); 992e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } catch (RemoteException e) { 993e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.i(TAG, "Remote error getting media item."); 994e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mHandler.post(new Runnable() { 995e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 996e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void run() { 997e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake cb.onError(mediaId); 998e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 999e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake }); 1000e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1001e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1002e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 10037a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 100416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onServiceConnected(final Messenger callback, final String root, 10053f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim final MediaSessionCompat.Token session, final Bundle extra) { 10063f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Check to make sure there hasn't been a disconnect or a different ServiceConnection. 10073f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (!isCurrent(callback, "onConnect")) { 10083f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim return; 10093f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 10103f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Don't allow them to call us twice. 10113f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mState != CONNECT_STATE_CONNECTING) { 10123f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.w(TAG, "onConnect from service while mState=" + getStateLabel(mState) 10133f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + "... ignoring"); 10143f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim return; 10153f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 10163f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mRootId = root; 10173f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mMediaSessionToken = session; 10183f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mExtras = extra; 10193f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mState = CONNECT_STATE_CONNECTED; 1020e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10217a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 10223f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.d(TAG, "ServiceCallbacks.onConnect..."); 10233f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim dump(); 10243f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 10253f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mCallback.onConnected(); 10263f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim 10273f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // we may receive some subscriptions before we are connected, so re-subscribe 10283f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // everything now 102982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim try { 103082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim for (Map.Entry<String, Subscription> subscriptionEntry 103182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim : mSubscriptions.entrySet()) { 103282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim String id = subscriptionEntry.getKey(); 103382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim Subscription sub = subscriptionEntry.getValue(); 10347a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim List<SubscriptionCallback> callbackList = sub.getCallbacks(); 10357a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim List<Bundle> optionsList = sub.getOptionsList(); 10367a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim for (int i = 0; i < callbackList.size(); ++i) { 10377a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mServiceBinderWrapper.addSubscription(id, callbackList.get(i).mToken, 10387a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim optionsList.get(i), mCallbacksMessenger); 103982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 1040e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 104182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } catch (RemoteException ex) { 104282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 104382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // automatically reregister. So nothing to do here. 104482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim Log.d(TAG, "addSubscription failed with RemoteException."); 10453f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 1046e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1047e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10487a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 104916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnectionFailed(final Messenger callback) { 10503f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.e(TAG, "onConnectFailed for " + mServiceComponent); 1051e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10523f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Check to make sure there hasn't been a disconnect or a different ServiceConnection. 10533f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (!isCurrent(callback, "onConnectFailed")) { 10543f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim return; 10553f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 10563f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Don't allow them to call us twice. 10573f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mState != CONNECT_STATE_CONNECTING) { 10583f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.w(TAG, "onConnect from service while mState=" + getStateLabel(mState) 10593f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + "... ignoring"); 10603f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim return; 10613f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 1062e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10633f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Clean up 10643f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim forceCloseConnection(); 1065e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10663f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Tell the app. 10673f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mCallback.onConnectionFailed(); 1068e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1069e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10707a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim @Override 107116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onLoadChildren(final Messenger callback, final String parentId, 107282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim final List list, final Bundle options) { 107382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim // Check that there hasn't been a disconnect or a different ServiceConnection. 107482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (!isCurrent(callback, "onLoadChildren")) { 107582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim return; 107682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 1077e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 107882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim List<MediaItem> data = list; 10797a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 108082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId); 108182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 1082e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 108382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim // Check that the subscription is still subscribed. 108482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim final Subscription subscription = mSubscriptions.get(parentId); 108582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (subscription == null) { 10867a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 108782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim Log.d(TAG, "onLoadChildren for id that isn't subscribed id=" + parentId); 108882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 108982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim return; 109082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 109182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 109282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim // Tell the app. 109382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim SubscriptionCallback subscriptionCallback = subscription.getCallback(options); 109482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (subscriptionCallback != null) { 109582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (options == null) { 109682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim subscriptionCallback.onChildrenLoaded(parentId, data); 109782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } else { 109882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim subscriptionCallback.onChildrenLoaded(parentId, data, options); 109982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 110082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 1101e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1102e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1103e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake /** 110416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * For debugging. 110516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim */ 110616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static String getStateLabel(int state) { 110716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim switch (state) { 110816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case CONNECT_STATE_DISCONNECTED: 110916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "CONNECT_STATE_DISCONNECTED"; 111016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case CONNECT_STATE_CONNECTING: 111116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "CONNECT_STATE_CONNECTING"; 111216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case CONNECT_STATE_CONNECTED: 111316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "CONNECT_STATE_CONNECTED"; 111416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case CONNECT_STATE_SUSPENDED: 111516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "CONNECT_STATE_SUSPENDED"; 111616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim default: 111716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "UNKNOWN/" + state; 111816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 111916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 112016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 112116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim /** 112282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Return true if {@code callback} is the current ServiceCallbacks. Also logs if it's not. 1123e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake */ 11243f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim private boolean isCurrent(Messenger callback, String funcName) { 11253f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mCallbacksMessenger != callback) { 1126e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo if (mState != CONNECT_STATE_DISCONNECTED) { 11273f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.i(TAG, funcName + " for " + mServiceComponent + " with mCallbacksMessenger=" 11283f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + mCallbacksMessenger + " this=" + this); 1129e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1130e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return false; 1131e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1132e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return true; 1133e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1134e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 1135e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake /** 1136e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * Log internal state. 1137e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * @hide 1138e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake */ 1139e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake void dump() { 1140e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, "MediaBrowserCompat..."); 1141e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mServiceComponent=" + mServiceComponent); 1142e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mCallback=" + mCallback); 1143e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mRootHints=" + mRootHints); 1144e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mState=" + getStateLabel(mState)); 1145e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mServiceConnection=" + mServiceConnection); 11463f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.d(TAG, " mServiceBinderWrapper=" + mServiceBinderWrapper); 11473f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.d(TAG, " mCallbacksMessenger=" + mCallbacksMessenger); 1148e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mRootId=" + mRootId); 1149e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mMediaSessionToken=" + mMediaSessionToken); 1150e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1151e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 1152e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 1153e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * ServiceConnection to the other app. 1154e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 1155e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private class MediaServiceConnection implements ServiceConnection { 1156e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 1157a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim public void onServiceConnected(final ComponentName name, final IBinder binder) { 1158a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim postOrRun(new Runnable() { 1159a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim @Override 1160a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim public void run() { 11617a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 1162a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.d(TAG, "MediaServiceConnection.onServiceConnected name=" + name 1163a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim + " binder=" + binder); 1164a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim dump(); 1165a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 11663f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim 1167a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Make sure we are still the current connection, and that they haven't 1168a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // called disconnect(). 1169a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (!isCurrent("onServiceConnected")) { 1170a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim return; 1171a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1172e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1173a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Save their binder 1174fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim mServiceBinderWrapper = new ServiceBinderWrapper(binder, mRootHints); 1175a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim 1176a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // We make a new mServiceCallbacks each time we connect so that we can drop 1177a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // responses from previous connections. 1178a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mCallbacksMessenger = new Messenger(mHandler); 117916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mHandler.setCallbacksMessenger(mCallbacksMessenger); 1180a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim 1181a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mState = CONNECT_STATE_CONNECTING; 1182a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim 1183a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Call connect, which is async. When we get a response from that we will 1184a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // say that we're connected. 1185a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim try { 11867a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 1187a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.d(TAG, "ServiceCallbacks.onConnect..."); 1188a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim dump(); 1189a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1190fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim mServiceBinderWrapper.connect(mContext, mCallbacksMessenger); 1191a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } catch (RemoteException ex) { 1192a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Connect failed, which isn't good. But the auto-reconnect on the 119382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // service will take over and we will come back. We will also get the 119482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // onServiceDisconnected, which has all the cleanup code. So let that 1195a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // do it. 1196a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.w(TAG, "RemoteException during connect for " + mServiceComponent); 11977a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 1198a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.d(TAG, "ServiceCallbacks.onConnect..."); 1199a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim dump(); 1200a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1201a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1202e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1203a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim }); 1204e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1205e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1206e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 1207a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim public void onServiceDisconnected(final ComponentName name) { 1208a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim postOrRun(new Runnable() { 1209a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim @Override 1210a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim public void run() { 12117a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 1212a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.d(TAG, "MediaServiceConnection.onServiceDisconnected name=" + name 1213a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim + " this=" + this + " mServiceConnection=" + 1214a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mServiceConnection); 1215a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim dump(); 1216a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1217e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1218a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Make sure we are still the current connection, and that they haven't 1219a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // called disconnect(). 1220a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (!isCurrent("onServiceDisconnected")) { 1221a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim return; 1222a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1223e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1224a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Clear out what we set in onServiceConnected 1225a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mServiceBinderWrapper = null; 1226a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mCallbacksMessenger = null; 122716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mHandler.setCallbacksMessenger(null); 1228e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1229a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // And tell the app that it's suspended. 1230a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mState = CONNECT_STATE_SUSPENDED; 1231a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mCallback.onConnectionSuspended(); 1232a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1233a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim }); 1234a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1235a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim 1236a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim private void postOrRun(Runnable r) { 1237a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (Thread.currentThread() == mHandler.getLooper().getThread()) { 1238a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim r.run(); 1239a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } else { 1240a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mHandler.post(r); 1241a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1242e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1243e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1244e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake /** 124582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Return true if this is the current ServiceConnection. Also logs if it's not. 1246e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake */ 1247e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private boolean isCurrent(String funcName) { 1248e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mServiceConnection != this) { 1249e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mState != CONNECT_STATE_DISCONNECTED) { 1250e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Check mState, because otherwise this log is noisy. 1251e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.i(TAG, funcName + " for " + mServiceComponent + 1252e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake " with mServiceConnection=" + mServiceConnection + " this=" + this); 1253e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1254e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return false; 1255e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1256e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return true; 1257e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1258e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 125916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 1260e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 126116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim static class MediaBrowserImplApi21 implements MediaBrowserImpl, MediaBrowserServiceCallbackImpl, 126216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim ConnectionCallback.ConnectionCallbackInternal { 1263fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim protected final Object mBrowserObj; 1264fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim protected final Bundle mRootHints; 12652e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim protected final CallbackHandler mHandler = new CallbackHandler(this); 126616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final ArrayMap<String, Subscription> mSubscriptions = new ArrayMap<>(); 12676b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12682e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim protected ServiceBinderWrapper mServiceBinderWrapper; 12692e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim protected Messenger mCallbacksMessenger; 12706b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12716b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public MediaBrowserImplApi21(Context context, ComponentName serviceComponent, 12726b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ConnectionCallback callback, Bundle rootHints) { 12732e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim // Do not send the client version for API 24 and higher, since we don't need to use 12742e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim // EXTRA_MESSENGER_BINDER for API 24 and higher. 1275ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim if (Build.VERSION.SDK_INT < 24 && !BuildCompat.isAtLeastN()) { 12762e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim if (rootHints == null) { 12772e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim rootHints = new Bundle(); 12782e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim } 12792e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim rootHints.putInt(EXTRA_CLIENT_VERSION, CLIENT_VERSION_CURRENT); 12802e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim mRootHints = new Bundle(rootHints); 12812e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim } else { 12822e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim mRootHints = rootHints == null ? null : new Bundle(rootHints); 12837a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 128416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim callback.setInternalConnectionCallback(this); 12856b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim mBrowserObj = MediaBrowserCompatApi21.createBrowser(context, serviceComponent, 1286fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim callback.mConnectionCallbackObj, mRootHints); 12876b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12886b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12896b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12906b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void connect() { 12916b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim MediaBrowserCompatApi21.connect(mBrowserObj); 12926b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12936b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12946b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12956b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void disconnect() { 129699f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim if (mServiceBinderWrapper != null && mCallbacksMessenger != null) { 129799f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim try { 129899f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim mServiceBinderWrapper.unregisterCallbackMessenger(mCallbacksMessenger); 129999f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim } catch (RemoteException e) { 130099f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim Log.i(TAG, "Remote error unregistering client messenger." ); 130199f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim } 130299f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim } 13036b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim MediaBrowserCompatApi21.disconnect(mBrowserObj); 13046b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13056b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13066b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 13076b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public boolean isConnected() { 13086b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaBrowserCompatApi21.isConnected(mBrowserObj); 13096b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13106b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13116b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 13126b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public ComponentName getServiceComponent() { 13136b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaBrowserCompatApi21.getServiceComponent(mBrowserObj); 13146b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13156b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13166b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @NonNull 13176b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 13186b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public String getRoot() { 13196b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaBrowserCompatApi21.getRoot(mBrowserObj); 13206b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13216b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13226b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Nullable 13236b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 13246b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public Bundle getExtras() { 13256b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaBrowserCompatApi21.getExtras(mBrowserObj); 13266b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13276b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13286b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @NonNull 13296b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 13306b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public MediaSessionCompat.Token getSessionToken() { 13316b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaSessionCompat.Token.fromToken( 13326b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim MediaBrowserCompatApi21.getSessionToken(mBrowserObj)); 13336b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13346b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13356b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 133616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void subscribe(@NonNull final String parentId, final Bundle options, 133716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @NonNull final SubscriptionCallback callback) { 133816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Update or create the subscription. 133916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Subscription sub = mSubscriptions.get(parentId); 134016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (sub == null) { 134116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sub = new Subscription(); 134216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptions.put(parentId, sub); 134316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 1344ac127f074a064c2b5e87102bd7f6c3e4a5d5cdfdSungsoo Lim callback.setSubscription(sub); 13457a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim sub.putCallback(options, callback); 13467a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim 13477a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (mServiceBinderWrapper == null) { 13487a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim MediaBrowserCompatApi21.subscribe( 13497a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mBrowserObj, parentId, callback.mSubscriptionCallbackObj); 13507a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } else { 13517a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim try { 13527a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mServiceBinderWrapper.addSubscription( 13537a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim parentId, callback.mToken, options, mCallbacksMessenger); 13547a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } catch (RemoteException e) { 13557a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 13567a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // automatically reregister. So nothing to do here. 13577a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim Log.i(TAG, "Remote error subscribing media item: " + parentId); 135816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 135916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 13606b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13616b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13626b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 13637a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim public void unsubscribe(@NonNull String parentId, SubscriptionCallback callback) { 13647a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim Subscription sub = mSubscriptions.get(parentId); 13657a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (sub == null) { 13667a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim return; 136716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 136816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 13697a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (mServiceBinderWrapper == null) { 13707a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callback == null) { 13717a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim MediaBrowserCompatApi21.unsubscribe(mBrowserObj, parentId); 13727a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } else { 13737a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim final List<SubscriptionCallback> callbacks = sub.getCallbacks(); 13747a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim final List<Bundle> optionsList = sub.getOptionsList(); 13757a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim for (int i = callbacks.size() - 1; i >= 0; --i) { 13767a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callbacks.get(i) == callback) { 13777a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim callbacks.remove(i); 13787a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim optionsList.remove(i); 13797a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 13807a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 13817a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callbacks.size() == 0) { 138216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim MediaBrowserCompatApi21.unsubscribe(mBrowserObj, parentId); 138316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 13847a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 13857a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } else { 13867a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // Tell the service if necessary. 13877a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim try { 13887a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callback == null) { 13897a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mServiceBinderWrapper.removeSubscription(parentId, null, 13907a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mCallbacksMessenger); 13917a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } else { 13927a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim final List<SubscriptionCallback> callbacks = sub.getCallbacks(); 13937a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim final List<Bundle> optionsList = sub.getOptionsList(); 13947a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim for (int i = callbacks.size() - 1; i >= 0; --i) { 13957a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callbacks.get(i) == callback) { 13967a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mServiceBinderWrapper.removeSubscription( 13977a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim parentId, callback.mToken, mCallbacksMessenger); 13987a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim callbacks.remove(i); 13997a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim optionsList.remove(i); 14007a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 14017a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 140216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 14037a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } catch (RemoteException ex) { 14047a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 14057a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // automatically reregister. So nothing to do here. 14067a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim Log.d(TAG, "removeSubscription failed with RemoteException parentId=" 14077a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim + parentId); 140816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 140916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 14107a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim 14117a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (sub.isEmpty() || callback == null) { 141216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptions.remove(parentId); 141316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 14146b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 14156b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 14166b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 141782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void getItem(@NonNull final String mediaId, @NonNull final ItemCallback cb) { 141882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (TextUtils.isEmpty(mediaId)) { 14197a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("mediaId is empty"); 142082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 142182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (cb == null) { 14227a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim throw new IllegalArgumentException("cb is null"); 142382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 142482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (!MediaBrowserCompatApi21.isConnected(mBrowserObj)) { 142582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim Log.i(TAG, "Not connected, unable to retrieve the MediaItem."); 142682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mHandler.post(new Runnable() { 142782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 142882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void run() { 142982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim cb.onError(mediaId); 143082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 143182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim }); 143282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim return; 143382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 143416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mServiceBinderWrapper == null) { 143582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mHandler.post(new Runnable() { 143682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 143782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void run() { 143882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim // Default framework implementation. 143982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim cb.onItemLoaded(null); 144082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 144182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim }); 144282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim return; 144382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 1444d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim ResultReceiver receiver = new ItemReceiver(mediaId, cb, mHandler); 144582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim try { 1446fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim mServiceBinderWrapper.getMediaItem(mediaId, receiver, mCallbacksMessenger); 144782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } catch (RemoteException e) { 144816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.i(TAG, "Remote error getting media item: " + mediaId); 144982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mHandler.post(new Runnable() { 145082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 145182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void run() { 145282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim cb.onError(mediaId); 145382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 145482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim }); 145582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 145682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 145782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 145816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 145916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnected() { 146016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle extras = MediaBrowserCompatApi21.getExtras(mBrowserObj); 146116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (extras == null) { 146216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 146316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 146416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim IBinder serviceBinder = BundleCompat.getBinder(extras, EXTRA_MESSENGER_BINDER); 146516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (serviceBinder != null) { 1466fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim mServiceBinderWrapper = new ServiceBinderWrapper(serviceBinder, mRootHints); 146716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacksMessenger = new Messenger(mHandler); 146816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mHandler.setCallbacksMessenger(mCallbacksMessenger); 146916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim try { 147016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.registerCallbackMessenger(mCallbacksMessenger); 147116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } catch (RemoteException e) { 147216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.i(TAG, "Remote error registering client messenger." ); 147316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 147416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 147516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 147616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 147716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 147816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnectionSuspended() { 147916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper = null; 148016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacksMessenger = null; 148199f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim mHandler.setCallbacksMessenger(null); 148216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 148316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 148416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 148516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnectionFailed() { 148616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Do noting 148716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 148816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 148916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 149016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onServiceConnected(final Messenger callback, final String root, 149116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim final MediaSessionCompat.Token session, final Bundle extra) { 14927a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim // This method will not be called. 149316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 149416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 149516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 149616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnectionFailed(Messenger callback) { 149716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // This method will not be called. 149816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 149916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 150016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 1501b3f4a7d427953c3e197a2d362a39d918891698ffSungsoo Lim public void onLoadChildren(Messenger callback, String parentId, List list, Bundle options) { 150216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mCallbacksMessenger != callback) { 150316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 150416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 150516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 150616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Check that the subscription is still subscribed. 150716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Subscription subscription = mSubscriptions.get(parentId); 150816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (subscription == null) { 15097a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (DEBUG) { 151016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.d(TAG, "onLoadChildren for id that isn't subscribed id=" + parentId); 151116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 151216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 151316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 151416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 151516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Tell the app. 15167a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim SubscriptionCallback subscriptionCallback = subscription.getCallback(options); 15177a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (subscriptionCallback != null) { 1518b3f4a7d427953c3e197a2d362a39d918891698ffSungsoo Lim if (options == null) { 1519b3f4a7d427953c3e197a2d362a39d918891698ffSungsoo Lim subscriptionCallback.onChildrenLoaded(parentId, list); 1520b3f4a7d427953c3e197a2d362a39d918891698ffSungsoo Lim } else { 1521b3f4a7d427953c3e197a2d362a39d918891698ffSungsoo Lim subscriptionCallback.onChildrenLoaded(parentId, list, options); 1522b3f4a7d427953c3e197a2d362a39d918891698ffSungsoo Lim } 15237a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim } 152482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 152582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 152682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 152782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim static class MediaBrowserImplApi23 extends MediaBrowserImplApi21 { 152882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public MediaBrowserImplApi23(Context context, ComponentName serviceComponent, 152982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim ConnectionCallback callback, Bundle rootHints) { 153082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim super(context, serviceComponent, callback, rootHints); 153182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 153282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 153382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 15342e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim public void getItem(@NonNull final String mediaId, @NonNull final ItemCallback cb) { 15352e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim if (mServiceBinderWrapper == null) { 15362e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim MediaBrowserCompatApi23.getItem(mBrowserObj, mediaId, cb.mItemCallbackObj); 15372e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim } else { 15382e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim super.getItem(mediaId, cb); 15392e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim } 15406b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 15416b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 1542d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim 154301b922eddadab50910ce289921001a63855e1f8eSungsoo Lim static class MediaBrowserImplApi24 extends MediaBrowserImplApi23 { 154401b922eddadab50910ce289921001a63855e1f8eSungsoo Lim public MediaBrowserImplApi24(Context context, ComponentName serviceComponent, 154501b922eddadab50910ce289921001a63855e1f8eSungsoo Lim ConnectionCallback callback, Bundle rootHints) { 154601b922eddadab50910ce289921001a63855e1f8eSungsoo Lim super(context, serviceComponent, callback, rootHints); 154701b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 154801b922eddadab50910ce289921001a63855e1f8eSungsoo Lim 154901b922eddadab50910ce289921001a63855e1f8eSungsoo Lim @Override 155001b922eddadab50910ce289921001a63855e1f8eSungsoo Lim public void subscribe(@NonNull String parentId, @NonNull Bundle options, 155101b922eddadab50910ce289921001a63855e1f8eSungsoo Lim @NonNull SubscriptionCallback callback) { 155201b922eddadab50910ce289921001a63855e1f8eSungsoo Lim if (options == null) { 155301b922eddadab50910ce289921001a63855e1f8eSungsoo Lim MediaBrowserCompatApi21.subscribe( 15547a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mBrowserObj, parentId, callback.mSubscriptionCallbackObj); 155501b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } else { 155601b922eddadab50910ce289921001a63855e1f8eSungsoo Lim MediaBrowserCompatApi24.subscribe( 15577a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mBrowserObj, parentId, options, callback.mSubscriptionCallbackObj); 155801b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 155901b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 156001b922eddadab50910ce289921001a63855e1f8eSungsoo Lim 156101b922eddadab50910ce289921001a63855e1f8eSungsoo Lim @Override 15627a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim public void unsubscribe(@NonNull String parentId, SubscriptionCallback callback) { 15637a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (callback == null) { 156401b922eddadab50910ce289921001a63855e1f8eSungsoo Lim MediaBrowserCompatApi21.unsubscribe(mBrowserObj, parentId); 156501b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } else { 15667a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim MediaBrowserCompatApi24.unsubscribe(mBrowserObj, parentId, 15677a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim callback.mSubscriptionCallbackObj); 156801b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 156901b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 15702e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim 15712e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim @Override 15722e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim public void getItem(@NonNull final String mediaId, @NonNull final ItemCallback cb) { 15732e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim MediaBrowserCompatApi23.getItem(mBrowserObj, mediaId, cb.mItemCallbackObj); 15742e7d3a28e00195c160cc4f5668e2d7f64eb590daSungsoo Lim } 157501b922eddadab50910ce289921001a63855e1f8eSungsoo Lim } 157601b922eddadab50910ce289921001a63855e1f8eSungsoo Lim 157716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static class Subscription { 157816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final List<SubscriptionCallback> mCallbacks; 157916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final List<Bundle> mOptionsList; 158016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 158116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public Subscription() { 158216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacks = new ArrayList(); 158316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mOptionsList = new ArrayList(); 158416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 158516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 158616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public boolean isEmpty() { 158716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return mCallbacks.isEmpty(); 158816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 158916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 159016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public List<Bundle> getOptionsList() { 159116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return mOptionsList; 159216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 159316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 159416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public List<SubscriptionCallback> getCallbacks() { 159516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return mCallbacks; 159616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 159716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 159858302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim public SubscriptionCallback getCallback(Bundle options) { 159958302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim for (int i = 0; i < mOptionsList.size(); ++i) { 160058302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim if (MediaBrowserCompatUtils.areSameOptions(mOptionsList.get(i), options)) { 160158302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim return mCallbacks.get(i); 160258302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim } 160358302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim } 160458302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim return null; 160558302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim } 160658302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim 160758302bb8a709941cee04f2aa378b2496e30d0045Sungsoo Lim public void putCallback(Bundle options, SubscriptionCallback callback) { 160816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim for (int i = 0; i < mOptionsList.size(); ++i) { 160916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (MediaBrowserCompatUtils.areSameOptions(mOptionsList.get(i), options)) { 161016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacks.set(i, callback); 161116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 161216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 161316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 161416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacks.add(callback); 161516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mOptionsList.add(options); 161616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 161716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 161816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 161916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static class CallbackHandler extends Handler { 16207a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim private final WeakReference<MediaBrowserServiceCallbackImpl> mCallbackImplRef; 162116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private WeakReference<Messenger> mCallbacksMessengerRef; 162216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 162316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim CallbackHandler(MediaBrowserServiceCallbackImpl callbackImpl) { 162416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim super(); 16257a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mCallbackImplRef = new WeakReference<>(callbackImpl); 162616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 162716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 162816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 162916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void handleMessage(Message msg) { 16307a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim if (mCallbacksMessengerRef == null || mCallbacksMessengerRef.get() == null || 16317a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mCallbackImplRef.get() == null) { 163216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 163316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 163416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = msg.getData(); 163516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.setClassLoader(MediaSessionCompat.class.getClassLoader()); 163616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim switch (msg.what) { 163716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case SERVICE_MSG_ON_CONNECT: 16387a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mCallbackImplRef.get().onServiceConnected(mCallbacksMessengerRef.get(), 163916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getString(DATA_MEDIA_ITEM_ID), 164016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim (MediaSessionCompat.Token) data.getParcelable(DATA_MEDIA_SESSION_TOKEN), 164116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getBundle(DATA_ROOT_HINTS)); 164216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim break; 164316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case SERVICE_MSG_ON_CONNECT_FAILED: 16447a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mCallbackImplRef.get().onConnectionFailed(mCallbacksMessengerRef.get()); 164516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim break; 164616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case SERVICE_MSG_ON_LOAD_CHILDREN: 16477a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim mCallbackImplRef.get().onLoadChildren(mCallbacksMessengerRef.get(), 164816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getString(DATA_MEDIA_ITEM_ID), 164916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getParcelableArrayList(DATA_MEDIA_ITEM_LIST), 165016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getBundle(DATA_OPTIONS)); 165116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim break; 165216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim default: 165316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.w(TAG, "Unhandled message: " + msg 165416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim + "\n Client version: " + CLIENT_VERSION_CURRENT 165516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim + "\n Service version: " + msg.arg1); 165616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 165716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 165816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 165916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void setCallbacksMessenger(Messenger callbacksMessenger) { 166016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacksMessengerRef = new WeakReference<>(callbacksMessenger); 166116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 166216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 166316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 166416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static class ServiceBinderWrapper { 166516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private Messenger mMessenger; 1666fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim private Bundle mRootHints; 166716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 1668fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim public ServiceBinderWrapper(IBinder target, Bundle rootHints) { 166916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mMessenger = new Messenger(target); 1670fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim mRootHints = rootHints; 167116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 167216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 1673fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim void connect(Context context, Messenger callbacksMessenger) 167416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throws RemoteException { 167516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = new Bundle(); 167616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putString(DATA_PACKAGE_NAME, context.getPackageName()); 1677fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim data.putBundle(DATA_ROOT_HINTS, mRootHints); 167816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_CONNECT, data, callbacksMessenger); 167916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 168016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 168116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void disconnect(Messenger callbacksMessenger) throws RemoteException { 168216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_DISCONNECT, null, callbacksMessenger); 168316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 168416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 16857a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim void addSubscription(String parentId, IBinder callbackToken, Bundle options, 16867a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim Messenger callbacksMessenger) 168716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throws RemoteException { 168816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = new Bundle(); 168916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putString(DATA_MEDIA_ITEM_ID, parentId); 16907a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim BundleCompat.putBinder(data, DATA_CALLBACK_TOKEN, callbackToken); 169116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putBundle(DATA_OPTIONS, options); 169216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_ADD_SUBSCRIPTION, data, callbacksMessenger); 169316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 169416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 16957a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim void removeSubscription(String parentId, IBinder callbackToken, 16967a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim Messenger callbacksMessenger) 169716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throws RemoteException { 169816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = new Bundle(); 169916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putString(DATA_MEDIA_ITEM_ID, parentId); 17007a7ac26ee6d9ff4f5410991fa9cc97d0090ddaefSungsoo Lim BundleCompat.putBinder(data, DATA_CALLBACK_TOKEN, callbackToken); 170116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_REMOVE_SUBSCRIPTION, data, callbacksMessenger); 170216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 170316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 1704fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim void getMediaItem(String mediaId, ResultReceiver receiver, Messenger callbacksMessenger) 1705fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim throws RemoteException { 170616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = new Bundle(); 170716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putString(DATA_MEDIA_ITEM_ID, mediaId); 170816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putParcelable(DATA_RESULT_RECEIVER, receiver); 1709fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim sendRequest(CLIENT_MSG_GET_MEDIA_ITEM, data, callbacksMessenger); 171016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 171116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 171216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void registerCallbackMessenger(Messenger callbackMessenger) throws RemoteException { 1713fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim Bundle data = new Bundle(); 1714fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim data.putBundle(DATA_ROOT_HINTS, mRootHints); 1715fda621da7916073852394d14fcd2cb37f202287dSungsoo Lim sendRequest(CLIENT_MSG_REGISTER_CALLBACK_MESSENGER, data, callbackMessenger); 171616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 171716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 171899f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim void unregisterCallbackMessenger(Messenger callbackMessenger) throws RemoteException { 171999f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim sendRequest(CLIENT_MSG_UNREGISTER_CALLBACK_MESSENGER, null, callbackMessenger); 172099f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim } 172199f783676dda9a66b2f1a576c12ee2402d8bbcd0Sungsoo Lim 172216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private void sendRequest(int what, Bundle data, Messenger cbMessenger) 172316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throws RemoteException { 172416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Message msg = Message.obtain(); 172516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim msg.what = what; 172616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim msg.arg1 = CLIENT_VERSION_CURRENT; 172716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim msg.setData(data); 172816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim msg.replyTo = cbMessenger; 172916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mMessenger.send(msg); 173016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 173116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 173216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 173316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static class ItemReceiver extends ResultReceiver { 1734d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim private final String mMediaId; 1735d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim private final ItemCallback mCallback; 1736d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim 1737d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim ItemReceiver(String mediaId, ItemCallback callback, Handler handler) { 1738d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim super(handler); 1739d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mMediaId = mediaId; 1740d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mCallback = callback; 1741d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1742d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim 1743d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim @Override 1744d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim protected void onReceiveResult(int resultCode, Bundle resultData) { 1745d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim resultData.setClassLoader(MediaBrowserCompat.class.getClassLoader()); 1746d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim if (resultCode != 0 || resultData == null 1747d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim || !resultData.containsKey(MediaBrowserServiceCompat.KEY_MEDIA_ITEM)) { 1748d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mCallback.onError(mMediaId); 1749d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim return; 1750d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1751d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim Parcelable item = resultData.getParcelable(MediaBrowserServiceCompat.KEY_MEDIA_ITEM); 1752d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim if (item instanceof MediaItem) { 1753d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mCallback.onItemLoaded((MediaItem) item); 1754d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } else { 1755d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mCallback.onError(mMediaId); 1756d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1757d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1758d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1759e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo} 1760