Merge "Enable network type icon overlays by carrier Id" into tm-qpr-dev
This commit is contained in:
@@ -0,0 +1,33 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:viewportWidth="22"
|
||||||
|
android:viewportHeight="17"
|
||||||
|
android:width="22dp"
|
||||||
|
android:height="17dp">
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<path android:fillColor="#FF000000"
|
||||||
|
android:pathData="M1.03 8.47l0.43-4.96h4.33v1.17H2.48L2.25 7.39C2.66 7.1 3.1 6.96 3.57 6.96c0.77 0 1.38 0.3 1.83 0.9 s0.66 1.41 0.66 2.43c0 1.03-0.24 1.84-0.72 2.43S4.2 13.6 3.36 13.6c-0.75 0-1.36-0.24-1.83-0.73s-0.74-1.16-0.81-2.02h1.13 c0.07 0.57 0.23 1 0.49 1.29s0.59 0.43 1.01 0.43c0.47 0 0.84-0.2 1.1-0.61c0.26-0.41 0.4-0.96 0.4-1.65 c0-0.65-0.14-1.18-0.43-1.59S3.76 8.09 3.28 8.09c-0.4 0-0.72 0.1-0.96 0.31L1.99 8.73L1.03 8.47z"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<path android:fillColor="#FF000000"
|
||||||
|
android:pathData="M 18.93,5.74 L 18.93,3.39 L 17.63,3.39 L 17.63,5.74 L 15.28,5.74 L 15.28,7.04 L 17.63,7.04 L 17.63,9.39 L 18.93,9.39 L 18.93,7.04 L 21.28,7.04 L 21.28,5.74 z"/>
|
||||||
|
</group>
|
||||||
|
<path android:fillColor="#FF000000"
|
||||||
|
android:pathData="M13.78 12.24l-0.22 0.27c-0.63 0.73-1.55 1.1-2.76 1.1c-1.08 0-1.92-0.36-2.53-1.07s-0.93-1.72-0.94-3.02V7.56 c0-1.39 0.28-2.44 0.84-3.13s1.39-1.04 2.51-1.04c0.95 0 1.69 0.26 2.23 0.79s0.83 1.28 0.89 2.26h-1.25 c-0.05-0.62-0.22-1.1-0.52-1.45s-0.74-0.52-1.34-0.52c-0.72 0-1.24 0.23-1.57 0.7S8.6 6.37 8.59 7.4v2.03c0 1 0.19 1.77 0.57 2.31 c0.38 0.54 0.93 0.8 1.65 0.8c0.67 0 1.19-0.16 1.54-0.49l0.18-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
|
||||||
|
</group>
|
||||||
|
</vector>
|
||||||
32
packages/SettingsLib/res/values/carrierid_icon_overrides.xml
Normal file
32
packages/SettingsLib/res/values/carrierid_icon_overrides.xml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ 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.
|
||||||
|
-->
|
||||||
|
<!--
|
||||||
|
~ This resource file exists to enumerate all network type icon overrides on a
|
||||||
|
~ per-carrierId basis
|
||||||
|
-->
|
||||||
|
<resources>
|
||||||
|
<!--
|
||||||
|
Network type (RAT) icon overrides can be configured here on a per-carrierId basis.
|
||||||
|
1. Add a new TypedArray here, using the naming scheme below
|
||||||
|
2. The entries are (NetworkType, drawable ID) pairs
|
||||||
|
3. Add this array's ID to the MAPPING field of MobileIconCarrierIdOverrides.kt
|
||||||
|
-->
|
||||||
|
<array name="carrierId_2032_iconOverrides">
|
||||||
|
<item>5G_PLUS</item>
|
||||||
|
<item>@drawable/ic_5g_plus_mobiledata_default</item>
|
||||||
|
</array>
|
||||||
|
</resources>
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
/*
|
||||||
|
* 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.settingslib.mobile
|
||||||
|
|
||||||
|
import android.annotation.DrawableRes
|
||||||
|
import android.content.res.Resources
|
||||||
|
import android.content.res.TypedArray
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.annotation.VisibleForTesting
|
||||||
|
import com.android.settingslib.R
|
||||||
|
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class defines a network type (3G, 4G, etc.) override mechanism on a per-carrierId basis.
|
||||||
|
*
|
||||||
|
* Traditionally, carrier-customized network type iconography was achieved using the `MCC/MNC`
|
||||||
|
* resource qualifiers, and swapping out the drawable resource by name. It would look like this:
|
||||||
|
*
|
||||||
|
* res/
|
||||||
|
* drawable/
|
||||||
|
* 3g_mobiledata_icon.xml
|
||||||
|
* drawable-MCC-MNC/
|
||||||
|
* 3g_mobiledata_icon.xml
|
||||||
|
*
|
||||||
|
* This would mean that, provided a context created with this MCC/MNC configuration set, loading
|
||||||
|
* the network type icon through [MobileIconGroup] would provide a carrier-defined network type
|
||||||
|
* icon rather than the AOSP-defined default.
|
||||||
|
*
|
||||||
|
* The MCC/MNC mechanism no longer can fully define carrier-specific network type icons, because
|
||||||
|
* there is no longer a 1:1 mapping between MCC/MNC and carrier. With the advent of MVNOs, multiple
|
||||||
|
* carriers can have the same MCC/MNC value, but wish to differentiate based on their carrier ID.
|
||||||
|
* CarrierId is a newer concept than MCC/MNC, and provides more granularity when it comes to
|
||||||
|
* determining the carrier (e.g. MVNOs can share MCC/MNC values with the network owner), therefore
|
||||||
|
* it can fit all of the same use cases currently handled by `MCC/MNC`, without the need to apply a
|
||||||
|
* configuration context in order to get the proper UI for a given SIM icon.
|
||||||
|
*
|
||||||
|
* NOTE: CarrierId icon overrides will always take precedence over those defined using `MCC/MNC`
|
||||||
|
* resource qualifiers.
|
||||||
|
*
|
||||||
|
* [MAPPING] encodes the relationship between CarrierId and the corresponding override array
|
||||||
|
* that exists in the config.xml. An alternative approach could be to generate the resource name
|
||||||
|
* by string concatenation at run-time:
|
||||||
|
*
|
||||||
|
* val resName = "carrierId_$carrierId_iconOverrides"
|
||||||
|
* val override = resources.getResourceIdentifier(resName)
|
||||||
|
*
|
||||||
|
* However, that's going to be far less efficient until MAPPING grows to a sufficient size. For now,
|
||||||
|
* given a relatively small number of entries, we should just maintain the mapping here.
|
||||||
|
*/
|
||||||
|
interface MobileIconCarrierIdOverrides {
|
||||||
|
@DrawableRes
|
||||||
|
fun getOverrideFor(carrierId: Int, networkType: String, resources: Resources): Int
|
||||||
|
fun carrierIdEntryExists(carrierId: Int): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
class MobileIconCarrierIdOverridesImpl : MobileIconCarrierIdOverrides {
|
||||||
|
@DrawableRes
|
||||||
|
override fun getOverrideFor(carrierId: Int, networkType: String, resources: Resources): Int {
|
||||||
|
val resId = MAPPING[carrierId] ?: return 0
|
||||||
|
val ta = resources.obtainTypedArray(resId)
|
||||||
|
val map = parseNetworkIconOverrideTypedArray(ta)
|
||||||
|
ta.recycle()
|
||||||
|
return map[networkType] ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun carrierIdEntryExists(carrierId: Int) =
|
||||||
|
overrideExists(carrierId, MAPPING)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "MobileIconOverrides"
|
||||||
|
/**
|
||||||
|
* This map maintains the lookup from the canonical carrier ID (see below link) to the
|
||||||
|
* corresponding overlay resource. New overrides should add an entry below in order to
|
||||||
|
* change the network type icon resources based on carrier ID
|
||||||
|
*
|
||||||
|
* Refer to the link below for the canonical mapping maintained in AOSP:
|
||||||
|
* https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/latest_carrier_id/carrier_list.textpb
|
||||||
|
*/
|
||||||
|
private val MAPPING = mapOf(
|
||||||
|
// 2032 == Xfinity Mobile
|
||||||
|
2032 to R.array.carrierId_2032_iconOverrides,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse `carrierId_XXXX_iconOverrides` for a particular network type. The resource file
|
||||||
|
* "carrierid_icon_overrides.xml" defines a TypedArray format for overriding specific
|
||||||
|
* network type icons (a.k.a. RAT icons) for a particular carrier ID. The format is defined
|
||||||
|
* as an array of (network type name, drawable) pairs:
|
||||||
|
* <array name="carrierId_XXXX_iconOverrides>
|
||||||
|
* <item>NET_TYPE_1</item>
|
||||||
|
* <item>@drawable/net_type_1_override</item>
|
||||||
|
* <item>NET_TYPE_2</item>
|
||||||
|
* <item>@drawable/net_type_2_override</item>
|
||||||
|
* </array>
|
||||||
|
*
|
||||||
|
* @param ta the [TypedArray] defined in carrierid_icon_overrides.xml
|
||||||
|
* @return the overridden drawable resource ID if it exists, or 0 if it does not
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
@JvmStatic
|
||||||
|
fun parseNetworkIconOverrideTypedArray(ta: TypedArray): Map<String, Int> {
|
||||||
|
if (ta.length() % 2 != 0) {
|
||||||
|
Log.w(TAG,
|
||||||
|
"override must contain an even number of (key, value) entries. skipping")
|
||||||
|
|
||||||
|
return mapOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = mutableMapOf<String, Int>()
|
||||||
|
// The array is defined as Pair(String, resourceId), so walk by 2
|
||||||
|
for (i in 0 until ta.length() step 2) {
|
||||||
|
val key = ta.getString(i)
|
||||||
|
val override = ta.getResourceId(i + 1, 0)
|
||||||
|
if (key == null || override == 0) {
|
||||||
|
Log.w(TAG, "Invalid override found. Skipping")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result[key] = override
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
private fun overrideExists(carrierId: Int, mapping: Map<Int, Int>): Boolean =
|
||||||
|
mapping.containsKey(carrierId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* 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.settingslib.mobile;
|
||||||
|
|
||||||
|
import static com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl.parseNetworkIconOverrideTypedArray;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.doAnswer;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner.class)
|
||||||
|
public final class MobileIconCarrierIdOverridesTest {
|
||||||
|
private static final String OVERRIDE_ICON_1_NAME = "name_1";
|
||||||
|
private static final int OVERRIDE_ICON_1_RES = 1;
|
||||||
|
|
||||||
|
private static final String OVERRIDE_ICON_2_NAME = "name_2";
|
||||||
|
private static final int OVERRIDE_ICON_2_RES = 2;
|
||||||
|
|
||||||
|
NetworkOverrideTypedArrayMock mResourceMock;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
mResourceMock = new NetworkOverrideTypedArrayMock(
|
||||||
|
new String[] { OVERRIDE_ICON_1_NAME, OVERRIDE_ICON_2_NAME },
|
||||||
|
new int[] { OVERRIDE_ICON_1_RES, OVERRIDE_ICON_2_RES }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse_singleOverride() {
|
||||||
|
mResourceMock.setOverrides(
|
||||||
|
new String[] { OVERRIDE_ICON_1_NAME },
|
||||||
|
new int[] { OVERRIDE_ICON_1_RES }
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, Integer> parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock());
|
||||||
|
|
||||||
|
assertThat(parsed.get(OVERRIDE_ICON_1_NAME)).isEqualTo(OVERRIDE_ICON_1_RES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse_multipleOverrides() {
|
||||||
|
mResourceMock.setOverrides(
|
||||||
|
new String[] { OVERRIDE_ICON_1_NAME, OVERRIDE_ICON_2_NAME },
|
||||||
|
new int[] { OVERRIDE_ICON_1_RES, OVERRIDE_ICON_2_RES }
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, Integer> parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock());
|
||||||
|
|
||||||
|
assertThat(parsed.get(OVERRIDE_ICON_2_NAME)).isEqualTo(OVERRIDE_ICON_2_RES);
|
||||||
|
assertThat(parsed.get(OVERRIDE_ICON_1_NAME)).isEqualTo(OVERRIDE_ICON_1_RES);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testParse_nonexistentKey_isNull() {
|
||||||
|
mResourceMock.setOverrides(
|
||||||
|
new String[] { OVERRIDE_ICON_1_NAME },
|
||||||
|
new int[] { OVERRIDE_ICON_1_RES }
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, Integer> parsed = parseNetworkIconOverrideTypedArray(mResourceMock.getMock());
|
||||||
|
|
||||||
|
assertThat(parsed.get(OVERRIDE_ICON_2_NAME)).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class NetworkOverrideTypedArrayMock {
|
||||||
|
private Object[] mInterleaved;
|
||||||
|
|
||||||
|
private final TypedArray mMockTypedArray = mock(TypedArray.class);
|
||||||
|
|
||||||
|
NetworkOverrideTypedArrayMock(
|
||||||
|
String[] networkTypes,
|
||||||
|
int[] iconOverrides) {
|
||||||
|
|
||||||
|
mInterleaved = interleaveTypes(networkTypes, iconOverrides);
|
||||||
|
|
||||||
|
doAnswer(invocation -> {
|
||||||
|
return mInterleaved[(int) invocation.getArgument(0)];
|
||||||
|
}).when(mMockTypedArray).getString(/* index */ anyInt());
|
||||||
|
|
||||||
|
doAnswer(invocation -> {
|
||||||
|
return mInterleaved[(int) invocation.getArgument(0)];
|
||||||
|
}).when(mMockTypedArray).getResourceId(/* index */ anyInt(), /* default */ anyInt());
|
||||||
|
|
||||||
|
when(mMockTypedArray.length()).thenAnswer(invocation -> {
|
||||||
|
return mInterleaved.length;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
TypedArray getMock() {
|
||||||
|
return mMockTypedArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOverrides(String[] types, int[] resIds) {
|
||||||
|
mInterleaved = interleaveTypes(types, resIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Object[] interleaveTypes(String[] strs, int[] ints) {
|
||||||
|
assertThat(strs.length).isEqualTo(ints.length);
|
||||||
|
|
||||||
|
Object[] ret = new Object[strs.length * 2];
|
||||||
|
|
||||||
|
// Keep track of where we are in the interleaved array, but iterate the overrides
|
||||||
|
int interleavedIndex = 0;
|
||||||
|
for (int i = 0; i < strs.length; i++) {
|
||||||
|
ret[interleavedIndex] = strs[i];
|
||||||
|
interleavedIndex += 1;
|
||||||
|
ret[interleavedIndex] = ints[i];
|
||||||
|
interleavedIndex += 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,9 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.systemui.statusbar.connectivity;
|
package com.android.systemui.statusbar.connectivity;
|
||||||
|
|
||||||
import static com.android.settingslib.mobile.MobileMappings.getDefaultIcons;
|
import static android.telephony.TelephonyManager.UNKNOWN_CARRIER_ID;
|
||||||
import static com.android.settingslib.mobile.MobileMappings.getIconKey;
|
|
||||||
import static com.android.settingslib.mobile.MobileMappings.mapIconSets;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
@@ -46,6 +44,7 @@ import com.android.settingslib.mobile.MobileStatusTracker.SubscriptionDefaults;
|
|||||||
import com.android.settingslib.mobile.TelephonyIcons;
|
import com.android.settingslib.mobile.TelephonyIcons;
|
||||||
import com.android.settingslib.net.SignalStrengthUtil;
|
import com.android.settingslib.net.SignalStrengthUtil;
|
||||||
import com.android.systemui.R;
|
import com.android.systemui.R;
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy;
|
||||||
import com.android.systemui.util.CarrierConfigTracker;
|
import com.android.systemui.util.CarrierConfigTracker;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
@@ -63,6 +62,7 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
|
|||||||
private final TelephonyManager mPhone;
|
private final TelephonyManager mPhone;
|
||||||
private final CarrierConfigTracker mCarrierConfigTracker;
|
private final CarrierConfigTracker mCarrierConfigTracker;
|
||||||
private final SubscriptionDefaults mDefaults;
|
private final SubscriptionDefaults mDefaults;
|
||||||
|
private final MobileMappingsProxy mMobileMappingsProxy;
|
||||||
private final String mNetworkNameDefault;
|
private final String mNetworkNameDefault;
|
||||||
private final String mNetworkNameSeparator;
|
private final String mNetworkNameSeparator;
|
||||||
private final ContentObserver mObserver;
|
private final ContentObserver mObserver;
|
||||||
@@ -121,6 +121,7 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
|
|||||||
TelephonyManager phone,
|
TelephonyManager phone,
|
||||||
CallbackHandler callbackHandler,
|
CallbackHandler callbackHandler,
|
||||||
NetworkControllerImpl networkController,
|
NetworkControllerImpl networkController,
|
||||||
|
MobileMappingsProxy mobileMappingsProxy,
|
||||||
SubscriptionInfo info,
|
SubscriptionInfo info,
|
||||||
SubscriptionDefaults defaults,
|
SubscriptionDefaults defaults,
|
||||||
Looper receiverLooper,
|
Looper receiverLooper,
|
||||||
@@ -135,13 +136,14 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
|
|||||||
mPhone = phone;
|
mPhone = phone;
|
||||||
mDefaults = defaults;
|
mDefaults = defaults;
|
||||||
mSubscriptionInfo = info;
|
mSubscriptionInfo = info;
|
||||||
|
mMobileMappingsProxy = mobileMappingsProxy;
|
||||||
mNetworkNameSeparator = getTextIfExists(
|
mNetworkNameSeparator = getTextIfExists(
|
||||||
R.string.status_bar_network_name_separator).toString();
|
R.string.status_bar_network_name_separator).toString();
|
||||||
mNetworkNameDefault = getTextIfExists(
|
mNetworkNameDefault = getTextIfExists(
|
||||||
com.android.internal.R.string.lockscreen_carrier_default).toString();
|
com.android.internal.R.string.lockscreen_carrier_default).toString();
|
||||||
|
|
||||||
mNetworkToIconLookup = mapIconSets(mConfig);
|
mNetworkToIconLookup = mMobileMappingsProxy.mapIconSets(mConfig);
|
||||||
mDefaultIcons = getDefaultIcons(mConfig);
|
mDefaultIcons = mMobileMappingsProxy.getDefaultIcons(mConfig);
|
||||||
|
|
||||||
String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
|
String networkName = info.getCarrierName() != null ? info.getCarrierName().toString()
|
||||||
: mNetworkNameDefault;
|
: mNetworkNameDefault;
|
||||||
@@ -161,8 +163,8 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
|
|||||||
void setConfiguration(Config config) {
|
void setConfiguration(Config config) {
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
updateInflateSignalStrength();
|
updateInflateSignalStrength();
|
||||||
mNetworkToIconLookup = mapIconSets(mConfig);
|
mNetworkToIconLookup = mMobileMappingsProxy.mapIconSets(mConfig);
|
||||||
mDefaultIcons = getDefaultIcons(mConfig);
|
mDefaultIcons = mMobileMappingsProxy.getDefaultIcons(mConfig);
|
||||||
updateTelephony();
|
updateTelephony();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,8 +273,9 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
|
|||||||
dataContentDescription = mContext.getString(R.string.data_connection_no_internet);
|
dataContentDescription = mContext.getString(R.string.data_connection_no_internet);
|
||||||
}
|
}
|
||||||
|
|
||||||
final QsInfo qsInfo = getQsInfo(contentDescription, icons.dataType);
|
int iconId = mCurrentState.getNetworkTypeIcon(mContext);
|
||||||
final SbInfo sbInfo = getSbInfo(contentDescription, icons.dataType);
|
final QsInfo qsInfo = getQsInfo(contentDescription, iconId);
|
||||||
|
final SbInfo sbInfo = getSbInfo(contentDescription, iconId);
|
||||||
|
|
||||||
MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
|
MobileDataIndicators mobileDataIndicators = new MobileDataIndicators(
|
||||||
sbInfo.icon,
|
sbInfo.icon,
|
||||||
@@ -373,6 +376,10 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
|
|||||||
} else if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
|
} else if (action.equals(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
|
||||||
updateDataSim();
|
updateDataSim();
|
||||||
notifyListenersIfNecessary();
|
notifyListenersIfNecessary();
|
||||||
|
} else if (action.equals(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED)) {
|
||||||
|
int carrierId = intent.getIntExtra(
|
||||||
|
TelephonyManager.EXTRA_CARRIER_ID, UNKNOWN_CARRIER_ID);
|
||||||
|
mCurrentState.setCarrierId(carrierId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +484,8 @@ public class MobileSignalController extends SignalController<MobileState, Mobile
|
|||||||
mCurrentState.level = getSignalLevel(mCurrentState.signalStrength);
|
mCurrentState.level = getSignalLevel(mCurrentState.signalStrength);
|
||||||
}
|
}
|
||||||
|
|
||||||
String iconKey = getIconKey(mCurrentState.telephonyDisplayInfo);
|
mCurrentState.setCarrierId(mPhone.getSimCarrierId());
|
||||||
|
String iconKey = mMobileMappingsProxy.getIconKey(mCurrentState.telephonyDisplayInfo);
|
||||||
if (mNetworkToIconLookup.get(iconKey) != null) {
|
if (mNetworkToIconLookup.get(iconKey) != null) {
|
||||||
mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey);
|
mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.telephony.TelephonyManager
|
|||||||
import com.android.settingslib.mobile.MobileMappings
|
import com.android.settingslib.mobile.MobileMappings
|
||||||
import com.android.settingslib.mobile.MobileStatusTracker
|
import com.android.settingslib.mobile.MobileStatusTracker
|
||||||
import com.android.systemui.dagger.SysUISingleton
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||||
import com.android.systemui.util.CarrierConfigTracker
|
import com.android.systemui.util.CarrierConfigTracker
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@@ -33,6 +34,7 @@ internal class MobileSignalControllerFactory @Inject constructor(
|
|||||||
val context: Context,
|
val context: Context,
|
||||||
val callbackHandler: CallbackHandler,
|
val callbackHandler: CallbackHandler,
|
||||||
val carrierConfigTracker: CarrierConfigTracker,
|
val carrierConfigTracker: CarrierConfigTracker,
|
||||||
|
val mobileMappings: MobileMappingsProxy,
|
||||||
) {
|
) {
|
||||||
fun createMobileSignalController(
|
fun createMobileSignalController(
|
||||||
config: MobileMappings.Config,
|
config: MobileMappings.Config,
|
||||||
@@ -56,6 +58,7 @@ internal class MobileSignalControllerFactory @Inject constructor(
|
|||||||
phone,
|
phone,
|
||||||
callbackHandler,
|
callbackHandler,
|
||||||
networkController,
|
networkController,
|
||||||
|
mobileMappings,
|
||||||
subscriptionInfo,
|
subscriptionInfo,
|
||||||
subscriptionDefaults,
|
subscriptionDefaults,
|
||||||
receiverLooper,
|
receiverLooper,
|
||||||
|
|||||||
@@ -16,10 +16,14 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.connectivity
|
package com.android.systemui.statusbar.connectivity
|
||||||
|
|
||||||
|
import android.annotation.DrawableRes
|
||||||
|
import android.content.Context
|
||||||
import android.telephony.ServiceState
|
import android.telephony.ServiceState
|
||||||
import android.telephony.SignalStrength
|
import android.telephony.SignalStrength
|
||||||
import android.telephony.TelephonyDisplayInfo
|
import android.telephony.TelephonyDisplayInfo
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
|
import com.android.internal.annotations.VisibleForTesting
|
||||||
|
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||||
import com.android.settingslib.Utils
|
import com.android.settingslib.Utils
|
||||||
import com.android.settingslib.mobile.MobileStatusTracker.MobileStatus
|
import com.android.settingslib.mobile.MobileStatusTracker.MobileStatus
|
||||||
import com.android.settingslib.mobile.TelephonyIcons
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
@@ -41,7 +45,7 @@ internal class MobileState(
|
|||||||
@JvmField var roaming: Boolean = false,
|
@JvmField var roaming: Boolean = false,
|
||||||
@JvmField var dataState: Int = TelephonyManager.DATA_DISCONNECTED,
|
@JvmField var dataState: Int = TelephonyManager.DATA_DISCONNECTED,
|
||||||
// Tracks the on/off state of the defaultDataSubscription
|
// Tracks the on/off state of the defaultDataSubscription
|
||||||
@JvmField var defaultDataOff: Boolean = false
|
@JvmField var defaultDataOff: Boolean = false,
|
||||||
) : ConnectivityState() {
|
) : ConnectivityState() {
|
||||||
|
|
||||||
@JvmField var telephonyDisplayInfo = TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
|
@JvmField var telephonyDisplayInfo = TelephonyDisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
|
||||||
@@ -49,6 +53,11 @@ internal class MobileState(
|
|||||||
@JvmField var serviceState: ServiceState? = null
|
@JvmField var serviceState: ServiceState? = null
|
||||||
@JvmField var signalStrength: SignalStrength? = null
|
@JvmField var signalStrength: SignalStrength? = null
|
||||||
|
|
||||||
|
var carrierId = TelephonyManager.UNKNOWN_CARRIER_ID
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
var networkTypeResIdCache: NetworkTypeResIdCache = NetworkTypeResIdCache()
|
||||||
|
|
||||||
/** @return true if this state is disabled or not default data */
|
/** @return true if this state is disabled or not default data */
|
||||||
val isDataDisabledOrNotDefault: Boolean
|
val isDataDisabledOrNotDefault: Boolean
|
||||||
get() = (iconGroup === TelephonyIcons.DATA_DISABLED ||
|
get() = (iconGroup === TelephonyIcons.DATA_DISABLED ||
|
||||||
@@ -125,6 +134,21 @@ internal class MobileState(
|
|||||||
return serviceState != null && serviceState!!.roaming
|
return serviceState != null && serviceState!!.roaming
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Load the (potentially customized) icon resource id for the current network type. Note that
|
||||||
|
* this operation caches the result. Note that reading the [MobileIconGroup.dataType] field
|
||||||
|
* directly will not yield correct results in cases where the carrierId has an associated
|
||||||
|
* override. This is the preferred method for getting the network type indicator.
|
||||||
|
*
|
||||||
|
* @return a drawable res id appropriate for the current (carrierId, networkType) pair
|
||||||
|
*/
|
||||||
|
@DrawableRes
|
||||||
|
fun getNetworkTypeIcon(context: Context): Int {
|
||||||
|
val icon = (iconGroup as MobileIconGroup)
|
||||||
|
return networkTypeResIdCache.get(icon, carrierId, context)
|
||||||
|
}
|
||||||
|
|
||||||
fun setFromMobileStatus(mobileStatus: MobileStatus) {
|
fun setFromMobileStatus(mobileStatus: MobileStatus) {
|
||||||
activityIn = mobileStatus.activityIn
|
activityIn = mobileStatus.activityIn
|
||||||
activityOut = mobileStatus.activityOut
|
activityOut = mobileStatus.activityOut
|
||||||
@@ -140,6 +164,7 @@ internal class MobileState(
|
|||||||
super.toString(builder)
|
super.toString(builder)
|
||||||
builder.append(',')
|
builder.append(',')
|
||||||
builder.append("dataSim=$dataSim,")
|
builder.append("dataSim=$dataSim,")
|
||||||
|
builder.append("carrierId=$carrierId")
|
||||||
builder.append("networkName=$networkName,")
|
builder.append("networkName=$networkName,")
|
||||||
builder.append("networkNameData=$networkNameData,")
|
builder.append("networkNameData=$networkNameData,")
|
||||||
builder.append("dataConnected=$dataConnected,")
|
builder.append("dataConnected=$dataConnected,")
|
||||||
@@ -157,6 +182,8 @@ internal class MobileState(
|
|||||||
builder.append("voiceServiceState=${getVoiceServiceState()},")
|
builder.append("voiceServiceState=${getVoiceServiceState()},")
|
||||||
builder.append("isInService=${isInService()},")
|
builder.append("isInService=${isInService()},")
|
||||||
|
|
||||||
|
builder.append("networkTypeIconCache=$networkTypeResIdCache")
|
||||||
|
|
||||||
builder.append("serviceState=${serviceState?.minLog() ?: "(null)"},")
|
builder.append("serviceState=${serviceState?.minLog() ?: "(null)"},")
|
||||||
builder.append("signalStrength=${signalStrength?.minLog() ?: "(null)"},")
|
builder.append("signalStrength=${signalStrength?.minLog() ?: "(null)"},")
|
||||||
builder.append("displayInfo=$telephonyDisplayInfo")
|
builder.append("displayInfo=$telephonyDisplayInfo")
|
||||||
@@ -164,6 +191,7 @@ internal class MobileState(
|
|||||||
|
|
||||||
override fun tableColumns(): List<String> {
|
override fun tableColumns(): List<String> {
|
||||||
val columns = listOf("dataSim",
|
val columns = listOf("dataSim",
|
||||||
|
"carrierId",
|
||||||
"networkName",
|
"networkName",
|
||||||
"networkNameData",
|
"networkNameData",
|
||||||
"dataConnected",
|
"dataConnected",
|
||||||
@@ -178,6 +206,7 @@ internal class MobileState(
|
|||||||
"showQuickSettingsRatIcon",
|
"showQuickSettingsRatIcon",
|
||||||
"voiceServiceState",
|
"voiceServiceState",
|
||||||
"isInService",
|
"isInService",
|
||||||
|
"networkTypeIconCache",
|
||||||
"serviceState",
|
"serviceState",
|
||||||
"signalStrength",
|
"signalStrength",
|
||||||
"displayInfo")
|
"displayInfo")
|
||||||
@@ -187,6 +216,7 @@ internal class MobileState(
|
|||||||
|
|
||||||
override fun tableData(): List<String> {
|
override fun tableData(): List<String> {
|
||||||
val columns = listOf(dataSim,
|
val columns = listOf(dataSim,
|
||||||
|
carrierId,
|
||||||
networkName,
|
networkName,
|
||||||
networkNameData,
|
networkNameData,
|
||||||
dataConnected,
|
dataConnected,
|
||||||
@@ -201,6 +231,7 @@ internal class MobileState(
|
|||||||
showQuickSettingsRatIcon(),
|
showQuickSettingsRatIcon(),
|
||||||
getVoiceServiceState(),
|
getVoiceServiceState(),
|
||||||
isInService(),
|
isInService(),
|
||||||
|
networkTypeResIdCache,
|
||||||
serviceState?.minLog() ?: "(null)",
|
serviceState?.minLog() ?: "(null)",
|
||||||
signalStrength?.minLog() ?: "(null)",
|
signalStrength?.minLog() ?: "(null)",
|
||||||
telephonyDisplayInfo).map { it.toString() }
|
telephonyDisplayInfo).map { it.toString() }
|
||||||
@@ -217,6 +248,7 @@ internal class MobileState(
|
|||||||
|
|
||||||
if (networkName != other.networkName) return false
|
if (networkName != other.networkName) return false
|
||||||
if (networkNameData != other.networkNameData) return false
|
if (networkNameData != other.networkNameData) return false
|
||||||
|
if (carrierId != other.carrierId) return false
|
||||||
if (dataSim != other.dataSim) return false
|
if (dataSim != other.dataSim) return false
|
||||||
if (dataConnected != other.dataConnected) return false
|
if (dataConnected != other.dataConnected) return false
|
||||||
if (isEmergency != other.isEmergency) return false
|
if (isEmergency != other.isEmergency) return false
|
||||||
@@ -238,6 +270,7 @@ internal class MobileState(
|
|||||||
var result = super.hashCode()
|
var result = super.hashCode()
|
||||||
result = 31 * result + (networkName?.hashCode() ?: 0)
|
result = 31 * result + (networkName?.hashCode() ?: 0)
|
||||||
result = 31 * result + (networkNameData?.hashCode() ?: 0)
|
result = 31 * result + (networkNameData?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (carrierId.hashCode())
|
||||||
result = 31 * result + dataSim.hashCode()
|
result = 31 * result + dataSim.hashCode()
|
||||||
result = 31 * result + dataConnected.hashCode()
|
result = 31 * result + dataConnected.hashCode()
|
||||||
result = 31 * result + isEmergency.hashCode()
|
result = 31 * result + isEmergency.hashCode()
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN
|
|||||||
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
|
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_INOUT;
|
||||||
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
|
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
|
||||||
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
|
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
|
||||||
|
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
||||||
|
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
@@ -139,7 +140,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
|||||||
private final MobileSignalControllerFactory mMobileFactory;
|
private final MobileSignalControllerFactory mMobileFactory;
|
||||||
|
|
||||||
private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener;
|
private TelephonyCallback.ActiveDataSubscriptionIdListener mPhoneStateListener;
|
||||||
private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
|
private int mActiveMobileDataSubscription = INVALID_SUBSCRIPTION_ID;
|
||||||
|
|
||||||
// Subcontrollers.
|
// Subcontrollers.
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -503,6 +504,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
|||||||
filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
|
filter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
|
||||||
filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
|
filter.addAction(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED);
|
||||||
filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
|
filter.addAction(TelephonyManager.ACTION_SERVICE_PROVIDERS_UPDATED);
|
||||||
|
filter.addAction(TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
|
||||||
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||||
mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler);
|
mBroadcastDispatcher.registerReceiverWithHandler(this, filter, mReceiverHandler);
|
||||||
mListening = true;
|
mListening = true;
|
||||||
@@ -793,6 +795,20 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
|||||||
mConfig = Config.readConfig(mContext);
|
mConfig = Config.readConfig(mContext);
|
||||||
mReceiverHandler.post(this::handleConfigurationChanged);
|
mReceiverHandler.post(this::handleConfigurationChanged);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED: {
|
||||||
|
// Notify the relevant MobileSignalController of the change
|
||||||
|
int subId = intent.getIntExtra(
|
||||||
|
TelephonyManager.EXTRA_SUBSCRIPTION_ID,
|
||||||
|
INVALID_SUBSCRIPTION_ID
|
||||||
|
);
|
||||||
|
if (SubscriptionManager.isValidSubscriptionId(subId)) {
|
||||||
|
if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
|
||||||
|
mMobileSignalControllers.get(subId).handleBroadcast(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case Intent.ACTION_SIM_STATE_CHANGED:
|
case Intent.ACTION_SIM_STATE_CHANGED:
|
||||||
// Avoid rebroadcast because SysUI is direct boot aware.
|
// Avoid rebroadcast because SysUI is direct boot aware.
|
||||||
if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
|
if (intent.getBooleanExtra(Intent.EXTRA_REBROADCAST_ON_UNLOCK, false)) {
|
||||||
@@ -820,7 +836,7 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
|
int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
|
||||||
SubscriptionManager.INVALID_SUBSCRIPTION_ID);
|
INVALID_SUBSCRIPTION_ID);
|
||||||
if (SubscriptionManager.isValidSubscriptionId(subId)) {
|
if (SubscriptionManager.isValidSubscriptionId(subId)) {
|
||||||
if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
|
if (mMobileSignalControllers.indexOfKey(subId) >= 0) {
|
||||||
mMobileSignalControllers.get(subId).handleBroadcast(intent);
|
mMobileSignalControllers.get(subId).handleBroadcast(intent);
|
||||||
@@ -1336,6 +1352,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
|||||||
String slotString = args.getString("slot");
|
String slotString = args.getString("slot");
|
||||||
int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
|
int slot = TextUtils.isEmpty(slotString) ? 0 : Integer.parseInt(slotString);
|
||||||
slot = MathUtils.constrain(slot, 0, 8);
|
slot = MathUtils.constrain(slot, 0, 8);
|
||||||
|
String carrierIdString = args.getString("carrierid");
|
||||||
|
int carrierId = TextUtils.isEmpty(carrierIdString) ? 0
|
||||||
|
: Integer.parseInt(carrierIdString);
|
||||||
// Ensure we have enough sim slots
|
// Ensure we have enough sim slots
|
||||||
List<SubscriptionInfo> subs = new ArrayList<>();
|
List<SubscriptionInfo> subs = new ArrayList<>();
|
||||||
while (mMobileSignalControllers.size() <= slot) {
|
while (mMobileSignalControllers.size() <= slot) {
|
||||||
@@ -1347,6 +1366,9 @@ public class NetworkControllerImpl extends BroadcastReceiver
|
|||||||
}
|
}
|
||||||
// Hack to index linearly for easy use.
|
// Hack to index linearly for easy use.
|
||||||
MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
|
MobileSignalController controller = mMobileSignalControllers.valueAt(slot);
|
||||||
|
if (carrierId != 0) {
|
||||||
|
controller.getState().setCarrierId(carrierId);
|
||||||
|
}
|
||||||
controller.getState().dataSim = datatype != null;
|
controller.getState().dataSim = datatype != null;
|
||||||
controller.getState().isDefault = datatype != null;
|
controller.getState().isDefault = datatype != null;
|
||||||
controller.getState().dataConnected = datatype != null;
|
controller.getState().dataConnected = datatype != null;
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.statusbar.connectivity
|
||||||
|
|
||||||
|
import android.annotation.DrawableRes
|
||||||
|
import android.content.Context
|
||||||
|
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||||
|
import com.android.settingslib.mobile.MobileIconCarrierIdOverrides
|
||||||
|
import com.android.settingslib.mobile.MobileIconCarrierIdOverridesImpl
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache for network type resource IDs.
|
||||||
|
*
|
||||||
|
* The default framework behavior is to have a statically defined icon per network type. See
|
||||||
|
* [MobileIconGroup] for the standard mapping.
|
||||||
|
*
|
||||||
|
* For the case of carrierId-defined overrides, we want to check [MobileIconCarrierIdOverrides] for
|
||||||
|
* an existing icon override, and cache the result of the operation
|
||||||
|
*/
|
||||||
|
class NetworkTypeResIdCache(
|
||||||
|
private val overrides: MobileIconCarrierIdOverrides = MobileIconCarrierIdOverridesImpl()
|
||||||
|
) {
|
||||||
|
@DrawableRes private var cachedResId: Int = 0
|
||||||
|
private var lastCarrierId: Int? = null
|
||||||
|
private var lastIconGroup: MobileIconGroup? = null
|
||||||
|
private var isOverridden: Boolean = false
|
||||||
|
|
||||||
|
@DrawableRes
|
||||||
|
fun get(iconGroup: MobileIconGroup, carrierId: Int, context: Context): Int {
|
||||||
|
if (lastCarrierId != carrierId || lastIconGroup != iconGroup) {
|
||||||
|
lastCarrierId = carrierId
|
||||||
|
lastIconGroup = iconGroup
|
||||||
|
|
||||||
|
val maybeOverride = calculateOverriddenIcon(iconGroup, carrierId, context)
|
||||||
|
if (maybeOverride > 0) {
|
||||||
|
cachedResId = maybeOverride
|
||||||
|
isOverridden = true
|
||||||
|
} else {
|
||||||
|
cachedResId = iconGroup.dataType
|
||||||
|
isOverridden = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedResId
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "networkTypeResIdCache={id=$cachedResId, isOverridden=$isOverridden}"
|
||||||
|
}
|
||||||
|
|
||||||
|
@DrawableRes
|
||||||
|
private fun calculateOverriddenIcon(
|
||||||
|
iconGroup: MobileIconGroup,
|
||||||
|
carrierId: Int,
|
||||||
|
context: Context,
|
||||||
|
): Int {
|
||||||
|
val name = iconGroup.name
|
||||||
|
if (!overrides.carrierIdEntryExists(carrierId)) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return overrides.getOverrideFor(carrierId, name, context.resources)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,13 @@ import javax.inject.Inject
|
|||||||
* own [Configuration] and track resources based on the full set of available mcc-mnc combinations.
|
* own [Configuration] and track resources based on the full set of available mcc-mnc combinations.
|
||||||
*
|
*
|
||||||
* (for future reference: b/240555502 is the initiating bug for this)
|
* (for future reference: b/240555502 is the initiating bug for this)
|
||||||
|
*
|
||||||
|
* NOTE: MCC/MNC qualifiers are not sufficient to fully describe a network type icon qualified by
|
||||||
|
* network type + carrier ID. This class exists to keep the legacy behavior of using the MCC/MNC
|
||||||
|
* resource qualifiers working, but if a carrier-specific icon is requested, then the override
|
||||||
|
* provided by [MobileIconCarrierIdOverrides] will take precedence.
|
||||||
|
*
|
||||||
|
* TODO(b/258503704): consider removing this class in favor of the `carrierId` overrides
|
||||||
*/
|
*/
|
||||||
@SysUISingleton
|
@SysUISingleton
|
||||||
class MobileContextProvider
|
class MobileContextProvider
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import javax.inject.Inject
|
|||||||
interface MobileMappingsProxy {
|
interface MobileMappingsProxy {
|
||||||
fun mapIconSets(config: Config): Map<String, MobileIconGroup>
|
fun mapIconSets(config: Config): Map<String, MobileIconGroup>
|
||||||
fun getDefaultIcons(config: Config): MobileIconGroup
|
fun getDefaultIcons(config: Config): MobileIconGroup
|
||||||
|
fun getIconKey(displayInfo: TelephonyDisplayInfo): String
|
||||||
fun toIconKey(@NetworkType networkType: Int): String
|
fun toIconKey(@NetworkType networkType: Int): String
|
||||||
fun toIconKeyOverride(@NetworkType networkType: Int): String
|
fun toIconKeyOverride(@NetworkType networkType: Int): String
|
||||||
}
|
}
|
||||||
@@ -44,6 +45,9 @@ class MobileMappingsProxyImpl @Inject constructor() : MobileMappingsProxy {
|
|||||||
override fun getDefaultIcons(config: Config): MobileIconGroup =
|
override fun getDefaultIcons(config: Config): MobileIconGroup =
|
||||||
MobileMappings.getDefaultIcons(config)
|
MobileMappings.getDefaultIcons(config)
|
||||||
|
|
||||||
|
override fun getIconKey(displayInfo: TelephonyDisplayInfo): String =
|
||||||
|
MobileMappings.getIconKey(displayInfo)
|
||||||
|
|
||||||
override fun toIconKey(@NetworkType networkType: Int): String =
|
override fun toIconKey(@NetworkType networkType: Int): String =
|
||||||
MobileMappings.toIconKey(networkType)
|
MobileMappings.toIconKey(networkType)
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* 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.statusbar.connectivity
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
|
import com.android.settingslib.mobile.MobileIconCarrierIdOverrides
|
||||||
|
|
||||||
|
typealias CarrierId = Int
|
||||||
|
|
||||||
|
typealias NetworkType = String
|
||||||
|
|
||||||
|
typealias ResId = Int
|
||||||
|
|
||||||
|
class MobileIconCarrierIdOverridesFake : MobileIconCarrierIdOverrides {
|
||||||
|
/** Backing for [carrierIdEntryExists] */
|
||||||
|
var overriddenIds = mutableSetOf<Int>()
|
||||||
|
|
||||||
|
/** Backing for [getOverrideFor]. Map should be Map< CarrierId < NetworkType, ResId>> */
|
||||||
|
var overridesByCarrierId = mutableMapOf<CarrierId, Map<NetworkType, ResId>>()
|
||||||
|
|
||||||
|
override fun getOverrideFor(
|
||||||
|
carrierId: CarrierId,
|
||||||
|
networkType: NetworkType,
|
||||||
|
resources: Resources
|
||||||
|
): ResId {
|
||||||
|
if (!overriddenIds.contains(carrierId)) return 0
|
||||||
|
|
||||||
|
return overridesByCarrierId[carrierId]?.get(networkType) ?: 0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun carrierIdEntryExists(carrierId: Int): Boolean {
|
||||||
|
return overriddenIds.contains(carrierId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,137 +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.statusbar.connectivity;
|
|
||||||
|
|
||||||
import static junit.framework.Assert.assertFalse;
|
|
||||||
import static junit.framework.Assert.assertTrue;
|
|
||||||
|
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
|
||||||
import android.testing.AndroidTestingRunner;
|
|
||||||
|
|
||||||
import com.android.settingslib.mobile.TelephonyIcons;
|
|
||||||
import com.android.systemui.SysuiTestCase;
|
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
@SmallTest
|
|
||||||
@RunWith(AndroidTestingRunner.class)
|
|
||||||
public class MobileStateTest extends SysuiTestCase {
|
|
||||||
|
|
||||||
private final MobileState mState = new MobileState();
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public void setUp() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsDataDisabledOrNotDefault_dataDisabled() {
|
|
||||||
mState.iconGroup = TelephonyIcons.DATA_DISABLED;
|
|
||||||
mState.userSetup = true;
|
|
||||||
|
|
||||||
assertTrue(mState.isDataDisabledOrNotDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsDataDisabledOrNotDefault_notDefaultData() {
|
|
||||||
mState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA;
|
|
||||||
mState.userSetup = true;
|
|
||||||
|
|
||||||
assertTrue(mState.isDataDisabledOrNotDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsDataDisabledOrNotDefault_notDisabled() {
|
|
||||||
mState.iconGroup = TelephonyIcons.G;
|
|
||||||
mState.userSetup = true;
|
|
||||||
|
|
||||||
assertFalse(mState.isDataDisabledOrNotDefault());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasActivityIn_noData_noActivity() {
|
|
||||||
mState.dataConnected = false;
|
|
||||||
mState.carrierNetworkChangeMode = false;
|
|
||||||
mState.activityIn = false;
|
|
||||||
|
|
||||||
assertFalse(mState.hasActivityIn());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasActivityIn_noData_activityIn() {
|
|
||||||
mState.dataConnected = false;
|
|
||||||
mState.carrierNetworkChangeMode = false;
|
|
||||||
mState.activityIn = true;
|
|
||||||
|
|
||||||
assertFalse(mState.hasActivityIn());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasActivityIn_dataConnected_activityIn() {
|
|
||||||
mState.dataConnected = true;
|
|
||||||
mState.carrierNetworkChangeMode = false;
|
|
||||||
mState.activityIn = true;
|
|
||||||
|
|
||||||
assertTrue(mState.hasActivityIn());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasActivityIn_carrierNetworkChange() {
|
|
||||||
mState.dataConnected = true;
|
|
||||||
mState.carrierNetworkChangeMode = true;
|
|
||||||
mState.activityIn = true;
|
|
||||||
|
|
||||||
assertFalse(mState.hasActivityIn());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasActivityOut_noData_noActivity() {
|
|
||||||
mState.dataConnected = false;
|
|
||||||
mState.carrierNetworkChangeMode = false;
|
|
||||||
mState.activityOut = false;
|
|
||||||
|
|
||||||
assertFalse(mState.hasActivityOut());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasActivityOut_noData_activityOut() {
|
|
||||||
mState.dataConnected = false;
|
|
||||||
mState.carrierNetworkChangeMode = false;
|
|
||||||
mState.activityOut = true;
|
|
||||||
|
|
||||||
assertFalse(mState.hasActivityOut());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasActivityOut_dataConnected_activityOut() {
|
|
||||||
mState.dataConnected = true;
|
|
||||||
mState.carrierNetworkChangeMode = false;
|
|
||||||
mState.activityOut = true;
|
|
||||||
|
|
||||||
assertTrue(mState.hasActivityOut());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testHasActivityOut_carrierNetworkChange() {
|
|
||||||
mState.dataConnected = true;
|
|
||||||
mState.carrierNetworkChangeMode = true;
|
|
||||||
mState.activityOut = true;
|
|
||||||
|
|
||||||
assertFalse(mState.hasActivityOut());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* 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.statusbar.connectivity
|
||||||
|
|
||||||
|
import android.test.suitebuilder.annotation.SmallTest
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import junit.framework.Assert.assertFalse
|
||||||
|
import junit.framework.Assert.assertTrue
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
class MobileStateTest : SysuiTestCase() {
|
||||||
|
|
||||||
|
private val state = MobileState()
|
||||||
|
@Before fun setUp() {}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIsDataDisabledOrNotDefault_dataDisabled() {
|
||||||
|
state.iconGroup = TelephonyIcons.DATA_DISABLED
|
||||||
|
state.userSetup = true
|
||||||
|
assertTrue(state.isDataDisabledOrNotDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIsDataDisabledOrNotDefault_notDefaultData() {
|
||||||
|
state.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA
|
||||||
|
state.userSetup = true
|
||||||
|
assertTrue(state.isDataDisabledOrNotDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIsDataDisabledOrNotDefault_notDisabled() {
|
||||||
|
state.iconGroup = TelephonyIcons.G
|
||||||
|
state.userSetup = true
|
||||||
|
assertFalse(state.isDataDisabledOrNotDefault)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasActivityIn_noData_noActivity() {
|
||||||
|
state.dataConnected = false
|
||||||
|
state.carrierNetworkChangeMode = false
|
||||||
|
state.activityIn = false
|
||||||
|
assertFalse(state.hasActivityIn())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasActivityIn_noData_activityIn() {
|
||||||
|
state.dataConnected = false
|
||||||
|
state.carrierNetworkChangeMode = false
|
||||||
|
state.activityIn = true
|
||||||
|
assertFalse(state.hasActivityIn())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasActivityIn_dataConnected_activityIn() {
|
||||||
|
state.dataConnected = true
|
||||||
|
state.carrierNetworkChangeMode = false
|
||||||
|
state.activityIn = true
|
||||||
|
assertTrue(state.hasActivityIn())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasActivityIn_carrierNetworkChange() {
|
||||||
|
state.dataConnected = true
|
||||||
|
state.carrierNetworkChangeMode = true
|
||||||
|
state.activityIn = true
|
||||||
|
assertFalse(state.hasActivityIn())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasActivityOut_noData_noActivity() {
|
||||||
|
state.dataConnected = false
|
||||||
|
state.carrierNetworkChangeMode = false
|
||||||
|
state.activityOut = false
|
||||||
|
assertFalse(state.hasActivityOut())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasActivityOut_noData_activityOut() {
|
||||||
|
state.dataConnected = false
|
||||||
|
state.carrierNetworkChangeMode = false
|
||||||
|
state.activityOut = true
|
||||||
|
assertFalse(state.hasActivityOut())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasActivityOut_dataConnected_activityOut() {
|
||||||
|
state.dataConnected = true
|
||||||
|
state.carrierNetworkChangeMode = false
|
||||||
|
state.activityOut = true
|
||||||
|
assertTrue(state.hasActivityOut())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testHasActivityOut_carrierNetworkChange() {
|
||||||
|
state.dataConnected = true
|
||||||
|
state.carrierNetworkChangeMode = true
|
||||||
|
state.activityOut = true
|
||||||
|
assertFalse(state.hasActivityOut())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,6 +71,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
|
|||||||
import com.android.systemui.demomode.DemoModeController;
|
import com.android.systemui.demomode.DemoModeController;
|
||||||
import com.android.systemui.dump.DumpManager;
|
import com.android.systemui.dump.DumpManager;
|
||||||
import com.android.systemui.plugins.log.LogBuffer;
|
import com.android.systemui.plugins.log.LogBuffer;
|
||||||
|
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy;
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
|
||||||
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
|
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
|
||||||
import com.android.systemui.telephony.TelephonyListenerManager;
|
import com.android.systemui.telephony.TelephonyListenerManager;
|
||||||
@@ -125,6 +126,8 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
|||||||
protected CarrierConfigTracker mCarrierConfigTracker;
|
protected CarrierConfigTracker mCarrierConfigTracker;
|
||||||
protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
protected FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
|
||||||
protected Handler mMainHandler;
|
protected Handler mMainHandler;
|
||||||
|
// Use a real mobile mappings object since lots of tests rely on it
|
||||||
|
protected FakeMobileMappingsProxy mMobileMappingsProxy = new FakeMobileMappingsProxy();
|
||||||
protected WifiStatusTrackerFactory mWifiStatusTrackerFactory;
|
protected WifiStatusTrackerFactory mWifiStatusTrackerFactory;
|
||||||
protected MobileSignalControllerFactory mMobileFactory;
|
protected MobileSignalControllerFactory mMobileFactory;
|
||||||
|
|
||||||
@@ -219,10 +222,13 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
|
|||||||
|
|
||||||
mWifiStatusTrackerFactory = new WifiStatusTrackerFactory(
|
mWifiStatusTrackerFactory = new WifiStatusTrackerFactory(
|
||||||
mContext, mMockWm, mMockNsm, mMockCm, mMainHandler);
|
mContext, mMockWm, mMockNsm, mMockCm, mMainHandler);
|
||||||
|
// Most of these tests rely on the actual MobileMappings behavior
|
||||||
|
mMobileMappingsProxy.setUseRealImpl(true);
|
||||||
mMobileFactory = new MobileSignalControllerFactory(
|
mMobileFactory = new MobileSignalControllerFactory(
|
||||||
mContext,
|
mContext,
|
||||||
mCallbackHandler,
|
mCallbackHandler,
|
||||||
mCarrierConfigTracker
|
mCarrierConfigTracker,
|
||||||
|
mMobileMappingsProxy
|
||||||
);
|
);
|
||||||
|
|
||||||
mNetworkController = new NetworkControllerImpl(mContext,
|
mNetworkController = new NetworkControllerImpl(mContext,
|
||||||
|
|||||||
@@ -18,12 +18,21 @@ package com.android.systemui.statusbar.connectivity;
|
|||||||
|
|
||||||
import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
|
import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
|
||||||
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
|
import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
|
||||||
|
import static android.telephony.TelephonyManager.ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED;
|
||||||
|
import static android.telephony.TelephonyManager.EXTRA_CARRIER_ID;
|
||||||
|
import static android.telephony.TelephonyManager.EXTRA_SUBSCRIPTION_ID;
|
||||||
|
|
||||||
|
import static com.android.settingslib.mobile.TelephonyIcons.NR_5G_PLUS;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
import android.content.Intent;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -35,6 +44,7 @@ import android.testing.AndroidTestingRunner;
|
|||||||
import android.testing.TestableLooper;
|
import android.testing.TestableLooper;
|
||||||
import android.testing.TestableLooper.RunWithLooper;
|
import android.testing.TestableLooper.RunWithLooper;
|
||||||
|
|
||||||
|
import com.android.settingslib.SignalIcon.MobileIconGroup;
|
||||||
import com.android.settingslib.mobile.TelephonyIcons;
|
import com.android.settingslib.mobile.TelephonyIcons;
|
||||||
import com.android.settingslib.net.DataUsageController;
|
import com.android.settingslib.net.DataUsageController;
|
||||||
import com.android.systemui.dump.DumpManager;
|
import com.android.systemui.dump.DumpManager;
|
||||||
@@ -45,6 +55,8 @@ import com.android.systemui.util.CarrierConfigTracker;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
@RunWithLooper
|
@RunWithLooper
|
||||||
@@ -329,6 +341,57 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
|
|||||||
assertFalse(mNetworkController.isMobileDataNetworkInService());
|
assertFalse(mNetworkController.isMobileDataNetworkInService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mobileSignalController_getsCarrierId() {
|
||||||
|
when(mMockTm.getSimCarrierId()).thenReturn(1);
|
||||||
|
setupDefaultSignal();
|
||||||
|
|
||||||
|
assertEquals(1, mMobileSignalController.getState().getCarrierId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void mobileSignalController_updatesCarrierId_onChange() {
|
||||||
|
when(mMockTm.getSimCarrierId()).thenReturn(1);
|
||||||
|
setupDefaultSignal();
|
||||||
|
|
||||||
|
// Updates are sent down through this broadcast, we can send the intent directly
|
||||||
|
Intent intent = new Intent(ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED);
|
||||||
|
intent.putExtra(EXTRA_SUBSCRIPTION_ID, mSubId);
|
||||||
|
intent.putExtra(EXTRA_CARRIER_ID, 2);
|
||||||
|
|
||||||
|
mMobileSignalController.handleBroadcast(intent);
|
||||||
|
|
||||||
|
assertEquals(2, mMobileSignalController.getState().getCarrierId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void networkTypeIcon_hasCarrierIdOverride() {
|
||||||
|
int fakeCarrier = 1;
|
||||||
|
int fakeIconOverride = 12345;
|
||||||
|
int testDataNetType = 100;
|
||||||
|
String testDataString = "100";
|
||||||
|
HashMap<String, MobileIconGroup> testMap = new HashMap<>();
|
||||||
|
testMap.put(testDataString, NR_5G_PLUS);
|
||||||
|
|
||||||
|
// Pretend that there is an override for this icon, and this carrier ID
|
||||||
|
NetworkTypeResIdCache mockCache = mock(NetworkTypeResIdCache.class);
|
||||||
|
when(mockCache.get(eq(NR_5G_PLUS), eq(fakeCarrier), any())).thenReturn(fakeIconOverride);
|
||||||
|
|
||||||
|
// Turn off the default mobile mapping, so we can override
|
||||||
|
mMobileMappingsProxy.setUseRealImpl(false);
|
||||||
|
mMobileMappingsProxy.setIconMap(testMap);
|
||||||
|
// Use the mocked cache
|
||||||
|
mMobileSignalController.mCurrentState.setNetworkTypeResIdCache(mockCache);
|
||||||
|
// Rebuild the network map
|
||||||
|
mMobileSignalController.setConfiguration(mConfig);
|
||||||
|
when(mMockTm.getSimCarrierId()).thenReturn(fakeCarrier);
|
||||||
|
|
||||||
|
setupDefaultSignal();
|
||||||
|
updateDataConnectionState(TelephonyManager.DATA_CONNECTED, testDataNetType);
|
||||||
|
|
||||||
|
verifyDataIndicators(fakeIconOverride);
|
||||||
|
}
|
||||||
|
|
||||||
private void testDataActivity(int direction, boolean in, boolean out) {
|
private void testDataActivity(int direction, boolean in, boolean out) {
|
||||||
updateDataActivity(direction);
|
updateDataActivity(direction);
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* 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.statusbar.connectivity
|
||||||
|
|
||||||
|
import android.test.suitebuilder.annotation.SmallTest
|
||||||
|
import android.testing.AndroidTestingRunner
|
||||||
|
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidTestingRunner::class)
|
||||||
|
class NetworkTypeResIdCacheTest : SysuiTestCase() {
|
||||||
|
private lateinit var cache: NetworkTypeResIdCache
|
||||||
|
private var overrides = MobileIconCarrierIdOverridesFake()
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
cache = NetworkTypeResIdCache(overrides)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun carrier1_noOverride_usesDefault() {
|
||||||
|
assertThat(cache.get(group1, CARRIER_1, context)).isEqualTo(iconDefault1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun carrier1_overridden_usesOverride() {
|
||||||
|
overrides.overriddenIds.add(CARRIER_1)
|
||||||
|
overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1)
|
||||||
|
|
||||||
|
assertThat(cache.get(group1, CARRIER_1, context)).isEqualTo(iconOverride1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun carrier1_override_carrier2UsesDefault() {
|
||||||
|
overrides.overriddenIds.add(CARRIER_1)
|
||||||
|
overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1)
|
||||||
|
|
||||||
|
assertThat(cache.get(group1, CARRIER_2, context)).isEqualTo(iconDefault1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun carrier1_overrideType1_type2UsesDefault() {
|
||||||
|
overrides.overriddenIds.add(CARRIER_1)
|
||||||
|
overrides.overridesByCarrierId[CARRIER_1] = mapOf(NET_TYPE_1 to iconOverride1)
|
||||||
|
|
||||||
|
assertThat(cache.get(group2, CARRIER_1, context)).isEqualTo(iconDefault2)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// Simplified icon overrides here
|
||||||
|
const val CARRIER_1 = 1
|
||||||
|
const val CARRIER_2 = 2
|
||||||
|
|
||||||
|
const val NET_TYPE_1 = "one"
|
||||||
|
const val iconDefault1 = 123
|
||||||
|
const val iconOverride1 = 321
|
||||||
|
val group1 = MobileIconGroup(NET_TYPE_1, /* dataContentDesc */ 0, iconDefault1)
|
||||||
|
|
||||||
|
const val NET_TYPE_2 = "two"
|
||||||
|
const val iconDefault2 = 234
|
||||||
|
|
||||||
|
val group2 = MobileIconGroup(NET_TYPE_2, /* dataContentDesc*/ 0, iconDefault2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,31 +16,59 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.pipeline.mobile.util
|
package com.android.systemui.statusbar.pipeline.mobile.util
|
||||||
|
|
||||||
|
import android.telephony.TelephonyDisplayInfo
|
||||||
import com.android.settingslib.SignalIcon.MobileIconGroup
|
import com.android.settingslib.SignalIcon.MobileIconGroup
|
||||||
import com.android.settingslib.mobile.MobileMappings.Config
|
import com.android.settingslib.mobile.MobileMappings.Config
|
||||||
import com.android.settingslib.mobile.TelephonyIcons
|
import com.android.settingslib.mobile.TelephonyIcons
|
||||||
|
|
||||||
class FakeMobileMappingsProxy : MobileMappingsProxy {
|
class FakeMobileMappingsProxy : MobileMappingsProxy {
|
||||||
|
// The old [NetworkControllerDataTest] infra requires us to be able to use the real
|
||||||
|
// impl sometimes
|
||||||
|
var useRealImpl = false
|
||||||
|
|
||||||
|
private var realImpl = MobileMappingsProxyImpl()
|
||||||
private var iconMap = mapOf<String, MobileIconGroup>()
|
private var iconMap = mapOf<String, MobileIconGroup>()
|
||||||
private var defaultIcons = TelephonyIcons.THREE_G
|
private var defaultIcons = TelephonyIcons.THREE_G
|
||||||
|
|
||||||
fun setIconMap(map: Map<String, MobileIconGroup>) {
|
fun setIconMap(map: Map<String, MobileIconGroup>) {
|
||||||
iconMap = map
|
iconMap = map
|
||||||
}
|
}
|
||||||
override fun mapIconSets(config: Config): Map<String, MobileIconGroup> = iconMap
|
override fun mapIconSets(config: Config): Map<String, MobileIconGroup> {
|
||||||
|
if (useRealImpl) {
|
||||||
|
return realImpl.mapIconSets(config)
|
||||||
|
}
|
||||||
|
return iconMap
|
||||||
|
}
|
||||||
fun getIconMap() = iconMap
|
fun getIconMap() = iconMap
|
||||||
|
|
||||||
fun setDefaultIcons(group: MobileIconGroup) {
|
fun setDefaultIcons(group: MobileIconGroup) {
|
||||||
defaultIcons = group
|
defaultIcons = group
|
||||||
}
|
}
|
||||||
override fun getDefaultIcons(config: Config): MobileIconGroup = defaultIcons
|
override fun getDefaultIcons(config: Config): MobileIconGroup {
|
||||||
|
if (useRealImpl) {
|
||||||
|
return realImpl.getDefaultIcons(config)
|
||||||
|
}
|
||||||
|
return defaultIcons
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This is only used in the old pipeline, use the real impl always */
|
||||||
|
override fun getIconKey(displayInfo: TelephonyDisplayInfo): String {
|
||||||
|
return realImpl.getIconKey(displayInfo)
|
||||||
|
}
|
||||||
|
|
||||||
fun getDefaultIcons(): MobileIconGroup = defaultIcons
|
fun getDefaultIcons(): MobileIconGroup = defaultIcons
|
||||||
|
|
||||||
override fun toIconKey(networkType: Int): String {
|
override fun toIconKey(networkType: Int): String {
|
||||||
|
if (useRealImpl) {
|
||||||
|
return realImpl.toIconKeyOverride(networkType)
|
||||||
|
}
|
||||||
return networkType.toString()
|
return networkType.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toIconKeyOverride(networkType: Int): String {
|
override fun toIconKeyOverride(networkType: Int): String {
|
||||||
|
if (useRealImpl) {
|
||||||
|
return realImpl.toIconKeyOverride(networkType)
|
||||||
|
}
|
||||||
return toIconKey(networkType) + "_override"
|
return toIconKey(networkType) + "_override"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user