diff options
5 files changed, 99 insertions, 53 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt index 842a1b92f690..44ef2b658fe2 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/FooterActionsController.kt @@ -140,6 +140,7 @@ internal class FooterActionsController @Inject constructor( override fun onInit() { multiUserSwitchController.init() + securityFooterController.init() fgsManagerFooterController.init() } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index 10d792098608..b46f9c374253 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -214,10 +214,6 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { return mHost; } - /** Show the device monitoring dialog. */ - public void showDeviceMonitoringDialog() { - mQsSecurityFooter.showDeviceMonitoringDialog(); - } /** Update appearance of QSPanel. */ public void updateResources() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index ea9bc6946ffe..7e0410c0674b 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -41,25 +41,26 @@ import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_PE import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_MONITORING; import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NAMED_VPN; import static android.app.admin.DevicePolicyResources.Strings.SystemUi.QS_MSG_WORK_PROFILE_NETWORK; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static com.android.systemui.qs.dagger.QSFragmentModule.QS_SECURITY_FOOTER_VIEW; import android.app.AlertDialog; +import android.app.Dialog; import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyEventLogger; import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.UserInfo; -import android.content.res.Configuration; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; import android.os.Message; +import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.text.SpannableStringBuilder; @@ -69,7 +70,6 @@ import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; -import android.view.ViewGroup; import android.view.Window; import android.widget.ImageView; import android.widget.TextView; @@ -81,15 +81,15 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; -import com.android.systemui.flags.FeatureFlags; -import com.android.systemui.flags.Flags; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.statusbar.policy.SecurityController; +import com.android.systemui.util.ViewController; import java.util.concurrent.atomic.AtomicBoolean; @@ -97,13 +97,13 @@ import javax.inject.Inject; import javax.inject.Named; @QSScope -class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListener, +class QSSecurityFooter extends ViewController<View> + implements OnClickListener, DialogInterface.OnClickListener, VisibilityChangedDispatcher { protected static final String TAG = "QSSecurityFooter"; protected static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private static final boolean DEBUG_FORCE_VISIBLE = false; - private final View mRootView; private final TextView mFooterText; private final ImageView mPrimaryFooterIcon; private final Context mContext; @@ -114,15 +114,13 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen private final Handler mMainHandler; private final UserTracker mUserTracker; private final DialogLaunchAnimator mDialogLaunchAnimator; + private final BroadcastDispatcher mBroadcastDispatcher; private final AtomicBoolean mShouldUseSettingsButton = new AtomicBoolean(false); private AlertDialog mDialog; protected H mHandler; - // Does it move between footer and header? Remove this once all the flagging is removed - private final boolean mNewQsFooter; - private boolean mIsVisible; @Nullable private CharSequence mFooterTextContent = null; @@ -133,15 +131,24 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen @Nullable private VisibilityChangedDispatcher.OnVisibilityChangedListener mVisibilityChangedListener; + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals( + DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG)) { + showDeviceMonitoringDialog(); + } + } + }; + @Inject QSSecurityFooter(@Named(QS_SECURITY_FOOTER_VIEW) View rootView, UserTracker userTracker, @Main Handler mainHandler, ActivityStarter activityStarter, SecurityController securityController, DialogLaunchAnimator dialogLaunchAnimator, - @Background Looper bgLooper, FeatureFlags featureFlags) { - mRootView = rootView; - mRootView.setOnClickListener(this); - mFooterText = mRootView.findViewById(R.id.footer_text); - mPrimaryFooterIcon = mRootView.findViewById(R.id.primary_footer_icon); + @Background Looper bgLooper, BroadcastDispatcher broadcastDispatcher) { + super(rootView); + mFooterText = mView.findViewById(R.id.footer_text); + mPrimaryFooterIcon = mView.findViewById(R.id.primary_footer_icon); mFooterIconId = R.drawable.ic_info_outline; mContext = rootView.getContext(); mDpm = rootView.getContext().getSystemService(DevicePolicyManager.class); @@ -151,7 +158,22 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen mHandler = new H(bgLooper); mUserTracker = userTracker; mDialogLaunchAnimator = dialogLaunchAnimator; - mNewQsFooter = featureFlags.isEnabled(Flags.NEW_FOOTER); + mBroadcastDispatcher = broadcastDispatcher; + } + + @Override + protected void onViewAttached() { + // Use background handler, as it's the same thread that handleClick is called on. + mBroadcastDispatcher.registerReceiverWithHandler(mReceiver, + new IntentFilter(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG), + mHandler, UserHandle.ALL); + mView.setOnClickListener(this); + } + + @Override + protected void onViewDetached() { + mBroadcastDispatcher.unregisterReceiver(mReceiver); + mView.setOnClickListener(null); } public void setListening(boolean listening) { @@ -173,29 +195,17 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen FontSizeUtils.updateFontSize(mFooterText, R.dimen.qs_tile_text_size); Resources r = mContext.getResources(); - if (!mNewQsFooter) { - mFooterText.setMaxLines(r.getInteger(R.integer.qs_security_footer_maxLines)); - - int bottomMargin = r.getDimensionPixelSize(R.dimen.qs_footers_margin_bottom); - ViewGroup.MarginLayoutParams lp = - (ViewGroup.MarginLayoutParams) mRootView.getLayoutParams(); - lp.bottomMargin = bottomMargin; - lp.width = r.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT - ? MATCH_PARENT : WRAP_CONTENT; - mRootView.setLayoutParams(lp); - } - int padding = r.getDimensionPixelSize(R.dimen.qs_footer_padding); - mRootView.setPaddingRelative(padding, padding, padding, padding); - mRootView.setBackground(mContext.getDrawable(R.drawable.qs_security_footer_background)); + mView.setPaddingRelative(padding, 0, padding, 0); + mView.setBackground(mContext.getDrawable(R.drawable.qs_security_footer_background)); } public View getView() { - return mRootView; + return mView; } public boolean hasFooter() { - return mRootView.getVisibility() != View.GONE; + return mView.getVisibility() != View.GONE; } @Override @@ -252,11 +262,11 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen // b) a specific work policy set but the work profile is turned off. if (mIsVisible && isProfileOwnerOfOrganizationOwnedDevice && (!hasDisclosableWorkProfilePolicy || !isWorkProfileOn)) { - mRootView.setClickable(false); - mRootView.findViewById(R.id.footer_icon).setVisibility(View.GONE); + mView.setClickable(false); + mView.findViewById(R.id.footer_icon).setVisibility(View.GONE); } else { - mRootView.setClickable(true); - mRootView.findViewById(R.id.footer_icon).setVisibility(View.VISIBLE); + mView.setClickable(true); + mView.findViewById(R.id.footer_icon).setVisibility(View.VISIBLE); } // Update the string mFooterTextContent = getFooterText(isDeviceManaged, hasWorkProfile, @@ -493,12 +503,20 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen this); mDialog.setView(view); - - mDialogLaunchAnimator.showFromView(mDialog, mRootView); + if (mView.isAggregatedVisible()) { + mDialogLaunchAnimator.showFromView(mDialog, mView); + } else { + mDialog.show(); + } }); } @VisibleForTesting + Dialog getDialog() { + return mDialog; + } + + @VisibleForTesting View createDialogView() { if (mSecurityController.isParentalControlsEnabled()) { return createParentalControlsDialogView(); @@ -805,9 +823,9 @@ class QSSecurityFooter implements OnClickListener, DialogInterface.OnClickListen if (mFooterTextContent != null) { mFooterText.setText(mFooterTextContent); } - mRootView.setVisibility(mIsVisible || DEBUG_FORCE_VISIBLE ? View.VISIBLE : View.GONE); + mView.setVisibility(mIsVisible || DEBUG_FORCE_VISIBLE ? View.VISIBLE : View.GONE); if (mVisibilityChangedListener != null) { - mVisibilityChangedListener.onVisibilityChanged(mRootView.getVisibility()); + mVisibilityChangedListener.onVisibilityChanged(mView.getVisibility()); } } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index ffe4d4f11819..9a9c340fcdc8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -1438,7 +1438,6 @@ public class CentralSurfaces extends CoreStartable implements IntentFilter filter = new IntentFilter(); filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); filter.addAction(Intent.ACTION_SCREEN_OFF); - filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG); mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL); } @@ -2628,8 +2627,6 @@ public class CentralSurfaces extends CoreStartable implements } finishBarAnimations(); resetUserExpandedStates(); - } else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) { - mQSPanelController.showDeviceMonitoringDialog(); } Trace.endSection(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java index 15013469c6f7..a3c353b5a666 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSecurityFooterTest.java @@ -30,8 +30,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.AlertDialog; +import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.DialogInterface; +import android.content.Intent; import android.content.pm.UserInfo; import android.graphics.drawable.Drawable; import android.graphics.drawable.VectorDrawable; @@ -44,6 +47,7 @@ import android.testing.LayoutInflaterBuilder; import android.testing.TestableImageView; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; +import android.testing.ViewUtils; import android.text.SpannableStringBuilder; import android.view.LayoutInflater; import android.view.View; @@ -53,11 +57,12 @@ import android.widget.TextView; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.animation.DialogLaunchAnimator; -import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.policy.SecurityController; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -104,7 +109,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { @Mock private DialogLaunchAnimator mDialogLaunchAnimator; @Mock - private FeatureFlags mFeatureFlags; + private BroadcastDispatcher mBroadcastDispatcher; private TestableLooper mTestableLooper; @@ -119,7 +124,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { .build().inflate(R.layout.quick_settings_security_footer, null, false); mFooter = new QSSecurityFooter(mRootView, mUserTracker, new Handler(looper), mActivityStarter, mSecurityController, mDialogLaunchAnimator, looper, - mFeatureFlags); + mBroadcastDispatcher); mFooterText = mRootView.findViewById(R.id.footer_text); mPrimaryFooterIcon = mRootView.findViewById(R.id.primary_footer_icon); @@ -127,6 +132,14 @@ public class QSSecurityFooterTest extends SysuiTestCase { .thenReturn(DEVICE_OWNER_COMPONENT); when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT)) .thenReturn(DEVICE_OWNER_TYPE_DEFAULT); + ViewUtils.attachView(mRootView); + + mFooter.init(); + } + + @After + public void tearDown() { + ViewUtils.detachView(mRootView); } @Test @@ -769,8 +782,7 @@ public class QSSecurityFooterTest extends SysuiTestCase { @Test public void testVisibilityListener() { final AtomicInteger lastVisibility = new AtomicInteger(-1); - VisibilityChangedDispatcher.OnVisibilityChangedListener listener = - (VisibilityChangedDispatcher.OnVisibilityChangedListener) lastVisibility::set; + VisibilityChangedDispatcher.OnVisibilityChangedListener listener = lastVisibility::set; mFooter.setOnVisibilityChangedListener(listener); @@ -785,6 +797,28 @@ public class QSSecurityFooterTest extends SysuiTestCase { assertEquals(View.GONE, lastVisibility.get()); } + @Test + public void testBroadcastShowsDialog() { + // Setup dialog content + when(mSecurityController.isDeviceManaged()).thenReturn(true); + when(mSecurityController.getDeviceOwnerOrganizationName()) + .thenReturn(MANAGING_ORGANIZATION); + when(mSecurityController.getDeviceOwnerType(DEVICE_OWNER_COMPONENT)) + .thenReturn(DEVICE_OWNER_TYPE_FINANCED); + + ArgumentCaptor<BroadcastReceiver> captor = ArgumentCaptor.forClass(BroadcastReceiver.class); + verify(mBroadcastDispatcher).registerReceiverWithHandler(captor.capture(), any(), any(), + any()); + + // Pretend view is not visible temporarily + mRootView.onVisibilityAggregated(false); + captor.getValue().onReceive(mContext, + new Intent(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG)); + mTestableLooper.processAllMessages(); + + assertTrue(mFooter.getDialog().isShowing()); + mFooter.getDialog().dismiss(); + } private CharSequence addLink(CharSequence description) { final SpannableStringBuilder message = new SpannableStringBuilder(); |