MediaBrowserCompat.java revision 26e88318c8f69f62f41591b0df0720cc48b4ce11
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; 22e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.Bundle; 23e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.Handler; 24e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.IBinder; 253f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Limimport android.os.Message; 263f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Limimport android.os.Messenger; 27e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.Parcel; 28e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.Parcelable; 29e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.os.RemoteException; 30e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.annotation.IntDef; 31e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.annotation.NonNull; 32e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.annotation.Nullable; 3382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Limimport android.support.v4.app.BundleCompat; 342490f437a4111d64520f891b2c81685f8fae323cJae Seoimport android.support.v4.media.session.MediaControllerCompat; 35e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.v4.media.session.MediaSessionCompat; 36e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.v4.os.ResultReceiver; 37e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.support.v4.util.ArrayMap; 38e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.text.TextUtils; 39e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport android.util.Log; 40e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 41e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport java.lang.annotation.Retention; 42e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport java.lang.annotation.RetentionPolicy; 4316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Limimport java.lang.ref.WeakReference; 446b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Limimport java.util.ArrayList; 45e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seoimport java.util.List; 4682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Limimport java.util.Map; 47e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 4882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Limimport static android.support.v4.media.MediaBrowserProtocol.*; 4982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 50e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo/** 51096f2531cb790bc1106377d2da344614a3b88d39Jae Seo * Browses media content offered by a {@link MediaBrowserServiceCompat}. 52e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 53e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * This object is not thread-safe. All calls should happen on the thread on which the browser 54e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * was constructed. 55e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 56e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 57096f2531cb790bc1106377d2da344614a3b88d39Jae Seopublic final class MediaBrowserCompat { 5882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim private static final String TAG = "MediaBrowserCompat"; 593f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim 6082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 6182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Used as an int extra field to denote the page number to subscribe. 6282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * The value of {@code EXTRA_PAGE} should be greater than or equal to 1. 6382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 6482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @see android.service.media.MediaBrowserService.BrowserRoot 6582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @see #EXTRA_PAGE_SIZE 6682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * {@hide} 6782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 6882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public static final String EXTRA_PAGE = "android.media.browse.extra.PAGE"; 6982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 7082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 7182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Used as an int extra field to denote the number of media items in a page. 7282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * The value of {@code EXTRA_PAGE_SIZE} should be greater than or equal to 1. 7382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 7482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @see android.service.media.MediaBrowserService.BrowserRoot 7582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @see #EXTRA_PAGE 7682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * {@hide} 7782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 7882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public static final String EXTRA_PAGE_SIZE = "android.media.browse.extra.PAGE_SIZE"; 7982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 806b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim private final MediaBrowserImpl mImpl; 81e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 82e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 83e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Creates a media browser for the specified media browse service. 84e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 85e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param context The context. 86e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param serviceComponent The component name of the media browse service. 87e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param callback The connection callback. 88e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param rootHints An optional bundle of service-specific arguments to send 89e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * to the media browse service when connecting and retrieving the root id 9082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * for browsing, or null if none. The contents of this bundle may affect 91e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * the information returned when browsing. 9226e88318c8f69f62f41591b0df0720cc48b4ce11Jae Seo * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_RECENT 9326e88318c8f69f62f41591b0df0720cc48b4ce11Jae Seo * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_OFFLINE 9426e88318c8f69f62f41591b0df0720cc48b4ce11Jae Seo * @see MediaBrowserServiceCompat.BrowserRoot#EXTRA_SUGGESTED 95e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 96096f2531cb790bc1106377d2da344614a3b88d39Jae Seo public MediaBrowserCompat(Context context, ComponentName serviceComponent, 97e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo ConnectionCallback callback, Bundle rootHints) { 9865fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes if (android.os.Build.VERSION.SDK_INT >= 23) { 9982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mImpl = new MediaBrowserImplApi23(context, serviceComponent, callback, rootHints); 10065fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes } else if (android.os.Build.VERSION.SDK_INT >= 21) { 1016b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim mImpl = new MediaBrowserImplApi21(context, serviceComponent, callback, rootHints); 1026b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } else { 10316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mImpl = new MediaBrowserServiceImplBase(context, serviceComponent, callback, rootHints); 1046b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 105e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 106e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 107e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 108e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Connects to the media browse service. 109e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 110e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * The connection callback specified in the constructor will be invoked 111e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * when the connection completes or fails. 112e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 113e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 114e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void connect() { 115e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mImpl.connect(); 116e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 117e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 118e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 119e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Disconnects from the media browse service. 120e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * After this, no more callbacks will be received. 121e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 122e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void disconnect() { 123e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mImpl.disconnect(); 124e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 125e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 126e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 127e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns whether the browser is connected to the service. 128e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 129e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public boolean isConnected() { 130e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.isConnected(); 131e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 132e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 133e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 134e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets the service component that the media browser is connected to. 135e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 136e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull 137e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo ComponentName getServiceComponent() { 138e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.getServiceComponent(); 139e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 140e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 141e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 142e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets the root id. 143e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 144e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Note that the root id may become invalid or change when when the 145e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * browser is disconnected. 146e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 147e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 148e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @throws IllegalStateException if not connected. 149e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 150e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull String getRoot() { 151e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.getRoot(); 152e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 153e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 154e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 155e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets any extras for the media service. 156e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 157e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @throws IllegalStateException if not connected. 158e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 159e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @Nullable 160e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo Bundle getExtras() { 161e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.getExtras(); 162e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 163e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 164e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 165e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets the media session token associated with the media browser. 166e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 167e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Note that the session token may become invalid or change when when the 168e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * browser is disconnected. 169e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 170e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 171e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @return The session token for the browser, never null. 172e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 173e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @throws IllegalStateException if not connected. 174e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 175e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull MediaSessionCompat.Token getSessionToken() { 176e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mImpl.getSessionToken(); 177e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 178e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 179e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 180e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Queries for information about the media items that are contained within 181e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * the specified id and subscribes to receive updates when they change. 182e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 183e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * The list of subscriptions is maintained even when not connected and is 18482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * restored after the reconnection. It is ok to subscribe while not connected 185e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * but the results will not be returned until the connection completes. 186e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 187e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 188e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * If the id is already subscribed with a different callback then the new 189e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * callback will replace the previous one and the child data will be 190e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * reloaded. 191e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 192e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 193e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param parentId The id of the parent media item whose list of children 194e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * will be subscribed. 195e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param callback The callback to receive the list of children. 196e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 197e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void subscribe(@NonNull String parentId, @NonNull SubscriptionCallback callback) { 19882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mImpl.subscribe(parentId, null, callback); 19982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 20082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 20182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 20282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Queries with service-specific arguments for information about the media items 20382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * that are contained within the specified id and subscribes to receive updates 20482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * when they change. 20582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * <p> 20682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * The list of subscriptions is maintained even when not connected and is 20782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * restored after the reconnection. It is ok to subscribe while not connected 20882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * but the results will not be returned until the connection completes. 20982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * </p> 21082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * <p> 21182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * If the id is already subscribed with a different callback then the new 21282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * callback will replace the previous one and the child data will be 21382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * reloaded. 21482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * </p> 21582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 21682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param parentId The id of the parent media item whose list of children 21782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * will be subscribed. 21882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param options A bundle of service-specific arguments to send to the media 21982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * browse service. The contents of this bundle may affect the 22082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * information returned when browsing. 22182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param callback The callback to receive the list of children. 22282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * {@hide} 22382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 22482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void subscribe(@NonNull String parentId, @NonNull Bundle options, 22582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim @NonNull SubscriptionCallback callback) { 22682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (options == null) { 22782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim throw new IllegalArgumentException("options are null"); 22882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 22982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mImpl.subscribe(parentId, options, callback); 230e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 231e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 232e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 233e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Unsubscribes for changes to the children of the specified media id. 234e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 235e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * The query callback will no longer be invoked for results associated with 236e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * this id once this method returns. 237e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 238e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 239e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param parentId The id of the parent media item whose list of children 24082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * will be unsubscribed. 241e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 242e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void unsubscribe(@NonNull String parentId) { 24382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mImpl.unsubscribe(parentId, null); 24482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 24582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 24682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 24782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Unsubscribes for changes to the children of the specified media id. 24882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * <p> 24982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * The query callback will no longer be invoked for results associated with 25082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * this id once this method returns. 25182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * </p> 25282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 25382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param parentId The id of the parent media item whose list of children 25482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * will be unsubscribed. 25582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param options A bundle sent to the media browse service to subscribe. 25682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * {@hide} 25782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 25882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void unsubscribe(@NonNull String parentId, @NonNull Bundle options) { 25982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (options == null) { 26082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim throw new IllegalArgumentException("options are null"); 26182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 26282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mImpl.unsubscribe(parentId, options); 263e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 264e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 265e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 266e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Retrieves a specific {@link MediaItem} from the connected service. Not 267e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * all services may support this, so falling back to subscribing to the 268e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * parent's id should be used when unavailable. 269e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 270e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param mediaId The id of the item to retrieve. 271e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param cb The callback to receive the result on. 272e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 273e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb) { 274e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mImpl.getItem(mediaId, cb); 275e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 276e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 27723471681e408dfe4e44975e13e7575ab5a04bc8cJae Seo /** 27823471681e408dfe4e44975e13e7575ab5a04bc8cJae Seo * A class with information on a single media item for use in browsing media. 27923471681e408dfe4e44975e13e7575ab5a04bc8cJae Seo */ 280e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static class MediaItem implements Parcelable { 281e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo private final int mFlags; 282e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo private final MediaDescriptionCompat mDescription; 283e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 284e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** @hide */ 285e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Retention(RetentionPolicy.SOURCE) 286e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @IntDef(flag=true, value = { FLAG_BROWSABLE, FLAG_PLAYABLE }) 287e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @interface Flags { } 288e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 289e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 290e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Flag: Indicates that the item has children of its own. 291e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 292e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static final int FLAG_BROWSABLE = 1 << 0; 293e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 294e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 295e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Flag: Indicates that the item is playable. 296e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 297e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * The id of this item may be passed to 2982490f437a4111d64520f891b2c81685f8fae323cJae Seo * {@link MediaControllerCompat.TransportControls#playFromMediaId(String, Bundle)} 299e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * to start playing it. 300e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 301e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 302e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static final int FLAG_PLAYABLE = 1 << 1; 303e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 304e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 305e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Create a new MediaItem for use in browsing media. 306e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param description The description of the media, which must include a 307e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * media id. 308e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param flags The flags for this item. 309e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 310e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public MediaItem(@NonNull MediaDescriptionCompat description, @Flags int flags) { 311e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo if (description == null) { 312e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo throw new IllegalArgumentException("description cannot be null"); 313e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 314e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo if (TextUtils.isEmpty(description.getMediaId())) { 315e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo throw new IllegalArgumentException("description must have a non-empty media id"); 316e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 317e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mFlags = flags; 318e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mDescription = description; 319e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 320e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 321e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 322e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Private constructor. 323e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 324e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo private MediaItem(Parcel in) { 325e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mFlags = in.readInt(); 326e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mDescription = MediaDescriptionCompat.CREATOR.createFromParcel(in); 327e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 328e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 329e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 330e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public int describeContents() { 331e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return 0; 332e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 333e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 334e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 335e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void writeToParcel(Parcel out, int flags) { 336e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo out.writeInt(mFlags); 337e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mDescription.writeToParcel(out, flags); 338e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 339e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 340e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 341e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public String toString() { 342e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo final StringBuilder sb = new StringBuilder("MediaItem{"); 343e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo sb.append("mFlags=").append(mFlags); 344e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo sb.append(", mDescription=").append(mDescription); 345e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo sb.append('}'); 346e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return sb.toString(); 347e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 348e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 349e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static final Parcelable.Creator<MediaItem> CREATOR = 350e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo new Parcelable.Creator<MediaItem>() { 351e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 352e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public MediaItem createFromParcel(Parcel in) { 353e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return new MediaItem(in); 354e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 355e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 356e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo @Override 357e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public MediaItem[] newArray(int size) { 358e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return new MediaItem[size]; 359e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 360e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo }; 361e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 362e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 363e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Gets the flags of the item. 364e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 365e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @Flags int getFlags() { 366e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return mFlags; 367e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 368e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 369e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 370e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns whether this item is browsable. 371e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @see #FLAG_BROWSABLE 372e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 373e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public boolean isBrowsable() { 374e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return (mFlags & FLAG_BROWSABLE) != 0; 375e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 376e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 377e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 378e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns whether this item is playable. 379e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @see #FLAG_PLAYABLE 380e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 381e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public boolean isPlayable() { 382e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return (mFlags & FLAG_PLAYABLE) != 0; 383e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 384e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 385e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 386e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns the description of the media. 387e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 388e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull MediaDescriptionCompat getDescription() { 389e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return mDescription; 390e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 391e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 392e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 393e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Returns the media id for this item. 394e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 395e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public @NonNull String getMediaId() { 396e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return mDescription.getMediaId(); 397e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 398e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 399e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 400e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 401e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Callbacks for connection related events. 402e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 403e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static class ConnectionCallback { 4046b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim final Object mConnectionCallbackObj; 40516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private ConnectionCallbackInternal mConnectionCallbackInternal; 4066b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 4076b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public ConnectionCallback() { 40865fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes if (android.os.Build.VERSION.SDK_INT >= 21) { 4096b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim mConnectionCallbackObj = 4106b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim MediaBrowserCompatApi21.createConnectionCallback(new StubApi21()); 4116b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } else { 4126b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim mConnectionCallbackObj = null; 4136b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4146b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4156b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 416e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 417096f2531cb790bc1106377d2da344614a3b88d39Jae Seo * Invoked after {@link MediaBrowserCompat#connect()} when the request has successfully 418096f2531cb790bc1106377d2da344614a3b88d39Jae Seo * completed. 419e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 420e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onConnected() { 421e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 422e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 423e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 424e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Invoked when the client is disconnected from the media browser. 425e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 426e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onConnectionSuspended() { 427e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 428e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 429e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 430e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Invoked when the connection to the media browser failed. 431e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 432e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onConnectionFailed() { 433e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 4346b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 43516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void setInternalConnectionCallback(ConnectionCallbackInternal connectionCallbackInternal) { 43616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mConnectionCallbackInternal = connectionCallbackInternal; 43716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 43816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 43916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim interface ConnectionCallbackInternal { 44016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onConnected(); 44116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onConnectionSuspended(); 44216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onConnectionFailed(); 44316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4446b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 4456b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim private class StubApi21 implements MediaBrowserCompatApi21.ConnectionCallback { 4466b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 4476b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void onConnected() { 44816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mConnectionCallbackInternal != null) { 44916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mConnectionCallbackInternal.onConnected(); 45016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4516b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ConnectionCallback.this.onConnected(); 4526b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4536b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 4546b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 4556b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void onConnectionSuspended() { 45616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mConnectionCallbackInternal != null) { 45716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mConnectionCallbackInternal.onConnectionSuspended(); 45816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4596b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ConnectionCallback.this.onConnectionSuspended(); 4606b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4616b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 4626b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 4636b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void onConnectionFailed() { 46416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mConnectionCallbackInternal != null) { 46516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mConnectionCallbackInternal.onConnectionFailed(); 46616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4676b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ConnectionCallback.this.onConnectionFailed(); 4686b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 4696b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 470e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 471e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 472e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 473e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Callbacks for subscription related events. 474e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 475e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static abstract class SubscriptionCallback { 47616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim /** 47716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * Called when the list of children is loaded or updated. 47816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * 47916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param parentId The media id of the parent media item. 48016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param children The children which were loaded, or null if the id is invalid. 48116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim */ 48216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children) { 48316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 4846b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 48516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim /** 48616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * Called when the list of children is loaded or updated. 48716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * 48816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param parentId The media id of the parent media item. 48916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param children The children which were loaded, or null if the id is invalid. 49016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param options A bundle of service-specific arguments to send to the media 49116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * browse service. The contents of this bundle may affect the 49216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * information returned when browsing. 49316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * {@hide} 49416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim */ 49516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children, 49616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @NonNull Bundle options) { 49716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 49816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 49916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim /** 50016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * Called when the id doesn't exist or other errors in subscribing. 50116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * <p> 50216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} 50316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * called, because some errors may heal themselves. 50416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * </p> 50516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * 50616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param parentId The media id of the parent media item whose children could not be loaded. 50716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim */ 50816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onError(@NonNull String parentId) { 50916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 51016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 51116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim /** 51216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * Called when the id doesn't exist or other errors in subscribing. 51316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * <p> 51416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} 51516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * called, because some errors may heal themselves. 51616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * </p> 51716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * 51816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param parentId The media id of the parent media item whose children could 51916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * not be loaded. 52016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param options A bundle of service-specific arguments sent to the media 52116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * browse service. 52216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * {@hide} 52316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim */ 52416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onError(@NonNull String parentId, @NonNull Bundle options) { 52516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 52616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 52716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 52816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim /** 52916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * Callbacks for subscription related events. 53016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim */ 531c0a233f1980faedbb9ff82334814a0d8cbe6148bChris Banes static class SubscriptionCallbackApi21 extends SubscriptionCallback { 53216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim SubscriptionCallback mSubscriptionCallback; 53316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final Object mSubscriptionCallbackObj; 53416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private Bundle mOptions; 53516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 53616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public SubscriptionCallbackApi21(SubscriptionCallback callback, Bundle options) { 53716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptionCallback = callback; 53816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mOptions = options; 53965fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes mSubscriptionCallbackObj = 54065fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes MediaBrowserCompatApi21.createSubscriptionCallback(new StubApi21()); 5416b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 5426b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 543e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 544e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Called when the list of children is loaded or updated. 545e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 546e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param parentId The media id of the parent media item. 547ae6d147640b8a868d2edff8ebac8d2a6bb03c594Sungsoo Lim * @param children The children which were loaded, or null if the id is invalid. 548e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 549ae6d147640b8a868d2edff8ebac8d2a6bb03c594Sungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children) { 55016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptionCallback.onChildrenLoaded(parentId, children); 551e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 552e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 553e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 55482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Called when the list of children is loaded or updated. 55582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 55682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param parentId The media id of the parent media item. 55782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param children The children which were loaded, or null if the id is invalid. 55882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param options A bundle of service-specific arguments to send to the media 55982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * browse service. The contents of this bundle may affect the 56082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * information returned when browsing. 56182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * {@hide} 56282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 56382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<MediaItem> children, 56482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim @NonNull Bundle options) { 56516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptionCallback.onChildrenLoaded(parentId, children, options); 56682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 56782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 56882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 569e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Called when the id doesn't exist or other errors in subscribing. 570e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * <p> 571096f2531cb790bc1106377d2da344614a3b88d39Jae Seo * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} 572e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * called, because some errors may heal themselves. 573e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * </p> 574e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 57516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * @param parentId The media id of the parent media item whose children could not be loaded. 576e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 577e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onError(@NonNull String parentId) { 57816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptionCallback.onError(parentId); 579e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 5806b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 58182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim /** 58282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Called when the id doesn't exist or other errors in subscribing. 58382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * <p> 58482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * If this is called, the subscription remains until {@link MediaBrowserCompat#unsubscribe} 58582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * called, because some errors may heal themselves. 58682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * </p> 58782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * 58882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param parentId The media id of the parent media item whose children could 58982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * not be loaded. 59082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * @param options A bundle of service-specific arguments sent to the media 59182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * browse service. 59282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * {@hide} 59382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim */ 59482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void onError(@NonNull String parentId, @NonNull Bundle options) { 59516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptionCallback.onError(parentId, options); 59682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 59782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 5986b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim private class StubApi21 implements MediaBrowserCompatApi21.SubscriptionCallback { 5996b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 60082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void onChildrenLoaded(@NonNull String parentId, List<Parcel> children) { 60165fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes List<MediaBrowserCompat.MediaItem> mediaItems = null; 60265fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes if (children != null) { 60365fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes mediaItems = new ArrayList<>(); 60465fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes for (Parcel parcel : children) { 60565fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes parcel.setDataPosition(0); 60665fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes mediaItems.add( 60765fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes MediaBrowserCompat.MediaItem.CREATOR.createFromParcel(parcel)); 60865fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes parcel.recycle(); 60965fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes } 61065fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes } 61116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mOptions != null) { 61216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim SubscriptionCallbackApi21.this.onChildrenLoaded(parentId, 61316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim MediaBrowserCompatUtils.applyOptions(mediaItems, mOptions), 61416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mOptions); 61516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } else { 61616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim SubscriptionCallbackApi21.this.onChildrenLoaded(parentId, mediaItems); 61716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 6186b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 6196b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 6206b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 6216b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void onError(@NonNull String parentId) { 62216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mOptions != null) { 62316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim SubscriptionCallbackApi21.this.onError(parentId, mOptions); 62416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } else { 62516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim SubscriptionCallbackApi21.this.onError(parentId); 62616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 6276b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 6286b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 629e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 630e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 631e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 632e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Callback for receiving the result of {@link #getItem}. 633e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 634e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public static abstract class ItemCallback { 63582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim final Object mItemCallbackObj; 63682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 63782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public ItemCallback() { 63865fa61412f46d6cddca410aeb07a79fd081536c0Chris Banes if (android.os.Build.VERSION.SDK_INT >= 23) { 63982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mItemCallbackObj = MediaBrowserCompatApi23.createItemCallback(new StubApi23()); 64082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } else { 64182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mItemCallbackObj = null; 64282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 64382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 64482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 645e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 646e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Called when the item has been returned by the browser service. 647e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 648e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param item The item that was returned or null if it doesn't exist. 649e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 650e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onItemLoaded(MediaItem item) { 651e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 652e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 653e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 654e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * Called when the item doesn't exist or there was an error retrieving it. 655e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * 656e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo * @param itemId The media id of the media item which could not be loaded. 657e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 658e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo public void onError(@NonNull String itemId) { 659e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 66082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 66182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim private class StubApi23 implements MediaBrowserCompatApi23.ItemCallback { 66282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 66382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void onItemLoaded(Parcel itemParcel) { 66482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim itemParcel.setDataPosition(0); 66582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim MediaItem item = MediaBrowserCompat.MediaItem.CREATOR.createFromParcel(itemParcel); 66682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim itemParcel.recycle(); 66782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim ItemCallback.this.onItemLoaded(item); 66882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 66982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 67082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 67182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void onError(@NonNull String itemId) { 67282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim ItemCallback.this.onError(itemId); 67382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 67482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 675e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 676e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 6776b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim interface MediaBrowserImpl { 6786b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim void connect(); 6796b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim void disconnect(); 6806b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim boolean isConnected(); 6816b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ComponentName getServiceComponent(); 6826b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @NonNull String getRoot(); 6836b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Nullable Bundle getExtras(); 6846b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @NonNull MediaSessionCompat.Token getSessionToken(); 68582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim void subscribe(@NonNull String parentId, Bundle options, 68682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim @NonNull SubscriptionCallback callback); 68782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim void unsubscribe(@NonNull String parentId, Bundle options); 6886b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim void getItem(final @NonNull String mediaId, @NonNull final ItemCallback cb); 6896b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 6906b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 69116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim interface MediaBrowserServiceCallbackImpl { 69216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onServiceConnected(Messenger callback, String root, MediaSessionCompat.Token session, 69316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle extra); 69416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onConnectionFailed(Messenger callback); 69516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void onLoadChildren(Messenger callback, String parentId, List list, Bundle options); 69616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 69716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 69816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim static class MediaBrowserServiceImplBase 69916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim implements MediaBrowserImpl, MediaBrowserServiceCallbackImpl { 700e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final boolean DBG = false; 701e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 702e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final int CONNECT_STATE_DISCONNECTED = 0; 703e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final int CONNECT_STATE_CONNECTING = 1; 704e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final int CONNECT_STATE_CONNECTED = 2; 705e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private static final int CONNECT_STATE_SUSPENDED = 3; 706e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 707e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private final Context mContext; 708e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private final ComponentName mServiceComponent; 709e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private final ConnectionCallback mCallback; 710e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private final Bundle mRootHints; 71116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final CallbackHandler mHandler = new CallbackHandler(this); 71282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim private final ArrayMap<String, Subscription> mSubscriptions = new ArrayMap<>(); 713e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 714e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private int mState = CONNECT_STATE_DISCONNECTED; 715e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private MediaServiceConnection mServiceConnection; 7163f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim private ServiceBinderWrapper mServiceBinderWrapper; 7173f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim private Messenger mCallbacksMessenger; 718e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private String mRootId; 719e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private MediaSessionCompat.Token mMediaSessionToken; 720e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private Bundle mExtras; 721e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 72216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public MediaBrowserServiceImplBase(Context context, ComponentName serviceComponent, 723e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake ConnectionCallback callback, Bundle rootHints) { 724e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (context == null) { 725e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("context must not be null"); 726e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 727e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (serviceComponent == null) { 728e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("service component must not be null"); 729e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 730e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (callback == null) { 731e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("connection callback must not be null"); 732e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 733e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mContext = context; 734e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mServiceComponent = serviceComponent; 735e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mCallback = callback; 736e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mRootHints = rootHints; 737e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 738e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 739e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void connect() { 740e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mState != CONNECT_STATE_DISCONNECTED) { 741e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalStateException("connect() called while not disconnected (state=" 742e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + getStateLabel(mState) + ")"); 743e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 744e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // TODO: remove this extra check. 745e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (DBG) { 746e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mServiceConnection != null) { 747e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new RuntimeException("mServiceConnection should be null. Instead it is " 748e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + mServiceConnection); 749e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 750e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 7513f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mServiceBinderWrapper != null) { 7523f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim throw new RuntimeException("mServiceBinderWrapper should be null. Instead it is " 7533f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + mServiceBinderWrapper); 754e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 7553f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mCallbacksMessenger != null) { 7563f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim throw new RuntimeException("mCallbacksMessenger should be null. Instead it is " 7573f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + mCallbacksMessenger); 758e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 759e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 760e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo mState = CONNECT_STATE_CONNECTING; 761e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 762e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake final Intent intent = new Intent(MediaBrowserServiceCompat.SERVICE_INTERFACE); 763e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake intent.setComponent(mServiceComponent); 764e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 765e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake final ServiceConnection thisConnection = mServiceConnection = 766e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake new MediaServiceConnection(); 767e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 768e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake boolean bound = false; 769e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo try { 770e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); 771e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } catch (Exception ex) { 772e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.e(TAG, "Failed binding to service " + mServiceComponent); 773e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 774e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 775e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!bound) { 77682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // Tell them that it didn't work. We are already on the main thread, 77782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // but we don't want to do callbacks inside of connect(). So post it, 77882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // and then check that we are on the same ServiceConnection. We know 779e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // we won't also get an onServiceConnected or onServiceDisconnected, 780e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // so we won't be doing double callbacks. 781e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mHandler.post(new Runnable() { 782e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 783e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void run() { 784e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Ensure that nobody else came in or tried to connect again. 785e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (thisConnection == mServiceConnection) { 786e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake forceCloseConnection(); 787e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mCallback.onConnectionFailed(); 788e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 789e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 790e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake }); 791e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 792e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 793e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo if (DBG) { 794e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, "connect..."); 795e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo dump(); 796e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 797e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 798e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 799e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void disconnect() { 800e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // It's ok to call this any state, because allowing this lets apps not have 80182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // to check isConnected() unnecessarily. They won't appreciate the extra 80282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // assertions for this. We do everything we can here to go back to a sane state. 8033f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mCallbacksMessenger != null) { 804e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake try { 80516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.disconnect(mCallbacksMessenger); 806e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } catch (RemoteException ex) { 80782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // We are disconnecting anyway. Log, just for posterity but it's not 808e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // a big problem. 809e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.w(TAG, "RemoteException during connect for " + mServiceComponent); 810e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 811e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 812e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake forceCloseConnection(); 813e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 814e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (DBG) { 815e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, "disconnect..."); 816e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake dump(); 817e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 818e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 819e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 820e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake /** 82182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Null out the variables and unbind from the service. This doesn't include 822e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * calling disconnect on the service, because we only try to do that in the 823e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * clean shutdown cases. 824e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * <p> 825e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * Everywhere that calls this EXCEPT for disconnect() should follow it with 82682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * a call to mCallback.onConnectionFailed(). Disconnect doesn't do that callback 827e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * for a clean shutdown, but everywhere else is a dirty shutdown and should 828e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * notify the app. 829e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake */ 830e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private void forceCloseConnection() { 831e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mServiceConnection != null) { 832e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mContext.unbindService(mServiceConnection); 833e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 834e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mState = CONNECT_STATE_DISCONNECTED; 835e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mServiceConnection = null; 8363f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mServiceBinderWrapper = null; 8373f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mCallbacksMessenger = null; 838e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mRootId = null; 839e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mMediaSessionToken = null; 840e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 841e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 842e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public boolean isConnected() { 843e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mState == CONNECT_STATE_CONNECTED; 844e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 845e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 846e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public @NonNull 847e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake ComponentName getServiceComponent() { 848e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!isConnected()) { 849e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalStateException("getServiceComponent() called while not connected" + 850e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake " (state=" + mState + ")"); 851e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 852e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mServiceComponent; 853e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 854e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 855e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public @NonNull String getRoot() { 856e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!isConnected()) { 857dfed7fbde83fb36b1993582317a27c5247af958cDongwon Kang throw new IllegalStateException("getRoot() called while not connected" 858e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + "(state=" + getStateLabel(mState) + ")"); 859e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 860e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mRootId; 861e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 862e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 863e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public @Nullable 864e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Bundle getExtras() { 865e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!isConnected()) { 866e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalStateException("getExtras() called while not connected (state=" 867e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + getStateLabel(mState) + ")"); 868e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 869e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mExtras; 870e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 871e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 872e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public @NonNull MediaSessionCompat.Token getSessionToken() { 873e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (!isConnected()) { 874e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalStateException("getSessionToken() called while not connected" 875e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + "(state=" + mState + ")"); 876e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 877e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return mMediaSessionToken; 878e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 879e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 88082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void subscribe(@NonNull String parentId, Bundle options, 88182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim @NonNull SubscriptionCallback callback) { 882e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Check arguments. 88382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (TextUtils.isEmpty(parentId)) { 88482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim throw new IllegalArgumentException("parentId is empty."); 885e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 886e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (callback == null) { 887e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("callback is null"); 888e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 889e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Update or create the subscription. 890e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Subscription sub = mSubscriptions.get(parentId); 89182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (sub == null) { 89282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim sub = new Subscription(); 893e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mSubscriptions.put(parentId, sub); 894e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 89516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sub.setCallbackForOptions(callback, options); 896e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 89782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // If we are connected, tell the service that we are watching. If we aren't 898e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // connected, the service will be told when we connect. 899e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mState == CONNECT_STATE_CONNECTED) { 900e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake try { 90116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.addSubscription(parentId, options, mCallbacksMessenger); 90216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } catch (RemoteException e) { 90382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 904e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // automatically reregister. So nothing to do here. 905e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, "addSubscription failed with RemoteException parentId=" + parentId); 906e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 907e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 908e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 909e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 91082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void unsubscribe(@NonNull String parentId, Bundle options) { 911e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Check arguments. 912e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (TextUtils.isEmpty(parentId)) { 913e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("parentId is empty."); 914e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 915e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 916e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Remove from our list. 91782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim Subscription sub = mSubscriptions.get(parentId); 918e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 919e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Tell the service if necessary. 92082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (sub != null && sub.remove(options) && mState == CONNECT_STATE_CONNECTED) { 921e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake try { 92216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.removeSubscription( 92316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim parentId, options, 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, "removeSubscription failed with RemoteException parentId=" 928e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake + parentId); 929e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 930e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 93182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (sub != null && sub.isEmpty()) { 93282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim mSubscriptions.remove(parentId); 93382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 934e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 935e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 936d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim public void getItem(@NonNull final String mediaId, @NonNull final ItemCallback cb) { 937e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (TextUtils.isEmpty(mediaId)) { 938e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("mediaId is empty."); 939e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 940e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (cb == null) { 941e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake throw new IllegalArgumentException("cb is null."); 942e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 943e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mState != CONNECT_STATE_CONNECTED) { 944e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.i(TAG, "Not connected, unable to retrieve the MediaItem."); 945e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mHandler.post(new Runnable() { 946e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 947e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void run() { 948e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake cb.onError(mediaId); 949e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 950e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake }); 951e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return; 952e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 953d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim ResultReceiver receiver = new ItemReceiver(mediaId, cb, mHandler); 954e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake try { 9553f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mServiceBinderWrapper.getMediaItem(mediaId, receiver); 956e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } catch (RemoteException e) { 957e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.i(TAG, "Remote error getting media item."); 958e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake mHandler.post(new Runnable() { 959e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 960e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake public void run() { 961e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake cb.onError(mediaId); 962e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 963e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake }); 964e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 965e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 966e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 96716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onServiceConnected(final Messenger callback, final String root, 9683f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim final MediaSessionCompat.Token session, final Bundle extra) { 9693f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Check to make sure there hasn't been a disconnect or a different ServiceConnection. 9703f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (!isCurrent(callback, "onConnect")) { 9713f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim return; 9723f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 9733f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Don't allow them to call us twice. 9743f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mState != CONNECT_STATE_CONNECTING) { 9753f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.w(TAG, "onConnect from service while mState=" + getStateLabel(mState) 9763f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + "... ignoring"); 9773f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim return; 9783f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 9793f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mRootId = root; 9803f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mMediaSessionToken = session; 9813f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mExtras = extra; 9823f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mState = CONNECT_STATE_CONNECTED; 983e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 9843f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (DBG) { 9853f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.d(TAG, "ServiceCallbacks.onConnect..."); 9863f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim dump(); 9873f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 9883f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mCallback.onConnected(); 9893f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim 9903f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // we may receive some subscriptions before we are connected, so re-subscribe 9913f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // everything now 99282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim try { 99382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim for (Map.Entry<String, Subscription> subscriptionEntry 99482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim : mSubscriptions.entrySet()) { 99582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim String id = subscriptionEntry.getKey(); 99682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim Subscription sub = subscriptionEntry.getValue(); 99782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim for (Bundle options : sub.getOptionsList()) { 99816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.addSubscription(id, options, mCallbacksMessenger); 99982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 1000e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 100182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } catch (RemoteException ex) { 100282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 100382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // automatically reregister. So nothing to do here. 100482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim Log.d(TAG, "addSubscription failed with RemoteException."); 10053f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 1006e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1007e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 100816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnectionFailed(final Messenger callback) { 10093f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.e(TAG, "onConnectFailed for " + mServiceComponent); 1010e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10113f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Check to make sure there hasn't been a disconnect or a different ServiceConnection. 10123f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (!isCurrent(callback, "onConnectFailed")) { 10133f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim return; 10143f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 10153f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Don't allow them to call us twice. 10163f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mState != CONNECT_STATE_CONNECTING) { 10173f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.w(TAG, "onConnect from service while mState=" + getStateLabel(mState) 10183f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + "... ignoring"); 10193f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim return; 10203f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim } 1021e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10223f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Clean up 10233f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim forceCloseConnection(); 1024e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 10253f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim // Tell the app. 10263f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim mCallback.onConnectionFailed(); 1027e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1028e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 102916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onLoadChildren(final Messenger callback, final String parentId, 103082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim final List list, final Bundle options) { 103182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim // Check that there hasn't been a disconnect or a different ServiceConnection. 103282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (!isCurrent(callback, "onLoadChildren")) { 103382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim return; 103482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 1035e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 103682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim List<MediaItem> data = list; 10373f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (DBG) { 103882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId); 103982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 1040e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 104182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim // Check that the subscription is still subscribed. 104282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim final Subscription subscription = mSubscriptions.get(parentId); 104382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (subscription == null) { 104482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (DBG) { 104582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim Log.d(TAG, "onLoadChildren for id that isn't subscribed id=" + parentId); 104682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 104782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim return; 104882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 104982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 105082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim // Tell the app. 105182387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim SubscriptionCallback subscriptionCallback = subscription.getCallback(options); 105282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (subscriptionCallback != null) { 105382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim if (options == null) { 105482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim subscriptionCallback.onChildrenLoaded(parentId, data); 105582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } else { 105682387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim subscriptionCallback.onChildrenLoaded(parentId, data, options); 105782387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 105882387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim } 1059e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1060e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1061e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake /** 106216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim * For debugging. 106316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim */ 106416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static String getStateLabel(int state) { 106516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim switch (state) { 106616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case CONNECT_STATE_DISCONNECTED: 106716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "CONNECT_STATE_DISCONNECTED"; 106816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case CONNECT_STATE_CONNECTING: 106916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "CONNECT_STATE_CONNECTING"; 107016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case CONNECT_STATE_CONNECTED: 107116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "CONNECT_STATE_CONNECTED"; 107216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case CONNECT_STATE_SUSPENDED: 107316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "CONNECT_STATE_SUSPENDED"; 107416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim default: 107516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return "UNKNOWN/" + state; 107616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 107716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 107816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 107916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim /** 108082387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Return true if {@code callback} is the current ServiceCallbacks. Also logs if it's not. 1081e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake */ 10823f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim private boolean isCurrent(Messenger callback, String funcName) { 10833f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim if (mCallbacksMessenger != callback) { 1084e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo if (mState != CONNECT_STATE_DISCONNECTED) { 10853f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.i(TAG, funcName + " for " + mServiceComponent + " with mCallbacksMessenger=" 10863f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim + mCallbacksMessenger + " this=" + this); 1087e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1088e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return false; 1089e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1090e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo return true; 1091e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1092e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 1093e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake /** 1094e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * Log internal state. 1095e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * @hide 1096e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake */ 1097e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake void dump() { 1098e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, "MediaBrowserCompat..."); 1099e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mServiceComponent=" + mServiceComponent); 1100e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mCallback=" + mCallback); 1101e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mRootHints=" + mRootHints); 1102e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mState=" + getStateLabel(mState)); 1103e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mServiceConnection=" + mServiceConnection); 11043f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.d(TAG, " mServiceBinderWrapper=" + mServiceBinderWrapper); 11053f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim Log.d(TAG, " mCallbacksMessenger=" + mCallbacksMessenger); 1106e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mRootId=" + mRootId); 1107e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.d(TAG, " mMediaSessionToken=" + mMediaSessionToken); 1108e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1109e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 1110e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo /** 1111e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake * ServiceConnection to the other app. 1112e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo */ 1113e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private class MediaServiceConnection implements ServiceConnection { 1114e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 1115a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim public void onServiceConnected(final ComponentName name, final IBinder binder) { 1116a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim postOrRun(new Runnable() { 1117a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim @Override 1118a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim public void run() { 1119a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (DBG) { 1120a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.d(TAG, "MediaServiceConnection.onServiceConnected name=" + name 1121a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim + " binder=" + binder); 1122a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim dump(); 1123a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 11243f61f1657d13dacf4eb42d9371595b8075cff222Sungsoo Lim 1125a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Make sure we are still the current connection, and that they haven't 1126a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // called disconnect(). 1127a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (!isCurrent("onServiceConnected")) { 1128a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim return; 1129a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1130e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1131a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Save their binder 1132a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mServiceBinderWrapper = new ServiceBinderWrapper(binder); 1133a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim 1134a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // We make a new mServiceCallbacks each time we connect so that we can drop 1135a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // responses from previous connections. 1136a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mCallbacksMessenger = new Messenger(mHandler); 113716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mHandler.setCallbacksMessenger(mCallbacksMessenger); 1138a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim 1139a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mState = CONNECT_STATE_CONNECTING; 1140a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim 1141a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Call connect, which is async. When we get a response from that we will 1142a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // say that we're connected. 1143a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim try { 1144a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (DBG) { 1145a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.d(TAG, "ServiceCallbacks.onConnect..."); 1146a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim dump(); 1147a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 114816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.connect( 114916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mContext, mRootHints, mCallbacksMessenger); 1150a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } catch (RemoteException ex) { 1151a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Connect failed, which isn't good. But the auto-reconnect on the 115282387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // service will take over and we will come back. We will also get the 115382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim // onServiceDisconnected, which has all the cleanup code. So let that 1154a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // do it. 1155a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.w(TAG, "RemoteException during connect for " + mServiceComponent); 1156a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (DBG) { 1157a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.d(TAG, "ServiceCallbacks.onConnect..."); 1158a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim dump(); 1159a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1160a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1161e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1162a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim }); 1163e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1164e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1165e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake @Override 1166a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim public void onServiceDisconnected(final ComponentName name) { 1167a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim postOrRun(new Runnable() { 1168a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim @Override 1169a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim public void run() { 1170a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (DBG) { 1171a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim Log.d(TAG, "MediaServiceConnection.onServiceDisconnected name=" + name 1172a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim + " this=" + this + " mServiceConnection=" + 1173a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mServiceConnection); 1174a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim dump(); 1175a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1176e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1177a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Make sure we are still the current connection, and that they haven't 1178a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // called disconnect(). 1179a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (!isCurrent("onServiceDisconnected")) { 1180a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim return; 1181a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1182e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1183a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // Clear out what we set in onServiceConnected 1184a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mServiceBinderWrapper = null; 1185a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mCallbacksMessenger = null; 118616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mHandler.setCallbacksMessenger(null); 1187e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1188a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim // And tell the app that it's suspended. 1189a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mState = CONNECT_STATE_SUSPENDED; 1190a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mCallback.onConnectionSuspended(); 1191a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1192a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim }); 1193a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1194a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim 1195a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim private void postOrRun(Runnable r) { 1196a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim if (Thread.currentThread() == mHandler.getLooper().getThread()) { 1197a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim r.run(); 1198a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } else { 1199a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim mHandler.post(r); 1200a4b87b4df1dda9f012dad8b50d462d7396a80faaSungsoo Lim } 1201e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1202e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake 1203e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake /** 120482387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim * Return true if this is the current ServiceConnection. Also logs if it's not. 1205e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake */ 1206e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake private boolean isCurrent(String funcName) { 1207e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mServiceConnection != this) { 1208e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake if (mState != CONNECT_STATE_DISCONNECTED) { 1209e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake // Check mState, because otherwise this log is noisy. 1210e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake Log.i(TAG, funcName + " for " + mServiceComponent + 1211e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake " with mServiceConnection=" + mServiceConnection + " this=" + this); 1212e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1213e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return false; 1214e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake } 1215e2447bb2dce5401b3cd473c1d276bc7d58592540Ian Lake return true; 1216e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 1217e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo } 121816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 1219e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo 122016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim static class MediaBrowserImplApi21 implements MediaBrowserImpl, MediaBrowserServiceCallbackImpl, 122116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim ConnectionCallback.ConnectionCallbackInternal { 122216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static final boolean DBG = false; 122382387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 122416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim protected Object mBrowserObj; 122582387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim 122616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final ComponentName mServiceComponent; 122716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final CallbackHandler mHandler = new CallbackHandler(this); 122816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final ArrayMap<String, Subscription> mSubscriptions = new ArrayMap<>(); 12296b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 123016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private ServiceBinderWrapper mServiceBinderWrapper; 123116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private Messenger mCallbacksMessenger; 12326b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12336b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public MediaBrowserImplApi21(Context context, ComponentName serviceComponent, 12346b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim ConnectionCallback callback, Bundle rootHints) { 123516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceComponent = serviceComponent; 123616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim callback.setInternalConnectionCallback(this); 12376b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim mBrowserObj = MediaBrowserCompatApi21.createBrowser(context, serviceComponent, 12386b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim callback.mConnectionCallbackObj, rootHints); 12396b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12406b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12416b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12426b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void connect() { 12436b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim MediaBrowserCompatApi21.connect(mBrowserObj); 12446b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12456b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12466b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12476b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void disconnect() { 12486b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim MediaBrowserCompatApi21.disconnect(mBrowserObj); 12496b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12506b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12516b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12526b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public boolean isConnected() { 12536b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaBrowserCompatApi21.isConnected(mBrowserObj); 12546b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12556b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12566b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12576b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public ComponentName getServiceComponent() { 12586b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaBrowserCompatApi21.getServiceComponent(mBrowserObj); 12596b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12606b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12616b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @NonNull 12626b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12636b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public String getRoot() { 12646b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaBrowserCompatApi21.getRoot(mBrowserObj); 12656b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12666b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12676b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Nullable 12686b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12696b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public Bundle getExtras() { 12706b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaBrowserCompatApi21.getExtras(mBrowserObj); 12716b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12726b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12736b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @NonNull 12746b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 12756b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public MediaSessionCompat.Token getSessionToken() { 12766b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim return MediaSessionCompat.Token.fromToken( 12776b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim MediaBrowserCompatApi21.getSessionToken(mBrowserObj)); 12786b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 12796b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 12806b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 128116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void subscribe(@NonNull final String parentId, final Bundle options, 128216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @NonNull final SubscriptionCallback callback) { 128316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Update or create the subscription. 128416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim SubscriptionCallbackApi21 cb21 = new SubscriptionCallbackApi21(callback, options); 128516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Subscription sub = mSubscriptions.get(parentId); 128616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (sub == null) { 128716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sub = new Subscription(); 128816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptions.put(parentId, sub); 128916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 129016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sub.setCallbackForOptions(cb21, options); 129116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (MediaBrowserCompatApi21.isConnected(mBrowserObj)) { 129216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (options == null || mServiceBinderWrapper == null) { 129316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim MediaBrowserCompatApi21.subscribe( 129416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mBrowserObj, parentId, cb21.mSubscriptionCallbackObj); 129516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } else { 129616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim try { 129716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.addSubscription( 129816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim parentId, options, mCallbacksMessenger); 129916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } catch (RemoteException e) { 130016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 130116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // automatically reregister. So nothing to do here. 130216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.i(TAG, "Remote error subscribing media item: " + parentId); 130316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 130416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 130516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 13066b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13076b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13086b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 130982387d9f1b1ed30028e4c9090ec5fadce7d146f1Sungsoo Lim public void unsubscribe(@NonNull String parentId, Bundle options) { 131016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Check arguments. 131116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (TextUtils.isEmpty(parentId)) { 131216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throw new IllegalArgumentException("parentId is empty."); 131316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 131416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 131516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Remove from our list. 131616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Subscription sub = mSubscriptions.get(parentId); 131716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (sub != null && sub.remove(options)) { 131816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Tell the service if necessary. 131916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (options == null || mServiceBinderWrapper == null) { 132016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mServiceBinderWrapper != null || sub.isEmpty()) { 132116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim MediaBrowserCompatApi21.unsubscribe(mBrowserObj, parentId); 132216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 132316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } else if (mServiceBinderWrapper == null) { 132416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim try { 132516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.removeSubscription( 132616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim parentId, options, mCallbacksMessenger); 132716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } catch (RemoteException e) { 132816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 132916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // automatically reregister. So nothing to do here. 133016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.d(TAG, "removeSubscription failed with RemoteException parentId=" 133116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim + parentId); 133216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 133316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 133416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 133516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (sub != null && sub.isEmpty()) { 133616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mSubscriptions.remove(parentId); 133716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 13386b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 13396b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim 13406b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim @Override 134182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void getItem(@NonNull final String mediaId, @NonNull final ItemCallback cb) { 134282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (TextUtils.isEmpty(mediaId)) { 134382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim throw new IllegalArgumentException("mediaId is empty."); 134482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 134582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (cb == null) { 134682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim throw new IllegalArgumentException("cb is null."); 134782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 134882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim if (!MediaBrowserCompatApi21.isConnected(mBrowserObj)) { 134982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim Log.i(TAG, "Not connected, unable to retrieve the MediaItem."); 135082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mHandler.post(new Runnable() { 135182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 135282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void run() { 135382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim cb.onError(mediaId); 135482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 135582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim }); 135682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim return; 135782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 135816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mServiceBinderWrapper == null) { 135982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mHandler.post(new Runnable() { 136082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 136182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void run() { 136282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim // Default framework implementation. 136382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim cb.onItemLoaded(null); 136482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 136582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim }); 136682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim return; 136782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 1368d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim ResultReceiver receiver = new ItemReceiver(mediaId, cb, mHandler); 136982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim try { 137016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.getMediaItem(mediaId, receiver); 137182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } catch (RemoteException e) { 137216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.i(TAG, "Remote error getting media item: " + mediaId); 137382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim mHandler.post(new Runnable() { 137482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 137582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public void run() { 137682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim cb.onError(mediaId); 137782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 137882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim }); 137982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 138082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 138182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 138216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 138316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnected() { 138416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle extras = MediaBrowserCompatApi21.getExtras(mBrowserObj); 138516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (extras == null) { 138616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 138716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 138816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim IBinder serviceBinder = BundleCompat.getBinder(extras, EXTRA_MESSENGER_BINDER); 138916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (serviceBinder != null) { 139016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper = new ServiceBinderWrapper(serviceBinder); 139116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacksMessenger = new Messenger(mHandler); 139216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mHandler.setCallbacksMessenger(mCallbacksMessenger); 139316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim try { 139416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.registerCallbackMessenger(mCallbacksMessenger); 139516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } catch (RemoteException e) { 139616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.i(TAG, "Remote error registering client messenger." ); 139716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 139816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim onServiceConnected(mCallbacksMessenger, null, null, null); 139916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 140016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 140116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 140216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 140316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnectionSuspended() { 140416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper = null; 140516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacksMessenger = null; 140616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 140716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 140816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 140916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnectionFailed() { 141016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Do noting 141116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 141216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 141316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // FYI, this method is not called by CallbackHandler. 141416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 141516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onServiceConnected(final Messenger callback, final String root, 141616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim final MediaSessionCompat.Token session, final Bundle extra) { 141716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // we may receive some subscriptions before we are connected, so re-subscribe 141816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // everything now 141916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim for (Map.Entry<String, Subscription> subscriptionEntry : mSubscriptions.entrySet()) { 142016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim String id = subscriptionEntry.getKey(); 142116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Subscription sub = subscriptionEntry.getValue(); 142216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim List<Bundle> optionsList = sub.getOptionsList(); 142316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim List<SubscriptionCallback> callbackList = sub.getCallbacks(); 142416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim for (int i = 0; i < optionsList.size(); ++i) { 142516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (optionsList.get(i) == null) { 142616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim MediaBrowserCompatApi21.subscribe(mBrowserObj, id, 142716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim ((SubscriptionCallbackApi21)callbackList.get(i)) 142816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim .mSubscriptionCallbackObj); 142916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } else { 143016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim try { 143116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mServiceBinderWrapper.addSubscription( 143216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim id, optionsList.get(i), mCallbacksMessenger); 143316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } catch (RemoteException e) { 143416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Process is crashing. We will disconnect, and upon reconnect we will 143516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // automatically reregister. So nothing to do here. 143616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.d(TAG, "addSubscription failed with RemoteException parentId=" + id); 143716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 143816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 143916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 144016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 144116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 144216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 144316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 144416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onConnectionFailed(Messenger callback) { 144516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // This method will not be called. 144616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 144716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 144816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 144916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void onLoadChildren(Messenger callback, String parentId, List list, 145016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @NonNull Bundle options) { 145116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mCallbacksMessenger != callback) { 145216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 145316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 145416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 145516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim List<MediaItem> data = list; 145616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (DBG) { 145716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.d(TAG, "onLoadChildren for " + mServiceComponent + " id=" + parentId); 145816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 145916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 146016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Check that the subscription is still subscribed. 146116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Subscription subscription = mSubscriptions.get(parentId); 146216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (subscription == null) { 146316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (DBG) { 146416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.d(TAG, "onLoadChildren for id that isn't subscribed id=" + parentId); 146516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 146616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 146716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 146816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 146916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim // Tell the app. 147016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim subscription.getCallback(options).onChildrenLoaded(parentId, data, options); 147182cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 147282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 147382cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 147482cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim static class MediaBrowserImplApi23 extends MediaBrowserImplApi21 { 147582cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim public MediaBrowserImplApi23(Context context, ComponentName serviceComponent, 147682cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim ConnectionCallback callback, Bundle rootHints) { 147782cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim super(context, serviceComponent, callback, rootHints); 147882cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim } 147982cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim 148082cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim @Override 14816b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim public void getItem(@NonNull String mediaId, @NonNull ItemCallback cb) { 148282cf659fd8dcc28e182274b17a401023ab879deaSungsoo Lim MediaBrowserCompatApi23.getItem(mBrowserObj, mediaId, cb.mItemCallbackObj); 14836b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 14846b565ded51fc2e48e9d5ac652e1fbf3d9255dd3eSungsoo Lim } 1485d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim 148616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static class Subscription { 148716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final List<SubscriptionCallback> mCallbacks; 148816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final List<Bundle> mOptionsList; 148916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 149016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public Subscription() { 149116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacks = new ArrayList(); 149216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mOptionsList = new ArrayList(); 149316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 149416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 149516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public boolean isEmpty() { 149616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return mCallbacks.isEmpty(); 149716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 149816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 149916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public List<Bundle> getOptionsList() { 150016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return mOptionsList; 150116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 150216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 150316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public List<SubscriptionCallback> getCallbacks() { 150416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return mCallbacks; 150516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 150616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 150716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void setCallbackForOptions(SubscriptionCallback callback, Bundle options) { 150816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim for (int i = 0; i < mOptionsList.size(); ++i) { 150916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (MediaBrowserCompatUtils.areSameOptions(mOptionsList.get(i), options)) { 151016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacks.set(i, callback); 151116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 151216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 151316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 151416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacks.add(callback); 151516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mOptionsList.add(options); 151616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 151716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 151816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public boolean remove(Bundle options) { 151916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim for (int i = 0; i < mOptionsList.size(); ++i) { 152016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (MediaBrowserCompatUtils.areSameOptions(mOptionsList.get(i), options)) { 152116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacks.remove(i); 152216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mOptionsList.remove(i); 152316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return true; 152416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 152516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 152616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return false; 152716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 152816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 152916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public SubscriptionCallback getCallback(Bundle options) { 153016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim for (int i = 0; i < mOptionsList.size(); ++i) { 153116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (MediaBrowserCompatUtils.areSameOptions(mOptionsList.get(i), options)) { 153216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return mCallbacks.get(i); 153316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 153416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 153516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return null; 153616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 153716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 153816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 153916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static class CallbackHandler extends Handler { 154016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private final MediaBrowserServiceCallbackImpl mCallbackImpl; 154116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private WeakReference<Messenger> mCallbacksMessengerRef; 154216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 154316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim CallbackHandler(MediaBrowserServiceCallbackImpl callbackImpl) { 154416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim super(); 154516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbackImpl = callbackImpl; 154616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 154716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 154816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim @Override 154916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public void handleMessage(Message msg) { 155016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim if (mCallbacksMessengerRef == null) { 155116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim return; 155216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 155316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = msg.getData(); 155416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.setClassLoader(MediaSessionCompat.class.getClassLoader()); 155516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim switch (msg.what) { 155616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case SERVICE_MSG_ON_CONNECT: 155716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbackImpl.onServiceConnected(mCallbacksMessengerRef.get(), 155816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getString(DATA_MEDIA_ITEM_ID), 155916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim (MediaSessionCompat.Token) data.getParcelable(DATA_MEDIA_SESSION_TOKEN), 156016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getBundle(DATA_ROOT_HINTS)); 156116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim break; 156216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case SERVICE_MSG_ON_CONNECT_FAILED: 156316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbackImpl.onConnectionFailed(mCallbacksMessengerRef.get()); 156416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim break; 156516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim case SERVICE_MSG_ON_LOAD_CHILDREN: 156616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbackImpl.onLoadChildren(mCallbacksMessengerRef.get(), 156716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getString(DATA_MEDIA_ITEM_ID), 156816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getParcelableArrayList(DATA_MEDIA_ITEM_LIST), 156916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.getBundle(DATA_OPTIONS)); 157016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim break; 157116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim default: 157216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Log.w(TAG, "Unhandled message: " + msg 157316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim + "\n Client version: " + CLIENT_VERSION_CURRENT 157416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim + "\n Service version: " + msg.arg1); 157516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 157616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 157716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 157816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void setCallbacksMessenger(Messenger callbacksMessenger) { 157916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mCallbacksMessengerRef = new WeakReference<>(callbacksMessenger); 158016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 158116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 158216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 158316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static class ServiceBinderWrapper { 158416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private Messenger mMessenger; 158516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 158616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim public ServiceBinderWrapper(IBinder target) { 158716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mMessenger = new Messenger(target); 158816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 158916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 159016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void connect(Context context, Bundle rootHint, Messenger callbacksMessenger) 159116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throws RemoteException { 159216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = new Bundle(); 159316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putString(DATA_PACKAGE_NAME, context.getPackageName()); 159416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putBundle(DATA_ROOT_HINTS, rootHint); 159516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_CONNECT, data, callbacksMessenger); 159616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 159716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 159816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void disconnect(Messenger callbacksMessenger) throws RemoteException { 159916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_DISCONNECT, null, callbacksMessenger); 160016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 160116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 160216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void addSubscription(String parentId, Bundle options, Messenger callbacksMessenger) 160316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throws RemoteException { 160416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = new Bundle(); 160516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putString(DATA_MEDIA_ITEM_ID, parentId); 160616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putBundle(DATA_OPTIONS, options); 160716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_ADD_SUBSCRIPTION, data, callbacksMessenger); 160816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 160916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 161016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void removeSubscription(String parentId, Bundle options, Messenger callbacksMessenger) 161116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throws RemoteException { 161216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = new Bundle(); 161316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putString(DATA_MEDIA_ITEM_ID, parentId); 161416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putBundle(DATA_OPTIONS, options); 161516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_REMOVE_SUBSCRIPTION, data, callbacksMessenger); 161616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 161716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 161816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void getMediaItem(String mediaId, ResultReceiver receiver) throws RemoteException { 161916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Bundle data = new Bundle(); 162016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putString(DATA_MEDIA_ITEM_ID, mediaId); 162116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim data.putParcelable(DATA_RESULT_RECEIVER, receiver); 162216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_GET_MEDIA_ITEM, data, null); 162316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 162416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 162516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim void registerCallbackMessenger(Messenger callbackMessenger) throws RemoteException { 162616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim sendRequest(CLIENT_MSG_REGISTER_CALLBACK_MESSENGER, null, callbackMessenger); 162716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 162816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 162916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private void sendRequest(int what, Bundle data, Messenger cbMessenger) 163016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim throws RemoteException { 163116d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim Message msg = Message.obtain(); 163216d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim msg.what = what; 163316d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim msg.arg1 = CLIENT_VERSION_CURRENT; 163416d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim msg.setData(data); 163516d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim msg.replyTo = cbMessenger; 163616d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim mMessenger.send(msg); 163716d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 163816d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim } 163916d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim 164016d709bad185d0d5e9bf2ba88132fb592e63041dSungsoo Lim private static class ItemReceiver extends ResultReceiver { 1641d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim private final String mMediaId; 1642d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim private final ItemCallback mCallback; 1643d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim 1644d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim ItemReceiver(String mediaId, ItemCallback callback, Handler handler) { 1645d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim super(handler); 1646d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mMediaId = mediaId; 1647d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mCallback = callback; 1648d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1649d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim 1650d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim @Override 1651d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim protected void onReceiveResult(int resultCode, Bundle resultData) { 1652d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim resultData.setClassLoader(MediaBrowserCompat.class.getClassLoader()); 1653d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim if (resultCode != 0 || resultData == null 1654d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim || !resultData.containsKey(MediaBrowserServiceCompat.KEY_MEDIA_ITEM)) { 1655d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mCallback.onError(mMediaId); 1656d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim return; 1657d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1658d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim Parcelable item = resultData.getParcelable(MediaBrowserServiceCompat.KEY_MEDIA_ITEM); 1659d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim if (item instanceof MediaItem) { 1660d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mCallback.onItemLoaded((MediaItem) item); 1661d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } else { 1662d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim mCallback.onError(mMediaId); 1663d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1664d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1665d4c131eea07dc2593f70523979929e52cf80e31eSungsoo Lim } 1666e2dc54fb995a75eab424aafe4960799ed5512f4dJae Seo} 1667