diff options
5 files changed, 241 insertions, 87 deletions
diff --git a/packages/SystemUI/res/layout/qs_footer_carrier.xml b/packages/SystemUI/res/layout/qs_footer_carrier.xml new file mode 100644 index 000000000000..bd492b022e36 --- /dev/null +++ b/packages/SystemUI/res/layout/qs_footer_carrier.xml @@ -0,0 +1,49 @@ +<!-- + ~ 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 + --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/linear_footer_carrier" + android:layout_width="0dp" + android:layout_height="match_parent" + android:orientation="horizontal" + android:layout_weight="1" + android:gravity="center_vertical|start" + android:background="@android:color/transparent" + android:clickable="false" + android:clipChildren="false" + android:clipToPadding="false" + android:paddingStart="16dp" > + + <include + layout="@layout/mobile_signal_group" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="8dp" + android:visibility="gone" /> + + <view class="com.android.systemui.qs.QSFooterImpl$QSCarrierText" + android:id="@+id/qs_carrier_text" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:ellipsize="marquee" + android:textAppearance="@style/TextAppearance.QS.CarrierInfo" + android:textColor="?android:attr/textColorPrimary" + android:textDirection="locale" + android:singleLine="true" /> + +</LinearLayout>
\ No newline at end of file diff --git a/packages/SystemUI/res/layout/qs_footer_impl.xml b/packages/SystemUI/res/layout/qs_footer_impl.xml index 890bf5d8ac45..abf9e056ed22 100644 --- a/packages/SystemUI/res/layout/qs_footer_impl.xml +++ b/packages/SystemUI/res/layout/qs_footer_impl.xml @@ -42,30 +42,31 @@ android:gravity="end" > <LinearLayout + android:id="@+id/qs_mobile" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical|start" - android:paddingStart="16dp"> + android:orientation="horizontal" + android:layout_marginEnd="32dp"> <include - layout="@layout/mobile_signal_group" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginEnd="8dp" + layout="@layout/qs_footer_carrier" + android:id="@+id/carrier1" /> + + <View + android:id="@+id/qs_carrier_divider" + android:layout_width="2dp" + android:layout_height="match_parent" + android:layout_marginTop="15dp" + android:layout_marginBottom="15dp" + android:background="?android:attr/dividerVertical" android:visibility="gone" /> - <com.android.keyguard.CarrierText - android:id="@+id/qs_carrier_text" - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_marginEnd="32dp" - android:ellipsize="marquee" - android:textAppearance="@style/TextAppearance.QS.CarrierInfo" - android:textColor="?android:attr/textColorPrimary" - android:textDirection="locale" - android:singleLine="true" /> + <include + layout="@layout/qs_footer_carrier" + android:id="@+id/carrier2" + android:visibility="gone"/> </LinearLayout> diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierText.java b/packages/SystemUI/src/com/android/keyguard/CarrierText.java index 8069ce4c0100..adcb7a125e80 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierText.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierText.java @@ -42,8 +42,8 @@ public class CarrierText extends TextView { private CarrierTextController.CarrierTextCallback mCarrierTextCallback = new CarrierTextController.CarrierTextCallback() { @Override - public void updateCarrierText(CharSequence carrierText, boolean simsReady) { - setText(carrierText); + public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) { + setText(info.carrierText); } @Override @@ -53,7 +53,7 @@ public class CarrierText extends TextView { @Override public void finishedWakingUp() { - setSelected(mShouldMarquee); + setSelected(true); } }; @@ -85,7 +85,6 @@ public class CarrierText extends TextView { mShowMissingSim); mShouldMarquee = KeyguardUpdateMonitor.getInstance(mContext).isDeviceInteractive(); setSelected(mShouldMarquee); // Allow marquee to work. - } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java index 3698a6e6a776..2ce69650b65c 100644 --- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java +++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java @@ -46,17 +46,11 @@ public class CarrierTextController { private static final String TAG = "CarrierTextController"; private final boolean mIsEmergencyCallCapable; - private boolean mTelephonyCapable; - private boolean mShowMissingSim; - private boolean mShowAirplaneMode; - private KeyguardUpdateMonitor mKeyguardUpdateMonitor; - private WifiManager mWifiManager; - private boolean[] mSimErrorState = new boolean[TelephonyManager.getDefault().getPhoneCount()]; private CarrierTextCallback mCarrierTextCallback; private Context mContext; @@ -132,10 +126,8 @@ public class CarrierTextController { /** * Controller that provides updates on text with carriers names or SIM status. * Used by {@link CarrierText}. - * @param context + * * @param separator Separator between different parts of the text - * @param showAirplaneMode - * @param showMissingSim */ public CarrierTextController(Context context, CharSequence separator, boolean showAirplaneMode, boolean showMissingSim) { @@ -186,6 +178,7 @@ public class CarrierTextController { /** * Sets the listening status of this controller. If the callback is null, it is set to * not listening + * * @param callback Callback to provide text updates */ public void setListening(CarrierTextCallback callback) { @@ -199,7 +192,7 @@ public class CarrierTextController { } else { // Don't listen and clear out the text when the device isn't a phone. mKeyguardUpdateMonitor = null; - callback.updateCarrierText("", false); + callback.updateCarrierInfo(new CarrierTextCallbackInfo("", null, false, null)); } } else { mCarrierTextCallback = null; @@ -217,9 +210,11 @@ public class CarrierTextController { List<SubscriptionInfo> subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false); final int numSubs = subs.size(); + final int[] subsIds = new int[numSubs]; if (DEBUG) Log.d(TAG, "updateCarrierText(): " + numSubs); for (int i = 0; i < numSubs; i++) { int subId = subs.get(i).getSubscriptionId(); + subsIds[i] = subId; IccCardConstants.State simState = mKeyguardUpdateMonitor.getSimState(subId); CharSequence carrierName = subs.get(i).getCarrierName(); CharSequence carrierTextForSimState = getCarrierTextForSimState(simState, carrierName); @@ -294,9 +289,11 @@ public class CarrierTextController { } if (mCarrierTextCallback != null) { - mCarrierTextCallback.updateCarrierText(displayText, anySimReadyAndInService); - mCarrierTextCallback.updateCarrierList( - displayText.toString().split(mSeparator.toString()), anySimReadyAndInService); + mCarrierTextCallback.updateCarrierInfo(new CarrierTextCallbackInfo( + displayText, + displayText.toString().split(mSeparator.toString()), + anySimReadyAndInService, + subsIds)); } } @@ -482,22 +479,31 @@ public class CarrierTextController { } /** + * Data structure for passing information to CarrierTextController subscribers + */ + public static final class CarrierTextCallbackInfo { + public final CharSequence carrierText; + public final CharSequence[] listOfCarriers; + public final boolean anySimReady; + public final int[] subscriptionIds; + + CarrierTextCallbackInfo(CharSequence carrierText, CharSequence[] listOfCarriers, + boolean anySimReady, int[] subscriptionIds) { + this.carrierText = carrierText; + this.listOfCarriers = listOfCarriers; + this.anySimReady = anySimReady; + this.subscriptionIds = subscriptionIds; + } + } + + /** * Callback to communicate to Views */ public interface CarrierTextCallback { /** - * Provides an updated list of carrier names - * @param listOfCarriers - * @param simsReady Whether at least one SIM is ready and with service - */ - default void updateCarrierList(CharSequence[] listOfCarriers, boolean simsReady) {}; - - /** - * Provides an updated full carrier text - * @param carrierText - * @param simsReady Whether at least one SIM is ready and with service + * Provides updated carrier information. */ - default void updateCarrierText(CharSequence carrierText, boolean simsReady) {}; + default void updateCarrierInfo(CarrierTextCallbackInfo info) {}; /** * Notifies the View that the device is going to sleep diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java index e63f88a898cc..c0ed4b97eaff 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java @@ -30,14 +30,18 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.RippleDrawable; import android.os.Bundle; import android.os.UserManager; +import android.telephony.SubscriptionManager; import android.text.TextUtils; import android.util.AttributeSet; +import android.util.Log; import android.view.View; import android.view.View.OnClickListener; +import android.view.ViewGroup; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.TextView; import android.widget.Toast; import androidx.annotation.Nullable; @@ -45,7 +49,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto; -import com.android.keyguard.CarrierText; +import com.android.keyguard.CarrierTextController; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.settingslib.Utils; import com.android.settingslib.drawable.UserIconDrawable; @@ -68,7 +72,11 @@ import javax.inject.Inject; import javax.inject.Named; public class QSFooterImpl extends FrameLayout implements QSFooter, - OnClickListener, OnUserInfoChangedListener, EmergencyListener, SignalCallback { + OnClickListener, OnUserInfoChangedListener, EmergencyListener, SignalCallback, + CarrierTextController.CarrierTextCallback { + + private static final int SIM_SLOTS = 2; + private static final String TAG = "QSFooterImpl"; private final ActivityStarter mActivityStarter; private final UserInfoController mUserInfoController; @@ -77,7 +85,6 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, private SettingsButton mSettingsButton; protected View mSettingsContainer; private PageIndicator mPageIndicator; - private CarrierText mCarrierText; private boolean mQsDisabled; private QSPanel mQsPanel; @@ -99,12 +106,20 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, private View mActionsContainer; private View mDragHandle; - private View mMobileGroup; - private ImageView mMobileSignal; - private ImageView mMobileRoaming; + + private View mCarrierDivider; + private ViewGroup mMobileFooter; + private View[] mMobileGroups = new View[SIM_SLOTS]; + private ViewGroup[] mCarrierGroups = new ViewGroup[SIM_SLOTS]; + private TextView[] mCarrierTexts = new TextView[SIM_SLOTS]; + private ImageView[] mMobileSignals = new ImageView[SIM_SLOTS]; + private ImageView[] mMobileRoamings = new ImageView[SIM_SLOTS]; + private final CellSignalState[] mInfos = + new CellSignalState[]{new CellSignalState(), new CellSignalState()}; + private final int mColorForeground; - private final CellSignalState mInfo = new CellSignalState(); private OnClickListener mExpandClickListener; + private CarrierTextController mCarrierTextController; @Inject public QSFooterImpl(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs, @@ -134,10 +149,20 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mSettingsContainer = findViewById(R.id.settings_button_container); mSettingsButton.setOnClickListener(this); - mMobileGroup = findViewById(R.id.mobile_combo); - mMobileSignal = findViewById(R.id.mobile_signal); - mMobileRoaming = findViewById(R.id.mobile_roaming); - mCarrierText = findViewById(R.id.qs_carrier_text); + mMobileFooter = findViewById(R.id.qs_mobile); + mCarrierGroups[0] = findViewById(R.id.carrier1); + mCarrierGroups[1] = findViewById(R.id.carrier2); + + for (int i = 0; i < SIM_SLOTS; i++) { + mMobileGroups[i] = mCarrierGroups[i].findViewById(R.id.mobile_combo); + mMobileSignals[i] = mCarrierGroups[i].findViewById(R.id.mobile_signal); + mMobileRoamings[i] = mCarrierGroups[i].findViewById(R.id.mobile_roaming); + mCarrierTexts[i] = mCarrierGroups[i].findViewById(R.id.qs_carrier_text); + } + mCarrierDivider = findViewById(R.id.qs_carrier_divider); + CharSequence separator = mContext.getString( + com.android.internal.R.string.kg_text_message_separator); + mCarrierTextController = new CarrierTextController(mContext, separator, false, false); mMultiUserSwitch = findViewById(R.id.multi_user_switch); mMultiUserAvatar = mMultiUserSwitch.findViewById(R.id.multi_user_avatar); @@ -204,8 +229,8 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, private TouchAnimator createFooterAnimator() { return new TouchAnimator.Builder() .addFloat(mDivider, "alpha", 0, 1) - .addFloat(mCarrierText, "alpha", 0, 0, 1) - .addFloat(mMobileGroup, "alpha", 0, 1) + .addFloat(mMobileFooter, "alpha", 0, 0, 1) + .addFloat(mCarrierDivider, "alpha", 0, 1) .addFloat(mActionsContainer, "alpha", 0, 1) .addFloat(mDragHandle, "alpha", 1, 0, 0) .addFloat(mPageIndicator, "alpha", 0, 1) @@ -332,10 +357,12 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, mNetworkController.addEmergencyListener(this); mNetworkController.addCallback(this); } + mCarrierTextController.setListening(this); } else { mUserInfoController.removeCallback(this); mNetworkController.removeEmergencyListener(this); mNetworkController.removeCallback(this); + mCarrierTextController.setListening(null); } } @@ -358,7 +385,8 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, if (v == mSettingsButton) { if (!mDeviceProvisionedController.isCurrentUserSetup()) { // If user isn't setup just unlock the device and dump them back at SUW. - mActivityStarter.postQSRunnableDismissingKeyguard(() -> { }); + mActivityStarter.postQSRunnableDismissingKeyguard(() -> { + }); return; } MetricsLogger.action(mContext, @@ -415,32 +443,64 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, } private void handleUpdateState() { - mMobileGroup.setVisibility(mInfo.visible ? View.VISIBLE : View.GONE); - if (mInfo.visible) { - mMobileRoaming.setVisibility(mInfo.roaming ? View.VISIBLE : View.GONE); - mMobileRoaming.setImageTintList(ColorStateList.valueOf(mColorForeground)); - SignalDrawable d = new SignalDrawable(mContext); - d.setDarkIntensity(QuickStatusBarHeader.getColorIntensity(mColorForeground)); - mMobileSignal.setImageDrawable(d); - mMobileSignal.setImageLevel(mInfo.mobileSignalIconId); - - StringBuilder contentDescription = new StringBuilder(); - if (mInfo.contentDescription != null) { - contentDescription.append(mInfo.contentDescription).append(", "); + for (int i = 0; i < SIM_SLOTS; i++) { + mMobileGroups[i].setVisibility(mInfos[i].visible ? View.VISIBLE : View.GONE); + if (mInfos[i].visible) { + mMobileRoamings[i].setVisibility(mInfos[i].roaming ? View.VISIBLE : View.GONE); + mMobileRoamings[i].setImageTintList(ColorStateList.valueOf(mColorForeground)); + SignalDrawable d = new SignalDrawable(mContext); + d.setDarkIntensity(QuickStatusBarHeader.getColorIntensity(mColorForeground)); + mMobileSignals[i].setImageDrawable(d); + mMobileSignals[i].setImageLevel(mInfos[i].mobileSignalIconId); + + StringBuilder contentDescription = new StringBuilder(); + if (mInfos[i].contentDescription != null) { + contentDescription.append(mInfos[i].contentDescription).append(", "); + } + if (mInfos[i].roaming) { + contentDescription + .append(mContext.getString(R.string.data_connection_roaming)) + .append(", "); + } + // TODO: show mobile data off/no internet text for 5 seconds before carrier text + if (TextUtils.equals(mInfos[i].typeContentDescription, + mContext.getString(R.string.data_connection_no_internet)) + || TextUtils.equals(mInfos[i].typeContentDescription, + mContext.getString(R.string.cell_data_off_content_description))) { + contentDescription.append(mInfos[i].typeContentDescription); + } + mMobileSignals[i].setContentDescription(contentDescription); } - if (mInfo.roaming) { - contentDescription - .append(mContext.getString(R.string.data_connection_roaming)) - .append(", "); + } + mCarrierDivider.setVisibility( + mInfos[0].visible && mInfos[1].visible ? View.VISIBLE : View.GONE); + } + + @Override + public void updateCarrierInfo(CarrierTextController.CarrierTextCallbackInfo info) { + if (info.anySimReady) { + boolean[] slotSeen = new boolean[SIM_SLOTS]; + for (int i = 0; i < SIM_SLOTS && i < info.listOfCarriers.length; i++) { + int slot = SubscriptionManager.getSlotIndex(info.subscriptionIds[i]); + mInfos[slot].visible = true; + slotSeen[slot] = true; + mCarrierTexts[slot].setText(info.listOfCarriers[i].toString().trim()); + mCarrierGroups[slot].setVisibility(View.VISIBLE); } - // TODO: show mobile data off/no internet text for 5 seconds before carrier text - if (TextUtils.equals(mInfo.typeContentDescription, - mContext.getString(R.string.data_connection_no_internet)) - || TextUtils.equals(mInfo.typeContentDescription, - mContext.getString(R.string.cell_data_off_content_description))) { - contentDescription.append(mInfo.typeContentDescription); + for (int i = 0; i < SIM_SLOTS; i++) { + if (!slotSeen[i]) { + mInfos[i].visible = false; + mCarrierGroups[i].setVisibility(View.GONE); + } } - mMobileSignal.setContentDescription(contentDescription); + handleUpdateState(); + } else { + mInfos[0].visible = false; + mInfos[1].visible = false; + mCarrierTexts[0].setText(info.carrierText); + mCarrierGroups[0].setVisibility(View.VISIBLE); + mCarrierGroups[1].setVisibility(View.GONE); + handleUpdateState(); } } @@ -450,18 +510,23 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, int qsType, boolean activityIn, boolean activityOut, String typeContentDescription, String description, boolean isWide, int subId, boolean roaming) { - mInfo.visible = statusIcon.visible; - mInfo.mobileSignalIconId = statusIcon.icon; - mInfo.contentDescription = statusIcon.contentDescription; - mInfo.typeContentDescription = typeContentDescription; - mInfo.roaming = roaming; + int slotIndex = SubscriptionManager.getSlotIndex(subId); + if (slotIndex >= SIM_SLOTS) { + Log.e(TAG, "setMobileDataIndicators - slot: " + slotIndex); + } + mInfos[slotIndex].visible = statusIcon.visible; + mInfos[slotIndex].mobileSignalIconId = statusIcon.icon; + mInfos[slotIndex].contentDescription = statusIcon.contentDescription; + mInfos[slotIndex].typeContentDescription = typeContentDescription; + mInfos[slotIndex].roaming = roaming; handleUpdateState(); } @Override public void setNoSims(boolean hasNoSims, boolean simDetected) { if (hasNoSims) { - mInfo.visible = false; + mInfos[0].visible = false; + mInfos[1].visible = false; } handleUpdateState(); } @@ -473,4 +538,38 @@ public class QSFooterImpl extends FrameLayout implements QSFooter, String typeContentDescription; boolean roaming; } + + + /** + * TextView that changes its ellipsize value with its visibility. + */ + public static class QSCarrierText extends TextView { + public QSCarrierText(Context context) { + super(context); + } + + public QSCarrierText(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public QSCarrierText(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public QSCarrierText(Context context, AttributeSet attrs, int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onVisibilityChanged(View changedView, int visibility) { + super.onVisibilityChanged(changedView, visibility); + // Only show marquee when visible + if (visibility == VISIBLE) { + setEllipsize(TextUtils.TruncateAt.MARQUEE); + } else { + setEllipsize(TextUtils.TruncateAt.END); + } + } + } } |