diff options
Diffstat (limited to 'src')
4 files changed, 172 insertions, 8 deletions
diff --git a/src/com/android/settings/panel/MediaOutputPanel.java b/src/com/android/settings/panel/MediaOutputPanel.java index d6030cc409..7b69fe382b 100644 --- a/src/com/android/settings/panel/MediaOutputPanel.java +++ b/src/com/android/settings/panel/MediaOutputPanel.java @@ -16,6 +16,9 @@ package com.android.settings.panel; +import static androidx.lifecycle.Lifecycle.Event.ON_START; +import static androidx.lifecycle.Lifecycle.Event.ON_STOP; + import static com.android.settings.media.MediaOutputSlice.MEDIA_PACKAGE_NAME; import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_SLICE_URI; @@ -35,9 +38,15 @@ import android.text.TextUtils; import android.util.Log; import androidx.core.graphics.drawable.IconCompat; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.OnLifecycleEvent; +import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.Utils; +import com.android.settingslib.media.InfoMediaDevice; +import com.android.settingslib.media.LocalMediaManager; +import com.android.settingslib.media.MediaDevice; import java.util.ArrayList; import java.util.List; @@ -49,13 +58,20 @@ import java.util.List; * Displays Media output item * </p> */ -public class MediaOutputPanel implements PanelContent { +public class MediaOutputPanel implements PanelContent, LocalMediaManager.DeviceCallback, + LifecycleObserver { private static final String TAG = "MediaOutputPanel"; private final Context mContext; private final String mPackageName; + private PanelCustomizedButtonCallback mCallback; + private boolean mIsCustomizedButtonUsed = true; + + @VisibleForTesting + LocalMediaManager mLocalMediaManager; + private MediaSessionManager mMediaSessionManager; private MediaController mMediaController; @@ -65,8 +81,9 @@ public class MediaOutputPanel implements PanelContent { private MediaOutputPanel(Context context, String packageName) { mContext = context.getApplicationContext(); - mPackageName = packageName; - if (mPackageName != null) { + mPackageName = TextUtils.isEmpty(packageName) ? "" : packageName; + + if (!TextUtils.isEmpty(mPackageName)) { mMediaSessionManager = mContext.getSystemService(MediaSessionManager.class); for (MediaController controller : mMediaSessionManager.getActiveSessions(null)) { if (TextUtils.equals(controller.getPackageName(), mPackageName)) { @@ -75,6 +92,7 @@ public class MediaOutputPanel implements PanelContent { } } } + if (mMediaController == null) { Log.e(TAG, "Unable to find " + mPackageName + " media controller"); } @@ -157,7 +175,68 @@ public class MediaOutputPanel implements PanelContent { } @Override + public boolean isCustomizedButtonUsed() { + return mIsCustomizedButtonUsed; + } + + @Override + public CharSequence getCustomButtonTitle() { + return mContext.getText(R.string.media_output_panel_stop_casting_button); + } + + @Override + public void onClickCustomizedButton() { + } + + @Override + public void registerCallback(PanelCustomizedButtonCallback callback) { + mCallback = callback; + } + + @Override public int getMetricsCategory() { return SettingsEnums.PANEL_MEDIA_OUTPUT; } + + @Override + public void onSelectedDeviceStateChanged(MediaDevice device, int state) { + dispatchCustomButtonStateChanged(); + } + + @Override + public void onDeviceListUpdate(List<MediaDevice> devices) { + dispatchCustomButtonStateChanged(); + } + + @Override + public void onDeviceAttributesChanged() { + dispatchCustomButtonStateChanged(); + } + + private void dispatchCustomButtonStateChanged() { + hideCustomButtonIfNecessary(); + if (mCallback != null) { + mCallback.onCustomizedButtonStateChanged(); + } + } + + private void hideCustomButtonIfNecessary() { + final MediaDevice device = mLocalMediaManager.getCurrentConnectedDevice(); + mIsCustomizedButtonUsed = device instanceof InfoMediaDevice; + } + + @OnLifecycleEvent(ON_START) + public void onStart() { + if (mLocalMediaManager == null) { + mLocalMediaManager = new LocalMediaManager(mContext, mPackageName, null); + } + mLocalMediaManager.registerCallback(this); + mLocalMediaManager.startScan(); + } + + @OnLifecycleEvent(ON_STOP) + public void onStop() { + mLocalMediaManager.unregisterCallback(this); + mLocalMediaManager.stopScan(); + } } diff --git a/src/com/android/settings/panel/PanelContent.java b/src/com/android/settings/panel/PanelContent.java index 60b9ed7ab1..352a304e24 100644 --- a/src/com/android/settings/panel/PanelContent.java +++ b/src/com/android/settings/panel/PanelContent.java @@ -74,4 +74,31 @@ public interface PanelContent extends Instrumentable { default Intent getHeaderIconIntent() { return null; } + + /** + * @return {@code true} to enable custom button to replace see more button, + * {@code false} otherwise. + */ + default boolean isCustomizedButtonUsed() { + return false; + } + + /** + * @return a string for the title of the custom button. + */ + default CharSequence getCustomButtonTitle() { + return null; + } + + /** + * Implement the click event for custom button. + */ + default void onClickCustomizedButton() {} + + /** + * Register to start receiving callbacks for custom button events. + * + * @param callback the callback to add. + */ + default void registerCallback(PanelCustomizedButtonCallback callback) {} } diff --git a/src/com/android/settings/panel/PanelCustomizedButtonCallback.java b/src/com/android/settings/panel/PanelCustomizedButtonCallback.java new file mode 100644 index 0000000000..8b4290ff1d --- /dev/null +++ b/src/com/android/settings/panel/PanelCustomizedButtonCallback.java @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.settings.panel; + +/** + * PanelCustomizedButtonCallback provides a callback interface for {@link PanelFragment} to receive + * events from {@link PanelContent}. + */ +public interface PanelCustomizedButtonCallback { + + /** + * It will be called when customized button state is changed. For example, custom button + * would be hidden for specific behavior. + */ + void onCustomizedButtonStateChanged(); +} diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java index 0f46758244..31e2ac6ee5 100644 --- a/src/com/android/settings/panel/PanelFragment.java +++ b/src/com/android/settings/panel/PanelFragment.java @@ -41,6 +41,7 @@ import androidx.annotation.Nullable; import androidx.core.graphics.drawable.IconCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; +import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.LiveData; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -53,6 +54,7 @@ import com.android.settings.R; import com.android.settings.overlay.FeatureFactory; import com.android.settings.panel.PanelLoggingContract.PanelClosedKeys; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; +import com.android.settingslib.utils.ThreadUtils; import com.google.android.setupdesign.DividerItemDecoration; @@ -183,6 +185,11 @@ public class PanelFragment extends Fragment { activity.finish(); } + mPanel.registerCallback(new LocalPanelCallback()); + if (mPanel instanceof LifecycleObserver) { + getLifecycle().addObserver((LifecycleObserver) mPanel); + } + mMetricsProvider = FeatureFactory.getFactory(activity).getMetricsFeatureProvider(); mPanelSlices.setLayoutManager(new LinearLayoutManager((activity))); @@ -208,8 +215,15 @@ public class PanelFragment extends Fragment { mSeeMoreButton.setOnClickListener(getSeeMoreListener()); mDoneButton.setOnClickListener(getCloseListener()); - // If getSeeMoreIntent() is null, hide the mSeeMoreButton. - if (mPanel.getSeeMoreIntent() == null) { + if (mPanel.isCustomizedButtonUsed()) { + final CharSequence customTitle = mPanel.getCustomButtonTitle(); + if (TextUtils.isEmpty(customTitle)) { + mSeeMoreButton.setVisibility(View.GONE); + } else { + mSeeMoreButton.setText(customTitle); + } + } else if (mPanel.getSeeMoreIntent() == null) { + // If getSeeMoreIntent() is null hide the mSeeMoreButton. mSeeMoreButton.setVisibility(View.GONE); } @@ -371,9 +385,13 @@ public class PanelFragment extends Fragment { View.OnClickListener getSeeMoreListener() { return (v) -> { mPanelClosedKey = PanelClosedKeys.KEY_SEE_MORE; - final FragmentActivity activity = getActivity(); - activity.startActivityForResult(mPanel.getSeeMoreIntent(), 0); - activity.finish(); + if (mPanel.isCustomizedButtonUsed()) { + mPanel.onClickCustomizedButton(); + } else { + final FragmentActivity activity = getActivity(); + activity.startActivityForResult(mPanel.getSeeMoreIntent(), 0); + activity.finish(); + } }; } @@ -392,4 +410,15 @@ public class PanelFragment extends Fragment { activity.startActivity(mPanel.getHeaderIconIntent()); }; } + + class LocalPanelCallback implements PanelCustomizedButtonCallback { + + @Override + public void onCustomizedButtonStateChanged() { + ThreadUtils.postOnMainThread(() -> { + mSeeMoreButton.setVisibility( + mPanel.isCustomizedButtonUsed() ? View.VISIBLE : View.GONE); + }); + } + } } |