1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.media; 18 19 20 import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_BROWSE; 21 22 import android.car.content.pm.CarPackageManager; 23 import android.content.ActivityNotFoundException; 24 import android.content.Intent; 25 import android.content.pm.ResolveInfo; 26 import android.content.res.Resources; 27 import android.graphics.drawable.BitmapDrawable; 28 import android.graphics.drawable.Drawable; 29 import android.media.audiofx.AudioEffect; 30 import android.util.Log; 31 import android.view.LayoutInflater; 32 import android.view.View; 33 import android.view.ViewGroup; 34 35 import androidx.annotation.CallSuper; 36 import androidx.annotation.LayoutRes; 37 import androidx.annotation.NonNull; 38 import androidx.annotation.Nullable; 39 import androidx.fragment.app.FragmentActivity; 40 41 import com.android.car.apps.common.util.CarPackageManagerUtils; 42 import com.android.car.media.common.source.MediaSource; 43 import com.android.car.media.common.source.MediaSourceViewModel; 44 import com.android.car.media.widgets.AppBarController; 45 46 import com.android.car.ui.baselayout.Insets; 47 import com.android.car.ui.baselayout.InsetsChangedListener; 48 import com.android.car.ui.core.CarUi; 49 import com.android.car.ui.toolbar.ToolbarController; 50 51 /** 52 * Functionality common to content view controllers. It mainly handles the AppBar view, 53 * which is common to all of them. 54 */ 55 abstract class ViewControllerBase implements InsetsChangedListener { 56 private static final String TAG = "ViewControllerBase"; 57 58 private final boolean mShouldShowSoundSettings; 59 private final CarPackageManager mCarPackageManager; 60 61 final FragmentActivity mActivity; 62 final int mFadeDuration; 63 final View mContent; 64 final AppBarController mAppBarController; 65 final MediaSourceViewModel mMediaSourceVM; 66 67 private Intent mCurrentSourcePreferences; 68 ViewControllerBase(FragmentActivity activity, CarPackageManager carPackageManager, ViewGroup container, @LayoutRes int resource)69 ViewControllerBase(FragmentActivity activity, CarPackageManager carPackageManager, 70 ViewGroup container, @LayoutRes int resource) { 71 mActivity = activity; 72 Resources res = mActivity.getResources(); 73 mFadeDuration = res.getInteger(R.integer.new_album_art_fade_in_duration); 74 mShouldShowSoundSettings = res.getBoolean(R.bool.show_sound_settings); 75 76 LayoutInflater inflater = LayoutInflater.from(container.getContext()); 77 mContent = inflater.inflate(resource, container, false); 78 container.addView(mContent); 79 80 GuidelinesUpdater updater = new GuidelinesUpdater(mContent); 81 updater.addListener(this); 82 ToolbarController toolbar = CarUi.installBaseLayoutAround(mContent, updater, true); 83 84 mAppBarController = new AppBarController(activity, toolbar); 85 mAppBarController.setSearchSupported(false); 86 mAppBarController.setHasEqualizer(false); 87 88 mCarPackageManager = carPackageManager; 89 90 mMediaSourceVM = MediaSourceViewModel.get(activity.getApplication(), 91 MEDIA_SOURCE_MODE_BROWSE); 92 93 } 94 95 @Override onCarUiInsetsChanged(@onNull Insets insets)96 public void onCarUiInsetsChanged(@NonNull Insets insets) { 97 // Overridden in subclasses 98 } 99 getAppBarDefaultTitle(@ullable MediaSource mediaSource)100 CharSequence getAppBarDefaultTitle(@Nullable MediaSource mediaSource) { 101 return (mediaSource != null) ? mediaSource.getDisplayName() 102 : mActivity.getResources().getString(R.string.media_app_title); 103 } 104 105 class BasicAppBarListener extends AppBarController.AppBarListener { 106 @Override onSettingsSelection()107 protected void onSettingsSelection() { 108 if (Log.isLoggable(TAG, Log.DEBUG)) { 109 Log.d(TAG, "onSettingsSelection"); 110 } 111 try { 112 if (mCurrentSourcePreferences != null) { 113 mActivity.startActivity(mCurrentSourcePreferences); 114 } 115 } catch (ActivityNotFoundException e) { 116 if (Log.isLoggable(TAG, Log.ERROR)) { 117 Log.e(TAG, "onSettingsSelection " + e); 118 } 119 } 120 } 121 122 @Override onEqualizerSelection()123 protected void onEqualizerSelection() { 124 Intent i = new Intent(AudioEffect.ACTION_DISPLAY_AUDIO_EFFECT_CONTROL_PANEL); 125 // Using startActivityForResult so that the control panel app can track changes for 126 // the launching package name. 127 mActivity.startActivityForResult(i, 0); 128 } 129 } 130 131 @CallSuper onMediaSourceChanged(@ullable MediaSource mediaSource)132 void onMediaSourceChanged(@Nullable MediaSource mediaSource) { 133 Resources res = mActivity.getResources(); 134 Drawable icon = null; 135 Drawable searchIcon = null; 136 String packageName = null; 137 if (mediaSource != null) { 138 // Drawables can't be shared due to the fact that the layout manager effects the 139 // underlying Drawable causing artifacts when then are both "on screen" 140 icon = new BitmapDrawable(res, mediaSource.getCroppedPackageIcon()); 141 searchIcon = new BitmapDrawable(res, mediaSource.getCroppedPackageIcon()); 142 packageName = mediaSource.getPackageName(); 143 } 144 145 mAppBarController.setLogo(icon); 146 mAppBarController.setSearchIcon(searchIcon); 147 updateSourcePreferences(packageName); 148 } 149 150 // TODO(b/136274938): display the preference screen for each media service. updateSourcePreferences(@ullable String packageName)151 private void updateSourcePreferences(@Nullable String packageName) { 152 mCurrentSourcePreferences = null; 153 if (packageName != null) { 154 Intent prefsIntent = new Intent(Intent.ACTION_APPLICATION_PREFERENCES); 155 prefsIntent.setPackage(packageName); 156 ResolveInfo info = mActivity.getPackageManager().resolveActivity(prefsIntent, 0); 157 if (info != null && info.activityInfo != null && info.activityInfo.exported) { 158 mCurrentSourcePreferences = new Intent(prefsIntent.getAction()) 159 .setClassName(info.activityInfo.packageName, info.activityInfo.name); 160 mAppBarController.setSettingsDistractionOptimized( 161 CarPackageManagerUtils.isDistractionOptimized( 162 mCarPackageManager, info.activityInfo)); 163 } 164 } 165 mAppBarController.setHasSettings(mCurrentSourcePreferences != null); 166 mAppBarController.setHasEqualizer(mShouldShowSoundSettings); 167 } 168 169 170 } 171