282 lines
11 KiB
Java
282 lines
11 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2020 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.internal.telephony;
|
||
|
|
||
|
import android.annotation.NonNull;
|
||
|
import android.os.Handler;
|
||
|
import android.os.Message;
|
||
|
import android.os.PersistableBundle;
|
||
|
import android.os.Registrant;
|
||
|
import android.os.RegistrantList;
|
||
|
import android.telephony.AnomalyReporter;
|
||
|
import android.telephony.CarrierConfigManager;
|
||
|
import android.telephony.ServiceState;
|
||
|
import android.telephony.TelephonyDisplayInfo;
|
||
|
import android.telephony.TelephonyManager;
|
||
|
import android.util.IndentingPrintWriter;
|
||
|
import android.util.LocalLog;
|
||
|
import android.util.Pair;
|
||
|
|
||
|
import com.android.internal.telephony.flags.FeatureFlags;
|
||
|
import com.android.telephony.Rlog;
|
||
|
|
||
|
import java.io.FileDescriptor;
|
||
|
import java.io.PrintWriter;
|
||
|
import java.util.Set;
|
||
|
import java.util.UUID;
|
||
|
|
||
|
import javax.sip.InvalidArgumentException;
|
||
|
|
||
|
/**
|
||
|
* The DisplayInfoController updates and broadcasts all changes to {@link TelephonyDisplayInfo}.
|
||
|
* It manages all the information necessary for display purposes. Clients can register for display
|
||
|
* info changes via {@link #registerForTelephonyDisplayInfoChanged} and obtain the current
|
||
|
* TelephonyDisplayInfo via {@link #getTelephonyDisplayInfo}.
|
||
|
*/
|
||
|
public class DisplayInfoController extends Handler {
|
||
|
private final String mLogTag;
|
||
|
private final LocalLog mLocalLog = new LocalLog(128);
|
||
|
|
||
|
private static final Set<Pair<Integer, Integer>> VALID_DISPLAY_INFO_SET = Set.of(
|
||
|
// LTE
|
||
|
Pair.create(TelephonyManager.NETWORK_TYPE_LTE,
|
||
|
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA),
|
||
|
Pair.create(TelephonyManager.NETWORK_TYPE_LTE,
|
||
|
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO),
|
||
|
Pair.create(TelephonyManager.NETWORK_TYPE_LTE,
|
||
|
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA),
|
||
|
Pair.create(TelephonyManager.NETWORK_TYPE_LTE,
|
||
|
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED),
|
||
|
|
||
|
// NR
|
||
|
Pair.create(TelephonyManager.NETWORK_TYPE_NR,
|
||
|
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NR_ADVANCED)
|
||
|
);
|
||
|
|
||
|
/** Event for service state changed (roaming). */
|
||
|
private static final int EVENT_SERVICE_STATE_CHANGED = 1;
|
||
|
/** Event for carrier config changed. */
|
||
|
private static final int EVENT_CARRIER_CONFIG_CHANGED = 2;
|
||
|
|
||
|
@NonNull private final Phone mPhone;
|
||
|
@NonNull private final NetworkTypeController mNetworkTypeController;
|
||
|
@NonNull private final RegistrantList mTelephonyDisplayInfoChangedRegistrants =
|
||
|
new RegistrantList();
|
||
|
@NonNull private final FeatureFlags mFeatureFlags;
|
||
|
@NonNull private TelephonyDisplayInfo mTelephonyDisplayInfo;
|
||
|
@NonNull private ServiceState mServiceState;
|
||
|
@NonNull private PersistableBundle mConfigs;
|
||
|
|
||
|
public DisplayInfoController(@NonNull Phone phone, @NonNull FeatureFlags featureFlags) {
|
||
|
mPhone = phone;
|
||
|
mFeatureFlags = featureFlags;
|
||
|
mLogTag = "DIC-" + mPhone.getPhoneId();
|
||
|
mServiceState = mPhone.getServiceStateTracker().getServiceState();
|
||
|
mConfigs = new PersistableBundle();
|
||
|
try {
|
||
|
mConfigs = mPhone.getContext().getSystemService(CarrierConfigManager.class)
|
||
|
.getConfigForSubId(mPhone.getSubId(),
|
||
|
CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL);
|
||
|
} catch (Exception ignored) {
|
||
|
// CarrierConfigLoader might not be available yet.
|
||
|
// Once it's available, configs will be updated through the listener.
|
||
|
}
|
||
|
mPhone.getServiceStateTracker()
|
||
|
.registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED, null);
|
||
|
mPhone.getContext().getSystemService(CarrierConfigManager.class)
|
||
|
.registerCarrierConfigChangeListener(Runnable::run,
|
||
|
(slotIndex, subId, carrierId, specificCarrierId) -> {
|
||
|
if (slotIndex == mPhone.getPhoneId()) {
|
||
|
obtainMessage(EVENT_CARRIER_CONFIG_CHANGED).sendToTarget();
|
||
|
}
|
||
|
});
|
||
|
mTelephonyDisplayInfo = new TelephonyDisplayInfo(
|
||
|
TelephonyManager.NETWORK_TYPE_UNKNOWN,
|
||
|
TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE,
|
||
|
false);
|
||
|
mNetworkTypeController = new NetworkTypeController(phone, this, featureFlags);
|
||
|
// EVENT_UPDATE will transition from DefaultState to the current state
|
||
|
// and update the TelephonyDisplayInfo based on the current state.
|
||
|
mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return the current TelephonyDisplayInfo
|
||
|
*/
|
||
|
@NonNull public TelephonyDisplayInfo getTelephonyDisplayInfo() {
|
||
|
return mTelephonyDisplayInfo;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update TelephonyDisplayInfo based on network type and override network type, received from
|
||
|
* NetworkTypeController.
|
||
|
*/
|
||
|
public void updateTelephonyDisplayInfo() {
|
||
|
TelephonyDisplayInfo newDisplayInfo = new TelephonyDisplayInfo(
|
||
|
mNetworkTypeController.getDataNetworkType(),
|
||
|
mNetworkTypeController.getOverrideNetworkType(),
|
||
|
isRoaming());
|
||
|
if (!newDisplayInfo.equals(mTelephonyDisplayInfo)) {
|
||
|
logl("TelephonyDisplayInfo changed from " + mTelephonyDisplayInfo + " to "
|
||
|
+ newDisplayInfo);
|
||
|
validateDisplayInfo(newDisplayInfo);
|
||
|
mTelephonyDisplayInfo = newDisplayInfo;
|
||
|
mTelephonyDisplayInfoChangedRegistrants.notifyRegistrants();
|
||
|
mPhone.notifyDisplayInfoChanged(mTelephonyDisplayInfo);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determine the roaming status for icon display only.
|
||
|
* If this is {@code true}, the roaming indicator will be shown, and if this is {@code false},
|
||
|
* the roaming indicator will not be shown.
|
||
|
* To get the actual roaming status, use {@link ServiceState#getRoaming()} instead.
|
||
|
*
|
||
|
* @return Whether the device is considered roaming for display purposes.
|
||
|
*/
|
||
|
private boolean isRoaming() {
|
||
|
boolean roaming = mServiceState.getRoaming();
|
||
|
if (roaming && mFeatureFlags.hideRoamingIcon()
|
||
|
&& !mConfigs.getBoolean(CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL)) {
|
||
|
logl("Override roaming for display due to carrier configs.");
|
||
|
roaming = false;
|
||
|
}
|
||
|
return roaming;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Validate the display info and trigger anomaly report if needed.
|
||
|
*
|
||
|
* @param displayInfo The display info to validate.
|
||
|
*/
|
||
|
private void validateDisplayInfo(@NonNull TelephonyDisplayInfo displayInfo) {
|
||
|
try {
|
||
|
if (displayInfo.getNetworkType() == TelephonyManager.NETWORK_TYPE_LTE_CA) {
|
||
|
throw new InvalidArgumentException("LTE_CA is not a valid network type.");
|
||
|
}
|
||
|
if (displayInfo.getNetworkType() < TelephonyManager.NETWORK_TYPE_UNKNOWN
|
||
|
&& displayInfo.getNetworkType() > TelephonyManager.NETWORK_TYPE_NR) {
|
||
|
throw new InvalidArgumentException("Invalid network type "
|
||
|
+ displayInfo.getNetworkType());
|
||
|
}
|
||
|
if (displayInfo.getOverrideNetworkType()
|
||
|
!= TelephonyDisplayInfo.OVERRIDE_NETWORK_TYPE_NONE
|
||
|
&& !VALID_DISPLAY_INFO_SET.contains(Pair.create(displayInfo.getNetworkType(),
|
||
|
displayInfo.getOverrideNetworkType()))) {
|
||
|
throw new InvalidArgumentException("Invalid network type override "
|
||
|
+ TelephonyDisplayInfo.overrideNetworkTypeToString(
|
||
|
displayInfo.getOverrideNetworkType())
|
||
|
+ " for " + TelephonyManager.getNetworkTypeName(
|
||
|
displayInfo.getNetworkType()));
|
||
|
}
|
||
|
} catch (InvalidArgumentException e) {
|
||
|
logel(e.getMessage());
|
||
|
AnomalyReporter.reportAnomaly(UUID.fromString("3aa92a2c-94ed-46a0-a744-d6b1dfec2a56"),
|
||
|
e.getMessage(), mPhone.getCarrierId());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Register for TelephonyDisplayInfo changed.
|
||
|
* @param h Handler to notify
|
||
|
* @param what msg.what when the message is delivered
|
||
|
* @param obj msg.obj when the message is delivered
|
||
|
*/
|
||
|
public void registerForTelephonyDisplayInfoChanged(Handler h, int what, Object obj) {
|
||
|
Registrant r = new Registrant(h, what, obj);
|
||
|
mTelephonyDisplayInfoChangedRegistrants.add(r);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Unregister for TelephonyDisplayInfo changed.
|
||
|
* @param h Handler to notify
|
||
|
*/
|
||
|
public void unregisterForTelephonyDisplayInfoChanged(Handler h) {
|
||
|
mTelephonyDisplayInfoChangedRegistrants.remove(h);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void handleMessage(@NonNull Message msg) {
|
||
|
switch (msg.what) {
|
||
|
case EVENT_SERVICE_STATE_CHANGED:
|
||
|
mServiceState = mPhone.getServiceStateTracker().getServiceState();
|
||
|
log("ServiceState updated, isRoaming=" + mServiceState.getRoaming());
|
||
|
updateTelephonyDisplayInfo();
|
||
|
break;
|
||
|
case EVENT_CARRIER_CONFIG_CHANGED:
|
||
|
mConfigs = mPhone.getContext().getSystemService(CarrierConfigManager.class)
|
||
|
.getConfigForSubId(mPhone.getSubId(),
|
||
|
CarrierConfigManager.KEY_SHOW_ROAMING_INDICATOR_BOOL);
|
||
|
log("Carrier configs updated: " + mConfigs);
|
||
|
updateTelephonyDisplayInfo();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Log debug messages.
|
||
|
* @param s debug messages
|
||
|
*/
|
||
|
private void log(@NonNull String s) {
|
||
|
Rlog.d(mLogTag, s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Log error messages.
|
||
|
* @param s error messages
|
||
|
*/
|
||
|
private void loge(@NonNull String s) {
|
||
|
Rlog.e(mLogTag, s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Log debug messages and also log into the local log.
|
||
|
* @param s debug messages
|
||
|
*/
|
||
|
private void logl(@NonNull String s) {
|
||
|
log(s);
|
||
|
mLocalLog.log(s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Log error messages and also log into the local log.
|
||
|
* @param s debug messages
|
||
|
*/
|
||
|
private void logel(@NonNull String s) {
|
||
|
loge(s);
|
||
|
mLocalLog.log(s);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Dump the current state.
|
||
|
*/
|
||
|
public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
|
||
|
IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
|
||
|
pw.println("DisplayInfoController:");
|
||
|
pw.println(" mPhone=" + mPhone.getPhoneName());
|
||
|
pw.println(" mTelephonyDisplayInfo=" + mTelephonyDisplayInfo.toString());
|
||
|
pw.flush();
|
||
|
pw.println("Local logs:");
|
||
|
pw.increaseIndent();
|
||
|
mLocalLog.dump(fd, pw, args);
|
||
|
pw.decreaseIndent();
|
||
|
pw.println(" ***************************************");
|
||
|
mNetworkTypeController.dump(fd, pw, args);
|
||
|
pw.flush();
|
||
|
}
|
||
|
}
|