Merge "Rename EmergencyCallDiagnosticParam API" into main
diff --git a/OWNERS b/OWNERS
index 7e68aea..6f90d48 100644
--- a/OWNERS
+++ b/OWNERS
@@ -5,3 +5,4 @@
rgreenwalt@google.com
pmadapurmath@google.com
grantmenke@google.com
+huiwang@google.com
diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml
index 9ead5f4..c9e5593 100644
--- a/res/values-my/strings.xml
+++ b/res/values-my/strings.xml
@@ -19,7 +19,7 @@
<string name="telecommAppLabel" product="default" msgid="1825598513414129827">"ဖုန်းခေါ်ဆိုမှုများ"</string>
<string name="userCallActivityLabel" product="default" msgid="3605391260292846248">"ဖုန်း"</string>
<string name="unknown" msgid="6993977514360123431">"မသိပါ"</string>
- <string name="notification_missedCallTitle" msgid="5060387047205532974">"လွဲသွားသော ဖုန်းခေါ်မှု"</string>
+ <string name="notification_missedCallTitle" msgid="5060387047205532974">"လွတ်သွားသော ခေါ်ဆိုမှု"</string>
<string name="notification_missedWorkCallTitle" msgid="6965463282259034953">"လွတ်သွားသည့် အလုပ်ဆိုင်ရာ ခေါ်ဆိုမှု"</string>
<string name="notification_missedCallsTitle" msgid="3910479625507893809">"လွဲသွားသော ဖုန်းခေါ်မှုများ"</string>
<string name="notification_missedCallsMsg" msgid="5055782736170916682">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g> လွဲသွားသော ဖုန်းခေါ်မှုများ"</string>
diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml
index 787711b..6f3ebe3 100644
--- a/res/values-or/strings.xml
+++ b/res/values-or/strings.xml
@@ -24,7 +24,7 @@
<string name="notification_missedCallsTitle" msgid="3910479625507893809">"ମିସ୍ଡ କଲ୍"</string>
<string name="notification_missedCallsMsg" msgid="5055782736170916682">"<xliff:g id="NUM_MISSED_CALLS">%s</xliff:g>ଟି ମିସ୍ଡ କଲ୍"</string>
<string name="notification_missedCallTicker" msgid="6731461957487087769">"<xliff:g id="MISSED_CALL_FROM">%s</xliff:g>ଙ୍କ ଠାରୁ ମିସ୍-କଲ୍ ମିଳିଛି"</string>
- <string name="notification_missedCall_call_back" msgid="7900333283939789732">"କଲବ୍ୟାକ୍ କରନ୍ତୁ"</string>
+ <string name="notification_missedCall_call_back" msgid="7900333283939789732">"କଲବେକ କରନ୍ତୁ"</string>
<string name="notification_missedCall_message" msgid="4054698824390076431">"ମେସେଜ୍ ଦିଅନ୍ତୁ"</string>
<string name="notification_disconnectedCall_title" msgid="1790131923692416928">"କଲ୍ ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି"</string>
<string name="notification_disconnectedCall_body" msgid="600491714584417536">"ଏକ ଜରୁରୀକାଳୀନ କଲ୍ କରାଯାଇଥିବାରୁ <xliff:g id="CALLER">%s</xliff:g>ଙ୍କୁ କରାଯାଇଥିବା କଲ୍ ବିଚ୍ଛିନ୍ନ କରାଯାଇଛି।"</string>
diff --git a/src/com/android/server/telecom/CallIntentProcessor.java b/src/com/android/server/telecom/CallIntentProcessor.java
index 062c872..c02d20d 100644
--- a/src/com/android/server/telecom/CallIntentProcessor.java
+++ b/src/com/android/server/telecom/CallIntentProcessor.java
@@ -172,9 +172,14 @@
// Show the toast to warn user that it is a personal call though initiated in work
// profile.
if (fixedInitiatingUser) {
- Toast.makeText(context, Looper.getMainLooper(),
- context.getString(R.string.toast_personal_call_msg),
- Toast.LENGTH_LONG).show();
+ if (featureFlags.telecomResolveHiddenDependencies()) {
+ Toast.makeText(context, context.getString(R.string.toast_personal_call_msg),
+ Toast.LENGTH_LONG).show();
+ } else {
+ Toast.makeText(context, Looper.getMainLooper(),
+ context.getString(R.string.toast_personal_call_msg),
+ Toast.LENGTH_LONG).show();
+ }
}
} else {
Log.i(CallIntentProcessor.class,
diff --git a/src/com/android/server/telecom/CallsManager.java b/src/com/android/server/telecom/CallsManager.java
index cc5a15d..a3b423a 100644
--- a/src/com/android/server/telecom/CallsManager.java
+++ b/src/com/android/server/telecom/CallsManager.java
@@ -4669,18 +4669,35 @@
}
/**
- * Determines if there are any ongoing self managed calls for the given package/user.
+ * Determines if there are any ongoing self-managed calls for the given package/user.
* @param packageName The package name to check.
- * @param userHandle The userhandle to check.
+ * @param userHandle The {@link UserHandle} to check.
* @return {@code true} if the app has ongoing calls, or {@code false} otherwise.
*/
public boolean isInSelfManagedCall(String packageName, UserHandle userHandle) {
+ return isInSelfManagedCallCrossUsers(packageName, userHandle, false);
+ }
+
+ /**
+ * Determines if there are any ongoing self-managed calls for the given package/user (unless
+ * hasCrossUsers has been enabled).
+ * @param packageName The package name to check.
+ * @param userHandle The {@link UserHandle} to check.
+ * @param hasCrossUserAccess indicates if calls across all users should be returned.
+ * @return {@code true} if the app has ongoing calls, or {@code false} otherwise.
+ */
+ public boolean isInSelfManagedCallCrossUsers(
+ String packageName, UserHandle userHandle, boolean hasCrossUserAccess) {
return mSelfManagedCallsBeingSetup.stream().anyMatch(c -> c.isSelfManaged()
&& c.getTargetPhoneAccount().getComponentName().getPackageName().equals(packageName)
- && c.getTargetPhoneAccount().getUserHandle().equals(userHandle)) ||
- mCalls.stream().anyMatch(c -> c.isSelfManaged()
+ && (!hasCrossUserAccess
+ ? c.getTargetPhoneAccount().getUserHandle().equals(userHandle)
+ : true))
+ || mCalls.stream().anyMatch(c -> c.isSelfManaged()
&& c.getTargetPhoneAccount().getComponentName().getPackageName().equals(packageName)
- && c.getTargetPhoneAccount().getUserHandle().equals(userHandle));
+ && (!hasCrossUserAccess
+ ? c.getTargetPhoneAccount().getUserHandle().equals(userHandle)
+ : true));
}
@VisibleForTesting
diff --git a/src/com/android/server/telecom/InCallAdapter.java b/src/com/android/server/telecom/InCallAdapter.java
index 9ce10bd..514ba48 100755
--- a/src/com/android/server/telecom/InCallAdapter.java
+++ b/src/com/android/server/telecom/InCallAdapter.java
@@ -20,6 +20,7 @@
import android.os.Binder;
import android.os.Bundle;
import android.os.ResultReceiver;
+import android.os.UserHandle;
import android.telecom.CallEndpoint;
import android.telecom.Log;
import android.telecom.PhoneAccountHandle;
@@ -420,7 +421,8 @@
Log.startSession(LogUtils.Sessions.ICA_ENTER_AUDIO_PROCESSING,
mOwnerPackageAbbreviation);
// TODO: enforce the extra permission.
- Binder.withCleanCallingIdentity(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
synchronized (mLock) {
Call call = mCallIdMapper.getCall(callId);
if (call != null) {
@@ -429,7 +431,9 @@
Log.w(this, "enterBackgroundAudioProcessing, unknown call id: %s", callId);
}
}
- });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
} finally {
Log.endSession();
}
@@ -440,7 +444,8 @@
try {
Log.startSession(LogUtils.Sessions.ICA_EXIT_AUDIO_PROCESSING,
mOwnerPackageAbbreviation);
- Binder.withCleanCallingIdentity(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
synchronized (mLock) {
Call call = mCallIdMapper.getCall(callId);
if (call != null) {
@@ -450,7 +455,9 @@
"exitBackgroundAudioProcessing, unknown call id: %s", callId);
}
}
- });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
} finally {
Log.endSession();
}
diff --git a/src/com/android/server/telecom/PhoneAccountRegistrar.java b/src/com/android/server/telecom/PhoneAccountRegistrar.java
index de73269..fc90edd 100644
--- a/src/com/android/server/telecom/PhoneAccountRegistrar.java
+++ b/src/com/android/server/telecom/PhoneAccountRegistrar.java
@@ -58,6 +58,7 @@
// TODO: Needed for move to system service: import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
import com.android.modules.utils.ModifiedUtf8;
@@ -81,10 +82,12 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
@@ -181,19 +184,19 @@
private interface PhoneAccountRegistrarWriteLock {}
private final PhoneAccountRegistrarWriteLock mWriteLock =
new PhoneAccountRegistrarWriteLock() {};
- private final com.android.internal.telephony.flags.FeatureFlags mTelephonyFeatureFlags;
+ private final FeatureFlags mTelephonyFeatureFlags;
@VisibleForTesting
public PhoneAccountRegistrar(Context context, TelecomSystem.SyncRoot lock,
DefaultDialerCache defaultDialerCache, AppLabelProxy appLabelProxy,
- com.android.internal.telephony.flags.FeatureFlags telephonyFeatureFlags) {
+ FeatureFlags telephonyFeatureFlags) {
this(context, lock, FILE_NAME, defaultDialerCache, appLabelProxy, telephonyFeatureFlags);
}
@VisibleForTesting
public PhoneAccountRegistrar(Context context, TelecomSystem.SyncRoot lock, String fileName,
DefaultDialerCache defaultDialerCache, AppLabelProxy appLabelProxy,
- com.android.internal.telephony.flags.FeatureFlags telephonyFeatureFlags) {
+ FeatureFlags telephonyFeatureFlags) {
mAtomicFile = new AtomicFile(new File(context.getFilesDir(), fileName));
@@ -951,6 +954,9 @@
enforceCharacterLimit(account);
enforceIconSizeLimit(account);
enforceMaxPhoneAccountLimit(account);
+ if (mTelephonyFeatureFlags.simultaneousCallingIndications()) {
+ enforceSimultaneousCallingRestrictionLimit(account);
+ }
addOrReplacePhoneAccount(account);
}
@@ -1079,6 +1085,43 @@
}
/**
+ * Enforce size limits on the simultaneous calling restriction of a PhoneAccount.
+ * If a PhoneAccount has a simultaneous calling restriction on it, enforce the following: the
+ * number of PhoneAccountHandles in the Set can not exceed the per app restriction on
+ * PhoneAccounts registered and each PhoneAccountHandle's fields must not exceed the per field
+ * character limit.
+ * @param account The PhoneAccount to enforce simultaneous calling restrictions on.
+ * @throws IllegalArgumentException if the PhoneAccount exceeds size limits.
+ */
+ public void enforceSimultaneousCallingRestrictionLimit(@NonNull PhoneAccount account) {
+ if (!account.hasSimultaneousCallingRestriction()) return;
+ Set<PhoneAccountHandle> restrictions = account.getSimultaneousCallingRestriction();
+ if (restrictions.size() > MAX_PHONE_ACCOUNT_REGISTRATIONS) {
+ throw new IllegalArgumentException("Can not register a PhoneAccount with a number"
+ + "of simultaneous calling restrictions that is greater than "
+ + MAX_PHONE_ACCOUNT_REGISTRATIONS);
+ }
+ for (PhoneAccountHandle handle : restrictions) {
+ ComponentName component = handle.getComponentName();
+ if (component.getPackageName().length() > MAX_PHONE_ACCOUNT_FIELD_CHAR_LIMIT) {
+ throw new IllegalArgumentException("A PhoneAccountHandle added as part of "
+ + "a simultaneous calling restriction has a package name that has exceeded "
+ + "the character limit of " + MAX_PHONE_ACCOUNT_FIELD_CHAR_LIMIT);
+ }
+ if (component.getClassName().length() > MAX_PHONE_ACCOUNT_FIELD_CHAR_LIMIT) {
+ throw new IllegalArgumentException("A PhoneAccountHandle added as part of "
+ + "a simultaneous calling restriction has a class name that has exceeded "
+ + "the character limit of " + MAX_PHONE_ACCOUNT_FIELD_CHAR_LIMIT);
+ }
+ if (handle.getId().length() > MAX_PHONE_ACCOUNT_FIELD_CHAR_LIMIT) {
+ throw new IllegalArgumentException("A PhoneAccountHandle added as part of "
+ + "a simultaneous calling restriction has an ID that has exceeded "
+ + "the character limit of " + MAX_PHONE_ACCOUNT_FIELD_CHAR_LIMIT);
+ }
+ }
+ }
+
+ /**
* Enforce a character limit on all PA and PAH string or char-sequence fields.
*
* @param account to enforce check on
@@ -1878,7 +1921,7 @@
sortPhoneAccounts();
ByteArrayOutputStream os = new ByteArrayOutputStream();
XmlSerializer serializer = Xml.resolveSerializer(os);
- writeToXml(mState, serializer, mContext);
+ writeToXml(mState, serializer, mContext, mTelephonyFeatureFlags);
serializer.flush();
new AsyncXmlWriter().execute(os);
} catch (IOException e) {
@@ -1899,7 +1942,7 @@
try {
XmlPullParser parser = Xml.resolvePullParser(is);
parser.nextTag();
- mState = readFromXml(parser, mContext);
+ mState = readFromXml(parser, mContext, mTelephonyFeatureFlags);
migratePhoneAccountHandle(mState);
versionChanged = mState.versionNumber < EXPECTED_STATE_VERSION;
@@ -1934,14 +1977,14 @@
}
}
- private static void writeToXml(State state, XmlSerializer serializer, Context context)
- throws IOException {
- sStateXml.writeToXml(state, serializer, context);
+ private static void writeToXml(State state, XmlSerializer serializer, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException {
+ sStateXml.writeToXml(state, serializer, context, telephonyFeatureFlags);
}
- private static State readFromXml(XmlPullParser parser, Context context)
- throws IOException, XmlPullParserException {
- State s = sStateXml.readFromXml(parser, 0, context);
+ private static State readFromXml(XmlPullParser parser, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException, XmlPullParserException {
+ State s = sStateXml.readFromXml(parser, 0, context, telephonyFeatureFlags);
return s != null ? s : new State();
}
@@ -2007,8 +2050,8 @@
/**
* Write the supplied object to XML
*/
- public abstract void writeToXml(T o, XmlSerializer serializer, Context context)
- throws IOException;
+ public abstract void writeToXml(T o, XmlSerializer serializer, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException;
/**
* Read from the supplied XML into a new object, returning null in case of an
@@ -2017,8 +2060,8 @@
* object's writeToXml(). This object tries to fail early without modifying
* 'parser' if it does not recognize the data it sees.
*/
- public abstract T readFromXml(XmlPullParser parser, int version, Context context)
- throws IOException, XmlPullParserException;
+ public abstract T readFromXml(XmlPullParser parser, int version, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException, XmlPullParserException;
protected void writeTextIfNonNull(String tagName, Object value, XmlSerializer serializer)
throws IOException {
@@ -2030,6 +2073,29 @@
}
/**
+ * Serializes a List of PhoneAccountHandles.
+ * @param tagName The tag for the List
+ * @param handles The List of PhoneAccountHandles to serialize
+ * @param serializer The serializer
+ * @throws IOException if serialization fails.
+ */
+ protected void writePhoneAccountHandleSet(String tagName, Set<PhoneAccountHandle> handles,
+ XmlSerializer serializer, Context context, FeatureFlags telephonyFeatureFlags)
+ throws IOException {
+ serializer.startTag(null, tagName);
+ if (handles != null) {
+ serializer.attribute(null, ATTRIBUTE_LENGTH, Objects.toString(handles.size()));
+ for (PhoneAccountHandle handle : handles) {
+ sPhoneAccountHandleXml.writeToXml(handle, serializer, context,
+ telephonyFeatureFlags);
+ }
+ } else {
+ serializer.attribute(null, ATTRIBUTE_LENGTH, "0");
+ }
+ serializer.endTag(null, tagName);
+ }
+
+ /**
* Serializes a string array.
*
* @param tagName The tag name for the string array.
@@ -2123,6 +2189,21 @@
serializer.endTag(null, tagName);
}
+ protected Set<PhoneAccountHandle> readPhoneAccountHandleSet(XmlPullParser parser,
+ int version, Context context, FeatureFlags telephonyFeatureFlags)
+ throws IOException, XmlPullParserException {
+ int length = Integer.parseInt(parser.getAttributeValue(null, ATTRIBUTE_LENGTH));
+ Set<PhoneAccountHandle> handles = new HashSet<>(length);
+ if (length == 0) return handles;
+
+ int outerDepth = parser.getDepth();
+ while (XmlUtils.nextElementWithin(parser, outerDepth)) {
+ handles.add(sPhoneAccountHandleXml.readFromXml(parser, version, context,
+ telephonyFeatureFlags));
+ }
+ return handles;
+ }
+
/**
* Reads a string array from the XML parser.
*
@@ -2230,8 +2311,8 @@
private static final String VERSION = "version";
@Override
- public void writeToXml(State o, XmlSerializer serializer, Context context)
- throws IOException {
+ public void writeToXml(State o, XmlSerializer serializer, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException {
if (o != null) {
serializer.startTag(null, CLASS_STATE);
serializer.attribute(null, VERSION, Objects.toString(EXPECTED_STATE_VERSION));
@@ -2239,14 +2320,15 @@
serializer.startTag(null, DEFAULT_OUTGOING);
for (DefaultPhoneAccountHandle defaultPhoneAccountHandle : o
.defaultOutgoingAccountHandles.values()) {
- sDefaultPhoneAcountHandleXml
- .writeToXml(defaultPhoneAccountHandle, serializer, context);
+ sDefaultPhoneAccountHandleXml
+ .writeToXml(defaultPhoneAccountHandle, serializer, context,
+ telephonyFeatureFlags);
}
serializer.endTag(null, DEFAULT_OUTGOING);
serializer.startTag(null, ACCOUNTS);
for (PhoneAccount m : o.accounts) {
- sPhoneAccountXml.writeToXml(m, serializer, context);
+ sPhoneAccountXml.writeToXml(m, serializer, context, telephonyFeatureFlags);
}
serializer.endTag(null, ACCOUNTS);
@@ -2255,8 +2337,8 @@
}
@Override
- public State readFromXml(XmlPullParser parser, int version, Context context)
- throws IOException, XmlPullParserException {
+ public State readFromXml(XmlPullParser parser, int version, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException, XmlPullParserException {
if (parser.getName().equals(CLASS_STATE)) {
State s = new State();
@@ -2272,7 +2354,8 @@
// assume there are no groups.
parser.nextTag();
PhoneAccountHandle phoneAccountHandle = sPhoneAccountHandleXml
- .readFromXml(parser, s.versionNumber, context);
+ .readFromXml(parser, s.versionNumber, context,
+ telephonyFeatureFlags);
UserManager userManager = UserManager.get(context);
UserInfo primaryUser = userManager.getPrimaryUser();
if (primaryUser != null) {
@@ -2287,8 +2370,9 @@
int defaultAccountHandlesDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, defaultAccountHandlesDepth)) {
DefaultPhoneAccountHandle accountHandle
- = sDefaultPhoneAcountHandleXml
- .readFromXml(parser, s.versionNumber, context);
+ = sDefaultPhoneAccountHandleXml
+ .readFromXml(parser, s.versionNumber, context,
+ telephonyFeatureFlags);
if (accountHandle != null && s.accounts != null) {
s.defaultOutgoingAccountHandles
.put(accountHandle.userHandle, accountHandle);
@@ -2299,7 +2383,7 @@
int accountsDepth = parser.getDepth();
while (XmlUtils.nextElementWithin(parser, accountsDepth)) {
PhoneAccount account = sPhoneAccountXml.readFromXml(parser,
- s.versionNumber, context);
+ s.versionNumber, context, telephonyFeatureFlags);
if (account != null && s.accounts != null) {
s.accounts.add(account);
@@ -2314,7 +2398,7 @@
};
@VisibleForTesting
- public static final XmlSerialization<DefaultPhoneAccountHandle> sDefaultPhoneAcountHandleXml =
+ public static final XmlSerialization<DefaultPhoneAccountHandle> sDefaultPhoneAccountHandleXml =
new XmlSerialization<DefaultPhoneAccountHandle>() {
private static final String CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE
= "default_outgoing_phone_account_handle";
@@ -2324,7 +2408,7 @@
@Override
public void writeToXml(DefaultPhoneAccountHandle o, XmlSerializer serializer,
- Context context) throws IOException {
+ Context context, FeatureFlags telephonyFeatureFlags) throws IOException {
if (o != null) {
final UserManager userManager = UserManager.get(context);
final long serialNumber = userManager.getSerialNumberForUser(o.userHandle);
@@ -2334,7 +2418,7 @@
writeNonNullString(GROUP_ID, o.groupId, serializer);
serializer.startTag(null, ACCOUNT_HANDLE);
sPhoneAccountHandleXml.writeToXml(o.phoneAccountHandle, serializer,
- context);
+ context, telephonyFeatureFlags);
serializer.endTag(null, ACCOUNT_HANDLE);
serializer.endTag(null, CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE);
}
@@ -2343,7 +2427,7 @@
@Override
public DefaultPhoneAccountHandle readFromXml(XmlPullParser parser, int version,
- Context context)
+ Context context, FeatureFlags telephonyFeatureFlags)
throws IOException, XmlPullParserException {
if (parser.getName().equals(CLASS_DEFAULT_OUTGOING_PHONE_ACCOUNT_HANDLE)) {
int outerDepth = parser.getDepth();
@@ -2354,7 +2438,7 @@
if (parser.getName().equals(ACCOUNT_HANDLE)) {
parser.nextTag();
accountHandle = sPhoneAccountHandleXml.readFromXml(parser, version,
- context);
+ context, telephonyFeatureFlags);
} else if (parser.getName().equals(USER_SERIAL_NUMBER)) {
parser.next();
userSerialNumberString = parser.getText();
@@ -2405,16 +2489,19 @@
private static final String ICON = "icon";
private static final String EXTRAS = "extras";
private static final String ENABLED = "enabled";
+ private static final String SIMULTANEOUS_CALLING_RESTRICTION
+ = "simultaneous_calling_restriction";
@Override
- public void writeToXml(PhoneAccount o, XmlSerializer serializer, Context context)
- throws IOException {
+ public void writeToXml(PhoneAccount o, XmlSerializer serializer, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException {
if (o != null) {
serializer.startTag(null, CLASS_PHONE_ACCOUNT);
if (o.getAccountHandle() != null) {
serializer.startTag(null, ACCOUNT_HANDLE);
- sPhoneAccountHandleXml.writeToXml(o.getAccountHandle(), serializer, context);
+ sPhoneAccountHandleXml.writeToXml(o.getAccountHandle(), serializer, context,
+ telephonyFeatureFlags);
serializer.endTag(null, ACCOUNT_HANDLE);
}
@@ -2431,13 +2518,19 @@
writeTextIfNonNull(ENABLED, o.isEnabled() ? "true" : "false" , serializer);
writeTextIfNonNull(SUPPORTED_AUDIO_ROUTES, Integer.toString(
o.getSupportedAudioRoutes()), serializer);
+ if (o.hasSimultaneousCallingRestriction()
+ && telephonyFeatureFlags.simultaneousCallingIndications()) {
+ writePhoneAccountHandleSet(SIMULTANEOUS_CALLING_RESTRICTION,
+ o.getSimultaneousCallingRestriction(), serializer, context,
+ telephonyFeatureFlags);
+ }
serializer.endTag(null, CLASS_PHONE_ACCOUNT);
}
}
- public PhoneAccount readFromXml(XmlPullParser parser, int version, Context context)
- throws IOException, XmlPullParserException {
+ public PhoneAccount readFromXml(XmlPullParser parser, int version, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException, XmlPullParserException {
if (parser.getName().equals(CLASS_PHONE_ACCOUNT)) {
int outerDepth = parser.getDepth();
PhoneAccountHandle accountHandle = null;
@@ -2456,12 +2549,13 @@
Icon icon = null;
boolean enabled = false;
Bundle extras = null;
+ Set<PhoneAccountHandle> simultaneousCallingRestriction = null;
while (XmlUtils.nextElementWithin(parser, outerDepth)) {
if (parser.getName().equals(ACCOUNT_HANDLE)) {
parser.nextTag();
accountHandle = sPhoneAccountHandleXml.readFromXml(parser, version,
- context);
+ context, telephonyFeatureFlags);
} else if (parser.getName().equals(ADDRESS)) {
parser.next();
address = Uri.parse(parser.getText());
@@ -2506,6 +2600,12 @@
} else if (parser.getName().equals(SUPPORTED_AUDIO_ROUTES)) {
parser.next();
supportedAudioRoutes = Integer.parseInt(parser.getText());
+ } else if (parser.getName().equals(SIMULTANEOUS_CALLING_RESTRICTION)) {
+ // We can not flag this because we always need to handle the case where
+ // this info is in the XML for parsing reasons. We only flag setting the
+ // parsed value below based on the flag.
+ simultaneousCallingRestriction = readPhoneAccountHandleSet(parser, version,
+ context, telephonyFeatureFlags);
}
}
@@ -2587,6 +2687,9 @@
} else if (!TextUtils.isEmpty(iconPackageName)) {
builder.setIcon(Icon.createWithResource(iconPackageName, iconResId));
// TODO: Need to set tint.
+ } else if (simultaneousCallingRestriction != null
+ && telephonyFeatureFlags.simultaneousCallingIndications()) {
+ builder.setSimultaneousCallingRestriction(simultaneousCallingRestriction);
}
return builder.build();
@@ -2618,8 +2721,8 @@
private static final String USER_SERIAL_NUMBER = "user_serial_number";
@Override
- public void writeToXml(PhoneAccountHandle o, XmlSerializer serializer, Context context)
- throws IOException {
+ public void writeToXml(PhoneAccountHandle o, XmlSerializer serializer, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException {
if (o != null) {
serializer.startTag(null, CLASS_PHONE_ACCOUNT_HANDLE);
@@ -2641,8 +2744,8 @@
}
@Override
- public PhoneAccountHandle readFromXml(XmlPullParser parser, int version, Context context)
- throws IOException, XmlPullParserException {
+ public PhoneAccountHandle readFromXml(XmlPullParser parser, int version, Context context,
+ FeatureFlags telephonyFeatureFlags) throws IOException, XmlPullParserException {
if (parser.getName().equals(CLASS_PHONE_ACCOUNT_HANDLE)) {
String componentNameString = null;
String idString = null;
@@ -2682,8 +2785,4 @@
return null;
}
};
-
- private String nullToEmpty(String str) {
- return str == null ? "" : str;
- }
}
diff --git a/src/com/android/server/telecom/TelecomServiceImpl.java b/src/com/android/server/telecom/TelecomServiceImpl.java
index 61fa9ba..b954588 100644
--- a/src/com/android/server/telecom/TelecomServiceImpl.java
+++ b/src/com/android/server/telecom/TelecomServiceImpl.java
@@ -1994,8 +1994,12 @@
if (args != null && args.length > 0 && Analytics.ANALYTICS_DUMPSYS_ARG.equals(
args[0])) {
- Binder.withCleanCallingIdentity(() ->
- Analytics.dumpToEncodedProto(mContext, writer, args));
+ long token = Binder.clearCallingIdentity();
+ try {
+ Analytics.dumpToEncodedProto(mContext, writer, args);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
return;
}
@@ -2243,7 +2247,8 @@
try {
synchronized (mLock) {
enforceShellOnly(Binder.getCallingUid(), "cleanupStuckCalls");
- Binder.withCleanCallingIdentity(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
Set<UserHandle> userHandles = new HashSet<>();
for (Call call : mCallsManager.getCalls()) {
call.cleanup();
@@ -2256,7 +2261,9 @@
for (UserHandle userHandle : userHandles) {
mCallsManager.getInCallController().unbindFromServices(userHandle);
}
- });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
} finally {
Log.endSession();
@@ -2333,11 +2340,14 @@
try {
synchronized (mLock) {
enforceShellOnly(Binder.getCallingUid(), "resetCarMode");
- Binder.withCleanCallingIdentity(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
UiModeManager uiModeManager =
mContext.getSystemService(UiModeManager.class);
uiModeManager.disableCarMode(UiModeManager.DISABLE_CAR_MODE_ALL_PRIORITIES);
- });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
}
} finally {
Log.endSession();
@@ -2500,19 +2510,18 @@
*/
@Override
public boolean isInSelfManagedCall(String packageName, UserHandle userHandle,
- String callingPackage) {
+ String callingPackage, boolean hasCrossUserAccess) {
try {
- if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("Only the system can call this API");
- }
mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE,
"READ_PRIVILEGED_PHONE_STATE required.");
+ enforceInAppCrossUserPermission();
Log.startSession("TSI.iISMC", Log.getPackageAbbreviation(callingPackage));
synchronized (mLock) {
long token = Binder.clearCallingIdentity();
try {
- return mCallsManager.isInSelfManagedCall(packageName, userHandle);
+ return mCallsManager.isInSelfManagedCallCrossUsers(
+ packageName, userHandle, hasCrossUserAccess);
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/src/com/android/server/telecom/TelecomSystem.java b/src/com/android/server/telecom/TelecomSystem.java
index 4310945..9f6fcba 100644
--- a/src/com/android/server/telecom/TelecomSystem.java
+++ b/src/com/android/server/telecom/TelecomSystem.java
@@ -141,6 +141,7 @@
private final TelecomServiceImpl mTelecomServiceImpl;
private final ContactsAsyncHelper mContactsAsyncHelper;
private final DialerCodeReceiver mDialerCodeReceiver;
+ private final FeatureFlags mFeatureFlags;
private boolean mIsBootComplete = false;
@@ -231,6 +232,7 @@
BlockedNumbersAdapter blockedNumbersAdapter,
FeatureFlags featureFlags) {
mContext = context.getApplicationContext();
+ mFeatureFlags = featureFlags;
LogUtils.initLogging(mContext);
android.telecom.Log.setLock(mLock);
AnomalyReporter.initialize(mContext);
@@ -347,14 +349,22 @@
ToastFactory toastFactory = new ToastFactory() {
@Override
public Toast makeText(Context context, int resId, int duration) {
- return Toast.makeText(context, context.getMainLooper(),
- context.getString(resId),
- duration);
+ if (mFeatureFlags.telecomResolveHiddenDependencies()) {
+ return Toast.makeText(context, resId, duration);
+ } else {
+ return Toast.makeText(context, context.getMainLooper(),
+ context.getString(resId),
+ duration);
+ }
}
@Override
public Toast makeText(Context context, CharSequence text, int duration) {
- return Toast.makeText(context, context.getMainLooper(), text, duration);
+ if (mFeatureFlags.telecomResolveHiddenDependencies()) {
+ return Toast.makeText(context, text, duration);
+ } else {
+ return Toast.makeText(context, context.getMainLooper(), text, duration);
+ }
}
};
diff --git a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
index 2d10f40..0ce5836 100644
--- a/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
+++ b/tests/src/com/android/server/telecom/tests/PhoneAccountRegistrarTest.java
@@ -26,7 +26,9 @@
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -62,6 +64,7 @@
import androidx.test.filters.SmallTest;
import com.android.internal.telecom.IConnectionService;
+import com.android.internal.telephony.flags.FeatureFlags;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.telecom.AppLabelProxy;
import com.android.server.telecom.DefaultDialerCache;
@@ -90,6 +93,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -115,7 +119,7 @@
@Mock private TelecomManager mTelecomManager;
@Mock private DefaultDialerCache mDefaultDialerCache;
@Mock private AppLabelProxy mAppLabelProxy;
- @Mock private com.android.internal.telephony.flags.FeatureFlags mTelephonyFeatureFlags;
+ @Mock private FeatureFlags mTelephonyFeatureFlags;
@Override
@Before
@@ -155,12 +159,12 @@
public void testPhoneAccountHandle() throws Exception {
PhoneAccountHandle input = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), "id0");
PhoneAccountHandle result = roundTripXml(this, input,
- PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
+ PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext, mTelephonyFeatureFlags);
assertPhoneAccountHandleEquals(input, result);
PhoneAccountHandle inputN = new PhoneAccountHandle(new ComponentName("pkg0", "cls0"), null);
PhoneAccountHandle resultN = roundTripXml(this, inputN,
- PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext);
+ PhoneAccountRegistrar.sPhoneAccountHandleXml, mContext, mTelephonyFeatureFlags);
Log.i(this, "inputN = %s, resultN = %s", inputN, resultN);
assertPhoneAccountHandleEquals(inputN, resultN);
}
@@ -183,7 +187,112 @@
.setIsEnabled(true)
.build();
PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
- mContext);
+ mContext, mTelephonyFeatureFlags);
+
+ assertPhoneAccountEquals(input, result);
+ }
+
+ @MediumTest
+ @Test
+ public void testPhoneAccountParsing_simultaneousCallingRestriction() throws Exception {
+ doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ // workaround: UserManager converts the user to a serial and back, we need to mock this
+ // behavior, unfortunately: USER_HANDLE_10 <-> 10L
+ UserManager userManager = UserManager.get(mContext);
+ doReturn(10L).when(userManager).getSerialNumberForUser(eq(USER_HANDLE_10));
+ doReturn(USER_HANDLE_10).when(userManager).getUserForSerialNumber(eq(10L));
+ Bundle testBundle = new Bundle();
+ testBundle.putInt("EXTRA_INT_1", 1);
+ testBundle.putInt("EXTRA_INT_100", 100);
+ testBundle.putBoolean("EXTRA_BOOL_TRUE", true);
+ testBundle.putBoolean("EXTRA_BOOL_FALSE", false);
+ testBundle.putString("EXTRA_STR1", "Hello");
+ testBundle.putString("EXTRA_STR2", "There");
+
+ Set<PhoneAccountHandle> restriction = new HashSet<>(10);
+ for (int i = 0; i < 10; i++) {
+ restriction.add(makeQuickAccountHandleForUser("id" + i, USER_HANDLE_10));
+ }
+
+ PhoneAccount input = makeQuickAccountBuilder("id0", 0, USER_HANDLE_10)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
+ .setExtras(testBundle)
+ .setIsEnabled(true)
+ .setSimultaneousCallingRestriction(restriction)
+ .build();
+ PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
+ mContext, mTelephonyFeatureFlags);
+
+ assertPhoneAccountEquals(input, result);
+ }
+
+ @MediumTest
+ @Test
+ public void testPhoneAccountParsing_simultaneousCallingRestrictionOnOffFlag() throws Exception {
+ // Start the test with the flag on
+ doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ // workaround: UserManager converts the user to a serial and back, we need to mock this
+ // behavior, unfortunately: USER_HANDLE_10 <-> 10L
+ UserManager userManager = UserManager.get(mContext);
+ doReturn(10L).when(userManager).getSerialNumberForUser(eq(USER_HANDLE_10));
+ doReturn(USER_HANDLE_10).when(userManager).getUserForSerialNumber(eq(10L));
+ Bundle testBundle = new Bundle();
+ testBundle.putInt("EXTRA_INT_1", 1);
+ testBundle.putInt("EXTRA_INT_100", 100);
+ testBundle.putBoolean("EXTRA_BOOL_TRUE", true);
+ testBundle.putBoolean("EXTRA_BOOL_FALSE", false);
+ testBundle.putString("EXTRA_STR1", "Hello");
+ testBundle.putString("EXTRA_STR2", "There");
+
+ Set<PhoneAccountHandle> restriction = new HashSet<>(10);
+ for (int i = 0; i < 10; i++) {
+ restriction.add(makeQuickAccountHandleForUser("id" + i, USER_HANDLE_10));
+ }
+
+ PhoneAccount input = makeQuickAccountBuilder("id0", 0, USER_HANDLE_10)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
+ .setExtras(testBundle)
+ .setIsEnabled(true)
+ .setSimultaneousCallingRestriction(restriction)
+ .build();
+ byte[] xmlData = toXml(input, PhoneAccountRegistrar.sPhoneAccountXml, mContext,
+ mTelephonyFeatureFlags);
+ // Simulate turning off the flag after reboot
+ doReturn(false).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ PhoneAccount result = fromXml(xmlData, PhoneAccountRegistrar.sPhoneAccountXml, mContext,
+ mTelephonyFeatureFlags);
+
+ assertNotNull(result);
+ assertFalse(result.hasSimultaneousCallingRestriction());
+ }
+
+ @MediumTest
+ @Test
+ public void testPhoneAccountParsing_simultaneousCallingRestrictionOffOnFlag() throws Exception {
+ // Start the test with the flag on
+ doReturn(false).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ Bundle testBundle = new Bundle();
+ testBundle.putInt("EXTRA_INT_1", 1);
+ testBundle.putInt("EXTRA_INT_100", 100);
+ testBundle.putBoolean("EXTRA_BOOL_TRUE", true);
+ testBundle.putBoolean("EXTRA_BOOL_FALSE", false);
+ testBundle.putString("EXTRA_STR1", "Hello");
+ testBundle.putString("EXTRA_STR2", "There");
+
+ PhoneAccount input = makeQuickAccountBuilder("id0", 0, USER_HANDLE_10)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_TEL)
+ .addSupportedUriScheme(PhoneAccount.SCHEME_VOICEMAIL)
+ .setExtras(testBundle)
+ .setIsEnabled(true)
+ .build();
+ byte[] xmlData = toXml(input, PhoneAccountRegistrar.sPhoneAccountXml, mContext,
+ mTelephonyFeatureFlags);
+ // Simulate turning on the flag after reboot
+ doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ PhoneAccount result = fromXml(xmlData, PhoneAccountRegistrar.sPhoneAccountXml, mContext,
+ mTelephonyFeatureFlags);
assertPhoneAccountEquals(input, result);
}
@@ -260,7 +369,8 @@
when(UserManager.get(mContext).getUserForSerialNumber(0L))
.thenReturn(input.userHandle);
DefaultPhoneAccountHandle result = roundTripXml(this, input,
- PhoneAccountRegistrar.sDefaultPhoneAcountHandleXml, mContext);
+ PhoneAccountRegistrar.sDefaultPhoneAccountHandleXml, mContext,
+ mTelephonyFeatureFlags);
assertDefaultPhoneAccountHandleEquals(input, result);
}
@@ -290,7 +400,7 @@
.setExtras(testBundle)
.build();
PhoneAccount result = roundTripXml(this, input, PhoneAccountRegistrar.sPhoneAccountXml,
- mContext);
+ mContext, mTelephonyFeatureFlags);
Bundle extras = result.getExtras();
assertFalse(extras.keySet().contains("EXTRA_STR2"));
@@ -304,8 +414,7 @@
public void testState() throws Exception {
PhoneAccountRegistrar.State input = makeQuickState();
PhoneAccountRegistrar.State result = roundTripXml(this, input,
- PhoneAccountRegistrar.sStateXml,
- mContext);
+ PhoneAccountRegistrar.sStateXml, mContext, mTelephonyFeatureFlags);
assertStateEquals(input, result);
}
@@ -1625,6 +1734,107 @@
}
/**
+ * Ensure an IllegalArgumentException is thrown when adding too many PhoneAccountHandles to
+ * a PhoneAccount.
+ */
+ @Test
+ public void testLimitOnSimultaneousCallingRestriction_tooManyElements() throws Exception {
+ doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+ Set<PhoneAccountHandle> tooManyElements = new HashSet<>(11);
+ for (int i = 0; i < 11; i++) {
+ tooManyElements.add(makeQuickAccountHandle(TEST_ID + i));
+ }
+ PhoneAccount tooManyRestrictionsPA = new PhoneAccount.Builder(
+ makeQuickAccountHandle(TEST_ID), TEST_LABEL)
+ .setSimultaneousCallingRestriction(tooManyElements)
+ .build();
+ try {
+ mRegistrar.registerPhoneAccount(tooManyRestrictionsPA);
+ fail("should have hit registrations exception in "
+ + "enforceSimultaneousCallingRestrictionLimit");
+ } catch (IllegalArgumentException e) {
+ // pass test
+ }
+ }
+
+ /**
+ * Ensure an IllegalArgumentException is thrown when adding a PhoneAccountHandle where the
+ * package name field is too large.
+ */
+ @Test
+ public void testLimitOnSimultaneousCallingRestriction_InvalidPackageName() throws Exception {
+ doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+ Set<PhoneAccountHandle> invalidElement = new HashSet<>(1);
+ invalidElement.add(new PhoneAccountHandle(new ComponentName(INVALID_STR, "Class"),
+ TEST_ID));
+ PhoneAccount invalidRestrictionPA = new PhoneAccount.Builder(
+ makeQuickAccountHandle(TEST_ID), TEST_LABEL)
+ .setSimultaneousCallingRestriction(invalidElement)
+ .build();
+ try {
+ mRegistrar.registerPhoneAccount(invalidRestrictionPA);
+ fail("should have hit package name size limit exception in "
+ + "enforceSimultaneousCallingRestrictionLimit");
+ } catch (IllegalArgumentException e) {
+ // pass test
+ }
+ }
+
+ /**
+ * Ensure an IllegalArgumentException is thrown when adding a PhoneAccountHandle where the
+ * class name field is too large.
+ */
+ @Test
+ public void testLimitOnSimultaneousCallingRestriction_InvalidClassName() throws Exception {
+ doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+ Set<PhoneAccountHandle> invalidElement = new HashSet<>(1);
+ invalidElement.add(new PhoneAccountHandle(new ComponentName("pkg", INVALID_STR),
+ TEST_ID));
+ PhoneAccount invalidRestrictionPA = new PhoneAccount.Builder(
+ makeQuickAccountHandle(TEST_ID), TEST_LABEL)
+ .setSimultaneousCallingRestriction(invalidElement)
+ .build();
+ try {
+ mRegistrar.registerPhoneAccount(invalidRestrictionPA);
+ fail("should have hit class name size limit exception in "
+ + "enforceSimultaneousCallingRestrictionLimit");
+ } catch (IllegalArgumentException e) {
+ // pass test
+ }
+ }
+
+ /**
+ * Ensure an IllegalArgumentException is thrown when adding a PhoneAccountHandle where the
+ * ID field is too large.
+ */
+ @Test
+ public void testLimitOnSimultaneousCallingRestriction_InvalidIdSize() throws Exception {
+ doReturn(true).when(mTelephonyFeatureFlags).simultaneousCallingIndications();
+ mComponentContextFixture.addConnectionService(makeQuickConnectionServiceComponentName(),
+ Mockito.mock(IConnectionService.class));
+ Set<PhoneAccountHandle> invalidIdElement = new HashSet<>(1);
+ invalidIdElement.add(new PhoneAccountHandle(makeQuickConnectionServiceComponentName(),
+ INVALID_STR));
+ PhoneAccount invalidRestrictionPA = new PhoneAccount.Builder(
+ makeQuickAccountHandle(TEST_ID), TEST_LABEL)
+ .setSimultaneousCallingRestriction(invalidIdElement)
+ .build();
+ try {
+ mRegistrar.registerPhoneAccount(invalidRestrictionPA);
+ fail("should have hit ID size limit exception in "
+ + "enforceSimultaneousCallingRestrictionLimit");
+ } catch (IllegalArgumentException e) {
+ // pass test
+ }
+ }
+
+ /**
* Ensure an IllegalArgumentException is thrown when adding an address over the limit
*/
@Test
@@ -1869,35 +2079,41 @@
Object self,
T input,
PhoneAccountRegistrar.XmlSerialization<T> xml,
- Context context)
+ Context context,
+ FeatureFlags telephonyFeatureFlags)
throws Exception {
Log.d(self, "Input = %s", input);
- byte[] data;
- {
- XmlSerializer serializer = new FastXmlSerializer();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
- serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
- xml.writeToXml(input, serializer, context);
- serializer.flush();
- data = baos.toByteArray();
- }
+ byte[] data = toXml(input, xml, context, telephonyFeatureFlags);
Log.i(self, "====== XML data ======\n%s", new String(data));
- T result = null;
- {
- XmlPullParser parser = Xml.newPullParser();
- parser.setInput(new BufferedInputStream(new ByteArrayInputStream(data)), null);
- parser.nextTag();
- result = xml.readFromXml(parser, MAX_VERSION, context);
- }
+ T result = fromXml(data, xml, context, telephonyFeatureFlags);
Log.i(self, "result = " + result);
return result;
}
+ private static <T> byte[] toXml(T input, PhoneAccountRegistrar.XmlSerialization<T> xml,
+ Context context, FeatureFlags telephonyFeatureFlags) throws Exception {
+ XmlSerializer serializer = new FastXmlSerializer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+ xml.writeToXml(input, serializer, context, telephonyFeatureFlags);
+ serializer.flush();
+ return baos.toByteArray();
+ }
+
+ private static <T> T fromXml(byte[] data, PhoneAccountRegistrar.XmlSerialization<T> xml,
+ Context context, FeatureFlags telephonyFeatureFlags) throws Exception {
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setInput(new BufferedInputStream(new ByteArrayInputStream(data)), null);
+ parser.nextTag();
+ return xml.readFromXml(parser, MAX_VERSION, context, telephonyFeatureFlags);
+
+ }
+
private static void assertPhoneAccountHandleEquals(PhoneAccountHandle a, PhoneAccountHandle b) {
if (a != b) {
assertEquals(
@@ -1946,6 +2162,12 @@
assertEquals(a.getSupportedUriSchemes(), b.getSupportedUriSchemes());
assertBundlesEqual(a.getExtras(), b.getExtras());
assertEquals(a.isEnabled(), b.isEnabled());
+ assertEquals(a.hasSimultaneousCallingRestriction(),
+ b.hasSimultaneousCallingRestriction());
+ if (a.hasSimultaneousCallingRestriction()) {
+ assertEquals(a.getSimultaneousCallingRestriction(),
+ b.getSimultaneousCallingRestriction());
+ }
} else {
fail("Phone accounts not equal: " + a + ", " + b);
}