164b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer/* 264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * Copyright (C) 2016 The Android Open Source Project 364b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * 464b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * Licensed under the Apache License, Version 2.0 (the "License"); 564b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * you may not use this file except in compliance with the License. 664b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * You may obtain a copy of the License at 764b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * 864b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * http://www.apache.org/licenses/LICENSE-2.0 964b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * 1064b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * Unless required by applicable law or agreed to in writing, software 1164b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * distributed under the License is distributed on an "AS IS" BASIS, 1264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1364b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * See the License for the specific language governing permissions and 1464b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * limitations under the License. 1564b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer */ 1664b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyerpackage com.android.car.media; 1764b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 18450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perezimport android.annotation.NonNull; 19450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perezimport android.car.Car; 2064b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyerimport android.content.ComponentName; 21450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perezimport android.content.Context; 2264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyerimport android.content.Intent; 23450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perezimport android.content.SharedPreferences; 24d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport android.graphics.Bitmap; 258a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perezimport android.media.session.MediaController; 2664b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyerimport android.os.Bundle; 27d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport android.support.v4.app.Fragment; 28d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport android.support.v4.app.FragmentManager; 291d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perezimport android.support.v4.widget.DrawerLayout; 3060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perezimport android.transition.Fade; 3164b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyerimport android.util.Log; 32d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport android.util.TypedValue; 33d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport android.view.View; 345289168183d65b16813447c2b160adab799f1ac8Roberto Perezimport android.view.ViewGroup; 35bff2cd02e423e6819b0568d5fa23c54b96c967d9Anthony Chen 368a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perezimport com.android.car.media.common.ActiveMediaSourceManager; 37d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport com.android.car.media.common.CrossfadeImageView; 38d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport com.android.car.media.common.MediaItemMetadata; 39cade0ffb8f53aee68f7d453c30871d1c32b53632Roberto Perezimport com.android.car.media.common.MediaSource; 4060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perezimport com.android.car.media.common.MediaSourcesManager; 415289168183d65b16813447c2b160adab799f1ac8Roberto Perezimport com.android.car.media.common.PlaybackControls; 42d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport com.android.car.media.common.PlaybackModel; 435cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathanimport com.android.car.media.drawer.MediaDrawerController; 445a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perezimport com.android.car.media.widgets.AppBarView; 455289168183d65b16813447c2b160adab799f1ac8Roberto Perezimport com.android.car.media.widgets.MetadataView; 46a51d23d9109f44187200495fdb4523d47255b14aRoberto Perezimport com.android.car.media.widgets.ViewUtils; 47d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 48d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport java.util.ArrayList; 49d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport java.util.List; 50d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport java.util.Objects; 51d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perezimport java.util.stream.Collectors; 525cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan 53ddd67d6fbdfcebec8c40a1f8c7d9d68ec2c9fd17Aurimas Liutikasimport androidx.car.drawer.CarDrawerActivity; 54ddd67d6fbdfcebec8c40a1f8c7d9d68ec2c9fd17Aurimas Liutikasimport androidx.car.drawer.CarDrawerAdapter; 55ddd67d6fbdfcebec8c40a1f8c7d9d68ec2c9fd17Aurimas Liutikas 5664b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer/** 5764b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer * This activity controls the UI of media. It also updates the connection status for the media app 585cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan * by broadcast. Drawer menu is controlled by {@link MediaDrawerController}. 5964b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer */ 6060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perezpublic class MediaActivity extends CarDrawerActivity implements BrowseFragment.Callbacks, 611d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez AppSelectionFragment.Callbacks, PlaybackFragment.Callbacks { 6264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer private static final String TAG = "MediaActivity"; 6364b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 64450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez /** Intent extra specifying the package with the MediaBrowser */ 65d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez public static final String KEY_MEDIA_PACKAGE = "media_package"; 66450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez /** Shared preferences files */ 67450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez public static final String SHARED_PREF = "com.android.car.media"; 68450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez /** Shared preference containing the last controlled source */ 69450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez public static final String LAST_MEDIA_SOURCE_SHARED_PREF_KEY = "last_media_source"; 7060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez 71d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez /** Configuration (controlled from resources) */ 72d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private boolean mContentForwardBrowseEnabled; 73d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private float mBackgroundBlurRadius; 74d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private float mBackgroundBlurScale; 75a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez private int mFadeDuration; 76d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 77d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez /** Models */ 785cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan private MediaDrawerController mDrawerController; 798a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez private ActiveMediaSourceManager mActiveMediaSourceManager; 80d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private MediaSource mMediaSource; 81d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private PlaybackModel mPlaybackModel; 8260561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez private MediaSourcesManager mMediaSourcesManager; 83450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez private SharedPreferences mSharedPreferences; 84d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 85d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez /** Layout views */ 865a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez private AppBarView mAppBarView; 87d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private CrossfadeImageView mAlbumBackground; 888189d452317e04e1c1852d2d3a2e9da3e0295147Roberto Perez private PlaybackFragment mPlaybackFragment; 8960561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez private AppSelectionFragment mAppSelectionFragment; 905289168183d65b16813447c2b160adab799f1ac8Roberto Perez private PlaybackControls mPlaybackControls; 915289168183d65b16813447c2b160adab799f1ac8Roberto Perez private MetadataView mMetadataView; 925289168183d65b16813447c2b160adab799f1ac8Roberto Perez private ViewGroup mBrowseControlsContainer; 93fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez private EmptyFragment mEmptyFragment; 94a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez private ViewGroup mBrowseContainer; 95a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez private ViewGroup mPlaybackContainer; 965289168183d65b16813447c2b160adab799f1ac8Roberto Perez 97d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez /** Current state */ 98d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private Fragment mCurrentFragment; 99d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private Mode mMode = Mode.BROWSING; 10060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez private boolean mIsAppSelectorOpen; 101a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez private MediaItemMetadata mCurrentMetadata; 102d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 103d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private MediaSource.Observer mMediaSourceObserver = new MediaSource.Observer() { 104d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 105d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez protected void onBrowseConnected(boolean success) { 106d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez MediaActivity.this.onBrowseConnected(success); 107d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 108d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 109d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 110d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez protected void onBrowseDisconnected() { 111d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez MediaActivity.this.onBrowseConnected(false); 112d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 113d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez }; 114d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private PlaybackModel.PlaybackObserver mPlaybackObserver = 115d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez new PlaybackModel.PlaybackObserver() { 1168a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez @Override 1178a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez protected void onSourceChanged() { 1188a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez updateMetadata(); 1198a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } 120d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 1218a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez @Override 1228a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez public void onMetadataChanged() { 1238a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mCurrentMetadata = null; 1248a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez updateMetadata(); 1258a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } 1268a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez }; 1278a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez private ActiveMediaSourceManager.Observer mActiveSourceObserver = () -> { 1288a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez // If the active media source changes and it is the one currently being browsed, then 1298a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez // we should capture the controller. 1308a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez MediaController controller = mActiveMediaSourceManager.getMediaController(); 1318a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez if (mPlaybackModel.getMediaController() == null 1328a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez && mMediaSource != null 1338a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez && controller != null 1348a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez && Objects.equals(controller.getPackageName(), mMediaSource.getPackageName())) { 1358a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mPlaybackModel.setMediaController(controller); 1368a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } 1378a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez }; 138fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez private MediaSource.ItemsSubscription mItemsSubscription = 139fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez new MediaSource.ItemsSubscription() { 1408a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez @Override 1418a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez public void onChildrenLoaded(MediaSource mediaSource, String parentId, 1428a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez List<MediaItemMetadata> items) { 1438a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez if (mediaSource == mMediaSource) { 1448a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez updateTabs(items); 1458a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } else { 1468a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez Log.w(TAG, "Received items for a wrong source: " + 1478a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mediaSource.getPackageName()); 1488a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } 1498a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } 1508a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez }; 1515a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez private AppBarView.AppBarListener mAppBarListener = new AppBarView.AppBarListener() { 152d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 1535a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez public void onTabSelected(MediaItemMetadata item) { 154fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez updateBrowseFragment(BrowseState.LOADED, item); 155a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez switchToMode(Mode.BROWSING); 156d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 157d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 158d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 1595a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez public void onBack() { 1605a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez if (mCurrentFragment != null && mCurrentFragment instanceof BrowseFragment) { 1615a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez BrowseFragment fragment = (BrowseFragment) mCurrentFragment; 1625a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez fragment.navigateBack(); 1635a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez } 164d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 165d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 166d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 1675a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez public void onCollapse() { 1685a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez switchToMode(Mode.BROWSING); 1695a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez } 1705a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez 1715a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez @Override 1725a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez public void onAppSelection() { 1731d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez Log.d(TAG, "onAppSelection clicked"); 17460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez if (mIsAppSelectorOpen) { 17560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez closeAppSelector(); 17660561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } else { 17760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez openAppSelector(); 17860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 179d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 180d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez }; 18160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez private MediaSourcesManager.Observer mMediaSourcesManagerObserver = () -> { 18260561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAppBarView.setAppSelection(!mMediaSourcesManager.getMediaSources().isEmpty()); 18360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAppSelectionFragment.refresh(); 18460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez }; 1851d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez private DrawerLayout.DrawerListener mDrawerListener = new DrawerLayout.DrawerListener() { 1861d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez @Override 1871d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez public void onDrawerSlide(@android.support.annotation.NonNull View view, float v) { 1881d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez } 1891d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez 1901d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez @Override 1911d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez public void onDrawerOpened(@android.support.annotation.NonNull View view) { 1921d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez closeAppSelector(); 1931d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez } 1941d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez 1951d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez @Override 1961d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez public void onDrawerClosed(@android.support.annotation.NonNull View view) { 1971d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez } 1981d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez 1991d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez @Override 2001d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez public void onDrawerStateChanged(int i) { 2011d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez } 2021d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez }; 203d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 204fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** 205fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * Possible modes of the application UI 206fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez */ 207d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private enum Mode { 208fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** The user is browsing a media source */ 209d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez BROWSING, 210fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** The user is interacting with the full screen playback UI */ 211d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez PLAYBACK 212d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 21364b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 214fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** 215fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * Possible states of the application UI 216fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez */ 217fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez public enum BrowseState { 218fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** There is no content to show */ 219fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez EMPTY, 220fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** We are still in the process of obtaining data */ 221fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez LOADING, 222fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** Data has been loaded */ 223fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez LOADED, 224fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** The content can't be shown due an error */ 225fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez ERROR 226fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez } 227fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez 22864b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer @Override 22964b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer protected void onCreate(Bundle savedInstanceState) { 23064b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer super.onCreate(savedInstanceState); 231d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 232d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez setMainContent(R.layout.media_activity); 233fd135a91a13b55d23768370dc81c2d349b19f6b7Anthony Chen setToolbarElevation(0f); 2345cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan 235d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mContentForwardBrowseEnabled = getResources() 236d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez .getBoolean(R.bool.forward_content_browse_enabled); 237d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mDrawerController = new MediaDrawerController(this, getDrawerController()); 238bff2cd02e423e6819b0568d5fa23c54b96c967d9Anthony Chen getDrawerController().setRootAdapter(getRootAdapter()); 2391d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez getDrawerController().addDrawerListener(mDrawerListener); 2401d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez if (mContentForwardBrowseEnabled) { 2411d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez getSupportActionBar().hide(); 2421d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez } 2435a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez mAppBarView = findViewById(R.id.app_bar); 2445a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez mAppBarView.setListener(mAppBarListener); 2451d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez mAppBarView.setContentForwardEnabled(mContentForwardBrowseEnabled); 246d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mPlaybackFragment = new PlaybackFragment(); 24760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAppSelectionFragment = new AppSelectionFragment(); 24860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez int fadeDuration = getResources().getInteger(R.integer.app_selector_fade_duration); 24960561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAppSelectionFragment.setEnterTransition(new Fade().setDuration(fadeDuration)); 25060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAppSelectionFragment.setExitTransition(new Fade().setDuration(fadeDuration)); 2518a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mActiveMediaSourceManager = new ActiveMediaSourceManager(this); 252d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mPlaybackModel = new PlaybackModel(this); 25360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mMediaSourcesManager = new MediaSourcesManager(this); 254d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mAlbumBackground = findViewById(R.id.media_background); 255a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mPlaybackControls = findViewById(R.id.browse_controls); 2565289168183d65b16813447c2b160adab799f1ac8Roberto Perez mPlaybackControls.setModel(mPlaybackModel); 257a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mMetadataView = findViewById(R.id.browse_metadata); 2585289168183d65b16813447c2b160adab799f1ac8Roberto Perez mMetadataView.setModel(mPlaybackModel); 2595289168183d65b16813447c2b160adab799f1ac8Roberto Perez mBrowseControlsContainer = findViewById(R.id.browse_controls_container); 2605289168183d65b16813447c2b160adab799f1ac8Roberto Perez mBrowseControlsContainer.setOnClickListener(view -> switchToMode(Mode.PLAYBACK)); 261d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez TypedValue outValue = new TypedValue(); 262d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez getResources().getValue(R.dimen.playback_background_blur_radius, outValue, true); 263d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mBackgroundBlurRadius = outValue.getFloat(); 264d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez getResources().getValue(R.dimen.playback_background_blur_scale, outValue, true); 265d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mBackgroundBlurScale = outValue.getFloat(); 266450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez mSharedPreferences = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE); 267a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mFadeDuration = getResources().getInteger( 268a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez R.integer.new_album_art_fade_in_duration); 269a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mEmptyFragment = new EmptyFragment(); 270a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mBrowseContainer = findViewById(R.id.fragment_container); 271a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mPlaybackContainer = findViewById(R.id.playback_container); 272a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez getSupportFragmentManager().beginTransaction() 273a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez .replace(R.id.playback_container, mPlaybackFragment) 274a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez .commit(); 275d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 276bff2cd02e423e6819b0568d5fa23c54b96c967d9Anthony Chen 277d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 27860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez public void onResume() { 27960561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez super.onResume(); 280d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mPlaybackModel.registerObserver(mPlaybackObserver); 2818a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mActiveMediaSourceManager.registerObserver(mActiveSourceObserver); 28260561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mMediaSourcesManager.registerObserver(mMediaSourcesManagerObserver); 283fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez handleIntent(); 284d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 2858189d452317e04e1c1852d2d3a2e9da3e0295147Roberto Perez 286d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 28760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez public void onPause() { 28860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez super.onPause(); 289d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mPlaybackModel.unregisterObserver(mPlaybackObserver); 2908a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mActiveMediaSourceManager.unregisterObserver(mActiveSourceObserver); 29160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mMediaSourcesManager.unregisterObserver(mMediaSourcesManagerObserver); 29264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer } 29364b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 29464b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer @Override 29564b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer public void onDestroy() { 29664b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer super.onDestroy(); 2975cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan mDrawerController.cleanup(); 2985289168183d65b16813447c2b160adab799f1ac8Roberto Perez mPlaybackControls.setModel(null); 2995289168183d65b16813447c2b160adab799f1ac8Roberto Perez mMetadataView.setModel(null); 3005cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan } 3015cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan 3025cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan @Override 3035cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan protected CarDrawerAdapter getRootAdapter() { 304bff2cd02e423e6819b0568d5fa23c54b96c967d9Anthony Chen return mDrawerController == null ? null : mDrawerController.getRootAdapter(); 30564b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer } 30664b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 30764b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer @Override 30864b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer protected void onNewIntent(Intent intent) { 30964b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer super.onNewIntent(intent); 31064b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer if (Log.isLoggable(TAG, Log.VERBOSE)) { 31164b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer Log.v(TAG, "onNewIntent(); intent: " + (intent == null ? "<< NULL >>" : intent)); 31264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer } 31364b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 31464b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer setIntent(intent); 315d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez handleIntent(); 31664b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer } 31764b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 31864b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer @Override 31964b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer public void onBackPressed() { 3208189d452317e04e1c1852d2d3a2e9da3e0295147Roberto Perez mPlaybackFragment.closeOverflowMenu(); 32164b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer super.onBackPressed(); 32264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer } 32364b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 324d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private void onBrowseConnected(boolean success) { 325d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (!success) { 326fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez updateTabs(null); 327fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mMediaSource.unsubscribeChildren(null, mItemsSubscription); 328fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mMediaSource.unsubscribe(mMediaSourceObserver); 329fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez updateBrowseFragment(BrowseState.ERROR, null); 330d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez return; 33164b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer } 332fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mMediaSource.subscribeChildren(null, mItemsSubscription); 3338a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez if (mPlaybackModel.getMediaController() == null) { 3348a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mPlaybackModel.setMediaController(mMediaSource.getMediaController()); 3358a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } 336d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 33764b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 338d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private void handleIntent() { 339450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez Intent intent = getIntent(); 340450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez String action = intent != null ? intent.getAction() : null; 341450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez 342450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez getDrawerController().closeDrawer(); 343450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez 344450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez if (Car.CAR_INTENT_ACTION_MEDIA_TEMPLATE.equals(action)) { 345450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // The user either wants to browse a particular media source or switch to the 346450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // playback UI. 347450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez String packageName = intent.getStringExtra(KEY_MEDIA_PACKAGE); 348450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez if (packageName != null) { 349450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // We were told to navigate to a particular package: we open browse for it. 350a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez closeAppSelector(); 3518a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez changeMediaSource(new MediaSource(this, packageName), null); 352450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez switchToMode(Mode.BROWSING); 353450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez return; 354450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 355450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez 3568a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez // If we didn't receive a package name and we are playing something: show the playback 357450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // UI for the playing media source. 3588a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez MediaController controller = mActiveMediaSourceManager.getMediaController(); 3598a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez if (controller != null) { 360a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez closeAppSelector(); 3618a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez changeMediaSource(new MediaSource(this, controller.getPackageName()), controller); 362450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez switchToMode(Mode.PLAYBACK); 363450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez return; 364450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 365450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 366450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez 367450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // In any other case, if we were already browsing something: just close drawers/overlays 368450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // and display what we have. 369450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez if (mMediaSource != null) { 370450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez closeAppSelector(); 371450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez return; 372450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 373450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez 374450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // If we don't have a current media source, we try with the last one we remember. 375450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez MediaSource lastMediaSource = getLastMediaSource(); 376450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez if (lastMediaSource != null) { 377450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez closeAppSelector(); 3788a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez changeMediaSource(lastMediaSource, null); 379fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez switchToMode(Mode.BROWSING); 380450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } else { 381450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // If we don't have anything from before: open the app selector. 382450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez openAppSelector(); 383450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 384d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 385cade0ffb8f53aee68f7d453c30871d1c32b53632Roberto Perez 386d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez /** 3878a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez * Sets the media source being browsed. 3888a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez * 3898a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez * @param mediaSource the media source we are going to try to browse 3908a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez * @param controller a controller we can use to control the playback state of the given 3918a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez * source. If not provided, we will try to obtain it from the session manager. 3928a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez * Otherwise, we will obtain a controller once the media browser is connected. 393d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez */ 3948a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez private void changeMediaSource(MediaSource mediaSource, MediaController controller) { 395d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (Objects.equals(mediaSource, mMediaSource)) { 396d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez // No change, nothing to do. 397d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez return; 398d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 399d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (mMediaSource != null) { 400fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mMediaSource.unsubscribeChildren(null, mItemsSubscription); 401d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mMediaSource.unsubscribe(mMediaSourceObserver); 402d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez updateTabs(new ArrayList<>()); 403d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 404d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mMediaSource = mediaSource; 4058a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mPlaybackModel.setMediaController(controller != null ? controller 4068a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez : mActiveMediaSourceManager.getControllerForPackage(mediaSource.getPackageName())); 407450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez setLastMediaSource(mMediaSource); 408d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (mMediaSource != null) { 409d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (Log.isLoggable(TAG, Log.INFO)) { 410d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez Log.i(TAG, "Browsing: " + mediaSource.getName()); 411d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 412e8f6fb8b486c5ae99452d2fc93a922d80df1d76dRoberto Perez // Prepare the media source for playback 413e8f6fb8b486c5ae99452d2fc93a922d80df1d76dRoberto Perez mPlaybackModel.onPrepare(); 414e8f6fb8b486c5ae99452d2fc93a922d80df1d76dRoberto Perez // Make the drawer display browse information of the selected source 415d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez ComponentName component = mMediaSource.getBrowseServiceComponentName(); 4165cb58af61618d6c457685a5feba630540f25567cSrinivas Visvanathan MediaManager.getInstance(this).setMediaClientComponent(component); 417d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez // If content forward browsing is disabled, then no need to subscribe to this media 418e8f6fb8b486c5ae99452d2fc93a922d80df1d76dRoberto Perez // source, we will use the drawer instead. 419d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (mContentForwardBrowseEnabled) { 420d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez Log.i(TAG, "Content forward is enabled: subscribing to " + 421d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mMediaSource.getPackageName()); 4221d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez updateBrowseFragment(BrowseState.LOADING, null); 423d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mMediaSource.subscribe(mMediaSourceObserver); 424d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 42560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAppBarView.setAppIcon(mMediaSource.getRoundPackageIcon()); 4265a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez mAppBarView.setTitle(mMediaSource.getName()); 4275a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez } else { 4285a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez mAppBarView.setAppIcon(null); 4295a5a06b91563988c671319c68d9ce1a66f352a95Roberto Perez mAppBarView.setTitle(null); 43064b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer } 431d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 43264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 433d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private boolean isCurrentMediaSourcePlaying() { 4348a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez return mMediaSource != null 4358a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez && mActiveMediaSourceManager.isPlaying(mMediaSource.getPackageName()); 436d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 437d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 438fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez /** 439fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * Updates the tabs displayed on the app bar, based on the top level items on the browse tree. 440fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * If there is at least one browsable item, we show the browse content of that node. 441fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * If there are only playable items, then we show those items. 442fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * If there are not items at all, we show the empty message. 443fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * If we receive null, we show the error message. 444fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * 445fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * @param items top level items, or null if there was an error trying load those items. 446fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez */ 447d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private void updateTabs(List<MediaItemMetadata> items) { 448fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez if (items == null || items.isEmpty()) { 449fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mAppBarView.setItems(null); 450fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez updateBrowseFragment(items == null ? BrowseState.ERROR : BrowseState.EMPTY, null); 451fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez return; 452fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez } 453fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez 454450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez items = customizeTabs(mMediaSource, items); 455d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez List<MediaItemMetadata> browsableTopLevel = items.stream() 456d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez .filter(item -> item.isBrowsable()) 457d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez .collect(Collectors.toList()); 458d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 459a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez if (!browsableTopLevel.isEmpty()) { 460a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez // If we have at least a few browsable items, we show the tabs 461a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mAppBarView.setItems(browsableTopLevel); 462fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez updateBrowseFragment(BrowseState.LOADED, browsableTopLevel.get(0)); 463d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } else { 464a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez // Otherwise, we show the top of the tree with no fabs 465a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mAppBarView.setItems(null); 466fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez updateBrowseFragment(BrowseState.LOADED, null); 467d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 468d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 469d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 470450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez /** 471450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez * Extension point used to customize media items displayed on the tabs. 472450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez * 473450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez * @param mediaSource media source these items belong to. 474450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez * @param items items to override. 475450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez * @return an updated list of items. 476450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez * @deprecated This method will be removed on b/79089344 477450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez */ 478450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez @Deprecated 479450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez protected List<MediaItemMetadata> customizeTabs(MediaSource mediaSource, 480450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez List<MediaItemMetadata> items) { 481450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez return items; 482450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 483450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez 484d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private void switchToMode(Mode mode) { 4851d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez // If content forward is not enable, then we always show the playback UI (browse will be 4861d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez // done in the drawer) 4871d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez mMode = mContentForwardBrowseEnabled ? mode : Mode.PLAYBACK; 4885289168183d65b16813447c2b160adab799f1ac8Roberto Perez updateMetadata(); 4891d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez switch (mMode) { 490a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez case PLAYBACK: 491a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez ViewUtils.showViewAnimated(mPlaybackContainer, mFadeDuration); 492a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez ViewUtils.hideViewAnimated(mBrowseContainer, mFadeDuration); 493a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mAppBarView.setState(AppBarView.State.PLAYING); 494a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez break; 495a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez case BROWSING: 496a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez ViewUtils.hideViewAnimated(mPlaybackContainer, mFadeDuration); 497a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez ViewUtils.showViewAnimated(mBrowseContainer, mFadeDuration); 498a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mAppBarView.setState(AppBarView.State.BROWSING); 499a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez break; 500a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez } 501d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 502d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 503a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez /** 504a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez * Updates the browse area with either a loading state, the root node content, or the 505a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez * content of a particular media item. 506a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez * 507fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * @param state state in the process of loading browse information. 508fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * @param topItem if state == IDLE, this will contain the item to display, 509fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez * or null to display the root node. 510a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez */ 511fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez private void updateBrowseFragment(BrowseState state, MediaItemMetadata topItem) { 512fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez switch(state) { 513fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez case LOADED: 514fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez if (topItem != null) { 515fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mCurrentFragment = BrowseFragment.newInstance(mMediaSource, topItem); 516fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mAppBarView.setActiveItem(topItem); 517fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez } else { 518fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mCurrentFragment = BrowseFragment.newInstance(mMediaSource, null); 519fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mAppBarView.setActiveItem(null); 520fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez } 521fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez break; 522fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez case EMPTY: 523fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez case LOADING: 524fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez case ERROR: 525fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mCurrentFragment = mEmptyFragment; 526fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mEmptyFragment.setState(state, mMediaSource); 527fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mAppBarView.setActiveItem(null); 528fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez break; 52964b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer } 530a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez getSupportFragmentManager().beginTransaction() 531a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez .replace(R.id.fragment_container, mCurrentFragment) 532fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez .commitAllowingStateLoss(); 533d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 534d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 535d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private void updateMetadata() { 536d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (isCurrentMediaSourcePlaying()) { 537a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez if (mMode == Mode.PLAYBACK) { 538a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez ViewUtils.hideViewAnimated(mBrowseControlsContainer, mFadeDuration); 539a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez } else { 540a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez ViewUtils.showViewAnimated(mBrowseControlsContainer, mFadeDuration); 541a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez } 542a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez MediaItemMetadata metadata = mPlaybackModel.getMetadata(); 543a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez if (Objects.equals(mCurrentMetadata, metadata)) { 544a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez return; 545a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez } 546a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez mCurrentMetadata = metadata; 54760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mUpdateAlbumArtRunnable.run(); 54860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } else { 54960561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAlbumBackground.setImageBitmap(null, true); 550a51d23d9109f44187200495fdb4523d47255b14aRoberto Perez ViewUtils.hideViewAnimated(mBrowseControlsContainer, mFadeDuration); 55160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 55260561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 55360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez 55460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez /** 55560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez * We might receive new album art before we are ready to display it. If that situation happens 55660561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez * we will retrieve and render the album art when the views are already laid out. 55760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez */ 55860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez private Runnable mUpdateAlbumArtRunnable = new Runnable() { 55960561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez @Override 56060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez public void run() { 56160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez MediaItemMetadata metadata = mPlaybackModel.getMetadata(); 562d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (metadata != null) { 56360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez if (mAlbumBackground.getWidth() == 0 || mAlbumBackground.getHeight() == 0) { 56460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez // We need to wait for the view to be measured before we can render this 56560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez // album art. 56660561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAlbumBackground.setImageBitmap(null, false); 56760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAlbumBackground.post(this); 56860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } else { 56960561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAlbumBackground.removeCallbacks(this); 57060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez metadata.getAlbumArt(MediaActivity.this, 57160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAlbumBackground.getWidth(), 57260561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAlbumBackground.getHeight(), 57360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez false) 57460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez .thenAccept(bitmap -> setBackgroundImage(bitmap)); 57560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 576d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } else { 57760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAlbumBackground.removeCallbacks(this); 578d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mAlbumBackground.setImageBitmap(null, true); 579d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 580d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 58160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez }; 58264b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 583d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez private void setBackgroundImage(Bitmap bitmap) { 584d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez // TODO(b/77551865): Implement image blurring once the following issue is solved: 585d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez // b/77551557 586d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez // bitmap = ImageUtils.blur(getContext(), bitmap, mBackgroundBlurScale, 587d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez // mBackgroundBlurRadius); 588d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mAlbumBackground.setImageBitmap(bitmap, true); 589d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 590d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 591d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 592d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez public MediaSource getMediaSource(String packageName) { 593d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez if (mMediaSource != null && mMediaSource.getPackageName().equals(packageName)) { 594d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez return mMediaSource; 595d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 596d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez return new MediaSource(this, packageName); 597d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 59864b173f33aa2d98ea00b9113b52e6f8cb35589adRakesh Iyer 599d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 600d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez public void onBackStackChanged() { 601d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez // TODO: Update ActionBar 602d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 603d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez 604d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez @Override 605d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez public void onPlayableItemClicked(MediaSource mediaSource, MediaItemMetadata item) { 606d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez mPlaybackModel.onStop(); 6078a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez if (!Objects.equals(mediaSource, mPlaybackModel.getMediaSource())) { 6088a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez Log.w(TAG, "Trying to play an item from a different source " 6098a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez + "(expected: " + mPlaybackModel.getMediaSource() + ", received" 6108a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez + mediaSource + ")"); 6118a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez changeMediaSource(mediaSource, mediaSource.getMediaController()); 6128a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } 6138a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez mPlaybackModel.onPlayItem(item.getId()); 614d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez setIntent(null); 615d1f0ec11284f6e6ed05d6a6fb7e2e086cc4a9837Roberto Perez } 61660561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez 61760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez private void openAppSelector() { 61860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mIsAppSelectorOpen = true; 61960561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez FragmentManager manager = getSupportFragmentManager(); 62060561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mAppBarView.setState(AppBarView.State.APP_SELECTION); 62160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez manager.beginTransaction() 62260561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez .replace(R.id.app_selection_container, mAppSelectionFragment) 62360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez .commit(); 62460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 62560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez 62660561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez private void closeAppSelector() { 62760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez mIsAppSelectorOpen = false; 62860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez FragmentManager manager = getSupportFragmentManager(); 629fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mAppBarView.setState(mMode == Mode.PLAYBACK ? AppBarView.State.PLAYING 630fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez : AppBarView.State.BROWSING); 63160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez manager.beginTransaction() 63260561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez .remove(mAppSelectionFragment) 63360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez .commit(); 63460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 63560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez 63660561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez @Override 63760561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez public List<MediaSource> getMediaSources() { 63860561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez return mMediaSourcesManager.getMediaSources() 63960561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez .stream() 640e8f6fb8b486c5ae99452d2fc93a922d80df1d76dRoberto Perez .filter(source -> source.getMediaBrowser() != null || source.isCustom()) 64160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez .collect(Collectors.toList()); 64260561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 64360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez 64460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez @Override 64560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez public void onMediaSourceSelected(MediaSource mediaSource) { 64660561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez closeAppSelector(); 647450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez if (mediaSource.getMediaBrowser() != null && !mediaSource.isCustom()) { 648fc30bbfdb4221ecd18adf59501d5ca82ca631310Roberto Perez mCurrentMetadata = null; 6498a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez changeMediaSource(mediaSource, null); 650450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez switchToMode(Mode.BROWSING); 65160561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } else { 652450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez String packageName = mediaSource.getPackageName(); 65360561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez Intent intent = getPackageManager().getLaunchIntentForPackage(packageName); 65460561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez startActivity(intent); 65560561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 65660561a06d4b8f10ca8c6f09f20c91b50fb6d3fa3Roberto Perez } 657450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez 658450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez private MediaSource getLastMediaSource() { 659450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez String packageName = mSharedPreferences.getString(LAST_MEDIA_SOURCE_SHARED_PREF_KEY, null); 660450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez if (packageName == null) { 661450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez return null; 662450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 663450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez // Verify that the stored package name corresponds to a currently installed media source. 664450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez for (MediaSource mediaSource : mMediaSourcesManager.getMediaSources()) { 665450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez if (mediaSource.getPackageName().equals(packageName)) { 666450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez return mediaSource; 667450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 668450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 669450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez return null; 670450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 671450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez 672450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez private void setLastMediaSource(@NonNull MediaSource mediaSource) { 673450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez mSharedPreferences.edit() 674450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez .putString(LAST_MEDIA_SOURCE_SHARED_PREF_KEY, mediaSource.getPackageName()) 675450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez .apply(); 676450c73a79e566f1c4a8758648525b457005e9f9aRoberto Perez } 6771d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez 6781d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez 6791d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez @Override 6808a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez public PlaybackModel getPlaybackModel() { 6818a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez return mPlaybackModel; 6828a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez } 6838a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez 6848a97fbcb2a74f960798dac29bca522cc8870daf3Roberto Perez @Override 6851d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez public void onQueueButtonClicked() { 6861d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez if (mContentForwardBrowseEnabled) { 6871d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez mPlaybackFragment.toggleQueueVisibility(); 6881d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez } else { 6891d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez mDrawerController.showPlayQueue(); 6901d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez } 6911d3e7e02676ed495b9f99701fa4647aa524d3f1bRoberto Perez } 692349880a1749d601dea9f20106b3dd09ee47f8eb9Anthony Chen} 693