1 /* 2 * Copyright (C) 2023 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.systemui.tv.media; 18 19 import android.annotation.SuppressLint; 20 import android.content.res.Resources; 21 import android.graphics.Rect; 22 import android.media.MediaRouter2; 23 import android.os.Bundle; 24 import android.util.DisplayMetrics; 25 import android.util.Log; 26 import android.view.Gravity; 27 import android.view.Window; 28 import android.view.WindowManager; 29 30 import androidx.fragment.app.FragmentActivity; 31 import androidx.fragment.app.FragmentManager; 32 import androidx.fragment.app.FragmentTransaction; 33 34 import com.android.settingslib.media.flags.Flags; 35 import com.android.systemui.tv.media.settings.SliceFragment; 36 import com.android.systemui.tv.res.R; 37 import com.android.tv.twopanelsettings.slices.SlicesConstants; 38 39 import java.util.Collections; 40 41 import javax.inject.Inject; 42 43 /** 44 * A TV specific variation of the {@link com.android.systemui.media.dialog.MediaOutputDialog}. This 45 * activity allows the user to select a default audio output, which is not based on the currently 46 * playing media. There are two entry points for the dialog, either by sending a broadcast via the 47 * {@link com.android.systemui.media.dialog.MediaOutputDialogReceiver} or by calling {@link 48 * MediaRouter2#showSystemOutputSwitcher()} 49 */ 50 public class TvMediaOutputDialogActivity extends FragmentActivity { 51 private static final String TAG = TvMediaOutputDialogActivity.class.getSimpleName(); 52 private static final boolean DEBUG = false; 53 54 private FragmentManager mFragmentManager; 55 private final OutputDevicesFragment mOutputDevicesFragment; 56 57 @Inject TvMediaOutputDialogActivity(OutputDevicesFragment outputDevicesFragment)58 public TvMediaOutputDialogActivity(OutputDevicesFragment outputDevicesFragment) { 59 mOutputDevicesFragment = outputDevicesFragment; 60 } 61 62 @SuppressLint("MissingPermission") 63 @Override onCreate(Bundle savedInstanceState)64 public void onCreate(Bundle savedInstanceState) { 65 super.onCreate(savedInstanceState); 66 if (DEBUG) Log.d(TAG, "package name: " + getPackageName()); 67 68 if (!Flags.enableTvMediaOutputDialog()) { 69 finish(); 70 return; 71 } 72 73 setContentView(R.layout.media_output_dialog); 74 75 76 Resources res = getResources(); 77 DisplayMetrics metrics = res.getDisplayMetrics(); 78 int screenWidth = metrics.widthPixels; 79 int screenHeight = metrics.heightPixels; 80 int marginVerticalPx = res.getDimensionPixelSize(R.dimen.media_dialog_margin_vertical); 81 int marginEndPx = res.getDimensionPixelSize(R.dimen.media_dialog_margin_end); 82 83 final Window window = getWindow(); 84 final WindowManager.LayoutParams lp = window.getAttributes(); 85 lp.gravity = Gravity.getAbsoluteGravity(Gravity.TOP | Gravity.END, 86 res.getConfiguration().getLayoutDirection()); 87 lp.width = res.getDimensionPixelSize(R.dimen.media_dialog_width); 88 lp.height = screenHeight - 2 * marginVerticalPx; 89 lp.horizontalMargin = ((float) marginEndPx) / screenWidth; 90 lp.verticalMargin = ((float) marginVerticalPx) / screenHeight; 91 window.setBackgroundDrawableResource(R.drawable.media_dialog_background); 92 window.setAttributes(lp); 93 window.setElevation(getWindow().getElevation() + 5); 94 window.setTitle(getString( 95 com.android.systemui.res.R.string.media_output_dialog_accessibility_title)); 96 97 window.getDecorView().addOnLayoutChangeListener( 98 (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) 99 -> findViewById(android.R.id.content).setUnrestrictedPreferKeepClearRects( 100 Collections.singletonList(new Rect(left, top, right, bottom)))); 101 102 mFragmentManager = getSupportFragmentManager(); 103 mFragmentManager.setFragmentResultListener( 104 "deviceSettings", 105 this, 106 (key, bundle) -> { 107 if (key.equals("deviceSettings")) { 108 CharSequence title = bundle.getString("title"); 109 CharSequence subtitle = bundle.getCharSequence("subtitle"); 110 String uri = bundle.getString("uri"); 111 112 SliceFragment sliceFragment = new SliceFragment(); 113 Bundle args = new Bundle(); 114 args.putString(SlicesConstants.TAG_TARGET_URI, uri); 115 args.putCharSequence(SlicesConstants.TAG_SCREEN_TITLE, title); 116 args.putCharSequence(SliceFragment.TAG_SCREEN_SUBTITLE, subtitle); 117 sliceFragment.setArguments(args); 118 119 mFragmentManager 120 .beginTransaction() 121 .replace(R.id.media_output_fragment, sliceFragment) 122 .addToBackStack("device") 123 .commit(); 124 } 125 }); 126 127 showMainFragment(); 128 } 129 showMainFragment()130 private void showMainFragment() { 131 FragmentTransaction transaction = mFragmentManager.beginTransaction(); 132 transaction.replace(R.id.media_output_fragment, mOutputDevicesFragment); 133 transaction.commit(); 134 } 135 136 } 137