diff options
30 files changed, 1 insertions, 3634 deletions
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 4fd47232a0df..58c9f777de33 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -549,26 +549,6 @@ </activity> <!-- started from UsbDeviceSettingsManager --> - <activity android:name=".usb.tv.TvUsbConfirmActivity" - android:exported="true" - android:launchMode="singleTop" - android:permission="android.permission.MANAGE_USB" - android:theme="@style/BottomSheet" - android:finishOnCloseSystemDialogs="true" - android:excludeFromRecents="true"> - </activity> - - <!-- started from UsbDeviceSettingsManager --> - <activity android:name=".usb.tv.TvUsbPermissionActivity" - android:exported="true" - android:launchMode="singleTop" - android:permission="android.permission.MANAGE_USB" - android:theme="@style/BottomSheet" - android:finishOnCloseSystemDialogs="true" - android:excludeFromRecents="true"> - </activity> - - <!-- started from UsbDeviceSettingsManager --> <activity android:name=".usb.UsbResolverActivity" android:exported="true" android:permission="android.permission.MANAGE_USB" @@ -577,16 +557,6 @@ android:excludeFromRecents="true"> </activity> - <!-- started from HdmiCecLocalDevicePlayback --> - <activity android:name=".hdmi.HdmiCecSetMenuLanguageActivity" - android:exported="true" - android:launchMode="singleTop" - android:permission="android.permission.CHANGE_CONFIGURATION" - android:theme="@style/BottomSheet" - android:finishOnCloseSystemDialogs="true" - android:excludeFromRecents="true"> - </activity> - <!-- started from SensoryPrivacyService --> <activity android:name=".sensorprivacy.SensorUseStartedActivity" android:exported="true" @@ -597,27 +567,6 @@ android:showForAllUsers="true"> </activity> - <!-- started from SensoryPrivacyService --> - <activity android:name=".sensorprivacy.television.TvUnblockSensorActivity" - android:exported="true" - android:launchMode="singleTop" - android:permission="android.permission.MANAGE_SENSOR_PRIVACY" - android:theme="@style/BottomSheet" - android:finishOnCloseSystemDialogs="true" - android:showForAllUsers="true"> - </activity> - - <!-- started from SensoryPrivacyService --> - <activity android:name=".sensorprivacy.television.TvSensorPrivacyChangedActivity" - android:exported="true" - android:launchMode="singleTop" - android:permission="android.permission.MANAGE_SENSOR_PRIVACY" - android:theme="@style/BottomSheet" - android:finishOnCloseSystemDialogs="true" - android:showForAllUsers="true"> - </activity> - - <!-- started from UsbDeviceSettingsManager --> <activity android:name=".usb.UsbAccessoryUriActivity" android:exported="true" @@ -703,14 +652,6 @@ android:exported="false" android:permission="android.permission.MANAGE_MEDIA_PROJECTION"/> - <!-- started from TvNotificationPanel --> - <activity - android:name=".statusbar.tv.notifications.TvNotificationPanelActivity" - android:excludeFromRecents="true" - android:launchMode="singleTask" - android:noHistory="true" - android:theme="@style/TvSidePanelTheme" /> - <!-- started from SliceProvider --> <activity android:name=".SlicePermissionActivity" android:theme="@style/Theme.SystemUI.Dialog.Alert" diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java index 04acd0b91173..b01e1369af76 100644 --- a/packages/SystemUI/src/com/android/systemui/Dependency.java +++ b/packages/SystemUI/src/com/android/systemui/Dependency.java @@ -49,7 +49,6 @@ import com.android.systemui.dock.DockManager; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.fragments.FragmentService; -import com.android.systemui.hdmi.HdmiCecSetMenuLanguageHelper; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.media.dialog.MediaOutputDialogFactory; @@ -242,7 +241,6 @@ public class Dependency { @Inject Lazy<LocationController> mLocationController; @Inject Lazy<RotationLockController> mRotationLockController; @Inject Lazy<ZenModeController> mZenModeController; - @Inject Lazy<HdmiCecSetMenuLanguageHelper> mHdmiCecSetMenuLanguageHelper; @Inject Lazy<HotspotController> mHotspotController; @Inject Lazy<CastController> mCastController; @Inject Lazy<FlashlightController> mFlashlightController; diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java index 8d5a2dd8df25..32e40c99a981 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java @@ -20,7 +20,6 @@ import android.app.Activity; import com.android.systemui.ForegroundServicesDialog; import com.android.systemui.contrast.ContrastDialogActivity; -import com.android.systemui.hdmi.HdmiCecSetMenuLanguageActivity; import com.android.systemui.keyguard.WorkLockActivity; import com.android.systemui.people.PeopleSpaceActivity; import com.android.systemui.people.widget.LaunchConversationActivity; @@ -28,10 +27,7 @@ import com.android.systemui.screenshot.LongScreenshotActivity; import com.android.systemui.screenshot.appclips.AppClipsActivity; import com.android.systemui.screenshot.appclips.AppClipsTrampolineActivity; import com.android.systemui.sensorprivacy.SensorUseStartedActivity; -import com.android.systemui.sensorprivacy.television.TvSensorPrivacyChangedActivity; -import com.android.systemui.sensorprivacy.television.TvUnblockSensorActivity; import com.android.systemui.settings.brightness.BrightnessDialog; -import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity; import com.android.systemui.telephony.ui.activity.SwitchToManagedProfileForCallActivity; import com.android.systemui.tuner.TunerActivity; import com.android.systemui.usb.UsbAccessoryUriActivity; @@ -118,12 +114,6 @@ public abstract class DefaultActivityBinder { @ClassKey(CreateUserActivity.class) public abstract Activity bindCreateUserActivity(CreateUserActivity activity); - /** Inject into TvNotificationPanelActivity. */ - @Binds - @IntoMap - @ClassKey(TvNotificationPanelActivity.class) - public abstract Activity bindTvNotificationPanelActivity(TvNotificationPanelActivity activity); - /** Inject into PeopleSpaceActivity. */ @Binds @IntoMap @@ -160,25 +150,7 @@ public abstract class DefaultActivityBinder { @ClassKey(SensorUseStartedActivity.class) public abstract Activity bindSensorUseStartedActivity(SensorUseStartedActivity activity); - /** Inject into TvUnblockSensorActivity. */ - @Binds - @IntoMap - @ClassKey(TvUnblockSensorActivity.class) - public abstract Activity bindTvUnblockSensorActivity(TvUnblockSensorActivity activity); - - /** Inject into HdmiCecSetMenuLanguageActivity. */ - @Binds - @IntoMap - @ClassKey(HdmiCecSetMenuLanguageActivity.class) - public abstract Activity bindHdmiCecSetMenuLanguageActivity( - HdmiCecSetMenuLanguageActivity activity); - /** Inject into TvSensorPrivacyChangedActivity. */ - @Binds - @IntoMap - @ClassKey(TvSensorPrivacyChangedActivity.class) - public abstract Activity bindTvSensorPrivacyChangedActivity( - TvSensorPrivacyChangedActivity activity); /** Inject into SwitchToManagedProfileForCallActivity. */ @Binds diff --git a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java index d70c57fda2e1..dfec771ced26 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/WMComponent.java @@ -21,11 +21,9 @@ import android.os.HandlerThread; import androidx.annotation.Nullable; import com.android.systemui.SystemUIInitializer; -import com.android.systemui.tv.TvWMComponent; import com.android.wm.shell.back.BackAnimation; import com.android.wm.shell.bubbles.Bubbles; import com.android.wm.shell.common.annotations.ShellMainThread; -import com.android.wm.shell.dagger.TvWMShellModule; import com.android.wm.shell.dagger.WMShellModule; import com.android.wm.shell.dagger.WMSingleton; import com.android.wm.shell.desktopmode.DesktopMode; @@ -52,7 +50,7 @@ import java.util.Optional; * provided by its particular device/form-factor SystemUI implementation. * * ie. {@link WMComponent} includes {@link WMShellModule} - * and {@link TvWMComponent} includes {@link TvWMShellModule} + * and {@code TvWMComponent} includes {@link com.android.wm.shell.dagger.TvWMShellModule} */ @WMSingleton @Subcomponent(modules = {WMShellModule.class}) diff --git a/packages/SystemUI/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageActivity.java b/packages/SystemUI/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageActivity.java deleted file mode 100644 index b304c3ca737a..000000000000 --- a/packages/SystemUI/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageActivity.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2022 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.systemui.hdmi; - -import android.hardware.hdmi.HdmiControlManager; -import android.os.Bundle; -import android.view.View; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; - -import com.android.systemui.R; -import com.android.systemui.tv.TvBottomSheetActivity; - -import javax.inject.Inject; - -/** - * Confirmation dialog shown when Set Menu Language CEC message was received. - */ -public class HdmiCecSetMenuLanguageActivity extends TvBottomSheetActivity - implements View.OnClickListener { - private static final String TAG = HdmiCecSetMenuLanguageActivity.class.getSimpleName(); - - private final HdmiCecSetMenuLanguageHelper mHdmiCecSetMenuLanguageHelper; - - @Inject - public HdmiCecSetMenuLanguageActivity( - HdmiCecSetMenuLanguageHelper hdmiCecSetMenuLanguageHelper) { - mHdmiCecSetMenuLanguageHelper = hdmiCecSetMenuLanguageHelper; - } - - @Override - public final void onCreate(Bundle b) { - super.onCreate(b); - getWindow().addPrivateFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); - String languageTag = getIntent().getStringExtra(HdmiControlManager.EXTRA_LOCALE); - mHdmiCecSetMenuLanguageHelper.setLocale(languageTag); - if (mHdmiCecSetMenuLanguageHelper.isLocaleDenylisted()) { - finish(); - } - } - - @Override - public void onResume() { - super.onResume(); - CharSequence title = getString(R.string.hdmi_cec_set_menu_language_title, - mHdmiCecSetMenuLanguageHelper.getLocale().getDisplayLanguage()); - CharSequence text = getString(R.string.hdmi_cec_set_menu_language_description); - initUI(title, text); - } - - @Override - public void onClick(View v) { - if (v.getId() == R.id.bottom_sheet_positive_button) { - mHdmiCecSetMenuLanguageHelper.acceptLocale(); - } else { - mHdmiCecSetMenuLanguageHelper.declineLocale(); - } - finish(); - } - - void initUI(CharSequence title, CharSequence text) { - TextView titleTextView = findViewById(R.id.bottom_sheet_title); - TextView contentTextView = findViewById(R.id.bottom_sheet_body); - ImageView icon = findViewById(R.id.bottom_sheet_icon); - ImageView secondIcon = findViewById(R.id.bottom_sheet_second_icon); - Button okButton = findViewById(R.id.bottom_sheet_positive_button); - Button cancelButton = findViewById(R.id.bottom_sheet_negative_button); - - titleTextView.setText(title); - contentTextView.setText(text); - icon.setImageResource(com.android.internal.R.drawable.ic_settings_language); - secondIcon.setVisibility(View.GONE); - - okButton.setText(R.string.hdmi_cec_set_menu_language_accept); - okButton.setOnClickListener(this); - - cancelButton.setText(R.string.hdmi_cec_set_menu_language_decline); - cancelButton.setOnClickListener(this); - cancelButton.requestFocus(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageHelper.java b/packages/SystemUI/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageHelper.java deleted file mode 100644 index 1f61647b713f..000000000000 --- a/packages/SystemUI/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageHelper.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2022 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.systemui.hdmi; - -import android.os.UserHandle; -import android.provider.Settings; - -import com.android.internal.app.LocalePicker; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Background; -import com.android.systemui.util.settings.SecureSettings; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; -import java.util.Locale; -import java.util.concurrent.Executor; - -import javax.inject.Inject; - -/** - * Helper class to separate model and view for system language change initiated by HDMI CEC. - */ -@SysUISingleton -public class HdmiCecSetMenuLanguageHelper { - private static final String TAG = HdmiCecSetMenuLanguageHelper.class.getSimpleName(); - private static final String SEPARATOR = ","; - - private final Executor mBackgroundExecutor; - private final SecureSettings mSecureSettings; - - private Locale mLocale; - private HashSet<String> mDenylist; - - @Inject - public HdmiCecSetMenuLanguageHelper(@Background Executor executor, - SecureSettings secureSettings) { - mBackgroundExecutor = executor; - mSecureSettings = secureSettings; - String denylist = mSecureSettings.getStringForUser( - Settings.Secure.HDMI_CEC_SET_MENU_LANGUAGE_DENYLIST, UserHandle.USER_CURRENT); - mDenylist = new HashSet<>(denylist == null - ? Collections.EMPTY_SET - : Arrays.asList(denylist.split(SEPARATOR))); - } - - /** - * Set internal locale based on given language tag. - */ - public void setLocale(String languageTag) { - mLocale = Locale.forLanguageTag(languageTag); - } - - /** - * Returns the locale from {@code <Set Menu Language>} CEC message. - */ - public Locale getLocale() { - return mLocale; - } - - /** - * Returns whether the locale from {@code <Set Menu Language>} CEC message was already - * denylisted. - */ - public boolean isLocaleDenylisted() { - return mDenylist.contains(mLocale.toLanguageTag()); - } - - /** - * Accepts the new locale and updates system language. - */ - public void acceptLocale() { - mBackgroundExecutor.execute(() -> LocalePicker.updateLocale(mLocale)); - } - - /** - * Declines the locale and puts it on the denylist. - */ - public void declineLocale() { - mDenylist.add(mLocale.toLanguageTag()); - mSecureSettings.putStringForUser(Settings.Secure.HDMI_CEC_SET_MENU_LANGUAGE_DENYLIST, - String.join(SEPARATOR, mDenylist), UserHandle.USER_CURRENT); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/privacy/television/PrivacyChipDrawable.java b/packages/SystemUI/src/com/android/systemui/privacy/television/PrivacyChipDrawable.java deleted file mode 100644 index 08911d4f8c32..000000000000 --- a/packages/SystemUI/src/com/android/systemui/privacy/television/PrivacyChipDrawable.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.privacy.television; - -import android.animation.Animator; -import android.animation.AnimatorInflater; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.util.Log; -import android.util.MathUtils; -import android.view.Gravity; - -import androidx.annotation.Keep; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.systemui.R; - -/** - * Drawable that can go from being the background of the privacy icons to a small dot. - * The icons are not included. - */ -public class PrivacyChipDrawable extends Drawable { - private static final String TAG = PrivacyChipDrawable.class.getSimpleName(); - private static final boolean DEBUG = false; - - private final Paint mChipPaint; - private final Paint mBgPaint; - private final Rect mTmpRect = new Rect(); - private final Rect mBgRect = new Rect(); - private final RectF mTmpRectF = new RectF(); - private final Path mPath = new Path(); - private final Animator mCollapse; - private final Animator mExpand; - private final int mLayoutDirection; - private final int mBgWidth; - private final int mBgHeight; - private final int mBgRadius; - private final int mDotSize; - private final float mExpandedChipRadius; - private final float mCollapsedChipRadius; - - private final boolean mCollapseToDot; - - private boolean mIsExpanded = true; - private float mCollapseProgress = 0f; - - public PrivacyChipDrawable(Context context, int chipColorRes, boolean collapseToDot) { - mCollapseToDot = collapseToDot; - - mChipPaint = new Paint(); - mChipPaint.setStyle(Paint.Style.FILL); - mChipPaint.setColor(context.getColor(chipColorRes)); - mChipPaint.setFlags(Paint.ANTI_ALIAS_FLAG); - - mBgPaint = new Paint(); - mBgPaint.setStyle(Paint.Style.FILL); - mBgPaint.setColor(context.getColor(R.color.privacy_chip_dot_bg_tint)); - mBgPaint.setFlags(Paint.ANTI_ALIAS_FLAG); - - Resources res = context.getResources(); - mLayoutDirection = res.getConfiguration().getLayoutDirection(); - mBgWidth = res.getDimensionPixelSize(R.dimen.privacy_chip_dot_bg_width); - mBgHeight = res.getDimensionPixelSize(R.dimen.privacy_chip_dot_bg_height); - mBgRadius = res.getDimensionPixelSize(R.dimen.privacy_chip_dot_bg_radius); - mDotSize = res.getDimensionPixelSize(R.dimen.privacy_chip_dot_size); - - mExpandedChipRadius = res.getDimensionPixelSize(R.dimen.privacy_chip_radius); - mCollapsedChipRadius = res.getDimensionPixelSize(R.dimen.privacy_chip_dot_radius); - - mExpand = AnimatorInflater.loadAnimator(context, R.anim.tv_privacy_chip_expand); - mExpand.setTarget(this); - mCollapse = AnimatorInflater.loadAnimator(context, R.anim.tv_privacy_chip_collapse); - mCollapse.setTarget(this); - } - - /** - * @return how far the chip is currently collapsed. - * @see #setCollapseProgress(float) - */ - @Keep - public float getCollapseProgress() { - return mCollapseProgress; - } - - /** - * Sets the collapsing progress of the chip to its collapsed state. - * @param pct How far the chip is collapsed, in the range 0-1. - * 0=fully expanded, 1=fully collapsed. - */ - @Keep - public void setCollapseProgress(float pct) { - mCollapseProgress = pct; - invalidateSelf(); - } - - @Override - public void draw(@NonNull Canvas canvas) { - if (mCollapseProgress > 0f) { - // draw background - getBackgroundBounds(mBgRect); - mTmpRectF.set(mBgRect); - canvas.drawRoundRect(mTmpRectF, mBgRadius, mBgRadius, mBgPaint); - } - - getForegroundBounds(mTmpRectF); - float radius = MathUtils.lerp( - mExpandedChipRadius, - mCollapseToDot ? mCollapsedChipRadius : mBgRadius, - mCollapseProgress); - - canvas.drawRoundRect(mTmpRectF, radius, radius, mChipPaint); - } - - private void getBackgroundBounds(Rect out) { - Rect bounds = getBounds(); - Gravity.apply(Gravity.END, mBgWidth, mBgHeight, bounds, out, mLayoutDirection); - } - - private void getCollapsedForegroundBounds(Rect out) { - Rect bounds = getBounds(); - getBackgroundBounds(mBgRect); - if (mCollapseToDot) { - Gravity.apply(Gravity.CENTER, mDotSize, mDotSize, mBgRect, out); - } else { - out.set(bounds.left, mBgRect.top, bounds.right, mBgRect.bottom); - } - } - - private void getForegroundBounds(RectF out) { - Rect bounds = getBounds(); - getCollapsedForegroundBounds(mTmpRect); - lerpRect(bounds, mTmpRect, mCollapseProgress, out); - } - - private void lerpRect(Rect start, Rect stop, float amount, RectF out) { - float left = MathUtils.lerp(start.left, stop.left, amount); - float top = MathUtils.lerp(start.top, stop.top, amount); - float right = MathUtils.lerp(start.right, stop.right, amount); - float bottom = MathUtils.lerp(start.bottom, stop.bottom, amount); - out.set(left, top, right, bottom); - } - - /** - * Clips the given canvas to this chip's foreground shape. - * @param canvas Canvas to clip. - */ - public void clipToForeground(Canvas canvas) { - getForegroundBounds(mTmpRectF); - float radius = MathUtils.lerp( - mExpandedChipRadius, - mCollapseToDot ? mCollapsedChipRadius : mBgRadius, - mCollapseProgress); - - mPath.reset(); - mPath.addRoundRect(mTmpRectF, radius, radius, Path.Direction.CW); - canvas.clipPath(mPath); - } - - @Override - protected void onBoundsChange(@NonNull Rect bounds) { - super.onBoundsChange(bounds); - invalidateSelf(); - } - - @Override - public void setAlpha(int alpha) { - mChipPaint.setAlpha(alpha); - mBgPaint.setAlpha(alpha); - } - - /** - * Transitions to a full chip. - * - * @param animate Whether to animate the change to a full chip, or expand instantly. - */ - public void expand(boolean animate) { - if (DEBUG) Log.d(TAG, "expanding"); - if (mIsExpanded) { - return; - } - mIsExpanded = true; - if (animate) { - mCollapse.cancel(); - mExpand.start(); - } else { - mCollapseProgress = 0f; - invalidateSelf(); - } - } - - /** - * Starts the animation to a dot. - */ - public void collapse() { - if (DEBUG) Log.d(TAG, "collapsing"); - if (!mIsExpanded) { - return; - } - mIsExpanded = false; - mExpand.cancel(); - mCollapse.start(); - } - - @Override - public void setColorFilter(@Nullable ColorFilter colorFilter) { - // no-op - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/privacy/television/PrivacyItemsChip.java b/packages/SystemUI/src/com/android/systemui/privacy/television/PrivacyItemsChip.java deleted file mode 100644 index 158a5918bfb7..000000000000 --- a/packages/SystemUI/src/com/android/systemui/privacy/television/PrivacyItemsChip.java +++ /dev/null @@ -1,247 +0,0 @@ -/* - * Copyright (C) 2022 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.systemui.privacy.television; - -import android.annotation.ColorRes; -import android.annotation.IntDef; -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.drawable.Drawable; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import androidx.annotation.NonNull; - -import com.android.systemui.R; -import com.android.systemui.privacy.PrivacyType; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -/** - * View that shows indicator icons for privacy items. - */ -public class PrivacyItemsChip extends FrameLayout { - private static final String TAG = "PrivacyItemsChip"; - private static final boolean DEBUG = false; - - /** - * Configuration for a PrivacyItemsChip's appearance. - */ - public static class ChipConfig { - public final List<PrivacyType> privacyTypes; - @ColorRes - public final int colorRes; - public final boolean collapseToDot; - - /** - * @param privacyTypes Privacy types to show icons for, in order. - * @param colorRes Color resource for the chip's foreground color. - * @param collapseToDot Whether to collapse the chip in to a dot, - * or just collapse it into a smaller chip with icons still visible. - */ - public ChipConfig(@NonNull List<PrivacyType> privacyTypes, int colorRes, - boolean collapseToDot) { - this.privacyTypes = privacyTypes; - this.colorRes = colorRes; - this.collapseToDot = collapseToDot; - } - } - - @Retention(RetentionPolicy.SOURCE) - @IntDef(prefix = {"STATE_"}, value = { - STATE_NOT_SHOWN, - STATE_EXPANDED, - STATE_COLLAPSED, - }) - public @interface State { - } - - private static final int STATE_NOT_SHOWN = 0; - private static final int STATE_EXPANDED = 1; - private static final int STATE_COLLAPSED = 2; - - private final ChipConfig mConfig; - private final int mIconSize; - private final int mCollapsedIconSize; - private final int mIconMarginHorizontal; - private final PrivacyChipDrawable mChipBackgroundDrawable; - private final List<ImageView> mIcons = new ArrayList<>(); - - @State - private int mState = STATE_NOT_SHOWN; - - public PrivacyItemsChip(@NonNull Context context, @NonNull ChipConfig config) { - super(context); - mConfig = config; - setVisibility(View.GONE); - - Resources res = context.getResources(); - mIconSize = res.getDimensionPixelSize(R.dimen.privacy_chip_icon_size); - mCollapsedIconSize = res.getDimensionPixelSize(R.dimen.privacy_chip_collapsed_icon_size); - mIconMarginHorizontal = - res.getDimensionPixelSize(R.dimen.privacy_chip_icon_margin_in_between); - - LayoutInflater.from(context).inflate(R.layout.tv_ongoing_privacy_chip, this); - LinearLayout iconsContainer = findViewById(R.id.icons_container); - - mChipBackgroundDrawable = new PrivacyChipDrawable( - context, config.colorRes, config.collapseToDot); - mChipBackgroundDrawable.setCallback(new Drawable.Callback() { - @Override - public void invalidateDrawable(@NonNull Drawable who) { - invalidate(); - } - - @Override - public void scheduleDrawable(@NonNull Drawable who, @NonNull Runnable what, long when) { - } - - @Override - public void unscheduleDrawable(@NonNull Drawable who, @NonNull Runnable what) { - } - }); - - setBackground(mChipBackgroundDrawable); - - for (PrivacyType type : config.privacyTypes) { - ImageView typeIconView = new ImageView(context); - Drawable icon = type.getIcon(context); - icon.mutate().setTint(context.getColor(R.color.privacy_icon_tint)); - - typeIconView.setImageDrawable(icon); - typeIconView.setScaleType(ImageView.ScaleType.FIT_CENTER); - mIcons.add(typeIconView); - iconsContainer.addView(typeIconView, mIconSize, mIconSize); - LinearLayout.LayoutParams lp = - (LinearLayout.LayoutParams) typeIconView.getLayoutParams(); - lp.leftMargin = mIconMarginHorizontal; - lp.rightMargin = mIconMarginHorizontal; - typeIconView.setVisibility(View.GONE); - } - } - - /** - * Sets the active privacy types, and expands the chip if there are active items and the chip is - * currently collapsed, or hides the chip if there are no active items. - * - * @param types The set of active privacy types. Only types configured in {@link ChipConfig} - * are shown. - */ - public void expandForTypes(Set<PrivacyType> types) { - if (DEBUG) Log.d(TAG, "expandForTypes, state=" + stateToString(mState)); - - boolean hasActiveTypes = false; - - for (int i = 0; i < mConfig.privacyTypes.size(); i++) { - PrivacyType type = mConfig.privacyTypes.get(i); - ImageView icon = mIcons.get(i); - boolean isTypeActive = types.contains(type); - hasActiveTypes = hasActiveTypes || isTypeActive; - - icon.setVisibility(isTypeActive ? View.VISIBLE : View.GONE); - - // Set icon size to expanded size - ViewGroup.LayoutParams lp = icon.getLayoutParams(); - lp.width = mIconSize; - lp.height = mIconSize; - icon.requestLayout(); - } - - if (hasActiveTypes) { - if (DEBUG) Log.d(TAG, "Chip has active types, expanding"); - if (mState == STATE_NOT_SHOWN) { - mChipBackgroundDrawable.expand(/* animate= */ false); - } else if (mState == STATE_COLLAPSED) { - mChipBackgroundDrawable.expand(/* animate= */ true); - } - setVisibility(View.VISIBLE); - setState(STATE_EXPANDED); - } else { - if (DEBUG) Log.d(TAG, "Chip has no active types, hiding"); - setVisibility(View.GONE); - setState(STATE_NOT_SHOWN); - } - } - - /** - * Collapses this chip if currently expanded. - */ - public void collapse() { - if (DEBUG) Log.d(TAG, "collapse"); - - if (mState != STATE_EXPANDED) { - return; - } - setState(STATE_COLLAPSED); - - for (ImageView icon : mIcons) { - if (mConfig.collapseToDot) { - icon.setVisibility(View.GONE); - } else { - ViewGroup.LayoutParams lp = icon.getLayoutParams(); - lp.width = mCollapsedIconSize; - lp.height = mCollapsedIconSize; - icon.requestLayout(); - } - } - - mChipBackgroundDrawable.collapse(); - } - - public boolean isExpanded() { - return mState == STATE_EXPANDED; - } - - private void setState(@State int state) { - if (mState != state) { - if (DEBUG) Log.d(TAG, "State changed: " + stateToString(state)); - mState = state; - } - } - - @Override - protected void dispatchDraw(Canvas canvas) { - mChipBackgroundDrawable.clipToForeground(canvas); - super.dispatchDraw(canvas); - } - - /** - * Used in debug logs. - */ - private static String stateToString(@State int state) { - switch (state) { - case STATE_NOT_SHOWN: - return "NOT_SHOWN"; - case STATE_EXPANDED: - return "EXPANDED"; - case STATE_COLLAPSED: - return "COLLAPSED"; - default: - return "INVALID"; - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/privacy/television/TvPrivacyChipsController.java b/packages/SystemUI/src/com/android/systemui/privacy/television/TvPrivacyChipsController.java deleted file mode 100644 index 5e4c797b7de8..000000000000 --- a/packages/SystemUI/src/com/android/systemui/privacy/television/TvPrivacyChipsController.java +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.privacy.television; - -import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.UiThread; -import android.content.Context; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.os.Handler; -import android.os.Looper; -import android.os.RemoteException; -import android.transition.AutoTransition; -import android.transition.ChangeBounds; -import android.transition.Fade; -import android.transition.Transition; -import android.transition.TransitionManager; -import android.transition.TransitionSet; -import android.util.ArraySet; -import android.util.Log; -import android.view.ContextThemeWrapper; -import android.view.Gravity; -import android.view.IWindowManager; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.WindowManager; -import android.view.animation.AnimationUtils; -import android.view.animation.Interpolator; -import android.widget.ImageView; -import android.widget.LinearLayout; - -import com.android.systemui.CoreStartable; -import com.android.systemui.R; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.privacy.PrivacyItem; -import com.android.systemui.privacy.PrivacyItemController; -import com.android.systemui.privacy.PrivacyType; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Set; - -import javax.inject.Inject; - -/** - * A SystemUI component responsible for notifying the user whenever an application is - * recording audio, camera, the screen, or accessing the location. - */ -@SysUISingleton -public class TvPrivacyChipsController - implements CoreStartable, PrivacyItemController.Callback { - private static final String TAG = "TvPrivacyChipsController"; - private static final boolean DEBUG = false; - - // This title is used in CameraMicIndicatorsPermissionTest and - // RecognitionServiceMicIndicatorTest. - private static final String LAYOUT_PARAMS_TITLE = "MicrophoneCaptureIndicator"; - - // Chips configuration. We're not showing a location indicator on TV. - static final List<PrivacyItemsChip.ChipConfig> CHIPS = Arrays.asList( - new PrivacyItemsChip.ChipConfig( - Collections.singletonList(PrivacyType.TYPE_MEDIA_PROJECTION), - R.color.privacy_media_projection_chip, - /* collapseToDot= */ false), - new PrivacyItemsChip.ChipConfig( - Arrays.asList(PrivacyType.TYPE_CAMERA, PrivacyType.TYPE_MICROPHONE), - R.color.privacy_mic_cam_chip, - /* collapseToDot= */ true) - ); - - // Avoid multiple messages after rapid changes such as starting/stopping both camera and mic. - private static final int ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS = 500; - - /** - * Time to collect privacy item updates before applying them. - * Since MediaProjection and AppOps come from different data sources, - * PrivacyItem updates when screen & audio recording ends do not come at the same time. - * Without this, if eg. MediaProjection ends first, you'd see the microphone chip expand and - * almost immediately fade out as it is expanding. With this, the two chips disappear together. - */ - private static final int PRIVACY_ITEM_DEBOUNCE_TIMEOUT_MS = 200; - - // How long chips stay expanded after an update. - private static final int EXPANDED_DURATION_MS = 4000; - - private final Context mContext; - private final Handler mUiThreadHandler = new Handler(Looper.getMainLooper()); - private final Runnable mCollapseRunnable = this::collapseChips; - private final Runnable mUpdatePrivacyItemsRunnable = this::updateChipsAndAnnounce; - private final Runnable mAccessibilityRunnable = this::makeAccessibilityAnnouncement; - - private final PrivacyItemController mPrivacyItemController; - private final IWindowManager mIWindowManager; - private final Rect[] mBounds = new Rect[4]; - private final TransitionSet mTransition; - private final TransitionSet mCollapseTransition; - private boolean mIsRtl; - - @Nullable - private ViewGroup mChipsContainer; - @Nullable - private List<PrivacyItemsChip> mChips; - @NonNull - private List<PrivacyItem> mPrivacyItems = Collections.emptyList(); - @NonNull - private final List<PrivacyItem> mItemsBeforeLastAnnouncement = new ArrayList<>(); - - @Inject - public TvPrivacyChipsController(Context context, PrivacyItemController privacyItemController, - IWindowManager iWindowManager) { - mContext = context; - if (DEBUG) Log.d(TAG, "TvPrivacyChipsController running"); - mPrivacyItemController = privacyItemController; - mIWindowManager = iWindowManager; - - Resources res = mContext.getResources(); - mIsRtl = res.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; - updateStaticPrivacyIndicatorBounds(); - - Interpolator collapseInterpolator = AnimationUtils.loadInterpolator(context, - R.interpolator.tv_privacy_chip_collapse_interpolator); - Interpolator expandInterpolator = AnimationUtils.loadInterpolator(context, - R.interpolator.tv_privacy_chip_expand_interpolator); - - TransitionSet chipFadeTransition = new TransitionSet() - .addTransition(new Fade(Fade.IN)) - .addTransition(new Fade(Fade.OUT)); - chipFadeTransition.setOrdering(TransitionSet.ORDERING_TOGETHER); - chipFadeTransition.excludeTarget(ImageView.class, true); - - Transition chipBoundsExpandTransition = new ChangeBounds(); - chipBoundsExpandTransition.excludeTarget(ImageView.class, true); - chipBoundsExpandTransition.setInterpolator(expandInterpolator); - - Transition chipBoundsCollapseTransition = new ChangeBounds(); - chipBoundsCollapseTransition.excludeTarget(ImageView.class, true); - chipBoundsCollapseTransition.setInterpolator(collapseInterpolator); - - TransitionSet iconCollapseTransition = new AutoTransition(); - iconCollapseTransition.setOrdering(TransitionSet.ORDERING_TOGETHER); - iconCollapseTransition.addTarget(ImageView.class); - iconCollapseTransition.setInterpolator(collapseInterpolator); - - TransitionSet iconExpandTransition = new AutoTransition(); - iconExpandTransition.setOrdering(TransitionSet.ORDERING_TOGETHER); - iconExpandTransition.addTarget(ImageView.class); - iconExpandTransition.setInterpolator(expandInterpolator); - - mTransition = new TransitionSet() - .addTransition(chipFadeTransition) - .addTransition(chipBoundsExpandTransition) - .addTransition(iconExpandTransition) - .setOrdering(TransitionSet.ORDERING_TOGETHER) - .setDuration(res.getInteger(R.integer.privacy_chip_animation_millis)); - - mCollapseTransition = new TransitionSet() - .addTransition(chipFadeTransition) - .addTransition(chipBoundsCollapseTransition) - .addTransition(iconCollapseTransition) - .setOrdering(TransitionSet.ORDERING_TOGETHER) - .setDuration(res.getInteger(R.integer.privacy_chip_animation_millis)); - - Transition.TransitionListener transitionListener = new Transition.TransitionListener() { - @Override - public void onTransitionStart(Transition transition) { - if (DEBUG) Log.v(TAG, "onTransitionStart"); - } - - @Override - public void onTransitionEnd(Transition transition) { - if (DEBUG) Log.v(TAG, "onTransitionEnd"); - if (mChips != null) { - boolean hasVisibleChip = false; - boolean hasExpandedChip = false; - for (PrivacyItemsChip chip : mChips) { - hasVisibleChip = hasVisibleChip || chip.getVisibility() == View.VISIBLE; - hasExpandedChip = hasExpandedChip || chip.isExpanded(); - } - - if (!hasVisibleChip) { - if (DEBUG) Log.d(TAG, "No chips visible anymore"); - removeIndicatorView(); - } else if (hasExpandedChip) { - if (DEBUG) Log.d(TAG, "Has expanded chips"); - collapseLater(); - } - } - } - - @Override - public void onTransitionCancel(Transition transition) { - } - - @Override - public void onTransitionPause(Transition transition) { - } - - @Override - public void onTransitionResume(Transition transition) { - } - }; - - mTransition.addListener(transitionListener); - mCollapseTransition.addListener(transitionListener); - } - - @Override - public void onConfigurationChanged(Configuration config) { - boolean updatedRtl = config.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL; - if (mIsRtl == updatedRtl) { - return; - } - mIsRtl = updatedRtl; - - // Update privacy chip location. - if (mChipsContainer != null) { - removeIndicatorView(); - createAndShowIndicator(); - } - updateStaticPrivacyIndicatorBounds(); - } - - @Override - public void start() { - mPrivacyItemController.addCallback(this); - } - - @UiThread - @Override - public void onPrivacyItemsChanged(List<PrivacyItem> privacyItems) { - if (DEBUG) Log.d(TAG, "onPrivacyItemsChanged"); - - List<PrivacyItem> filteredPrivacyItems = new ArrayList<>(privacyItems); - if (filteredPrivacyItems.removeIf( - privacyItem -> !isPrivacyTypeShown(privacyItem.getPrivacyType()))) { - if (DEBUG) Log.v(TAG, "Removed privacy items we don't show"); - } - - // Do they have the same elements? (order doesn't matter) - if (privacyItems.size() == mPrivacyItems.size() && mPrivacyItems.containsAll( - privacyItems)) { - if (DEBUG) Log.d(TAG, "No change to relevant privacy items"); - return; - } - - mPrivacyItems = privacyItems; - - if (!mUiThreadHandler.hasCallbacks(mUpdatePrivacyItemsRunnable)) { - mUiThreadHandler.postDelayed(mUpdatePrivacyItemsRunnable, - PRIVACY_ITEM_DEBOUNCE_TIMEOUT_MS); - } - } - - private boolean isPrivacyTypeShown(@NonNull PrivacyType type) { - for (PrivacyItemsChip.ChipConfig chip : CHIPS) { - if (chip.privacyTypes.contains(type)) { - return true; - } - } - return false; - } - - @UiThread - private void updateChipsAndAnnounce() { - updateChips(); - postAccessibilityAnnouncement(); - } - - private void updateStaticPrivacyIndicatorBounds() { - Resources res = mContext.getResources(); - int mMaxExpandedWidth = res.getDimensionPixelSize(R.dimen.privacy_chips_max_width); - int mMaxExpandedHeight = res.getDimensionPixelSize(R.dimen.privacy_chip_height); - int mChipMarginTotal = 2 * res.getDimensionPixelSize(R.dimen.privacy_chip_margin); - - final WindowManager windowManager = mContext.getSystemService(WindowManager.class); - Rect screenBounds = windowManager.getCurrentWindowMetrics().getBounds(); - mBounds[0] = new Rect( - mIsRtl ? screenBounds.left - : screenBounds.right - mMaxExpandedWidth, - screenBounds.top, - mIsRtl ? screenBounds.left + mMaxExpandedWidth - : screenBounds.right, - screenBounds.top + mChipMarginTotal + mMaxExpandedHeight - ); - - if (DEBUG) Log.v(TAG, "privacy indicator bounds: " + mBounds[0].toShortString()); - - try { - mIWindowManager.updateStaticPrivacyIndicatorBounds(mContext.getDisplayId(), mBounds); - } catch (RemoteException e) { - Log.w(TAG, "could not update privacy indicator bounds"); - } - } - - @UiThread - private void updateChips() { - if (DEBUG) Log.d(TAG, "updateChips: " + mPrivacyItems.size() + " privacy items"); - - if (mChipsContainer == null) { - if (!mPrivacyItems.isEmpty()) { - createAndShowIndicator(); - } - return; - } - - Set<PrivacyType> activePrivacyTypes = new ArraySet<>(); - mPrivacyItems.forEach(item -> activePrivacyTypes.add(item.getPrivacyType())); - - TransitionManager.beginDelayedTransition(mChipsContainer, mTransition); - mChips.forEach(chip -> chip.expandForTypes(activePrivacyTypes)); - } - - /** - * Collapse the chip {@link #EXPANDED_DURATION_MS} from now. - */ - private void collapseLater() { - mUiThreadHandler.removeCallbacks(mCollapseRunnable); - if (DEBUG) Log.d(TAG, "Chips will collapse in " + EXPANDED_DURATION_MS + "ms"); - mUiThreadHandler.postDelayed(mCollapseRunnable, EXPANDED_DURATION_MS); - } - - private void collapseChips() { - if (DEBUG) Log.d(TAG, "collapseChips"); - if (mChipsContainer == null) { - return; - } - - boolean hasExpandedChip = false; - for (PrivacyItemsChip chip : mChips) { - hasExpandedChip |= chip.isExpanded(); - } - - if (mChipsContainer != null && hasExpandedChip) { - TransitionManager.beginDelayedTransition(mChipsContainer, mCollapseTransition); - for (PrivacyItemsChip chip : mChips) { - chip.collapse(); - } - } - } - - @UiThread - private void createAndShowIndicator() { - if (DEBUG) Log.i(TAG, "Creating privacy indicators"); - - Context privacyChipContext = new ContextThemeWrapper(mContext, R.style.PrivacyChip); - mChips = new ArrayList<>(); - mChipsContainer = (ViewGroup) LayoutInflater.from(privacyChipContext) - .inflate(R.layout.tv_privacy_chip_container, null); - - int chipMargins = privacyChipContext.getResources() - .getDimensionPixelSize(R.dimen.privacy_chip_margin); - LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT); - lp.setMarginStart(chipMargins); - lp.setMarginEnd(chipMargins); - - for (PrivacyItemsChip.ChipConfig chipConfig : CHIPS) { - PrivacyItemsChip chip = new PrivacyItemsChip(privacyChipContext, chipConfig); - mChipsContainer.addView(chip, lp); - mChips.add(chip); - } - - final WindowManager windowManager = mContext.getSystemService(WindowManager.class); - windowManager.addView(mChipsContainer, getWindowLayoutParams()); - - final ViewGroup container = mChipsContainer; - mChipsContainer.getViewTreeObserver() - .addOnGlobalLayoutListener( - new ViewTreeObserver.OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (DEBUG) Log.v(TAG, "Chips container laid out"); - container.getViewTreeObserver().removeOnGlobalLayoutListener(this); - updateChips(); - } - }); - } - - private WindowManager.LayoutParams getWindowLayoutParams() { - final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams( - WRAP_CONTENT, - WRAP_CONTENT, - WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, - WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, - PixelFormat.TRANSLUCENT); - layoutParams.gravity = Gravity.TOP | (mIsRtl ? Gravity.LEFT : Gravity.RIGHT); - layoutParams.setTitle(LAYOUT_PARAMS_TITLE); - layoutParams.packageName = mContext.getPackageName(); - return layoutParams; - } - - @UiThread - private void removeIndicatorView() { - if (DEBUG) Log.d(TAG, "removeIndicatorView"); - mUiThreadHandler.removeCallbacks(mCollapseRunnable); - - final WindowManager windowManager = mContext.getSystemService(WindowManager.class); - if (windowManager != null && mChipsContainer != null) { - windowManager.removeView(mChipsContainer); - } - - mChipsContainer = null; - mChips = null; - } - - /** - * Schedules the accessibility announcement to be made after {@link - * #ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS} (if possible). This is so that only one announcement is - * made instead of two separate ones if both the camera and the mic are started/stopped. - */ - @UiThread - private void postAccessibilityAnnouncement() { - mUiThreadHandler.removeCallbacks(mAccessibilityRunnable); - - if (mPrivacyItems.size() == 0) { - // Announce immediately since announcement cannot be made once the chip is gone. - makeAccessibilityAnnouncement(); - } else { - mUiThreadHandler.postDelayed(mAccessibilityRunnable, - ACCESSIBILITY_ANNOUNCEMENT_DELAY_MS); - } - } - - private void makeAccessibilityAnnouncement() { - if (mChipsContainer == null) { - return; - } - - boolean cameraWasRecording = listContainsPrivacyType(mItemsBeforeLastAnnouncement, - PrivacyType.TYPE_CAMERA); - boolean cameraIsRecording = listContainsPrivacyType(mPrivacyItems, - PrivacyType.TYPE_CAMERA); - boolean micWasRecording = listContainsPrivacyType(mItemsBeforeLastAnnouncement, - PrivacyType.TYPE_MICROPHONE); - boolean micIsRecording = listContainsPrivacyType(mPrivacyItems, - PrivacyType.TYPE_MICROPHONE); - - boolean screenWasRecording = listContainsPrivacyType(mItemsBeforeLastAnnouncement, - PrivacyType.TYPE_MEDIA_PROJECTION); - boolean screenIsRecording = listContainsPrivacyType(mPrivacyItems, - PrivacyType.TYPE_MEDIA_PROJECTION); - - int announcement = 0; - if (!cameraWasRecording && cameraIsRecording && !micWasRecording && micIsRecording) { - // Both started - announcement = R.string.mic_and_camera_recording_announcement; - } else if (cameraWasRecording && !cameraIsRecording && micWasRecording && !micIsRecording) { - // Both stopped - announcement = R.string.mic_camera_stopped_recording_announcement; - } else { - // Did the camera start or stop? - if (cameraWasRecording && !cameraIsRecording) { - announcement = R.string.camera_stopped_recording_announcement; - } else if (!cameraWasRecording && cameraIsRecording) { - announcement = R.string.camera_recording_announcement; - } - - // Announce camera changes now since we might need a second announcement about the mic. - if (announcement != 0) { - mChipsContainer.announceForAccessibility(mContext.getString(announcement)); - announcement = 0; - } - - // Did the mic start or stop? - if (micWasRecording && !micIsRecording) { - announcement = R.string.mic_stopped_recording_announcement; - } else if (!micWasRecording && micIsRecording) { - announcement = R.string.mic_recording_announcement; - } - } - - if (announcement != 0) { - mChipsContainer.announceForAccessibility(mContext.getString(announcement)); - } - - if (!screenWasRecording && screenIsRecording) { - mChipsContainer.announceForAccessibility( - mContext.getString(R.string.screen_recording_announcement)); - } else if (screenWasRecording && !screenIsRecording) { - mChipsContainer.announceForAccessibility( - mContext.getString(R.string.screen_stopped_recording_announcement)); - } - - mItemsBeforeLastAnnouncement.clear(); - mItemsBeforeLastAnnouncement.addAll(mPrivacyItems); - } - - private boolean listContainsPrivacyType(List<PrivacyItem> list, PrivacyType privacyType) { - for (PrivacyItem item : list) { - if (item.getPrivacyType() == privacyType) { - return true; - } - } - return false; - } -} diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvSensorPrivacyChangedActivity.java b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvSensorPrivacyChangedActivity.java deleted file mode 100644 index 731b177a58a6..000000000000 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvSensorPrivacyChangedActivity.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2022 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.systemui.sensorprivacy.television; - -import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; -import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE; - -import android.annotation.DimenRes; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.Drawable; -import android.hardware.SensorPrivacyManager; -import android.os.Bundle; -import android.provider.Settings; -import android.util.Log; -import android.view.View; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; - -import com.android.systemui.R; -import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; -import com.android.systemui.tv.TvBottomSheetActivity; -import com.android.systemui.util.settings.GlobalSettings; - -import javax.inject.Inject; - -/** - * Bottom sheet that is shown when the camera/mic sensors privacy state changed - * by the global software toggle or physical privacy switch. - */ -public class TvSensorPrivacyChangedActivity extends TvBottomSheetActivity { - - private static final String TAG = TvSensorPrivacyChangedActivity.class.getSimpleName(); - - private static final int ALL_SENSORS = Integer.MAX_VALUE; - - private int mSensor = -1; - private int mToggleType = -1; - - private final GlobalSettings mGlobalSettings; - private final IndividualSensorPrivacyController mSensorPrivacyController; - private IndividualSensorPrivacyController.Callback mSensorPrivacyCallback; - private TextView mTitle; - private TextView mContent; - private ImageView mIcon; - private ImageView mSecondIcon; - private Button mPositiveButton; - private Button mCancelButton; - - @Inject - public TvSensorPrivacyChangedActivity( - IndividualSensorPrivacyController individualSensorPrivacyController, - GlobalSettings globalSettings) { - mSensorPrivacyController = individualSensorPrivacyController; - mGlobalSettings = globalSettings; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); - - boolean allSensors = getIntent().getBooleanExtra(SensorPrivacyManager.EXTRA_ALL_SENSORS, - false); - if (allSensors) { - mSensor = ALL_SENSORS; - } else { - mSensor = getIntent().getIntExtra(SensorPrivacyManager.EXTRA_SENSOR, -1); - } - - mToggleType = getIntent().getIntExtra(SensorPrivacyManager.EXTRA_TOGGLE_TYPE, -1); - - if (mSensor == -1 || mToggleType == -1) { - Log.v(TAG, "Invalid extras"); - finish(); - return; - } - - // Do not show for software toggles - if (mToggleType == SensorPrivacyManager.TOGGLE_TYPE_SOFTWARE) { - finish(); - return; - } - - mSensorPrivacyCallback = (sensor, blocked) -> { - updateUI(); - }; - - initUI(); - } - - private void initUI() { - mTitle = findViewById(R.id.bottom_sheet_title); - mContent = findViewById(R.id.bottom_sheet_body); - mIcon = findViewById(R.id.bottom_sheet_icon); - // mic icon if both icons are shown - mSecondIcon = findViewById(R.id.bottom_sheet_second_icon); - mPositiveButton = findViewById(R.id.bottom_sheet_positive_button); - mCancelButton = findViewById(R.id.bottom_sheet_negative_button); - - mCancelButton.setText(android.R.string.cancel); - mCancelButton.setOnClickListener(v -> finish()); - - updateUI(); - } - - private void updateUI() { - final Resources resources = getResources(); - setIconTint(resources.getBoolean(R.bool.config_unblockHwSensorIconEnableTint)); - setIconSize(R.dimen.unblock_hw_sensor_icon_width, R.dimen.unblock_hw_sensor_icon_height); - - switch (mSensor) { - case CAMERA: - updateUiForCameraUpdate( - mSensorPrivacyController.isSensorBlockedByHardwareToggle(CAMERA)); - break; - case MICROPHONE: - default: - updateUiForMicUpdate( - mSensorPrivacyController.isSensorBlockedByHardwareToggle(MICROPHONE)); - break; - } - - // Start animation if drawable is animated - Drawable iconDrawable = mIcon.getDrawable(); - if (iconDrawable instanceof Animatable) { - ((Animatable) iconDrawable).start(); - } - - mPositiveButton.setVisibility(View.GONE); - mCancelButton.setText(android.R.string.ok); - } - - private void updateUiForMicUpdate(boolean blocked) { - if (blocked) { - mTitle.setText(R.string.sensor_privacy_mic_turned_off_dialog_title); - if (isExplicitUserInteractionAudioBypassAllowed()) { - mContent.setText(R.string.sensor_privacy_mic_blocked_with_exception_dialog_content); - } else { - mContent.setText(R.string.sensor_privacy_mic_blocked_no_exception_dialog_content); - } - mIcon.setImageResource(R.drawable.unblock_hw_sensor_microphone); - mSecondIcon.setVisibility(View.GONE); - } else { - mTitle.setText(R.string.sensor_privacy_mic_turned_on_dialog_title); - mContent.setText(R.string.sensor_privacy_mic_unblocked_dialog_content); - mIcon.setImageResource(com.android.internal.R.drawable.ic_mic_allowed); - mSecondIcon.setVisibility(View.GONE); - } - } - - private void updateUiForCameraUpdate(boolean blocked) { - if (blocked) { - mTitle.setText(R.string.sensor_privacy_camera_turned_off_dialog_title); - mContent.setText(R.string.sensor_privacy_camera_blocked_dialog_content); - mIcon.setImageResource(R.drawable.unblock_hw_sensor_camera); - mSecondIcon.setVisibility(View.GONE); - } else { - mTitle.setText(R.string.sensor_privacy_camera_turned_on_dialog_title); - mContent.setText(R.string.sensor_privacy_camera_unblocked_dialog_content); - mIcon.setImageResource(com.android.internal.R.drawable.ic_camera_allowed); - mSecondIcon.setVisibility(View.GONE); - } - } - - private void setIconTint(boolean enableTint) { - final Resources resources = getResources(); - - if (enableTint) { - final ColorStateList iconTint = resources.getColorStateList( - R.color.bottom_sheet_icon_color, getTheme()); - mIcon.setImageTintList(iconTint); - mSecondIcon.setImageTintList(iconTint); - } else { - mIcon.setImageTintList(null); - mSecondIcon.setImageTintList(null); - } - - mIcon.invalidate(); - mSecondIcon.invalidate(); - } - - private void setIconSize(@DimenRes int widthRes, @DimenRes int heightRes) { - final Resources resources = getResources(); - final int iconWidth = resources.getDimensionPixelSize(widthRes); - final int iconHeight = resources.getDimensionPixelSize(heightRes); - - mIcon.getLayoutParams().width = iconWidth; - mIcon.getLayoutParams().height = iconHeight; - mIcon.invalidate(); - - mSecondIcon.getLayoutParams().width = iconWidth; - mSecondIcon.getLayoutParams().height = iconHeight; - mSecondIcon.invalidate(); - } - - private boolean isExplicitUserInteractionAudioBypassAllowed() { - return mGlobalSettings.getInt( - Settings.Global.RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO_ENABLED, 1) == 1; - } - - @Override - public void onResume() { - super.onResume(); - updateUI(); - mSensorPrivacyController.addCallback(mSensorPrivacyCallback); - } - - @Override - public void onPause() { - mSensorPrivacyController.removeCallback(mSensorPrivacyCallback); - super.onPause(); - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java b/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java deleted file mode 100644 index 1b9657f3dca7..000000000000 --- a/packages/SystemUI/src/com/android/systemui/sensorprivacy/television/TvUnblockSensorActivity.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.sensorprivacy.television; - -import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY; -import static android.hardware.SensorPrivacyManager.Sensors.CAMERA; -import static android.hardware.SensorPrivacyManager.Sensors.MICROPHONE; -import static android.hardware.SensorPrivacyManager.Sources.OTHER; - -import android.annotation.DimenRes; -import android.app.AppOpsManager; -import android.app.role.RoleManager; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.content.res.ColorStateList; -import android.content.res.Resources; -import android.graphics.drawable.Animatable; -import android.graphics.drawable.Drawable; -import android.hardware.SensorPrivacyManager; -import android.os.Bundle; -import android.os.UserHandle; -import android.util.Log; -import android.view.View; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; -import android.widget.Toast; - -import com.android.systemui.R; -import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; -import com.android.systemui.tv.TvBottomSheetActivity; - -import java.util.List; - -import javax.inject.Inject; - -/** - * Bottom sheet that is shown when the camera/mic sensors are blocked by the global software toggle - * or physical privacy switch. - */ -public class TvUnblockSensorActivity extends TvBottomSheetActivity { - - private static final String TAG = TvUnblockSensorActivity.class.getSimpleName(); - private static final String ACTION_MANAGE_CAMERA_PRIVACY = - "android.settings.MANAGE_CAMERA_PRIVACY"; - private static final String ACTION_MANAGE_MICROPHONE_PRIVACY = - "android.settings.MANAGE_MICROPHONE_PRIVACY"; - - private static final int ALL_SENSORS = Integer.MAX_VALUE; - - private int mSensor = -1; - - private final AppOpsManager mAppOpsManager; - private final RoleManager mRoleManager; - private final IndividualSensorPrivacyController mSensorPrivacyController; - private IndividualSensorPrivacyController.Callback mSensorPrivacyCallback; - private TextView mTitle; - private TextView mContent; - private ImageView mIcon; - private ImageView mSecondIcon; - private Button mPositiveButton; - private Button mCancelButton; - - @Inject - public TvUnblockSensorActivity( - IndividualSensorPrivacyController individualSensorPrivacyController, - AppOpsManager appOpsManager, RoleManager roleManager) { - mSensorPrivacyController = individualSensorPrivacyController; - mAppOpsManager = appOpsManager; - mRoleManager = roleManager; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - getWindow().addSystemFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); - - boolean allSensors = getIntent().getBooleanExtra(SensorPrivacyManager.EXTRA_ALL_SENSORS, - false); - if (allSensors) { - mSensor = ALL_SENSORS; - } else { - mSensor = getIntent().getIntExtra(SensorPrivacyManager.EXTRA_SENSOR, -1); - } - - if (mSensor == -1) { - Log.v(TAG, "Invalid extras"); - finish(); - return; - } - - mSensorPrivacyCallback = (sensor, blocked) -> { - if (mSensor == ALL_SENSORS && !mSensorPrivacyController.isSensorBlocked(CAMERA) - && !mSensorPrivacyController.isSensorBlocked(MICROPHONE)) { - showToastAndFinish(); - } else if (this.mSensor == sensor && !blocked) { - showToastAndFinish(); - } else { - updateUI(); - } - }; - - initUI(); - } - - private void showToastAndFinish() { - final int toastMsgResId; - switch(mSensor) { - case MICROPHONE: - toastMsgResId = R.string.sensor_privacy_mic_unblocked_toast_content; - break; - case CAMERA: - toastMsgResId = R.string.sensor_privacy_camera_unblocked_toast_content; - break; - case ALL_SENSORS: - default: - toastMsgResId = R.string.sensor_privacy_mic_camera_unblocked_toast_content; - break; - } - showToastAndFinish(toastMsgResId); - } - - private void showToastAndFinish(int toastMsgResId) { - Toast.makeText(this, toastMsgResId, Toast.LENGTH_SHORT).show(); - finish(); - } - - private boolean isBlockedByHardwareToggle() { - if (mSensor == ALL_SENSORS) { - return mSensorPrivacyController.isSensorBlockedByHardwareToggle(CAMERA) - || mSensorPrivacyController.isSensorBlockedByHardwareToggle(MICROPHONE); - } else { - return mSensorPrivacyController.isSensorBlockedByHardwareToggle(mSensor); - } - } - - private void initUI() { - mTitle = findViewById(R.id.bottom_sheet_title); - mContent = findViewById(R.id.bottom_sheet_body); - mIcon = findViewById(R.id.bottom_sheet_icon); - // mic icon if both icons are shown - mSecondIcon = findViewById(R.id.bottom_sheet_second_icon); - mPositiveButton = findViewById(R.id.bottom_sheet_positive_button); - mCancelButton = findViewById(R.id.bottom_sheet_negative_button); - - mCancelButton.setText(android.R.string.cancel); - mCancelButton.setOnClickListener(v -> finish()); - - updateUI(); - } - - private void updateUI() { - if (isHTTAccessDisabled()) { - updateUiForHTT(); - } else if (isBlockedByHardwareToggle()) { - updateUiForHardwareToggle(); - } else { - updateUiForSoftwareToggle(); - } - } - - private void updateUiForHardwareToggle() { - final Resources resources = getResources(); - - boolean micBlocked = (mSensor == MICROPHONE || mSensor == ALL_SENSORS) - && mSensorPrivacyController.isSensorBlockedByHardwareToggle(MICROPHONE); - boolean cameraBlocked = (mSensor == CAMERA || mSensor == ALL_SENSORS) - && mSensorPrivacyController.isSensorBlockedByHardwareToggle(CAMERA); - - setIconTint(resources.getBoolean(R.bool.config_unblockHwSensorIconEnableTint)); - setIconSize(R.dimen.unblock_hw_sensor_icon_width, R.dimen.unblock_hw_sensor_icon_height); - - if (micBlocked && cameraBlocked) { - mTitle.setText(R.string.sensor_privacy_start_use_mic_camera_blocked_dialog_title); - mContent.setText( - R.string.sensor_privacy_start_use_mic_camera_blocked_dialog_content); - mIcon.setImageResource(R.drawable.unblock_hw_sensor_all); - - Drawable secondIconDrawable = resources.getDrawable( - R.drawable.unblock_hw_sensor_all_second, getTheme()); - if (secondIconDrawable == null) { - mSecondIcon.setVisibility(View.GONE); - } else { - mSecondIcon.setImageDrawable(secondIconDrawable); - } - } else if (cameraBlocked) { - mTitle.setText(R.string.sensor_privacy_start_use_camera_blocked_dialog_title); - mContent.setText(R.string.sensor_privacy_start_use_camera_blocked_dialog_content); - mIcon.setImageResource(R.drawable.unblock_hw_sensor_camera); - mSecondIcon.setVisibility(View.GONE); - } else if (micBlocked) { - mTitle.setText(R.string.sensor_privacy_start_use_mic_blocked_dialog_title); - mContent.setText(R.string.sensor_privacy_start_use_mic_blocked_dialog_content); - mIcon.setImageResource(R.drawable.unblock_hw_sensor_microphone); - mSecondIcon.setVisibility(View.GONE); - } - - // Start animation if drawable is animated - Drawable iconDrawable = mIcon.getDrawable(); - if (iconDrawable instanceof Animatable) { - ((Animatable) iconDrawable).start(); - } - - mPositiveButton.setVisibility(View.GONE); - mCancelButton.setText(android.R.string.ok); - } - - private void updateUiForSoftwareToggle() { - setIconTint(true); - setIconSize(R.dimen.bottom_sheet_icon_size, R.dimen.bottom_sheet_icon_size); - - switch (mSensor) { - case MICROPHONE: - mTitle.setText(R.string.sensor_privacy_start_use_mic_blocked_dialog_title); - mContent.setText(R.string.sensor_privacy_start_use_mic_dialog_content); - mIcon.setImageResource(com.android.internal.R.drawable.perm_group_microphone); - mSecondIcon.setVisibility(View.GONE); - break; - case CAMERA: - mTitle.setText(R.string.sensor_privacy_start_use_camera_blocked_dialog_title); - mContent.setText(R.string.sensor_privacy_start_use_camera_dialog_content); - mIcon.setImageResource(com.android.internal.R.drawable.perm_group_camera); - mSecondIcon.setVisibility(View.GONE); - break; - case ALL_SENSORS: - default: - mTitle.setText(R.string.sensor_privacy_start_use_mic_camera_blocked_dialog_title); - mContent.setText(R.string.sensor_privacy_start_use_mic_camera_dialog_content); - mIcon.setImageResource(com.android.internal.R.drawable.perm_group_camera); - mSecondIcon.setImageResource( - com.android.internal.R.drawable.perm_group_microphone); - break; - } - - mPositiveButton.setText( - com.android.internal.R.string.sensor_privacy_start_use_dialog_turn_on_button); - mPositiveButton.setOnClickListener(v -> { - if (mSensor == ALL_SENSORS) { - mSensorPrivacyController.setSensorBlocked(OTHER, CAMERA, false); - mSensorPrivacyController.setSensorBlocked(OTHER, MICROPHONE, false); - } else { - mSensorPrivacyController.setSensorBlocked(OTHER, mSensor, false); - } - }); - } - - private void updateUiForHTT() { - setIconTint(true); - setIconSize(R.dimen.bottom_sheet_icon_size, R.dimen.bottom_sheet_icon_size); - - mTitle.setText(R.string.sensor_privacy_start_use_mic_blocked_dialog_title); - mContent.setText(R.string.sensor_privacy_htt_blocked_dialog_content); - mIcon.setImageResource(com.android.internal.R.drawable.perm_group_microphone); - mSecondIcon.setVisibility(View.GONE); - - mPositiveButton.setText(R.string.sensor_privacy_dialog_open_settings); - mPositiveButton.setOnClickListener(v -> { - Intent openPrivacySettings = new Intent(ACTION_MANAGE_MICROPHONE_PRIVACY); - ActivityInfo activityInfo = openPrivacySettings.resolveActivityInfo(getPackageManager(), - MATCH_SYSTEM_ONLY); - if (activityInfo == null) { - showToastAndFinish(com.android.internal.R.string.noApplications); - } else { - startActivity(openPrivacySettings); - finish(); - } - }); - } - - private void setIconTint(boolean enableTint) { - final Resources resources = getResources(); - - if (enableTint) { - final ColorStateList iconTint = resources.getColorStateList( - R.color.bottom_sheet_icon_color, getTheme()); - mIcon.setImageTintList(iconTint); - mSecondIcon.setImageTintList(iconTint); - } else { - mIcon.setImageTintList(null); - mSecondIcon.setImageTintList(null); - } - - mIcon.invalidate(); - mSecondIcon.invalidate(); - } - - private void setIconSize(@DimenRes int widthRes, @DimenRes int heightRes) { - final Resources resources = getResources(); - final int iconWidth = resources.getDimensionPixelSize(widthRes); - final int iconHeight = resources.getDimensionPixelSize(heightRes); - - mIcon.getLayoutParams().width = iconWidth; - mIcon.getLayoutParams().height = iconHeight; - mIcon.invalidate(); - - mSecondIcon.getLayoutParams().width = iconWidth; - mSecondIcon.getLayoutParams().height = iconHeight; - mSecondIcon.invalidate(); - } - - private boolean isHTTAccessDisabled() { - String pkg = getIntent().getStringExtra(Intent.EXTRA_PACKAGE_NAME); - List<String> assistantPkgs = mRoleManager.getRoleHolders(RoleManager.ROLE_ASSISTANT); - if (!assistantPkgs.contains(pkg)) { - return false; - } - - return (mAppOpsManager.checkOpNoThrow( - AppOpsManager.OP_RECEIVE_EXPLICIT_USER_INTERACTION_AUDIO, UserHandle.myUserId(), - pkg) != AppOpsManager.MODE_ALLOWED); - } - - @Override - public void onResume() { - super.onResume(); - updateUI(); - mSensorPrivacyController.addCallback(mSensorPrivacyCallback); - } - - @Override - public void onPause() { - mSensorPrivacyController.removeCallback(mSensorPrivacyCallback); - super.onPause(); - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS b/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS deleted file mode 100644 index a601e9b86ef4..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/OWNERS +++ /dev/null @@ -1,8 +0,0 @@ -# Android TV Core Framework -rgl@google.com -valiiftime@google.com -galinap@google.com -patrikf@google.com -robhor@google.com -sergeynv@google.com - diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java deleted file mode 100644 index d35d34063d1e..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2012 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.systemui.statusbar.tv; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.os.RemoteException; -import android.os.ServiceManager; - -import com.android.internal.statusbar.IStatusBarService; -import com.android.systemui.CoreStartable; -import com.android.systemui.assist.AssistManager; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.KeyboardShortcuts; - -import dagger.Lazy; - -import javax.inject.Inject; - -/** - * Status bar implementation for "large screen" products that mostly present no on-screen nav. - * Serves as a collection of UI components, rather than showing its own UI. - */ -@SysUISingleton -public class TvStatusBar implements CoreStartable, CommandQueue.Callbacks { - - private static final String ACTION_SHOW_PIP_MENU = - "com.android.wm.shell.pip.tv.notification.action.SHOW_PIP_MENU"; - private static final String SYSTEMUI_PERMISSION = "com.android.systemui.permission.SELF"; - - private final Context mContext; - private final CommandQueue mCommandQueue; - private final Lazy<AssistManager> mAssistManagerLazy; - - @Inject - public TvStatusBar(Context context, CommandQueue commandQueue, - Lazy<AssistManager> assistManagerLazy) { - mContext = context; - mCommandQueue = commandQueue; - mAssistManagerLazy = assistManagerLazy; - } - - @Override - public void start() { - final IStatusBarService barService = IStatusBarService.Stub.asInterface( - ServiceManager.getService(Context.STATUS_BAR_SERVICE)); - mCommandQueue.addCallback(this); - try { - barService.registerStatusBar(mCommandQueue); - } catch (RemoteException ex) { - // If the system process isn't there we're doomed anyway. - } - } - - @Override - public void startAssist(Bundle args) { - mAssistManagerLazy.get().startAssist(args); - } - - @Override - public void showPictureInPictureMenu() { - mContext.sendBroadcast( - new Intent(ACTION_SHOW_PIP_MENU).setPackage(mContext.getPackageName()), - SYSTEMUI_PERMISSION); - } - - @Override - public void toggleKeyboardShortcutsMenu(int deviceId) { - KeyboardShortcuts.show(mContext, deviceId); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt b/packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt deleted file mode 100644 index b938c9002d90..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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. - */ - -@file:JvmName("VpnStatusObserver") - -package com.android.systemui.statusbar.tv - -import android.app.Notification -import android.app.NotificationChannel -import android.app.NotificationManager -import android.content.Context -import com.android.internal.messages.nano.SystemMessageProto -import com.android.internal.net.VpnConfig -import com.android.systemui.CoreStartable -import com.android.systemui.R -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.statusbar.policy.SecurityController -import javax.inject.Inject - -/** - * Observes if a vpn connection is active and displays a notification to the user - */ -@SysUISingleton -class VpnStatusObserver @Inject constructor( - private val context: Context, - private val securityController: SecurityController -) : CoreStartable, - SecurityController.SecurityControllerCallback { - - private var vpnConnected = false - private val notificationManager = NotificationManager.from(context) - private val notificationChannel = createNotificationChannel() - private val vpnConnectedNotificationBuilder = createVpnConnectedNotificationBuilder() - private val vpnDisconnectedNotification = createVpnDisconnectedNotification() - - private val vpnIconId: Int - get() = if (securityController.isVpnBranded) { - R.drawable.stat_sys_branded_vpn - } else { - R.drawable.stat_sys_vpn_ic - } - - private val vpnName: String? - get() = securityController.primaryVpnName ?: securityController.workProfileVpnName - - override fun start() { - // register callback to vpn state changes - securityController.addCallback(this) - } - - override fun onStateChanged() { - securityController.isVpnEnabled.let { newVpnConnected -> - if (vpnConnected != newVpnConnected) { - if (newVpnConnected) { - notifyVpnConnected() - } else { - notifyVpnDisconnected() - } - vpnConnected = newVpnConnected - } - } - } - - private fun notifyVpnConnected() = notificationManager.notify( - NOTIFICATION_TAG, - SystemMessageProto.SystemMessage.NOTE_VPN_STATUS, - createVpnConnectedNotification() - ) - - private fun notifyVpnDisconnected() = notificationManager.run { - // remove existing connected notification - cancel(NOTIFICATION_TAG, SystemMessageProto.SystemMessage.NOTE_VPN_STATUS) - // show the disconnected notification only for a short while - notify(NOTIFICATION_TAG, SystemMessageProto.SystemMessage.NOTE_VPN_DISCONNECTED, - vpnDisconnectedNotification) - } - - private fun createNotificationChannel() = - NotificationChannel( - NOTIFICATION_CHANNEL_TV_VPN, - NOTIFICATION_CHANNEL_TV_VPN, - NotificationManager.IMPORTANCE_HIGH - ).also { - notificationManager.createNotificationChannel(it) - } - - private fun createVpnConnectedNotification() = - vpnConnectedNotificationBuilder - .apply { - vpnName?.let { - setContentText( - context.getString( - R.string.notification_disclosure_vpn_text, it - ) - ) - } - } - .build() - - private fun createVpnConnectedNotificationBuilder() = - Notification.Builder(context, NOTIFICATION_CHANNEL_TV_VPN) - .setSmallIcon(vpnIconId) - .setVisibility(Notification.VISIBILITY_PUBLIC) - .setCategory(Notification.CATEGORY_SYSTEM) - .extend(Notification.TvExtender()) - .setOngoing(true) - .setContentTitle(context.getString(R.string.notification_vpn_connected)) - .setContentIntent(VpnConfig.getIntentForStatusPanel(context)) - - private fun createVpnDisconnectedNotification() = - Notification.Builder(context, NOTIFICATION_CHANNEL_TV_VPN) - .setSmallIcon(vpnIconId) - .setVisibility(Notification.VISIBILITY_PUBLIC) - .setCategory(Notification.CATEGORY_SYSTEM) - .extend(Notification.TvExtender()) - .setTimeoutAfter(VPN_DISCONNECTED_NOTIFICATION_TIMEOUT_MS) - .setContentTitle(context.getString(R.string.notification_vpn_disconnected)) - .build() - - companion object { - const val NOTIFICATION_CHANNEL_TV_VPN = "VPN Status" - val NOTIFICATION_TAG: String = VpnStatusObserver::class.java.simpleName - - private const val TAG = "TvVpnNotification" - private const val VPN_DISCONNECTED_NOTIFICATION_TIMEOUT_MS = 5_000L - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationAdapter.java deleted file mode 100644 index fd7c30f39693..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationAdapter.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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.systemui.statusbar.tv.notifications; - -import android.app.BroadcastOptions; -import android.app.Notification; -import android.app.PendingIntent; -import android.service.notification.StatusBarNotification; -import android.util.Log; -import android.util.SparseArray; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; - -import com.android.systemui.R; - -/** - * Adapter for the VerticalGridView of the TvNotificationsPanelView. - */ -public class TvNotificationAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { - private static final String TAG = "TvNotificationAdapter"; - private SparseArray<StatusBarNotification> mNotifications; - - public TvNotificationAdapter() { - setHasStableIds(true); - } - - @NonNull - @Override - public TvNotificationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.tv_notification_item, - parent, false); - return new TvNotificationViewHolder(view); - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int position) { - if (mNotifications == null) { - Log.e(TAG, "Could not bind view holder because the notification is missing"); - return; - } - - TvNotificationViewHolder holder = (TvNotificationViewHolder) viewHolder; - Notification notification = mNotifications.valueAt(position).getNotification(); - holder.mTitle.setText(notification.extras.getString(Notification.EXTRA_TITLE)); - holder.mDetails.setText(notification.extras.getString(Notification.EXTRA_TEXT)); - holder.mPendingIntent = notification.contentIntent; - } - - @Override - public int getItemCount() { - return mNotifications == null ? 0 : mNotifications.size(); - } - - @Override - public long getItemId(int position) { - // the item id is the notification id - return mNotifications.keyAt(position); - } - - /** - * Updates the notifications and calls notifyDataSetChanged(). - */ - public void setNotifications(SparseArray<StatusBarNotification> notifications) { - this.mNotifications = notifications; - notifyDataSetChanged(); - } - - private static class TvNotificationViewHolder extends RecyclerView.ViewHolder implements - View.OnClickListener { - final TextView mTitle; - final TextView mDetails; - PendingIntent mPendingIntent; - - protected TvNotificationViewHolder(View itemView) { - super(itemView); - mTitle = itemView.findViewById(R.id.tv_notification_title); - mDetails = itemView.findViewById(R.id.tv_notification_details); - itemView.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - try { - if (mPendingIntent != null) { - BroadcastOptions options = BroadcastOptions.makeBasic(); - options.setInteractive(true); - options.setPendingIntentBackgroundActivityStartMode( - BroadcastOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED); - mPendingIntent.send(options.toBundle()); - } - } catch (PendingIntent.CanceledException e) { - Log.d(TAG, "Pending intent canceled for : " + mPendingIntent); - } - } - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationHandler.java deleted file mode 100644 index b92725bd7cf7..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationHandler.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.systemui.statusbar.tv.notifications; - -import android.annotation.Nullable; -import android.app.Notification; -import android.service.notification.NotificationListenerService; -import android.service.notification.StatusBarNotification; -import android.util.Log; -import android.util.SparseArray; - -import com.android.systemui.CoreStartable; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.statusbar.NotificationListener; - -import javax.inject.Inject; - -/** - * Keeps track of the notifications on TV. - */ -@SysUISingleton -public class TvNotificationHandler implements CoreStartable, - NotificationListener.NotificationHandler { - private static final String TAG = "TvNotificationHandler"; - private final NotificationListener mNotificationListener; - private final SparseArray<StatusBarNotification> mNotifications = new SparseArray<>(); - @Nullable - private Listener mUpdateListener; - - @Inject - public TvNotificationHandler(NotificationListener notificationListener) { - mNotificationListener = notificationListener; - } - - public SparseArray<StatusBarNotification> getCurrentNotifications() { - return mNotifications; - } - - public void setTvNotificationListener(Listener listener) { - mUpdateListener = listener; - } - - @Override - public void start() { - mNotificationListener.addNotificationHandler(this); - mNotificationListener.registerAsSystemService(); - } - - @Override - public void onNotificationPosted(StatusBarNotification sbn, - NotificationListenerService.RankingMap rankingMap) { - if (!new Notification.TvExtender(sbn.getNotification()).isAvailableOnTv()) { - Log.v(TAG, "Notification not added because it isn't relevant for tv"); - return; - } - - mNotifications.put(sbn.getId(), sbn); - if (mUpdateListener != null) { - mUpdateListener.notificationsUpdated(mNotifications); - } - Log.d(TAG, "Notification added"); - } - - @Override - public void onNotificationRemoved(StatusBarNotification sbn, - NotificationListenerService.RankingMap rankingMap) { - - if (mNotifications.contains(sbn.getId())) { - mNotifications.remove(sbn.getId()); - Log.d(TAG, "Notification removed"); - - if (mUpdateListener != null) { - mUpdateListener.notificationsUpdated(mNotifications); - } - } - } - - @Override - public void onNotificationRemoved(StatusBarNotification sbn, - NotificationListenerService.RankingMap rankingMap, int reason) { - onNotificationRemoved(sbn, rankingMap); - } - - @Override - public void onNotificationRankingUpdate(NotificationListenerService.RankingMap rankingMap) { - // noop - } - - @Override - public void onNotificationsInitialized() { - // noop - } - - /** - * Get notified when the notifications are updated. - */ - interface Listener { - void notificationsUpdated(SparseArray<StatusBarNotification> sbns); - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanel.java deleted file mode 100644 index dbbd0b8613de..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanel.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * 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.systemui.statusbar.tv.notifications; - -import android.Manifest; -import android.app.NotificationManager; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.os.UserHandle; -import android.util.Log; - -import com.android.systemui.CoreStartable; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.statusbar.CommandQueue; - -import javax.inject.Inject; - -/** - * Offers control methods for the notification panel handler on TV devices. - */ -@SysUISingleton -public class TvNotificationPanel implements CoreStartable, CommandQueue.Callbacks { - private static final String TAG = "TvNotificationPanel"; - private final Context mContext; - private final CommandQueue mCommandQueue; - private final String mNotificationHandlerPackage; - - @Inject - public TvNotificationPanel(Context context, CommandQueue commandQueue) { - mContext = context; - mCommandQueue = commandQueue; - mNotificationHandlerPackage = mContext.getResources().getString( - com.android.internal.R.string.config_notificationHandlerPackage); - } - - @Override - public void start() { - mCommandQueue.addCallback(this); - } - - @Override - public void togglePanel() { - if (!mNotificationHandlerPackage.isEmpty()) { - startNotificationHandlerActivity( - new Intent(NotificationManager.ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL)); - } else { - openInternalNotificationPanel( - NotificationManager.ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL); - } - } - - @Override - public void animateExpandNotificationsPanel() { - if (!mNotificationHandlerPackage.isEmpty()) { - startNotificationHandlerActivity( - new Intent(NotificationManager.ACTION_OPEN_NOTIFICATION_HANDLER_PANEL)); - } else { - openInternalNotificationPanel( - NotificationManager.ACTION_OPEN_NOTIFICATION_HANDLER_PANEL); - } - } - - @Override - public void animateCollapsePanels(int flags, boolean force) { - if (!mNotificationHandlerPackage.isEmpty() - && (flags & CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL) == 0) { - Intent closeNotificationIntent = new Intent( - NotificationManager.ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL); - closeNotificationIntent.setPackage(mNotificationHandlerPackage); - mContext.sendBroadcastAsUser(closeNotificationIntent, UserHandle.CURRENT); - } else { - openInternalNotificationPanel( - NotificationManager.ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL); - } - } - - private void openInternalNotificationPanel(String action) { - Intent intent = new Intent(mContext, TvNotificationPanelActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - intent.setAction(action); - mContext.startActivityAsUser(intent, UserHandle.SYSTEM); - } - - /** - * Starts the activity intent if all of the following are true - * <ul> - * <li> the notification handler package is a system component </li> - * <li> the provided intent is handled by the notification handler package </li> - * <li> the notification handler requests the - * {@link android.Manifest.permission#STATUS_BAR_SERVICE} permission for the given intent</li> - * </ul> - * - * @param intent The intent for starting the desired activity - */ - private void startNotificationHandlerActivity(Intent intent) { - intent.setPackage(mNotificationHandlerPackage); - PackageManager pm = mContext.getPackageManager(); - ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_SYSTEM_ONLY); - if (ri != null && ri.activityInfo != null) { - if (ri.activityInfo.permission != null && ri.activityInfo.permission.equals( - Manifest.permission.STATUS_BAR_SERVICE)) { - intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP); - mContext.startActivityAsUser(intent, UserHandle.CURRENT); - } else { - Log.e(TAG, - "Not launching notification handler activity: Notification handler does " - + "not require the STATUS_BAR_SERVICE permission for intent " - + intent.getAction()); - } - } else { - Log.e(TAG, - "Not launching notification handler activity: Could not resolve activityInfo " - + "for intent " - + intent.getAction()); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanelActivity.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanelActivity.java deleted file mode 100644 index b325b10957f7..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/notifications/TvNotificationPanelActivity.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.systemui.statusbar.tv.notifications; - -import android.annotation.NonNull; -import android.app.Activity; -import android.app.NotificationManager; -import android.content.Intent; -import android.graphics.drawable.ColorDrawable; -import android.os.Bundle; -import android.service.notification.StatusBarNotification; -import android.util.SparseArray; -import android.view.Gravity; -import android.view.View; - -import androidx.leanback.widget.VerticalGridView; - -import com.android.systemui.R; - -import java.util.function.Consumer; - -import javax.inject.Inject; - -/** - * This Activity shows a notification panel for tv. It is used if no other app (e.g. a launcher) can - * be found to show the notifications. - */ -public class TvNotificationPanelActivity extends Activity implements - TvNotificationHandler.Listener { - private final TvNotificationHandler mTvNotificationHandler; - private TvNotificationAdapter mTvNotificationAdapter; - private VerticalGridView mNotificationListView; - private View mNotificationPlaceholder; - private boolean mPanelAlreadyOpen = false; - private final Consumer<Boolean> mBlurConsumer = this::enableBlur; - - @Inject - public TvNotificationPanelActivity(TvNotificationHandler tvNotificationHandler) { - super(); - mTvNotificationHandler = tvNotificationHandler; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - if (maybeClosePanel(getIntent())) { - return; - } - mPanelAlreadyOpen = true; - - setContentView(R.layout.tv_notification_panel); - - mNotificationPlaceholder = findViewById(R.id.no_tv_notifications); - mTvNotificationAdapter = new TvNotificationAdapter(); - - mNotificationListView = findViewById(R.id.notifications_list); - mNotificationListView.setAdapter(mTvNotificationAdapter); - mNotificationListView.setColumnWidth(R.dimen.tv_notification_panel_width); - - mTvNotificationHandler.setTvNotificationListener(this); - notificationsUpdated(mTvNotificationHandler.getCurrentNotifications()); - } - - @Override - public void notificationsUpdated(@NonNull SparseArray<StatusBarNotification> notificationList) { - mTvNotificationAdapter.setNotifications(notificationList); - - boolean noNotifications = notificationList.size() == 0; - mNotificationListView.setVisibility(noNotifications ? View.GONE : View.VISIBLE); - mNotificationPlaceholder.setVisibility(noNotifications ? View.VISIBLE : View.GONE); - } - - @Override - public void onNewIntent(Intent intent) { - super.onNewIntent(intent); - maybeClosePanel(intent); - } - - /** - * Handles intents from onCreate and onNewIntent. - * - * @return true if the panel is being closed, false if it is being opened - */ - private boolean maybeClosePanel(Intent intent) { - if (NotificationManager.ACTION_CLOSE_NOTIFICATION_HANDLER_PANEL.equals(intent.getAction()) - || (mPanelAlreadyOpen - && NotificationManager.ACTION_TOGGLE_NOTIFICATION_HANDLER_PANEL.equals( - intent.getAction()))) { - finish(); - return true; - } - return false; - } - - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - getWindow().setGravity(Gravity.END); - getWindowManager().addCrossWindowBlurEnabledListener(mBlurConsumer); - } - - private void enableBlur(boolean enabled) { - if (enabled) { - int blurRadius = getResources().getDimensionPixelSize( - R.dimen.tv_notification_blur_radius); - getWindow().setBackgroundDrawable( - new ColorDrawable(getColor(R.color.tv_notification_blur_background_color))); - getWindow().setBackgroundBlurRadius(blurRadius); - } else { - getWindow().setBackgroundDrawable( - new ColorDrawable(getColor(R.color.tv_notification_default_background_color))); - getWindow().setBackgroundBlurRadius(0); - } - } - - @Override - public void onDetachedFromWindow() { - super.onDetachedFromWindow(); - getWindowManager().removeCrossWindowBlurEnabledListener(mBlurConsumer); - } - - @Override - public void onDestroy() { - super.onDestroy(); - mTvNotificationHandler.setTvNotificationListener(null); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt b/packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt deleted file mode 100644 index 573fbf79784e..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.tv - -import com.android.systemui.CoreStartable -import com.android.systemui.SliceBroadcastRelayHandler -import com.android.systemui.accessibility.WindowMagnification -import com.android.systemui.dagger.qualifiers.PerUser -import com.android.systemui.globalactions.GlobalActionsComponent -import com.android.systemui.keyboard.KeyboardUI -import com.android.systemui.media.RingtonePlayer -import com.android.systemui.media.systemsounds.HomeSoundEffectController -import com.android.systemui.power.PowerUI -import com.android.systemui.privacy.television.TvPrivacyChipsController -import com.android.systemui.shortcut.ShortcutKeyDispatcher -import com.android.systemui.statusbar.notification.InstantAppNotifier -import com.android.systemui.statusbar.tv.TvStatusBar -import com.android.systemui.statusbar.tv.VpnStatusObserver -import com.android.systemui.statusbar.tv.notifications.TvNotificationHandler -import com.android.systemui.statusbar.tv.notifications.TvNotificationPanel -import com.android.systemui.theme.ThemeOverlayController -import com.android.systemui.toast.ToastUI -import com.android.systemui.usb.StorageNotification -import com.android.systemui.util.NotificationChannels -import com.android.systemui.volume.VolumeUI -import com.android.systemui.wmshell.WMShell -import dagger.Binds -import dagger.Module -import dagger.multibindings.ClassKey -import dagger.multibindings.IntoMap - -/** - * Collection of {@link CoreStartable}s that should be run on TV. - */ -@Module -abstract class TVSystemUICoreStartableModule { - /** Inject into GlobalActionsComponent. */ - @Binds - @IntoMap - @ClassKey(GlobalActionsComponent::class) - abstract fun bindGlobalActionsComponent(sysui: GlobalActionsComponent): CoreStartable - - /** Inject into HomeSoundEffectController. */ - @Binds - @IntoMap - @ClassKey(HomeSoundEffectController::class) - abstract fun bindHomeSoundEffectController(sysui: HomeSoundEffectController): CoreStartable - - /** Inject into InstantAppNotifier. */ - @Binds - @IntoMap - @ClassKey(InstantAppNotifier::class) - abstract fun bindInstantAppNotifier(sysui: InstantAppNotifier): CoreStartable - - /** Inject into KeyboardUI. */ - @Binds - @IntoMap - @ClassKey(KeyboardUI::class) - abstract fun bindKeyboardUI(sysui: KeyboardUI): CoreStartable - - /** Inject into NotificationChannels. */ - @Binds - @IntoMap - @ClassKey(NotificationChannels::class) - @PerUser - abstract fun bindNotificationChannels(sysui: NotificationChannels): CoreStartable - - /** Inject into PowerUI. */ - @Binds - @IntoMap - @ClassKey(PowerUI::class) - abstract fun bindPowerUI(sysui: PowerUI): CoreStartable - - /** Inject into RingtonePlayer. */ - @Binds - @IntoMap - @ClassKey(RingtonePlayer::class) - abstract fun bind(sysui: RingtonePlayer): CoreStartable - - /** Inject into ShortcutKeyDispatcher. */ - @Binds - @IntoMap - @ClassKey(ShortcutKeyDispatcher::class) - abstract fun bindShortcutKeyDispatcher(sysui: ShortcutKeyDispatcher): CoreStartable - - /** Inject into SliceBroadcastRelayHandler. */ - @Binds - @IntoMap - @ClassKey(SliceBroadcastRelayHandler::class) - abstract fun bindSliceBroadcastRelayHandler(sysui: SliceBroadcastRelayHandler): CoreStartable - - /** Inject into StorageNotification. */ - @Binds - @IntoMap - @ClassKey(StorageNotification::class) - abstract fun bindStorageNotification(sysui: StorageNotification): CoreStartable - - /** Inject into ThemeOverlayController. */ - @Binds - @IntoMap - @ClassKey(ThemeOverlayController::class) - abstract fun bindThemeOverlayController(sysui: ThemeOverlayController): CoreStartable - - /** Inject into ToastUI. */ - @Binds - @IntoMap - @ClassKey(ToastUI::class) - abstract fun bindToastUI(service: ToastUI): CoreStartable - - /** Inject into TvNotificationHandler. */ - @Binds - @IntoMap - @ClassKey(TvNotificationHandler::class) - abstract fun bindTvNotificationHandler(sysui: TvNotificationHandler): CoreStartable - - /** Inject into TvNotificationPanel. */ - @Binds - @IntoMap - @ClassKey(TvNotificationPanel::class) - abstract fun bindTvNotificationPanel(sysui: TvNotificationPanel): CoreStartable - - /** Inject into TvPrivacyChipsController. */ - @Binds - @IntoMap - @ClassKey(TvPrivacyChipsController::class) - abstract fun bindTvPrivacyChipsController(sysui: TvPrivacyChipsController): CoreStartable - - /** Inject into TvStatusBar. */ - @Binds - @IntoMap - @ClassKey(TvStatusBar::class) - abstract fun bindTvStatusBar(sysui: TvStatusBar): CoreStartable - - /** Inject into VolumeUI. */ - @Binds - @IntoMap - @ClassKey(VolumeUI::class) - abstract fun bindVolumeUI(sysui: VolumeUI): CoreStartable - - /** Inject into VpnStatusObserver. */ - @Binds - @IntoMap - @ClassKey(VpnStatusObserver::class) - abstract fun bindVpnStatusObserver(sysui: VpnStatusObserver): CoreStartable - - /** Inject into WindowMagnification. */ - @Binds - @IntoMap - @ClassKey(WindowMagnification::class) - abstract fun bindWindowMagnification(sysui: WindowMagnification): CoreStartable - - /** Inject into WMShell. */ - @Binds - @IntoMap - @ClassKey(WMShell::class) - abstract fun bindWMShell(sysui: WMShell): CoreStartable -} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvBottomSheetActivity.java b/packages/SystemUI/src/com/android/systemui/tv/TvBottomSheetActivity.java deleted file mode 100644 index 90f24347d20d..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tv/TvBottomSheetActivity.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.tv; - -import android.app.Activity; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.os.Bundle; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.Gravity; -import android.view.View; -import android.view.WindowManager; - -import com.android.systemui.R; - -import java.util.Collections; -import java.util.function.Consumer; - -/** - * Generic bottom sheet with up to two icons in the beginning and two buttons. - */ -public abstract class TvBottomSheetActivity extends Activity { - - private static final String TAG = TvBottomSheetActivity.class.getSimpleName(); - private Drawable mBackgroundWithBlur; - private Drawable mBackgroundWithoutBlur; - - private final Consumer<Boolean> mBlurConsumer = this::onBlurChanged; - - private void onBlurChanged(boolean enabled) { - Log.v(TAG, "blur enabled: " + enabled); - getWindow().setBackgroundDrawable(enabled ? mBackgroundWithBlur : mBackgroundWithoutBlur); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.tv_bottom_sheet); - - overridePendingTransition(R.anim.tv_bottom_sheet_enter, 0); - - mBackgroundWithBlur = getResources() - .getDrawable(R.drawable.bottom_sheet_background_with_blur); - mBackgroundWithoutBlur = getResources().getDrawable(R.drawable.bottom_sheet_background); - - DisplayMetrics metrics = getResources().getDisplayMetrics(); - int screenWidth = metrics.widthPixels; - int screenHeight = metrics.heightPixels; - int marginPx = getResources().getDimensionPixelSize(R.dimen.bottom_sheet_margin); - - WindowManager.LayoutParams windowParams = getWindow().getAttributes(); - windowParams.width = screenWidth - marginPx * 2; - windowParams.height = WindowManager.LayoutParams.WRAP_CONTENT; - windowParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL; - windowParams.horizontalMargin = 0f; - windowParams.verticalMargin = (float) marginPx / screenHeight; - windowParams.format = PixelFormat.TRANSPARENT; - windowParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG; - windowParams.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - windowParams.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED; - getWindow().setAttributes(windowParams); - getWindow().setElevation(getWindow().getElevation() + 5); - getWindow().setBackgroundBlurRadius(getResources().getDimensionPixelSize( - R.dimen.bottom_sheet_background_blur_radius)); - - final View rootView = findViewById(R.id.bottom_sheet); - rootView.addOnLayoutChangeListener((view, l, t, r, b, oldL, oldT, oldR, oldB) -> { - rootView.setUnrestrictedPreferKeepClearRects( - Collections.singletonList(new Rect(0, 0, r - l, b - t))); - }); - } - - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - getWindowManager().addCrossWindowBlurEnabledListener(mBlurConsumer); - } - - @Override - public void onDetachedFromWindow() { - getWindowManager().removeCrossWindowBlurEnabledListener(mBlurConsumer); - super.onDetachedFromWindow(); - } - - @Override - public void finish() { - super.finish(); - overridePendingTransition(0, R.anim.tv_bottom_sheet_exit); - } - -} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java deleted file mode 100644 index 117cba7401e9..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tv/TvGlobalRootComponent.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2019 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.systemui.tv; - -import com.android.systemui.dagger.GlobalModule; -import com.android.systemui.dagger.GlobalRootComponent; - -import javax.inject.Singleton; - -import dagger.Component; - -/** - * Root component for Dagger injection. - */ -@Singleton -@Component(modules = {GlobalModule.class}) -public interface TvGlobalRootComponent extends GlobalRootComponent { - /** - * Component Builder interface. This allows to bind Context instance in the component - */ - @Component.Builder - interface Builder extends GlobalRootComponent.Builder { - TvGlobalRootComponent build(); - } - - @Override - TvWMComponent.Builder getWMComponentBuilder(); - - @Override - TvSysUIComponent.Builder getSysUIComponent(); -} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java deleted file mode 100644 index 82589d3ea1d4..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSysUIComponent.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2019 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.systemui.tv; - -import com.android.systemui.dagger.DefaultComponentBinder; -import com.android.systemui.dagger.DependencyProvider; -import com.android.systemui.dagger.SysUIComponent; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.SystemUIModule; -import com.android.systemui.globalactions.ShutdownUiModule; -import com.android.systemui.keyguard.dagger.KeyguardModule; -import com.android.systemui.recents.RecentsModule; -import com.android.systemui.statusbar.dagger.CentralSurfacesDependenciesModule; -import com.android.systemui.statusbar.notification.dagger.NotificationsModule; -import com.android.systemui.statusbar.notification.row.NotificationRowModule; -import com.android.systemui.wallpapers.dagger.NoopWallpaperModule; - -import dagger.Subcomponent; - -/** - * Dagger Subcomponent for Core SysUI. - */ -@SysUISingleton -@Subcomponent(modules = { - CentralSurfacesDependenciesModule.class, - DefaultComponentBinder.class, - DependencyProvider.class, - KeyguardModule.class, - NoopWallpaperModule.class, - NotificationRowModule.class, - NotificationsModule.class, - RecentsModule.class, - ShutdownUiModule.class, - SystemUIModule.class, - TvSystemUIBinder.class, - TVSystemUICoreStartableModule.class, - TvSystemUIModule.class}) -public interface TvSysUIComponent extends SysUIComponent { - - /** - * Builder for a SysUIComponent. - */ - @Subcomponent.Builder - interface Builder extends SysUIComponent.Builder { - TvSysUIComponent build(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java deleted file mode 100644 index 23f37ec8dc69..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIBinder.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2019 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.systemui.tv; - -import com.android.systemui.dagger.GlobalRootComponent; - -import dagger.Binds; -import dagger.Module; - -@Module -interface TvSystemUIBinder { - @Binds - GlobalRootComponent bindGlobalRootComponent(TvGlobalRootComponent globalRootComponent); -} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIInitializer.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIInitializer.java deleted file mode 100644 index fabbb2c1f44d..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIInitializer.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2019 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.systemui.tv; - -import android.content.Context; - -import com.android.systemui.SystemUIInitializer; -import com.android.systemui.dagger.GlobalRootComponent; - -/** - * TV variant {@link SystemUIInitializer}, that substitutes default {@link GlobalRootComponent} for - * {@link TvGlobalRootComponent} - */ -public class TvSystemUIInitializer extends SystemUIInitializer { - public TvSystemUIInitializer(Context context) { - super(context); - } - - @Override - protected GlobalRootComponent.Builder getGlobalRootComponentBuilder() { - return DaggerTvGlobalRootComponent.builder(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java deleted file mode 100644 index b0e8ec2f2df6..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2019 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.systemui.tv; - -import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME; -import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME; - -import android.content.Context; -import android.hardware.SensorPrivacyManager; -import android.os.Handler; - -import com.android.internal.logging.UiEventLogger; -import com.android.keyguard.KeyguardViewController; -import com.android.systemui.dagger.ReferenceSystemUIModule; -import com.android.systemui.dagger.SysUISingleton; -import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.dock.DockManager; -import com.android.systemui.dock.DockManagerImpl; -import com.android.systemui.doze.DozeHost; -import com.android.systemui.navigationbar.gestural.GestureModule; -import com.android.systemui.plugins.qs.QSFactory; -import com.android.systemui.plugins.statusbar.StatusBarStateController; -import com.android.systemui.power.dagger.PowerModule; -import com.android.systemui.privacy.MediaProjectionPrivacyItemMonitor; -import com.android.systemui.privacy.PrivacyItemMonitor; -import com.android.systemui.qs.dagger.QSModule; -import com.android.systemui.qs.tileimpl.QSFactoryImpl; -import com.android.systemui.recents.Recents; -import com.android.systemui.recents.RecentsImplementation; -import com.android.systemui.screenshot.ReferenceScreenshotModule; -import com.android.systemui.settings.dagger.MultiUserUtilsModule; -import com.android.systemui.shade.NotificationShadeWindowControllerImpl; -import com.android.systemui.shade.ShadeEmptyImplModule; -import com.android.systemui.shade.ShadeExpansionStateManager; -import com.android.systemui.statusbar.CommandQueue; -import com.android.systemui.statusbar.KeyboardShortcutsModule; -import com.android.systemui.statusbar.NotificationListener; -import com.android.systemui.statusbar.NotificationLockscreenUserManager; -import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl; -import com.android.systemui.statusbar.NotificationShadeWindowController; -import com.android.systemui.statusbar.events.StatusBarEventsModule; -import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider; -import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager; -import com.android.systemui.statusbar.phone.DozeServiceHost; -import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; -import com.android.systemui.statusbar.phone.KeyguardBypassController; -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; -import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper; -import com.android.systemui.statusbar.policy.AospPolicyModule; -import com.android.systemui.statusbar.policy.ConfigurationController; -import com.android.systemui.statusbar.policy.DeviceProvisionedController; -import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl; -import com.android.systemui.statusbar.policy.HeadsUpManager; -import com.android.systemui.statusbar.policy.HeadsUpManagerLogger; -import com.android.systemui.statusbar.policy.IndividualSensorPrivacyController; -import com.android.systemui.statusbar.policy.IndividualSensorPrivacyControllerImpl; -import com.android.systemui.statusbar.policy.SensorPrivacyController; -import com.android.systemui.statusbar.policy.SensorPrivacyControllerImpl; -import com.android.systemui.statusbar.tv.notifications.TvNotificationHandler; -import com.android.systemui.volume.dagger.VolumeModule; - -import dagger.Binds; -import dagger.Module; -import dagger.Provides; -import dagger.multibindings.IntoSet; - -import javax.inject.Named; - -/** - * A TV specific version of {@link ReferenceSystemUIModule}. - * - * Code here should be specific to the TV variant of SystemUI and will not be included in other - * variants of SystemUI. - */ -@Module( - includes = { - AospPolicyModule.class, - GestureModule.class, - MultiUserUtilsModule.class, - PowerModule.class, - QSModule.class, - ReferenceScreenshotModule.class, - ShadeEmptyImplModule.class, - StatusBarEventsModule.class, - VolumeModule.class, - KeyboardShortcutsModule.class - } -) -public abstract class TvSystemUIModule { - - @SysUISingleton - @Provides - @Named(LEAK_REPORT_EMAIL_NAME) - static String provideLeakReportEmail() { - return ""; - } - - @Binds - abstract NotificationLockscreenUserManager bindNotificationLockscreenUserManager( - NotificationLockscreenUserManagerImpl notificationLockscreenUserManager); - - @Provides - @SysUISingleton - static SensorPrivacyController provideSensorPrivacyController( - SensorPrivacyManager sensorPrivacyManager) { - SensorPrivacyController spC = new SensorPrivacyControllerImpl(sensorPrivacyManager); - spC.init(); - return spC; - } - - @Provides - @SysUISingleton - static IndividualSensorPrivacyController provideIndividualSensorPrivacyController( - SensorPrivacyManager sensorPrivacyManager) { - IndividualSensorPrivacyController spC = new IndividualSensorPrivacyControllerImpl( - sensorPrivacyManager); - spC.init(); - return spC; - } - - @Binds - @SysUISingleton - abstract QSFactory bindQSFactory(QSFactoryImpl qsFactoryImpl); - - @Binds - abstract DockManager bindDockManager(DockManagerImpl dockManager); - - @SysUISingleton - @Provides - @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) - static boolean provideAllowNotificationLongPress() { - return true; - } - - @SysUISingleton - @Provides - static HeadsUpManagerPhone provideHeadsUpManagerPhone( - Context context, - HeadsUpManagerLogger headsUpManagerLogger, - StatusBarStateController statusBarStateController, - KeyguardBypassController bypassController, - GroupMembershipManager groupManager, - VisualStabilityProvider visualStabilityProvider, - ConfigurationController configurationController, - @Main Handler handler, - AccessibilityManagerWrapper accessibilityManagerWrapper, - UiEventLogger uiEventLogger, - ShadeExpansionStateManager shadeExpansionStateManager) { - return new HeadsUpManagerPhone( - context, - headsUpManagerLogger, - statusBarStateController, - bypassController, - groupManager, - visualStabilityProvider, - configurationController, - handler, - accessibilityManagerWrapper, - uiEventLogger, - shadeExpansionStateManager - ); - } - - @Binds - abstract HeadsUpManager bindHeadsUpManagerPhone(HeadsUpManagerPhone headsUpManagerPhone); - - @Provides - @SysUISingleton - static Recents provideRecents(Context context, RecentsImplementation recentsImplementation, - CommandQueue commandQueue) { - return new Recents(context, recentsImplementation, commandQueue); - } - - @SysUISingleton - @Provides - static DeviceProvisionedController providesDeviceProvisionedController( - DeviceProvisionedControllerImpl deviceProvisionedController) { - deviceProvisionedController.init(); - return deviceProvisionedController; - } - - @Binds - abstract KeyguardViewController bindKeyguardViewController( - StatusBarKeyguardViewManager statusBarKeyguardViewManager); - - @Binds - abstract NotificationShadeWindowController bindNotificationShadeController( - NotificationShadeWindowControllerImpl notificationShadeWindowController); - - @Binds - abstract DozeHost provideDozeHost(DozeServiceHost dozeServiceHost); - - @Provides - @SysUISingleton - static TvNotificationHandler provideTvNotificationHandler( - NotificationListener notificationListener) { - return new TvNotificationHandler(notificationListener); - } - - /** - * Binds {@link MediaProjectionPrivacyItemMonitor} into the set of {@link PrivacyItemMonitor}. - */ - @Binds - @IntoSet - abstract PrivacyItemMonitor bindMediaProjectionPrivacyItemMonitor( - MediaProjectionPrivacyItemMonitor mediaProjectionPrivacyItemMonitor); -} diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java b/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java deleted file mode 100644 index 83706156927b..000000000000 --- a/packages/SystemUI/src/com/android/systemui/tv/TvWMComponent.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2019 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.systemui.tv; - -import com.android.systemui.dagger.WMComponent; -import com.android.wm.shell.dagger.WMSingleton; -import com.android.wm.shell.dagger.TvWMShellModule; - -import dagger.Subcomponent; - - -/** - * Dagger Subcomponent for WindowManager. - */ -@WMSingleton -@Subcomponent(modules = {TvWMShellModule.class}) -public interface TvWMComponent extends WMComponent { - - /** - * Builder for a SysUIComponent. - */ - @Subcomponent.Builder - interface Builder extends WMComponent.Builder { - TvWMComponent build(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbConfirmActivity.java deleted file mode 100644 index b03bedc86c4b..000000000000 --- a/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbConfirmActivity.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.usb.tv; - -import com.android.systemui.R; - -/** - * Dialog shown to confirm the package to start when a USB device or accessory is attached and there - * is only one package that claims to handle this USB device or accessory. - */ -public class TvUsbConfirmActivity extends TvUsbDialogActivity { - private static final String TAG = TvUsbConfirmActivity.class.getSimpleName(); - - @Override - protected void onResume() { - super.onResume(); - final int strId; - if (mDialogHelper.isUsbDevice()) { - boolean useRecordWarning = mDialogHelper.deviceHasAudioCapture() - && !mDialogHelper.packageHasAudioRecordingPermission(); - strId = useRecordWarning - ? R.string.usb_device_confirm_prompt_warn - : R.string.usb_device_confirm_prompt; - } else { - // UsbAccessory case - strId = R.string.usb_accessory_confirm_prompt; - } - CharSequence text = getString(strId, mDialogHelper.getAppName(), - mDialogHelper.getDeviceDescription()); - initUI(mDialogHelper.getAppName(), text); - } - - @Override - void onConfirm() { - mDialogHelper.grantUidAccessPermission(); - mDialogHelper.confirmDialogStartActivity(); - finish(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbDialogActivity.java b/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbDialogActivity.java deleted file mode 100644 index 1c003eac02be..000000000000 --- a/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbDialogActivity.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.usb.tv; - -import android.os.Bundle; -import android.util.Log; -import android.view.View; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.TextView; - -import com.android.systemui.R; -import com.android.systemui.tv.TvBottomSheetActivity; -import com.android.systemui.usb.UsbDialogHelper; - -abstract class TvUsbDialogActivity extends TvBottomSheetActivity implements View.OnClickListener { - private static final String TAG = TvUsbDialogActivity.class.getSimpleName(); - UsbDialogHelper mDialogHelper; - - @Override - public final void onCreate(Bundle b) { - super.onCreate(b); - getWindow().addPrivateFlags( - WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); - try { - mDialogHelper = new UsbDialogHelper(getApplicationContext(), getIntent()); - } catch (IllegalStateException e) { - Log.e(TAG, "unable to initialize", e); - finish(); - } - } - - @Override - protected void onResume() { - super.onResume(); - mDialogHelper.registerUsbDisconnectedReceiver(this); - } - - @Override - protected void onPause() { - if (mDialogHelper != null) { - mDialogHelper.unregisterUsbDisconnectedReceiver(this); - } - super.onPause(); - } - - @Override - public void onClick(View v) { - if (v.getId() == R.id.bottom_sheet_positive_button) { - onConfirm(); - } else { - finish(); - } - } - - /** - * Called when the ok button is clicked. - */ - abstract void onConfirm(); - - void initUI(CharSequence title, CharSequence text) { - TextView titleTextView = findViewById(R.id.bottom_sheet_title); - TextView contentTextView = findViewById(R.id.bottom_sheet_body); - ImageView icon = findViewById(R.id.bottom_sheet_icon); - ImageView secondIcon = findViewById(R.id.bottom_sheet_second_icon); - Button okButton = findViewById(R.id.bottom_sheet_positive_button); - Button cancelButton = findViewById(R.id.bottom_sheet_negative_button); - - titleTextView.setText(title); - contentTextView.setText(text); - icon.setImageResource(com.android.internal.R.drawable.ic_usb_48dp); - secondIcon.setVisibility(View.GONE); - okButton.setText(android.R.string.ok); - okButton.setOnClickListener(this); - - cancelButton.setText(android.R.string.cancel); - cancelButton.setOnClickListener(this); - cancelButton.requestFocus(); - } -} diff --git a/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbPermissionActivity.java deleted file mode 100644 index 7b415b77154c..000000000000 --- a/packages/SystemUI/src/com/android/systemui/usb/tv/TvUsbPermissionActivity.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.usb.tv; - -import com.android.systemui.R; - -/** - * Dialog shown when a package requests access to a USB device or accessory on TVs. - */ -public class TvUsbPermissionActivity extends TvUsbDialogActivity { - private static final String TAG = TvUsbPermissionActivity.class.getSimpleName(); - - private boolean mPermissionGranted = false; - - @Override - public void onResume() { - super.onResume(); - final int strId; - if (mDialogHelper.isUsbDevice()) { - boolean useRecordWarning = mDialogHelper.deviceHasAudioCapture() - && !mDialogHelper.packageHasAudioRecordingPermission(); - strId = useRecordWarning - ? R.string.usb_device_permission_prompt_warn - : R.string.usb_device_permission_prompt; - } else { - // UsbAccessory case - strId = R.string.usb_accessory_permission_prompt; - } - CharSequence text = getString(strId, mDialogHelper.getAppName(), - mDialogHelper.getDeviceDescription()); - initUI(mDialogHelper.getAppName(), text); - } - - @Override - protected void onPause() { - if (isFinishing()) { - mDialogHelper.sendPermissionDialogResponse(mPermissionGranted); - } - super.onPause(); - } - - @Override - void onConfirm() { - mDialogHelper.grantUidAccessPermission(); - mPermissionGranted = true; - finish(); - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageHelperTest.java deleted file mode 100644 index eb998cc588fd..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/hdmi/HdmiCecSetMenuLanguageHelperTest.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2022 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.systemui.hdmi; - -import static com.google.common.truth.Truth.assertThat; - -import static org.mockito.Mockito.any; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import android.os.UserHandle; -import android.provider.Settings; -import android.test.suitebuilder.annotation.SmallTest; -import android.testing.AndroidTestingRunner; - -import com.android.systemui.SysuiTestCase; -import com.android.systemui.util.settings.SecureSettings; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.Locale; -import java.util.concurrent.Executor; - -@SmallTest -@RunWith(AndroidTestingRunner.class) -public class HdmiCecSetMenuLanguageHelperTest extends SysuiTestCase { - - private HdmiCecSetMenuLanguageHelper mHdmiCecSetMenuLanguageHelper; - - @Mock - private Executor mExecutor; - - @Mock - private SecureSettings mSecureSettings; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - when(mSecureSettings.getStringForUser( - Settings.Secure.HDMI_CEC_SET_MENU_LANGUAGE_DENYLIST, - UserHandle.USER_CURRENT)).thenReturn(null); - mHdmiCecSetMenuLanguageHelper = - new HdmiCecSetMenuLanguageHelper(mExecutor, mSecureSettings); - } - - @Test - public void testSetGetLocale() { - mHdmiCecSetMenuLanguageHelper.setLocale("en"); - assertThat(mHdmiCecSetMenuLanguageHelper.getLocale()).isEqualTo(Locale.ENGLISH); - } - - @Test - public void testIsLocaleDenylisted_EmptyByDefault() { - mHdmiCecSetMenuLanguageHelper.setLocale("en"); - assertThat(mHdmiCecSetMenuLanguageHelper.isLocaleDenylisted()).isEqualTo(false); - } - - @Test - public void testIsLocaleDenylisted_AcceptLanguage() { - mHdmiCecSetMenuLanguageHelper.setLocale("de"); - mHdmiCecSetMenuLanguageHelper.acceptLocale(); - assertThat(mHdmiCecSetMenuLanguageHelper.isLocaleDenylisted()).isEqualTo(false); - verify(mExecutor).execute(any()); - } - - @Test - public void testIsLocaleDenylisted_DeclineLanguage() { - mHdmiCecSetMenuLanguageHelper.setLocale("de"); - mHdmiCecSetMenuLanguageHelper.declineLocale(); - assertThat(mHdmiCecSetMenuLanguageHelper.isLocaleDenylisted()).isEqualTo(true); - verify(mSecureSettings).putStringForUser( - Settings.Secure.HDMI_CEC_SET_MENU_LANGUAGE_DENYLIST, "de", - UserHandle.USER_CURRENT); - } - - @Test - public void testIsLocaleDenylisted_DeclineTwoLanguages() { - mHdmiCecSetMenuLanguageHelper.setLocale("de"); - mHdmiCecSetMenuLanguageHelper.declineLocale(); - assertThat(mHdmiCecSetMenuLanguageHelper.isLocaleDenylisted()).isEqualTo(true); - verify(mSecureSettings).putStringForUser( - Settings.Secure.HDMI_CEC_SET_MENU_LANGUAGE_DENYLIST, "de", - UserHandle.USER_CURRENT); - mHdmiCecSetMenuLanguageHelper.setLocale("pl"); - mHdmiCecSetMenuLanguageHelper.declineLocale(); - assertThat(mHdmiCecSetMenuLanguageHelper.isLocaleDenylisted()).isEqualTo(true); - verify(mSecureSettings).putStringForUser( - Settings.Secure.HDMI_CEC_SET_MENU_LANGUAGE_DENYLIST, "de,pl", - UserHandle.USER_CURRENT); - } -} |