script-astra/Android/Sdk/sources/android-35/com/android/internal/telephony/DisplayInfoController.java
localadmin 4380f00a78 init
2025-01-20 18:15:20 +03:00

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();
}
}