Messaging: Remove compatibility for old android versions

Change-Id: Id9065d60525a509271a0e64c0e349e857cb998e2
This commit is contained in:
Michael W
2024-12-26 14:55:12 +01:00
parent 9bbc7a8f99
commit 7c55a6d56a
104 changed files with 580 additions and 2306 deletions
@@ -73,8 +73,7 @@ public class AccessibilityUtil {
}
// Jelly Bean added support for speaking text verbatim
final int eventType = OsUtil.isAtLeastJB() ? AccessibilityEvent.TYPE_ANNOUNCEMENT
: AccessibilityEvent.TYPE_VIEW_FOCUSED;
final int eventType = AccessibilityEvent.TYPE_ANNOUNCEMENT;
// Construct an accessibility event with the minimum recommended
// attributes. An event without a class name or package may be dropped.
@@ -101,11 +100,7 @@ public class AccessibilityUtil {
* @return boolean Boolean indicating whether the currently locale is RTL.
*/
public static boolean isLayoutRtl(final View view) {
if (OsUtil.isAtLeastJB_MR1()) {
return View.LAYOUT_DIRECTION_RTL == view.getLayoutDirection();
} else {
return false;
}
return View.LAYOUT_DIRECTION_RTL == view.getLayoutDirection();
}
public static String getVocalizedPhoneNumber(final Resources res, final String phoneNumber) {
@@ -62,10 +62,6 @@ public class BugleActivityUtil {
* @return true if the user has SMS permissions, otherwise false.
*/
private static boolean checkHasSmsPermissionsForUser(Context context, Activity activity) {
if (!OsUtil.isAtLeastL()) {
// UserManager.DISALLOW_SMS added in L. No multiuser phones before this
return true;
}
UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
if (userManager.hasUserRestriction(UserManager.DISALLOW_SMS)) {
new AlertDialog.Builder(activity)
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -25,13 +26,6 @@ import com.android.messaging.datamodel.data.ParticipantData;
/**
* ConnectivityUtil listens to the network service state changes.
*
* On N and beyond, This class instance can be created via ConnectivityUtil(context, subId), use
* ConnectivityUtil(context) for others.
*
* Note that TelephonyManager has createForSubscriptionId() for a specific subId from N but listen()
* does not use the subId on the manager, and uses the default subId on PhoneStateListener. From O,
* the manager uses its' own subId in listen().
*/
public class ConnectivityUtil {
// Assume not connected until informed differently
@@ -45,12 +39,7 @@ public class ConnectivityUtil {
public void onPhoneStateChanged(int serviceState);
}
public ConnectivityUtil(final Context context) {
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
public ConnectivityUtil(final Context context, final int subId) {
Assert.isTrue(OsUtil.isAtLeastN());
mTelephonyManager =
((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE))
.createForSubscriptionId(subId);
@@ -519,27 +519,21 @@ public class ContactUtil {
* Returns if a given contact id belongs to managed profile.
*/
public static boolean isEnterpriseContactId(final long contactId) {
return OsUtil.isAtLeastL() && ContactsContract.Contacts.isEnterpriseContactId(contactId);
return ContactsContract.Contacts.isEnterpriseContactId(contactId);
}
/**
* Returns Email lookup uri that will query both primary and corp profile
*/
private static Uri getEmailContentLookupUri() {
if (OsUtil.isAtLeastM()) {
return Email.ENTERPRISE_CONTENT_LOOKUP_URI;
}
return Email.CONTENT_LOOKUP_URI;
return Email.ENTERPRISE_CONTENT_LOOKUP_URI;
}
/**
* Returns PhoneLookup URI.
*/
public static Uri getPhoneLookupUri() {
if (OsUtil.isAtLeastM()) {
return PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI;
}
return PhoneLookup.CONTENT_FILTER_URI;
return PhoneLookup.ENTERPRISE_CONTENT_FILTER_URI;
}
public static boolean hasReadContactsPermission() {
@@ -302,10 +302,7 @@ public class DebugUtils {
final int length = dis.readInt();
final byte[] pdu = new byte[length];
dis.read(pdu, 0, length);
messagesTemp[i] =
OsUtil.isAtLeastM()
? SmsMessage.createFromPdu(pdu, format)
: SmsMessage.createFromPdu(pdu);
messagesTemp[i] = SmsMessage.createFromPdu(pdu, format);
}
messages = messagesTemp;
} catch (final FileNotFoundException e) {
@@ -174,11 +174,7 @@ public class ImageUtils {
*/
@SuppressWarnings("deprecation")
public static void setBackgroundDrawableOnView(final View view, final Drawable drawable) {
if (OsUtil.isAtLeastJB()) {
view.setBackground(drawable);
} else {
view.setBackgroundDrawable(drawable);
}
view.setBackground(drawable);
}
/**
@@ -33,8 +33,4 @@ public abstract class MediaUtil {
*/
public abstract void playSound(final Context context, final int resId,
final OnCompletionListener completionListener);
public static boolean canAutoAccessIncomingMedia() {
return OsUtil.isAtLeastM();
}
}
@@ -20,7 +20,6 @@ import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Context;
import android.os.Build;
public final class NotificationsUtil {
public static final String DEFAULT_CHANNEL_ID = "messaging_channel";
@@ -37,10 +36,6 @@ public final class NotificationsUtil {
public static void createNotificationChannel(Context context, String id,
String title, int priority, String groupId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
NotificationManager manager = context.getSystemService(NotificationManager.class);
NotificationChannel existing = manager.getNotificationChannel(id);
if (existing != null) {
@@ -56,20 +51,12 @@ public final class NotificationsUtil {
}
public static void deleteNotificationChannel(Context context, String id) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
NotificationManager manager = context.getSystemService(NotificationManager.class);
manager.deleteNotificationChannel(id);
}
public static void createNotificationChannelGroup(Context context, String id,
int titleResId) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return;
}
NotificationManager manager = context.getSystemService(NotificationManager.class);
NotificationChannelGroup existing = manager.getNotificationChannelGroup(id);
if (existing != null) {
@@ -82,19 +69,11 @@ public final class NotificationsUtil {
}
public static NotificationChannel getNotificationChannel(Context context, String id) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return null;
}
NotificationManager manager = context.getSystemService(NotificationManager.class);
return manager.getNotificationChannel(id);
}
public static NotificationChannelGroup getNotificationChannelGroup(Context context, String id) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
return null;
}
NotificationManager manager = context.getSystemService(NotificationManager.class);
return manager.getNotificationChannelGroup(id);
}
+15 -125
View File
@@ -19,10 +19,8 @@ package com.android.messaging.util;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.UserHandle;
import android.os.UserManager;
import androidx.core.os.BuildCompat;
import com.android.messaging.Factory;
@@ -34,124 +32,20 @@ import java.util.Set;
* Android OS version utilities
*/
public class OsUtil {
private static boolean sIsAtLeastICS_MR1;
private static boolean sIsAtLeastJB;
private static boolean sIsAtLeastJB_MR1;
private static boolean sIsAtLeastJB_MR2;
private static boolean sIsAtLeastKLP;
private static boolean sIsAtLeastL;
private static boolean sIsAtLeastL_MR1;
private static boolean sIsAtLeastM;
private static boolean sIsAtLeastN;
private static Boolean sIsSecondaryUser = null;
static {
final int v = getApiVersion();
sIsAtLeastICS_MR1 = v >= android.os.Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1;
sIsAtLeastJB = v >= android.os.Build.VERSION_CODES.JELLY_BEAN;
sIsAtLeastJB_MR1 = v >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1;
sIsAtLeastJB_MR2 = v >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
sIsAtLeastKLP = v >= android.os.Build.VERSION_CODES.KITKAT;
sIsAtLeastL = v >= android.os.Build.VERSION_CODES.LOLLIPOP;
sIsAtLeastL_MR1 = v >= android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
sIsAtLeastM = v >= android.os.Build.VERSION_CODES.M;
sIsAtLeastN = BuildCompat.isAtLeastN();
}
/**
* @return True if the version of Android that we're running on is at least Ice Cream Sandwich
* MR1 (API level 15).
*/
public static boolean isAtLeastICS_MR1() {
return sIsAtLeastICS_MR1;
}
/**
* @return True if the version of Android that we're running on is at least Jelly Bean
* (API level 16).
*/
public static boolean isAtLeastJB() {
return sIsAtLeastJB;
}
/**
* @return True if the version of Android that we're running on is at least Jelly Bean MR1
* (API level 17).
*/
public static boolean isAtLeastJB_MR1() {
return sIsAtLeastJB_MR1;
}
/**
* @return True if the version of Android that we're running on is at least Jelly Bean MR2
* (API level 18).
*/
public static boolean isAtLeastJB_MR2() {
return sIsAtLeastJB_MR2;
}
/**
* @return True if the version of Android that we're running on is at least KLP
* (API level 19).
*/
public static boolean isAtLeastKLP() {
return sIsAtLeastKLP;
}
/**
* @return True if the version of Android that we're running on is at least L
* (API level 21).
*/
public static boolean isAtLeastL() {
return sIsAtLeastL;
}
/**
* @return True if the version of Android that we're running on is at least L MR1
* (API level 22).
*/
public static boolean isAtLeastL_MR1() {
return sIsAtLeastL_MR1;
}
/**
* @return True if the version of Android that we're running on is at least M
* (API level 23).
*/
public static boolean isAtLeastM() {
return sIsAtLeastM;
}
/**
* @return True if the version of Android that we're running on is at least N
* (API level 24).
*/
public static boolean isAtLeastN() {
return sIsAtLeastN;
}
/**
* @return The Android API version of the OS that we're currently running on.
*/
public static int getApiVersion() {
return android.os.Build.VERSION.SDK_INT;
}
public static boolean isSecondaryUser() {
if (sIsSecondaryUser == null) {
final Context context = Factory.get().getApplicationContext();
boolean isSecondaryUser = false;
// Only check for newer devices (but not the nexus 10)
if (OsUtil.sIsAtLeastJB_MR1 && !"Nexus 10".equals(Build.MODEL)) {
final UserHandle uh = android.os.Process.myUserHandle();
final UserManager userManager =
(UserManager) context.getSystemService(Context.USER_SERVICE);
if (userManager != null) {
final long userSerialNumber = userManager.getSerialNumberForUser(uh);
isSecondaryUser = (0 != userSerialNumber);
}
final UserHandle uh = android.os.Process.myUserHandle();
final UserManager userManager =
(UserManager) context.getSystemService(Context.USER_SERVICE);
if (userManager != null) {
final long userSerialNumber = userManager.getSerialNumberForUser(uh);
isSecondaryUser = (0 != userSerialNumber);
}
sIsSecondaryUser = isSecondaryUser;
}
@@ -192,20 +86,16 @@ public class OsUtil {
* @param permission A permission from {@link android.Manifest.permission}
*/
public static boolean hasPermission(final String permission) {
if (OsUtil.isAtLeastM()) {
// It is safe to cache the PERMISSION_GRANTED result as the process gets killed if the
// user revokes the permission setting. However, PERMISSION_DENIED should not be
// cached as the process does not get killed if the user enables the permission setting.
if (!sPermissions.containsKey(permission)
|| sPermissions.get(permission) == PackageManager.PERMISSION_DENIED) {
final Context context = Factory.get().getApplicationContext();
final int permissionState = context.checkSelfPermission(permission);
sPermissions.put(permission, permissionState);
}
return sPermissions.get(permission) == PackageManager.PERMISSION_GRANTED;
} else {
return true;
// It is safe to cache the PERMISSION_GRANTED result as the process gets killed if the
// user revokes the permission setting. However, PERMISSION_DENIED should not be
// cached as the process does not get killed if the user enables the permission setting.
if (!sPermissions.containsKey(permission)
|| sPermissions.get(permission) == PackageManager.PERMISSION_DENIED) {
final Context context = Factory.get().getApplicationContext();
final int permissionState = context.checkSelfPermission(permission);
sPermissions.put(permission, permissionState);
}
return sPermissions.get(permission) == PackageManager.PERMISSION_GRANTED;
}
/** Does the app have all the specified permissions */
+202 -466
View File
@@ -17,14 +17,13 @@
package com.android.messaging.util;
import android.app.role.RoleManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.provider.Settings;
import android.provider.Telephony;
import android.telephony.PhoneNumberUtils;
@@ -35,7 +34,6 @@ import android.telephony.TelephonyManager;
import android.text.TextUtils;
import androidx.collection.ArrayMap;
import androidx.core.os.BuildCompat;
import com.android.messaging.Factory;
import com.android.messaging.R;
@@ -64,7 +62,7 @@ import java.util.Locale;
*
* A convenient getDefault() method is provided for default subId (-1) on any platform
*/
public abstract class PhoneUtils {
public class PhoneUtils {
private static final String TAG = LogUtil.BUGLE_TAG;
private static final int MINIMUM_PHONE_NUMBER_LENGTH_TO_FORMAT = 6;
@@ -79,6 +77,7 @@ public abstract class PhoneUtils {
protected final Context mContext;
protected final TelephonyManager mTelephonyManager;
private final SubscriptionManager mSubscriptionManager;
protected final int mSubId;
public PhoneUtils(int subId) {
@@ -86,6 +85,7 @@ public abstract class PhoneUtils {
mContext = Factory.get().getApplicationContext();
mTelephonyManager =
(TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mSubscriptionManager = SubscriptionManager.from(Factory.get().getApplicationContext());
}
/**
@@ -93,49 +93,90 @@ public abstract class PhoneUtils {
*
* @return the country code on the SIM
*/
public abstract String getSimCountry();
public String getSimCountry() {
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo != null) {
final String country = subInfo.getCountryIso();
if (TextUtils.isEmpty(country)) {
return null;
}
return country.toUpperCase();
}
return null;
}
/**
* Get number of SIM slots
*
* @return the SIM slot count
*/
public abstract int getSimSlotCount();
public int getSimSlotCount() {
return mSubscriptionManager.getActiveSubscriptionInfoCountMax();
}
/**
* Get SIM's carrier name
*
* @return the carrier name of the SIM
*/
public abstract String getCarrierName();
public String getCarrierName() {
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo != null) {
final CharSequence displayName = subInfo.getDisplayName();
if (!TextUtils.isEmpty(displayName)) {
return displayName.toString();
}
final CharSequence carrierName = subInfo.getCarrierName();
if (carrierName != null) {
return carrierName.toString();
}
}
return null;
}
/**
* Check if there is SIM inserted on the device
*
* @return true if there is SIM inserted, false otherwise
*/
public abstract boolean hasSim();
public boolean hasSim() {
return mSubscriptionManager.getActiveSubscriptionInfoCount() > 0;
}
/**
* Check if the SIM is roaming
*
* @return true if the SIM is in romaing state, false otherwise
*/
public abstract boolean isRoaming();
public boolean isRoaming() {
return mSubscriptionManager.isNetworkRoaming(mSubId);
}
/**
* Get the MCC and MNC in integer of the SIM's provider
*
* @return an array of two ints, [0] is the MCC code and [1] is the MNC code
*/
public abstract int[] getMccMnc();
public int[] getMccMnc() {
int mcc = 0;
int mnc = 0;
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo != null) {
mcc = subInfo.getMcc();
mnc = subInfo.getMnc();
}
return new int[]{mcc, mnc};
}
/**
* Get the mcc/mnc string
*
* @return the text of mccmnc string
*/
public abstract String getSimOperatorNumeric();
public String getSimOperatorNumeric() {
// For L_MR1 we return the canonicalized (xxxxxx) string
return getMccMncString(getMccMnc());
}
/**
* Get the SIM's self raw number, i.e. not canonicalized
@@ -144,7 +185,25 @@ public abstract class PhoneUtils {
* @return the original self number
* @throws IllegalStateException if no active subscription on L-MR1+
*/
public abstract String getSelfRawNumber(final boolean allowOverride);
public String getSelfRawNumber(final boolean allowOverride) {
if (allowOverride) {
final String userDefinedNumber = getNumberFromPrefs(mContext, mSubId);
if (!TextUtils.isEmpty(userDefinedNumber)) {
return userDefinedNumber;
}
}
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo != null) {
String phoneNumber = subInfo.getNumber();
if (TextUtils.isEmpty(phoneNumber) && LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
LogUtil.d(TAG, "SubscriptionInfo phone number for self is empty!");
}
return phoneNumber;
}
LogUtil.w(TAG, "PhoneUtils.getSelfRawNumber: subInfo is null for " + mSubId);
throw new IllegalStateException("No active subscription");
}
/**
* Returns the "effective" subId, or the subId used in the context of actual messages,
@@ -159,31 +218,49 @@ public abstract class PhoneUtils {
* @param subId The input subId
* @return the real subId if we can convert
*/
public abstract int getEffectiveSubId(int subId);
public int getEffectiveSubId(int subId) {
if (subId == ParticipantData.DEFAULT_SELF_SUB_ID) {
return getDefaultSmsSubscriptionId();
}
return subId;
}
/**
* Returns the number of active subscriptions in the device.
*/
public abstract int getActiveSubscriptionCount();
public int getActiveSubscriptionCount() {
return mSubscriptionManager.getActiveSubscriptionInfoCount();
}
/**
* Get {@link SmsManager} instance
*
* @return the relevant SmsManager instance based on OS version and subId
*/
public abstract SmsManager getSmsManager();
public SmsManager getSmsManager() {
return SmsManager.getSmsManagerForSubscriptionId(mSubId);
}
/**
* Get the default SMS subscription id
*
* @return the default sub ID
*/
public abstract int getDefaultSmsSubscriptionId();
public int getDefaultSmsSubscriptionId() {
final int systemDefaultSubId = SmsManager.getDefaultSmsSubscriptionId();
if (systemDefaultSubId < 0) {
// Always use -1 for any negative subId from system
return ParticipantData.DEFAULT_SELF_SUB_ID;
}
return systemDefaultSubId;
}
/**
* Returns if there's currently a system default SIM selected for sending SMS.
*/
public abstract boolean getHasPreferredSmsSim();
public boolean getHasPreferredSmsSim() {
return getDefaultSmsSubscriptionId() != ParticipantData.DEFAULT_SELF_SUB_ID;
}
/**
* For L_MR1, system may return a negative subId. Convert this into our own
@@ -195,7 +272,23 @@ public abstract class PhoneUtils {
* @param extraName The name of the sub id extra
* @return the subId that is valid and meaningful for the app
*/
public abstract int getEffectiveIncomingSubIdFromSystem(Intent intent, String extraName);
public int getEffectiveIncomingSubIdFromSystem(Intent intent, String extraName) {
return getEffectiveIncomingSubIdFromSystem(intent.getIntExtra(extraName,
ParticipantData.DEFAULT_SELF_SUB_ID));
}
private int getEffectiveIncomingSubIdFromSystem(int subId) {
if (subId < 0) {
if (mSubscriptionManager.getActiveSubscriptionInfoCount() > 1) {
// For multi-SIM device, we can not decide which SIM to use if system
// does not know either. So just make it the invalid sub id.
return ParticipantData.DEFAULT_SELF_SUB_ID;
}
// For single-SIM device, it must come from the only SIM we have
return getDefaultSmsSubscriptionId();
}
return subId;
}
/**
* Get the subscription_id column value from a telephony provider cursor
@@ -204,438 +297,107 @@ public abstract class PhoneUtils {
* @param subIdIndex The index of the subId column in the cursor
* @return the subscription_id column value from the cursor
*/
public abstract int getSubIdFromTelephony(Cursor cursor, int subIdIndex);
public int getSubIdFromTelephony(Cursor cursor, int subIdIndex) {
return getEffectiveIncomingSubIdFromSystem(cursor.getInt(subIdIndex));
}
/**
* Check if data roaming is enabled
*
* @return true if data roaming is enabled, false otherwise
*/
public abstract boolean isDataRoamingEnabled();
public boolean isDataRoamingEnabled() {
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo == null) {
// There is nothing we can do if system give us empty sub info
LogUtil.e(TAG, "PhoneUtils.isDataRoamingEnabled: system return empty sub info for "
+ mSubId);
return false;
}
return subInfo.getDataRoaming() != SubscriptionManager.DATA_ROAMING_DISABLE;
}
/**
* Check if mobile data is enabled
*
* @return true if mobile data is enabled, false otherwise
*/
public abstract boolean isMobileDataEnabled();
public boolean isMobileDataEnabled() {
boolean mobileDataEnabled = false;
try {
final Class cmClass = mTelephonyManager.getClass();
final Method method = cmClass.getDeclaredMethod("getDataEnabled", Integer.TYPE);
method.setAccessible(true); // Make the method callable
// get the setting for "mobile data"
mobileDataEnabled = (Boolean) method.invoke(
mTelephonyManager, Integer.valueOf(mSubId));
} catch (final Exception e) {
LogUtil.e(TAG, "PhoneUtil.isMobileDataEnabled: system api not found", e);
}
return mobileDataEnabled;
}
/**
* Get the set of self phone numbers, all normalized
*
* @return the set of normalized self phone numbers
*/
public abstract HashSet<String> getNormalizedSelfNumbers();
/**
* This interface packages methods should only compile on L_MR1.
* This is needed to make unit tests happy when mockito tries to
* mock these methods. Calling on these methods on L_MR1 requires
* an extra invocation of toMr1().
*/
public interface LMr1 {
/**
* Get this SIM's information. Only applies to L_MR1 above
*
* @return the subscription info of the SIM
*/
public abstract SubscriptionInfo getActiveSubscriptionInfo();
/**
* Get the list of active SIMs in system. Only applies to L_MR1 above
*
* @return the list of subscription info for all inserted SIMs
*/
public abstract List<SubscriptionInfo> getActiveSubscriptionInfoList();
/**
* Register subscription change listener. Only applies to L_MR1 above
*
* @param listener The listener to register
*/
public abstract void registerOnSubscriptionsChangedListener(
SubscriptionManager.OnSubscriptionsChangedListener listener);
public HashSet<String> getNormalizedSelfNumbers() {
final HashSet<String> numbers = new HashSet<>();
for (SubscriptionInfo info : getActiveSubscriptionInfoList()) {
numbers.add(PhoneUtils.get(info.getSubscriptionId()).getCanonicalForSelf(
true/*allowOverride*/));
}
return numbers;
}
/**
* The PhoneUtils class for pre L_MR1
* Get this SIM's information. Only applies to L_MR1 above
*
* @return the subscription info of the SIM
*/
public static class PhoneUtilsPreLMR1 extends PhoneUtils {
private final ConnectivityManager mConnectivityManager;
public PhoneUtilsPreLMR1() {
super(ParticipantData.DEFAULT_SELF_SUB_ID);
mConnectivityManager =
(ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
}
@Override
public String getSimCountry() {
final String country = mTelephonyManager.getSimCountryIso();
if (TextUtils.isEmpty(country)) {
return null;
}
return country.toUpperCase();
}
@Override
public int getSimSlotCount() {
// Don't support MSIM pre-L_MR1
return 1;
}
@Override
public String getCarrierName() {
return mTelephonyManager.getNetworkOperatorName();
}
@Override
public boolean hasSim() {
return mTelephonyManager.getSimState() != TelephonyManager.SIM_STATE_ABSENT;
}
@Override
public boolean isRoaming() {
return mTelephonyManager.isNetworkRoaming();
}
@Override
public int[] getMccMnc() {
final String mccmnc = mTelephonyManager.getSimOperator();
int mcc = 0;
int mnc = 0;
try {
mcc = Integer.parseInt(mccmnc.substring(0, 3));
mnc = Integer.parseInt(mccmnc.substring(3));
} catch (Exception e) {
LogUtil.w(TAG, "PhoneUtils.getMccMnc: invalid string " + mccmnc, e);
}
return new int[]{mcc, mnc};
}
@Override
public String getSimOperatorNumeric() {
return mTelephonyManager.getSimOperator();
}
@Override
public String getSelfRawNumber(final boolean allowOverride) {
if (allowOverride) {
final String userDefinedNumber = getNumberFromPrefs(mContext,
ParticipantData.DEFAULT_SELF_SUB_ID);
if (!TextUtils.isEmpty(userDefinedNumber)) {
return userDefinedNumber;
}
}
return mTelephonyManager.getLine1Number();
}
@Override
public int getEffectiveSubId(int subId) {
Assert.equals(ParticipantData.DEFAULT_SELF_SUB_ID, subId);
return ParticipantData.DEFAULT_SELF_SUB_ID;
}
@Override
public SmsManager getSmsManager() {
return SmsManager.getDefault();
}
@Override
public int getDefaultSmsSubscriptionId() {
Assert.fail("PhoneUtils.getDefaultSmsSubscriptionId(): not supported before L MR1");
return ParticipantData.DEFAULT_SELF_SUB_ID;
}
@Override
public boolean getHasPreferredSmsSim() {
// SIM selection is not supported pre-L_MR1.
return true;
}
@Override
public int getActiveSubscriptionCount() {
return hasSim() ? 1 : 0;
}
@Override
public int getEffectiveIncomingSubIdFromSystem(Intent intent, String extraName) {
// Pre-L_MR1 always returns the default id
return ParticipantData.DEFAULT_SELF_SUB_ID;
}
@Override
public int getSubIdFromTelephony(Cursor cursor, int subIdIndex) {
// No subscription_id column before L_MR1
return ParticipantData.DEFAULT_SELF_SUB_ID;
}
@Override
@SuppressWarnings("deprecation")
public boolean isDataRoamingEnabled() {
if (BuildCompat.isAtLeastT()) {
return mTelephonyManager.isDataRoamingEnabled();
}
boolean dataRoamingEnabled = false;
final ContentResolver cr = mContext.getContentResolver();
if (OsUtil.isAtLeastJB_MR1()) {
dataRoamingEnabled =
(Settings.Global.getInt(cr, Settings.Global.DATA_ROAMING, 0) != 0);
} else {
dataRoamingEnabled =
(Settings.System.getInt(cr, Settings.System.DATA_ROAMING, 0) != 0);
}
return dataRoamingEnabled;
}
@Override
public boolean isMobileDataEnabled() {
boolean mobileDataEnabled = false;
try {
final Class cmClass = mConnectivityManager.getClass();
final Method method = cmClass.getDeclaredMethod("getMobileDataEnabled");
method.setAccessible(true); // Make the method callable
// get the setting for "mobile data"
mobileDataEnabled = (Boolean) method.invoke(mConnectivityManager);
} catch (final Exception e) {
LogUtil.e(TAG, "PhoneUtil.isMobileDataEnabled: system api not found", e);
}
return mobileDataEnabled;
}
@Override
public HashSet<String> getNormalizedSelfNumbers() {
final HashSet<String> numbers = new HashSet<>();
numbers.add(getCanonicalForSelf(true/*allowOverride*/));
return numbers;
}
}
/**
* The PhoneUtils class for L_MR1
*/
public static class PhoneUtilsLMR1 extends PhoneUtils implements LMr1 {
private final SubscriptionManager mSubscriptionManager;
public PhoneUtilsLMR1(final int subId) {
super(subId);
mSubscriptionManager = SubscriptionManager.from(Factory.get().getApplicationContext());
}
@Override
public String getSimCountry() {
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo != null) {
final String country = subInfo.getCountryIso();
if (TextUtils.isEmpty(country)) {
return null;
}
return country.toUpperCase();
}
return null;
}
@Override
public int getSimSlotCount() {
return mSubscriptionManager.getActiveSubscriptionInfoCountMax();
}
@Override
public String getCarrierName() {
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo != null) {
final CharSequence displayName = subInfo.getDisplayName();
if (!TextUtils.isEmpty(displayName)) {
return displayName.toString();
}
final CharSequence carrierName = subInfo.getCarrierName();
if (carrierName != null) {
return carrierName.toString();
}
}
return null;
}
@Override
public boolean hasSim() {
return mSubscriptionManager.getActiveSubscriptionInfoCount() > 0;
}
@Override
public boolean isRoaming() {
return mSubscriptionManager.isNetworkRoaming(mSubId);
}
@Override
public int[] getMccMnc() {
int mcc = 0;
int mnc = 0;
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo != null) {
mcc = subInfo.getMcc();
mnc = subInfo.getMnc();
}
return new int[]{mcc, mnc};
}
@Override
public String getSimOperatorNumeric() {
// For L_MR1 we return the canonicalized (xxxxxx) string
return getMccMncString(getMccMnc());
}
@Override
public String getSelfRawNumber(final boolean allowOverride) {
if (allowOverride) {
final String userDefinedNumber = getNumberFromPrefs(mContext, mSubId);
if (!TextUtils.isEmpty(userDefinedNumber)) {
return userDefinedNumber;
}
}
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
if (subInfo != null) {
String phoneNumber = subInfo.getNumber();
if (TextUtils.isEmpty(phoneNumber) && LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
LogUtil.d(TAG, "SubscriptionInfo phone number for self is empty!");
}
return phoneNumber;
}
LogUtil.w(TAG, "PhoneUtils.getSelfRawNumber: subInfo is null for " + mSubId);
throw new IllegalStateException("No active subscription");
}
@Override
public SubscriptionInfo getActiveSubscriptionInfo() {
try {
final SubscriptionInfo subInfo =
mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
if (subInfo == null) {
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
// This is possible if the sub id is no longer available.
LogUtil.d(TAG, "PhoneUtils.getActiveSubscriptionInfo(): empty sub info for "
+ mSubId);
}
}
return subInfo;
} catch (Exception e) {
LogUtil.e(TAG, "PhoneUtils.getActiveSubscriptionInfo: system exception for "
+ mSubId, e);
}
return null;
}
@Override
public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
final List<SubscriptionInfo> subscriptionInfos =
mSubscriptionManager.getActiveSubscriptionInfoList();
if (subscriptionInfos != null) {
return subscriptionInfos;
}
return EMPTY_SUBSCRIPTION_LIST;
}
@Override
public int getEffectiveSubId(int subId) {
if (subId == ParticipantData.DEFAULT_SELF_SUB_ID) {
return getDefaultSmsSubscriptionId();
}
return subId;
}
@Override
public void registerOnSubscriptionsChangedListener(
SubscriptionManager.OnSubscriptionsChangedListener listener) {
mSubscriptionManager.addOnSubscriptionsChangedListener(listener);
}
@Override
public SmsManager getSmsManager() {
return SmsManager.getSmsManagerForSubscriptionId(mSubId);
}
@Override
public int getDefaultSmsSubscriptionId() {
final int systemDefaultSubId = SmsManager.getDefaultSmsSubscriptionId();
if (systemDefaultSubId < 0) {
// Always use -1 for any negative subId from system
return ParticipantData.DEFAULT_SELF_SUB_ID;
}
return systemDefaultSubId;
}
@Override
public boolean getHasPreferredSmsSim() {
return getDefaultSmsSubscriptionId() != ParticipantData.DEFAULT_SELF_SUB_ID;
}
@Override
public int getActiveSubscriptionCount() {
return mSubscriptionManager.getActiveSubscriptionInfoCount();
}
@Override
public int getEffectiveIncomingSubIdFromSystem(Intent intent, String extraName) {
return getEffectiveIncomingSubIdFromSystem(intent.getIntExtra(extraName,
ParticipantData.DEFAULT_SELF_SUB_ID));
}
private int getEffectiveIncomingSubIdFromSystem(int subId) {
if (subId < 0) {
if (mSubscriptionManager.getActiveSubscriptionInfoCount() > 1) {
// For multi-SIM device, we can not decide which SIM to use if system
// does not know either. So just make it the invalid sub id.
return ParticipantData.DEFAULT_SELF_SUB_ID;
}
// For single-SIM device, it must come from the only SIM we have
return getDefaultSmsSubscriptionId();
}
return subId;
}
@Override
public int getSubIdFromTelephony(Cursor cursor, int subIdIndex) {
return getEffectiveIncomingSubIdFromSystem(cursor.getInt(subIdIndex));
}
@Override
public boolean isDataRoamingEnabled() {
final SubscriptionInfo subInfo = getActiveSubscriptionInfo();
public SubscriptionInfo getActiveSubscriptionInfo() {
try {
final SubscriptionInfo subInfo =
mSubscriptionManager.getActiveSubscriptionInfo(mSubId);
if (subInfo == null) {
// There is nothing we can do if system give us empty sub info
LogUtil.e(TAG, "PhoneUtils.isDataRoamingEnabled: system return empty sub info for "
+ mSubId);
return false;
if (LogUtil.isLoggable(TAG, LogUtil.DEBUG)) {
// This is possible if the sub id is no longer available.
LogUtil.d(TAG, "PhoneUtils.getActiveSubscriptionInfo(): empty sub info for "
+ mSubId);
}
}
return subInfo.getDataRoaming() != SubscriptionManager.DATA_ROAMING_DISABLE;
return subInfo;
} catch (Exception e) {
LogUtil.e(TAG, "PhoneUtils.getActiveSubscriptionInfo: system exception for "
+ mSubId, e);
}
return null;
}
@Override
public boolean isMobileDataEnabled() {
boolean mobileDataEnabled = false;
try {
final Class cmClass = mTelephonyManager.getClass();
final Method method = cmClass.getDeclaredMethod("getDataEnabled", Integer.TYPE);
method.setAccessible(true); // Make the method callable
// get the setting for "mobile data"
mobileDataEnabled = (Boolean) method.invoke(
mTelephonyManager, Integer.valueOf(mSubId));
} catch (final Exception e) {
LogUtil.e(TAG, "PhoneUtil.isMobileDataEnabled: system api not found", e);
}
return mobileDataEnabled;
/**
* Get the list of active SIMs in system. Only applies to L_MR1 above
*
* @return the list of subscription info for all inserted SIMs
*/
public List<SubscriptionInfo> getActiveSubscriptionInfoList() {
final List<SubscriptionInfo> subscriptionInfos =
mSubscriptionManager.getActiveSubscriptionInfoList();
if (subscriptionInfos != null) {
return subscriptionInfos;
}
return EMPTY_SUBSCRIPTION_LIST;
}
@Override
public HashSet<String> getNormalizedSelfNumbers() {
final HashSet<String> numbers = new HashSet<>();
for (SubscriptionInfo info : getActiveSubscriptionInfoList()) {
numbers.add(PhoneUtils.get(info.getSubscriptionId()).getCanonicalForSelf(
true/*allowOverride*/));
}
return numbers;
}
/**
* Register subscription change listener. Only applies to L_MR1 above
*
* @param listener The listener to register
*/
public void registerOnSubscriptionsChangedListener(
SubscriptionManager.OnSubscriptionsChangedListener listener) {
mSubscriptionManager.addOnSubscriptionsChangedListener(listener);
}
/**
@@ -659,15 +421,6 @@ public abstract class PhoneUtils {
return Factory.get().getPhoneUtils(subId);
}
public LMr1 toLMr1() {
if (OsUtil.isAtLeastL_MR1()) {
return (LMr1) this;
} else {
Assert.fail("PhoneUtils.toLMr1(): invalid OS version");
return null;
}
}
/**
* Check if this device supports SMS
*
@@ -897,12 +650,9 @@ public abstract class PhoneUtils {
* - On JB (and below) this always returns true, since the setting was added in KLP.
*/
public boolean isDefaultSmsApp() {
if (OsUtil.isAtLeastKLP()) {
RoleManager roleManager = mContext.getSystemService(RoleManager.class);
return roleManager.isRoleAvailable(RoleManager.ROLE_SMS)
&& roleManager.isRoleHeld(RoleManager.ROLE_SMS);
}
return true;
RoleManager roleManager = mContext.getSystemService(RoleManager.class);
return roleManager.isRoleAvailable(RoleManager.ROLE_SMS)
&& roleManager.isRoleHeld(RoleManager.ROLE_SMS);
}
/**
@@ -911,10 +661,7 @@ public abstract class PhoneUtils {
* @return the package name of default SMS app
*/
public String getDefaultSmsApp() {
if (OsUtil.isAtLeastKLP()) {
return Telephony.Sms.getDefaultSmsPackage(mContext);
}
return null;
return Telephony.Sms.getDefaultSmsPackage(mContext);
}
/**
@@ -931,15 +678,14 @@ public abstract class PhoneUtils {
* an error or there is no default app (e.g. JB and below).
*/
public String getDefaultSmsAppLabel() {
if (OsUtil.isAtLeastKLP()) {
final String packageName = Telephony.Sms.getDefaultSmsPackage(mContext);
final PackageManager pm = mContext.getPackageManager();
try {
final ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0);
return pm.getApplicationLabel(appInfo).toString();
} catch (NameNotFoundException e) {
// Fall through and return empty string
}
final String packageName = Telephony.Sms.getDefaultSmsPackage(mContext);
final PackageManager pm = mContext.getPackageManager();
try {
final ApplicationInfo appInfo = pm.getApplicationInfo(packageName,
ApplicationInfoFlags.of(0));
return pm.getApplicationLabel(appInfo).toString();
} catch (NameNotFoundException e) {
// Fall through and return empty string
}
return "";
}
@@ -949,15 +695,9 @@ public abstract class PhoneUtils {
*
* @return true if enabled.
*/
@SuppressWarnings("deprecation")
public boolean isAirplaneModeOn() {
if (OsUtil.isAtLeastJB_MR1()) {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
} else {
return Settings.System.getInt(mContext.getContentResolver(),
Settings.System.AIRPLANE_MODE_ON, 0) != 0;
}
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.AIRPLANE_MODE_ON, 0) != 0;
}
public static String getMccMncString(int[] mccmnc) {
@@ -995,14 +735,10 @@ public abstract class PhoneUtils {
* @param runnable a {@link SubscriptionRunnable} for performing work on each subscription.
*/
public static void forEachActiveSubscription(final SubscriptionRunnable runnable) {
if (OsUtil.isAtLeastL_MR1()) {
final List<SubscriptionInfo> subscriptionList =
getDefault().toLMr1().getActiveSubscriptionInfoList();
for (final SubscriptionInfo subscriptionInfo : subscriptionList) {
runnable.runForSubscription(subscriptionInfo.getSubscriptionId());
}
} else {
runnable.runForSubscription(ParticipantData.DEFAULT_SELF_SUB_ID);
final List<SubscriptionInfo> subscriptionList =
getDefault().getActiveSubscriptionInfoList();
for (final SubscriptionInfo subscriptionInfo : subscriptionList) {
runnable.runForSubscription(subscriptionInfo.getSubscriptionId());
}
}
+2 -13
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,20 +17,10 @@
package com.android.messaging.util;
import android.annotation.TargetApi;
import android.os.Build;
/**
* Helper class for systrace (see http://developer.android.com/tools/help/systrace.html).<p>
* To enable, set log.tag.Bugle_Trace (defined by {@link #TAG} to VERBOSE before
* the process starts.<p>
* Note that this will run only on JBMR2 or later; on earlier platforms or if the log
* tag isn't set, calls to {@link #beginSection(String)} or {@link #endSection()} are no-ops. <p>
* Internally, calls dispatch to either a class that actually does work or a class that doesn't.
* This avoids Dalvik complaining when it loads the class on earlier platforms that the
* opcodes aren't available, and, according to the Dalvik team, using vtable dispatching for
* something like this should be faster than if (OsUtil.isAtLeast...()) on each call.
*/
public final class Trace {
private static final String TAG = "Bugle_Trace";
@@ -44,8 +35,7 @@ public final class Trace {
static {
// Use android.util.Log instead of LogUtil here to avoid pulling in Gservices
// too early in app startup.
if (OsUtil.isAtLeastJB_MR2() &&
android.util.Log.isLoggable(TAG, android.util.Log.VERBOSE)) {
if (android.util.Log.isLoggable(TAG, android.util.Log.VERBOSE)) {
sTrace = new TraceJBMR2();
} else {
sTrace = new TraceShim();
@@ -87,7 +77,6 @@ public final class Trace {
/**
* Internal class that we use if we really did enable tracing.
*/
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
private static final class TraceJBMR2 extends AbstractTrace {
@Override
void beginSection(String sectionName) {
+9 -18
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
* Copyright (C) 2024 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -261,16 +262,14 @@ public class UiUtils {
}
public static void setStatusBarColor(final Activity activity, final int color) {
if (OsUtil.isAtLeastL()) {
// To achieve the appearance of an 80% opacity blend against a black background,
// each color channel is reduced in value by 20%.
final int blendedRed = (int) Math.floor(0.8 * Color.red(color));
final int blendedGreen = (int) Math.floor(0.8 * Color.green(color));
final int blendedBlue = (int) Math.floor(0.8 * Color.blue(color));
// To achieve the appearance of an 80% opacity blend against a black background,
// each color channel is reduced in value by 20%.
final int blendedRed = (int) Math.floor(0.8 * Color.red(color));
final int blendedGreen = (int) Math.floor(0.8 * Color.green(color));
final int blendedBlue = (int) Math.floor(0.8 * Color.blue(color));
activity.getWindow().setStatusBarColor(
Color.rgb(blendedRed, blendedGreen, blendedBlue));
}
activity.getWindow().setStatusBarColor(
Color.rgb(blendedRed, blendedGreen, blendedBlue));
}
public static void lockOrientation(final Activity activity) {
@@ -301,16 +300,8 @@ public class UiUtils {
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}
public static int getPaddingStart(final View view) {
return OsUtil.isAtLeastJB_MR1() ? view.getPaddingStart() : view.getPaddingLeft();
}
public static int getPaddingEnd(final View view) {
return OsUtil.isAtLeastJB_MR1() ? view.getPaddingEnd() : view.getPaddingRight();
}
public static boolean isRtlMode() {
return OsUtil.isAtLeastJB_MR2() && Factory.get().getApplicationContext().getResources()
return Factory.get().getApplicationContext().getResources()
.getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
}