Loading packages/SystemUI/res/layout/ongoing_privacy_chip.xml +8 −3 Original line number Diff line number Diff line Loading @@ -21,7 +21,8 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_margin="@dimen/ongoing_appops_chip_margin" android:gravity="center_vertical|end" android:gravity="center_vertical|center_horizontal" android:layout_gravity="center_vertical|end" android:orientation="horizontal" android:paddingStart="@dimen/ongoing_appops_chip_side_padding" android:paddingEnd="@dimen/ongoing_appops_chip_side_padding" Loading @@ -32,13 +33,17 @@ android:id="@+id/icons_container" android:layout_height="match_parent" android:layout_width="wrap_content" android:gravity="center_vertical|start" android:layout_gravity="center_vertical|start" android:gravity="center_vertical" /> <TextView android:id="@+id/app_name" android:layout_height="match_parent" android:layout_width="wrap_content" android:gravity="center_vertical|end" android:singleLine="true" android:ellipsize="end" android:layout_gravity="center_vertical|end" android:gravity="center_vertical" /> </com.android.systemui.privacy.OngoingPrivacyChip> No newline at end of file packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml +17 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,13 @@ android:paddingStart="@dimen/status_bar_padding_start" android:paddingEnd="@dimen/status_bar_padding_end" > <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal" android:gravity="center_vertical|start" > <com.android.systemui.statusbar.policy.Clock android:id="@+id/clock" android:layout_width="wrap_content" Loading @@ -38,13 +45,21 @@ android:singleLine="true" android:textAppearance="@style/TextAppearance.StatusBar.Clock" systemui:showDark="false" /> </LinearLayout> <android.widget.Space android:id="@+id/space" android:layout_width="0dp" android:layout_height="match_parent" android:layout_gravity="center_vertical|center_horizontal" android:visibility="gone" /> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" /> android:orientation="horizontal" android:gravity="center_vertical|end"> <include layout="@layout/ongoing_privacy_chip" /> Loading @@ -54,3 +69,4 @@ android:layout_width="wrap_content" android:gravity="center_vertical|end" /> </LinearLayout> </LinearLayout> packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt +6 −67 Original line number Diff line number Diff line Loading @@ -14,21 +14,14 @@ package com.android.systemui.privacy import android.app.ActivityManager import android.app.AppOpsManager import android.content.Context import android.graphics.Color import android.os.UserHandle import android.os.UserManager import android.util.AttributeSet import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import com.android.systemui.Dependency import com.android.systemui.R import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController class OngoingPrivacyChip @JvmOverloads constructor( context: Context, Loading @@ -37,36 +30,14 @@ class OngoingPrivacyChip @JvmOverloads constructor( defStyleRes: Int = 0 ) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) { companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_FINE_LOCATION) } private lateinit var appName: TextView private lateinit var iconsContainer: LinearLayout private var privacyList = emptyList<PrivacyItem>() private val appOpsController = Dependency.get(AppOpsController::class.java) private val userManager = context.getSystemService(UserManager::class.java) private val currentUser = ActivityManager.getCurrentUser() private val currentUserIds = userManager.getProfiles(currentUser).map { it.id } private var listening = false var builder = PrivacyDialogBuilder(context, privacyList) private val callback = object : AppOpsController.Callback { override fun onActiveStateChanged( code: Int, uid: Int, packageName: String, active: Boolean ) { val userId = UserHandle.getUserId(uid) if (userId in currentUserIds) { updatePrivacyList() } } var builder = PrivacyDialogBuilder(context, emptyList<PrivacyItem>()) var privacyList = emptyList<PrivacyItem>() set(value) { field = value builder = PrivacyDialogBuilder(context, value) updateView() } override fun onFinishInflate() { Loading @@ -76,36 +47,6 @@ class OngoingPrivacyChip @JvmOverloads constructor( iconsContainer = findViewById(R.id.icons_container) } fun setListening(listen: Boolean) { if (listening == listen) return listening = listen if (listening) { appOpsController.addCallback(OPS, callback) updatePrivacyList() } else { appOpsController.removeCallback(OPS, callback) } } private fun updatePrivacyList() { privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) } .mapNotNull { toPrivacyItem(it) } builder = PrivacyDialogBuilder(context, privacyList) updateView() } private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? { val type: PrivacyType = when (appOpItem.code) { AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE else -> return null } val app = PrivacyApplication(appOpItem.packageName, context) return PrivacyItem(type, app, appOpItem.timeStarted) } // Should only be called if the builder icons or app changed private fun updateView() { fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) { Loading @@ -121,11 +62,9 @@ class OngoingPrivacyChip @JvmOverloads constructor( } if (privacyList.isEmpty()) { visibility = GONE return } else { generateContentDescription() visibility = VISIBLE setIcons(builder, iconsContainer) appName.visibility = GONE builder.app?.let { Loading packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt 0 → 100644 +105 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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 import android.app.ActivityManager import android.app.AppOpsManager import android.content.Context import android.os.Handler import android.os.UserHandle import android.os.UserManager import com.android.systemui.Dependency import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController class PrivacyItemController(val context: Context, val callback: Callback) { companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_FINE_LOCATION) } private var privacyList = emptyList<PrivacyItem>() private val appOpsController = Dependency.get(AppOpsController::class.java) private val userManager = context.getSystemService(UserManager::class.java) private val currentUser = ActivityManager.getCurrentUser() private val currentUserIds = userManager.getProfiles(currentUser).map { it.id } private val bgHandler = Handler(Dependency.get(Dependency.BG_LOOPER)) private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER) private val notifyChanges = Runnable { callback.privacyChanged(privacyList) } private val updateListAndNotifyChanges = Runnable { updatePrivacyList() uiHandler.post(notifyChanges) } private var listening = false private val cb = object : AppOpsController.Callback { override fun onActiveStateChanged( code: Int, uid: Int, packageName: String, active: Boolean ) { val userId = UserHandle.getUserId(uid) if (userId in currentUserIds) { update() } } } private fun update() { bgHandler.post(updateListAndNotifyChanges) } fun setListening(listen: Boolean) { if (listening == listen) return listening = listen if (listening) { appOpsController.addCallback(OPS, cb) update() } else { appOpsController.removeCallback(OPS, cb) } } private fun updatePrivacyList() { privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) } .mapNotNull { toPrivacyItem(it) } } private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? { val type: PrivacyType = when (appOpItem.code) { AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE else -> return null } val app = PrivacyApplication(appOpItem.packageName, context) return PrivacyItem(type, app, appOpItem.timeStarted) } // Used by containing class to get notified of changes interface Callback { fun privacyChanged(privacyItems: List<PrivacyItem>) } } No newline at end of file packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +48 −2 Original line number Diff line number Diff line Loading @@ -39,12 +39,15 @@ import android.text.format.DateUtils; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; import android.view.DisplayCutout; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Space; import android.widget.TextView; import androidx.annotation.VisibleForTesting; Loading @@ -57,6 +60,8 @@ import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.privacy.OngoingPrivacyChip; import com.android.systemui.privacy.OngoingPrivacyDialog; import com.android.systemui.privacy.PrivacyItem; import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.qs.QSDetail.Callback; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.StatusBarIconController; Loading @@ -70,6 +75,7 @@ import com.android.systemui.statusbar.policy.DateView; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.ZenModeController; import java.util.List; import java.util.Locale; import java.util.Objects; Loading Loading @@ -125,9 +131,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements private Clock mClockView; private DateView mDateView; private OngoingPrivacyChip mPrivacyChip; private Space mSpace; private NextAlarmController mAlarmController; private ZenModeController mZenController; private PrivacyItemController mPrivacyItemController; /** Counts how many times the long press tooltip has been shown to the user. */ private int mShownCount; Loading @@ -138,16 +146,26 @@ public class QuickStatusBarHeader extends RelativeLayout implements updateStatusText(); } }; private boolean mHasTopCutout = false; /** * Runnable for automatically fading out the long press tooltip (as if it were animating away). */ private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false); private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() { @Override public void privacyChanged(List<PrivacyItem> privacyItems) { mPrivacyChip.setPrivacyList(privacyItems); setChipVisibility(!privacyItems.isEmpty()); } }; public QuickStatusBarHeader(Context context, AttributeSet attrs) { super(context, attrs); mAlarmController = Dependency.get(NextAlarmController.class); mZenController = Dependency.get(ZenModeController.class); mPrivacyItemController = new PrivacyItemController(context, mPICCallback); mShownCount = getStoredShownCount(); } Loading Loading @@ -194,6 +212,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements mDateView = findViewById(R.id.date); mPrivacyChip = findViewById(R.id.privacy_chip); mPrivacyChip.setOnClickListener(this); mSpace = findViewById(R.id.space); } private void updateStatusText() { Loading @@ -208,6 +227,16 @@ public class QuickStatusBarHeader extends RelativeLayout implements } } private void setChipVisibility(boolean chipVisible) { mBatteryMeterView.setVisibility(View.VISIBLE); if (chipVisible) { mPrivacyChip.setVisibility(View.VISIBLE); if (mHasTopCutout) mBatteryMeterView.setVisibility(View.GONE); } else { mPrivacyChip.setVisibility(View.GONE); } } private boolean updateRingerStatus() { boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE; CharSequence originalRingerText = mRingerModeTextView.getText(); Loading Loading @@ -411,8 +440,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { DisplayCutout cutout = insets.getDisplayCutout(); Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins( insets.getDisplayCutout(), getDisplay()); cutout, getDisplay()); if (padding == null) { mSystemIconsView.setPaddingRelative( getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0, Loading @@ -421,6 +451,22 @@ public class QuickStatusBarHeader extends RelativeLayout implements mSystemIconsView.setPadding(padding.first, 0, padding.second, 0); } LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams(); if (cutout != null) { Rect topCutout = cutout.getBoundingRectTop(); if (topCutout.isEmpty()) { mHasTopCutout = false; lp.width = 0; mSpace.setVisibility(View.GONE); } else { mHasTopCutout = true; lp.width = topCutout.width(); mSpace.setVisibility(View.VISIBLE); } } mSpace.setLayoutParams(lp); // Decide whether to show BatteryMeterView setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE); return super.onApplyWindowInsets(insets); } Loading @@ -437,7 +483,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements return; } mHeaderQsPanel.setListening(listening); mPrivacyChip.setListening(listening); mPrivacyItemController.setListening(listening); mListening = listening; if (listening) { Loading Loading
packages/SystemUI/res/layout/ongoing_privacy_chip.xml +8 −3 Original line number Diff line number Diff line Loading @@ -21,7 +21,8 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_margin="@dimen/ongoing_appops_chip_margin" android:gravity="center_vertical|end" android:gravity="center_vertical|center_horizontal" android:layout_gravity="center_vertical|end" android:orientation="horizontal" android:paddingStart="@dimen/ongoing_appops_chip_side_padding" android:paddingEnd="@dimen/ongoing_appops_chip_side_padding" Loading @@ -32,13 +33,17 @@ android:id="@+id/icons_container" android:layout_height="match_parent" android:layout_width="wrap_content" android:gravity="center_vertical|start" android:layout_gravity="center_vertical|start" android:gravity="center_vertical" /> <TextView android:id="@+id/app_name" android:layout_height="match_parent" android:layout_width="wrap_content" android:gravity="center_vertical|end" android:singleLine="true" android:ellipsize="end" android:layout_gravity="center_vertical|end" android:gravity="center_vertical" /> </com.android.systemui.privacy.OngoingPrivacyChip> No newline at end of file
packages/SystemUI/res/layout/quick_status_bar_header_system_icons.xml +17 −1 Original line number Diff line number Diff line Loading @@ -27,6 +27,13 @@ android:paddingStart="@dimen/status_bar_padding_start" android:paddingEnd="@dimen/status_bar_padding_end" > <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:orientation="horizontal" android:gravity="center_vertical|start" > <com.android.systemui.statusbar.policy.Clock android:id="@+id/clock" android:layout_width="wrap_content" Loading @@ -38,13 +45,21 @@ android:singleLine="true" android:textAppearance="@style/TextAppearance.StatusBar.Clock" systemui:showDark="false" /> </LinearLayout> <android.widget.Space android:id="@+id/space" android:layout_width="0dp" android:layout_height="match_parent" android:layout_gravity="center_vertical|center_horizontal" android:visibility="gone" /> <LinearLayout android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical|center_horizontal" /> android:orientation="horizontal" android:gravity="center_vertical|end"> <include layout="@layout/ongoing_privacy_chip" /> Loading @@ -54,3 +69,4 @@ android:layout_width="wrap_content" android:gravity="center_vertical|end" /> </LinearLayout> </LinearLayout>
packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyChip.kt +6 −67 Original line number Diff line number Diff line Loading @@ -14,21 +14,14 @@ package com.android.systemui.privacy import android.app.ActivityManager import android.app.AppOpsManager import android.content.Context import android.graphics.Color import android.os.UserHandle import android.os.UserManager import android.util.AttributeSet import android.view.ViewGroup import android.widget.ImageView import android.widget.LinearLayout import android.widget.TextView import com.android.systemui.Dependency import com.android.systemui.R import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController class OngoingPrivacyChip @JvmOverloads constructor( context: Context, Loading @@ -37,36 +30,14 @@ class OngoingPrivacyChip @JvmOverloads constructor( defStyleRes: Int = 0 ) : LinearLayout(context, attrs, defStyleAttrs, defStyleRes) { companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_FINE_LOCATION) } private lateinit var appName: TextView private lateinit var iconsContainer: LinearLayout private var privacyList = emptyList<PrivacyItem>() private val appOpsController = Dependency.get(AppOpsController::class.java) private val userManager = context.getSystemService(UserManager::class.java) private val currentUser = ActivityManager.getCurrentUser() private val currentUserIds = userManager.getProfiles(currentUser).map { it.id } private var listening = false var builder = PrivacyDialogBuilder(context, privacyList) private val callback = object : AppOpsController.Callback { override fun onActiveStateChanged( code: Int, uid: Int, packageName: String, active: Boolean ) { val userId = UserHandle.getUserId(uid) if (userId in currentUserIds) { updatePrivacyList() } } var builder = PrivacyDialogBuilder(context, emptyList<PrivacyItem>()) var privacyList = emptyList<PrivacyItem>() set(value) { field = value builder = PrivacyDialogBuilder(context, value) updateView() } override fun onFinishInflate() { Loading @@ -76,36 +47,6 @@ class OngoingPrivacyChip @JvmOverloads constructor( iconsContainer = findViewById(R.id.icons_container) } fun setListening(listen: Boolean) { if (listening == listen) return listening = listen if (listening) { appOpsController.addCallback(OPS, callback) updatePrivacyList() } else { appOpsController.removeCallback(OPS, callback) } } private fun updatePrivacyList() { privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) } .mapNotNull { toPrivacyItem(it) } builder = PrivacyDialogBuilder(context, privacyList) updateView() } private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? { val type: PrivacyType = when (appOpItem.code) { AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE else -> return null } val app = PrivacyApplication(appOpItem.packageName, context) return PrivacyItem(type, app, appOpItem.timeStarted) } // Should only be called if the builder icons or app changed private fun updateView() { fun setIcons(dialogBuilder: PrivacyDialogBuilder, iconsContainer: ViewGroup) { Loading @@ -121,11 +62,9 @@ class OngoingPrivacyChip @JvmOverloads constructor( } if (privacyList.isEmpty()) { visibility = GONE return } else { generateContentDescription() visibility = VISIBLE setIcons(builder, iconsContainer) appName.visibility = GONE builder.app?.let { Loading
packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt 0 → 100644 +105 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 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 import android.app.ActivityManager import android.app.AppOpsManager import android.content.Context import android.os.Handler import android.os.UserHandle import android.os.UserManager import com.android.systemui.Dependency import com.android.systemui.appops.AppOpItem import com.android.systemui.appops.AppOpsController class PrivacyItemController(val context: Context, val callback: Callback) { companion object { val OPS = intArrayOf(AppOpsManager.OP_CAMERA, AppOpsManager.OP_RECORD_AUDIO, AppOpsManager.OP_COARSE_LOCATION, AppOpsManager.OP_FINE_LOCATION) } private var privacyList = emptyList<PrivacyItem>() private val appOpsController = Dependency.get(AppOpsController::class.java) private val userManager = context.getSystemService(UserManager::class.java) private val currentUser = ActivityManager.getCurrentUser() private val currentUserIds = userManager.getProfiles(currentUser).map { it.id } private val bgHandler = Handler(Dependency.get(Dependency.BG_LOOPER)) private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER) private val notifyChanges = Runnable { callback.privacyChanged(privacyList) } private val updateListAndNotifyChanges = Runnable { updatePrivacyList() uiHandler.post(notifyChanges) } private var listening = false private val cb = object : AppOpsController.Callback { override fun onActiveStateChanged( code: Int, uid: Int, packageName: String, active: Boolean ) { val userId = UserHandle.getUserId(uid) if (userId in currentUserIds) { update() } } } private fun update() { bgHandler.post(updateListAndNotifyChanges) } fun setListening(listen: Boolean) { if (listening == listen) return listening = listen if (listening) { appOpsController.addCallback(OPS, cb) update() } else { appOpsController.removeCallback(OPS, cb) } } private fun updatePrivacyList() { privacyList = currentUserIds.flatMap { appOpsController.getActiveAppOpsForUser(it) } .mapNotNull { toPrivacyItem(it) } } private fun toPrivacyItem(appOpItem: AppOpItem): PrivacyItem? { val type: PrivacyType = when (appOpItem.code) { AppOpsManager.OP_CAMERA -> PrivacyType.TYPE_CAMERA AppOpsManager.OP_COARSE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_FINE_LOCATION -> PrivacyType.TYPE_LOCATION AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE else -> return null } val app = PrivacyApplication(appOpItem.packageName, context) return PrivacyItem(type, app, appOpItem.timeStarted) } // Used by containing class to get notified of changes interface Callback { fun privacyChanged(privacyItems: List<PrivacyItem>) } } No newline at end of file
packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java +48 −2 Original line number Diff line number Diff line Loading @@ -39,12 +39,15 @@ import android.text.format.DateUtils; import android.util.AttributeSet; import android.util.Log; import android.util.Pair; import android.view.DisplayCutout; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.Space; import android.widget.TextView; import androidx.annotation.VisibleForTesting; Loading @@ -57,6 +60,8 @@ import com.android.systemui.R; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.privacy.OngoingPrivacyChip; import com.android.systemui.privacy.OngoingPrivacyDialog; import com.android.systemui.privacy.PrivacyItem; import com.android.systemui.privacy.PrivacyItemController; import com.android.systemui.qs.QSDetail.Callback; import com.android.systemui.statusbar.phone.PhoneStatusBarView; import com.android.systemui.statusbar.phone.StatusBarIconController; Loading @@ -70,6 +75,7 @@ import com.android.systemui.statusbar.policy.DateView; import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.ZenModeController; import java.util.List; import java.util.Locale; import java.util.Objects; Loading Loading @@ -125,9 +131,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements private Clock mClockView; private DateView mDateView; private OngoingPrivacyChip mPrivacyChip; private Space mSpace; private NextAlarmController mAlarmController; private ZenModeController mZenController; private PrivacyItemController mPrivacyItemController; /** Counts how many times the long press tooltip has been shown to the user. */ private int mShownCount; Loading @@ -138,16 +146,26 @@ public class QuickStatusBarHeader extends RelativeLayout implements updateStatusText(); } }; private boolean mHasTopCutout = false; /** * Runnable for automatically fading out the long press tooltip (as if it were animating away). */ private final Runnable mAutoFadeOutTooltipRunnable = () -> hideLongPressTooltip(false); private PrivacyItemController.Callback mPICCallback = new PrivacyItemController.Callback() { @Override public void privacyChanged(List<PrivacyItem> privacyItems) { mPrivacyChip.setPrivacyList(privacyItems); setChipVisibility(!privacyItems.isEmpty()); } }; public QuickStatusBarHeader(Context context, AttributeSet attrs) { super(context, attrs); mAlarmController = Dependency.get(NextAlarmController.class); mZenController = Dependency.get(ZenModeController.class); mPrivacyItemController = new PrivacyItemController(context, mPICCallback); mShownCount = getStoredShownCount(); } Loading Loading @@ -194,6 +212,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements mDateView = findViewById(R.id.date); mPrivacyChip = findViewById(R.id.privacy_chip); mPrivacyChip.setOnClickListener(this); mSpace = findViewById(R.id.space); } private void updateStatusText() { Loading @@ -208,6 +227,16 @@ public class QuickStatusBarHeader extends RelativeLayout implements } } private void setChipVisibility(boolean chipVisible) { mBatteryMeterView.setVisibility(View.VISIBLE); if (chipVisible) { mPrivacyChip.setVisibility(View.VISIBLE); if (mHasTopCutout) mBatteryMeterView.setVisibility(View.GONE); } else { mPrivacyChip.setVisibility(View.GONE); } } private boolean updateRingerStatus() { boolean isOriginalVisible = mRingerModeTextView.getVisibility() == View.VISIBLE; CharSequence originalRingerText = mRingerModeTextView.getText(); Loading Loading @@ -411,8 +440,9 @@ public class QuickStatusBarHeader extends RelativeLayout implements @Override public WindowInsets onApplyWindowInsets(WindowInsets insets) { DisplayCutout cutout = insets.getDisplayCutout(); Pair<Integer, Integer> padding = PhoneStatusBarView.cornerCutoutMargins( insets.getDisplayCutout(), getDisplay()); cutout, getDisplay()); if (padding == null) { mSystemIconsView.setPaddingRelative( getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start), 0, Loading @@ -421,6 +451,22 @@ public class QuickStatusBarHeader extends RelativeLayout implements mSystemIconsView.setPadding(padding.first, 0, padding.second, 0); } LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mSpace.getLayoutParams(); if (cutout != null) { Rect topCutout = cutout.getBoundingRectTop(); if (topCutout.isEmpty()) { mHasTopCutout = false; lp.width = 0; mSpace.setVisibility(View.GONE); } else { mHasTopCutout = true; lp.width = topCutout.width(); mSpace.setVisibility(View.VISIBLE); } } mSpace.setLayoutParams(lp); // Decide whether to show BatteryMeterView setChipVisibility(mPrivacyChip.getVisibility() == View.VISIBLE); return super.onApplyWindowInsets(insets); } Loading @@ -437,7 +483,7 @@ public class QuickStatusBarHeader extends RelativeLayout implements return; } mHeaderQsPanel.setListening(listening); mPrivacyChip.setListening(listening); mPrivacyItemController.setListening(listening); mListening = listening; if (listening) { Loading