Loading packages/SystemUI/res/values/strings.xml +5 −0 Original line number Diff line number Diff line Loading @@ -2829,4 +2829,9 @@ <string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string> <!-- Title for pairing item [CHAR LIMIT=60] --> <string name="media_output_dialog_pairing_new">Pair new device</string> <!-- Label for clip data when copying the build number off QS [CHAR LIMIT=NONE]--> <string name="build_number_clip_data_label">Build number</string> <!-- Text to display when copying the build number off QS [CHAR LIMIT=NONE]--> <string name="build_number_copy_toast">Build number copied to clipboard.</string> </resources> packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +18 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; Loading @@ -34,6 +36,7 @@ import android.os.Handler; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; Loading Loading @@ -154,6 +157,19 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mActionsContainer = findViewById(R.id.qs_footer_actions_container); mEditContainer = findViewById(R.id.qs_footer_actions_edit_container); mBuildText = findViewById(R.id.build); mBuildText.setOnLongClickListener(view -> { CharSequence buildText = mBuildText.getText(); if (!TextUtils.isEmpty(buildText)) { ClipboardManager service = mUserTracker.getUserContext().getSystemService(ClipboardManager.class); String label = mContext.getString(R.string.build_number_clip_data_label); service.setPrimaryClip(ClipData.newPlainText(label, buildText)); Toast.makeText(mContext, R.string.build_number_copy_toast, Toast.LENGTH_SHORT) .show(); return true; } return false; }); // RenderThread is doing more harm than good when touching the header (to expand quick // settings), so disable it for this view Loading @@ -180,6 +196,7 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mBuildText.setSelected(true); mShouldShowBuildText = true; } else { mBuildText.setText(null); mShouldShowBuildText = false; mBuildText.setSelected(false); } Loading Loading @@ -321,6 +338,7 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mMultiUserSwitch.setClickable(mMultiUserSwitch.getVisibility() == View.VISIBLE); mEdit.setClickable(mEdit.getVisibility() == View.VISIBLE); mSettingsButton.setClickable(mSettingsButton.getVisibility() == View.VISIBLE); mBuildText.setLongClickable(mBuildText.getVisibility() == View.VISIBLE); } private void updateVisibilities() { Loading packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java +36 −1 Original line number Diff line number Diff line Loading @@ -14,17 +14,22 @@ package com.android.systemui.qs; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ClipData; import android.content.ClipboardManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; import androidx.test.filters.SmallTest; Loading @@ -33,12 +38,16 @@ import com.android.systemui.R.id; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.utils.leaks.LeakCheckedTest; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @RunWithLooper Loading @@ -48,19 +57,45 @@ public class QSFooterImplTest extends LeakCheckedTest { private QSFooterImpl mFooter; private ActivityStarter mActivityStarter; private DeviceProvisionedController mDeviceProvisionedController; private UserInfoController mUserInfoController; private UserTracker mUserTracker; @Mock private ClipboardManager mClipboardManager; @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); mActivityStarter = mDependency.injectMockDependency(ActivityStarter.class); mDeviceProvisionedController = mDependency.injectMockDependency( DeviceProvisionedController.class); mDependency.injectMockDependency(UserTracker.class); mUserInfoController = mDependency.injectMockDependency(UserInfoController.class); mUserTracker = mDependency.injectMockDependency(UserTracker.class); mContext.addMockSystemService(ClipboardManager.class, mClipboardManager); when(mUserTracker.getUserContext()).thenReturn(mContext); TestableLooper.get(this).runWithLooper( () -> mFooter = (QSFooterImpl) LayoutInflater.from(mContext).inflate( R.layout.qs_footer_impl, null)); } @Test public void testBuildTextCopy() { TextView buildTextView = mFooter.requireViewById(R.id.build); CharSequence buildText = "TEST"; buildTextView.setText(buildText); buildTextView.setLongClickable(true); buildTextView.performLongClick(); ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class); verify(mClipboardManager).setPrimaryClip(captor.capture()); assertThat(captor.getValue().getItemAt(0).getText()).isEqualTo(buildText); } @Test @Ignore("failing") public void testSettings_UserNotSetup() { Loading Loading
packages/SystemUI/res/values/strings.xml +5 −0 Original line number Diff line number Diff line Loading @@ -2829,4 +2829,9 @@ <string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string> <!-- Title for pairing item [CHAR LIMIT=60] --> <string name="media_output_dialog_pairing_new">Pair new device</string> <!-- Label for clip data when copying the build number off QS [CHAR LIMIT=NONE]--> <string name="build_number_clip_data_label">Build number</string> <!-- Text to display when copying the build number off QS [CHAR LIMIT=NONE]--> <string name="build_number_copy_toast">Build number copied to clipboard.</string> </resources>
packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +18 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS; import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; import android.content.Intent; import android.content.res.Configuration; Loading @@ -34,6 +36,7 @@ import android.os.Handler; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.text.TextUtils; import android.util.AttributeSet; import android.view.View; import android.view.View.OnClickListener; Loading Loading @@ -154,6 +157,19 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mActionsContainer = findViewById(R.id.qs_footer_actions_container); mEditContainer = findViewById(R.id.qs_footer_actions_edit_container); mBuildText = findViewById(R.id.build); mBuildText.setOnLongClickListener(view -> { CharSequence buildText = mBuildText.getText(); if (!TextUtils.isEmpty(buildText)) { ClipboardManager service = mUserTracker.getUserContext().getSystemService(ClipboardManager.class); String label = mContext.getString(R.string.build_number_clip_data_label); service.setPrimaryClip(ClipData.newPlainText(label, buildText)); Toast.makeText(mContext, R.string.build_number_copy_toast, Toast.LENGTH_SHORT) .show(); return true; } return false; }); // RenderThread is doing more harm than good when touching the header (to expand quick // settings), so disable it for this view Loading @@ -180,6 +196,7 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mBuildText.setSelected(true); mShouldShowBuildText = true; } else { mBuildText.setText(null); mShouldShowBuildText = false; mBuildText.setSelected(false); } Loading Loading @@ -321,6 +338,7 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mMultiUserSwitch.setClickable(mMultiUserSwitch.getVisibility() == View.VISIBLE); mEdit.setClickable(mEdit.getVisibility() == View.VISIBLE); mSettingsButton.setClickable(mSettingsButton.getVisibility() == View.VISIBLE); mBuildText.setLongClickable(mBuildText.getVisibility() == View.VISIBLE); } private void updateVisibilities() { Loading
packages/SystemUI/tests/src/com/android/systemui/qs/QSFooterImplTest.java +36 −1 Original line number Diff line number Diff line Loading @@ -14,17 +14,22 @@ package com.android.systemui.qs; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ClipData; import android.content.ClipboardManager; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; import androidx.test.filters.SmallTest; Loading @@ -33,12 +38,16 @@ import com.android.systemui.R.id; import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.settings.UserTracker; import com.android.systemui.statusbar.policy.DeviceProvisionedController; import com.android.systemui.statusbar.policy.UserInfoController; import com.android.systemui.utils.leaks.LeakCheckedTest; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @RunWith(AndroidTestingRunner.class) @RunWithLooper Loading @@ -48,19 +57,45 @@ public class QSFooterImplTest extends LeakCheckedTest { private QSFooterImpl mFooter; private ActivityStarter mActivityStarter; private DeviceProvisionedController mDeviceProvisionedController; private UserInfoController mUserInfoController; private UserTracker mUserTracker; @Mock private ClipboardManager mClipboardManager; @Before public void setup() throws Exception { MockitoAnnotations.initMocks(this); injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES); mActivityStarter = mDependency.injectMockDependency(ActivityStarter.class); mDeviceProvisionedController = mDependency.injectMockDependency( DeviceProvisionedController.class); mDependency.injectMockDependency(UserTracker.class); mUserInfoController = mDependency.injectMockDependency(UserInfoController.class); mUserTracker = mDependency.injectMockDependency(UserTracker.class); mContext.addMockSystemService(ClipboardManager.class, mClipboardManager); when(mUserTracker.getUserContext()).thenReturn(mContext); TestableLooper.get(this).runWithLooper( () -> mFooter = (QSFooterImpl) LayoutInflater.from(mContext).inflate( R.layout.qs_footer_impl, null)); } @Test public void testBuildTextCopy() { TextView buildTextView = mFooter.requireViewById(R.id.build); CharSequence buildText = "TEST"; buildTextView.setText(buildText); buildTextView.setLongClickable(true); buildTextView.performLongClick(); ArgumentCaptor<ClipData> captor = ArgumentCaptor.forClass(ClipData.class); verify(mClipboardManager).setPrimaryClip(captor.capture()); assertThat(captor.getValue().getItemAt(0).getText()).isEqualTo(buildText); } @Test @Ignore("failing") public void testSettings_UserNotSetup() { Loading