Improve Wi-Fi wiring
Bug: 16552606
Change-Id: Iddbde3d18e92ad1d40fb539d9177df582f317a7b
diff --git a/src/com/android/telecomm/PhoneAccountRegistrar.java b/src/com/android/telecomm/PhoneAccountRegistrar.java
index 4c781de..f236f58 100644
--- a/src/com/android/telecomm/PhoneAccountRegistrar.java
+++ b/src/com/android/telecomm/PhoneAccountRegistrar.java
@@ -49,50 +49,47 @@
private static final String PREFERENCE_PHONE_ACCOUNTS = "phone_accounts";
private final Context mContext;
+ private final State mState;
PhoneAccountRegistrar(Context context) {
mContext = context;
+ mState = readState();
}
public PhoneAccountHandle getDefaultOutgoingPhoneAccount() {
- State s = read();
-
- if (s.defaultOutgoingHandle != null) {
+ if (mState.defaultOutgoing != null) {
// Return the registered outgoing default iff it still exists (we keep a sticky
// default to survive account deletion and re-addition)
- for (int i = 0; i < s.accounts.size(); i++) {
- if (s.accounts.get(i).getAccountHandle().equals(s.defaultOutgoingHandle)) {
- return s.defaultOutgoingHandle;
+ for (int i = 0; i < mState.accounts.size(); i++) {
+ if (mState.accounts.get(i).getAccountHandle().equals(mState.defaultOutgoing)) {
+ return mState.defaultOutgoing;
}
}
- // At this point, there was a registered default but it has been deleted; remember
- // it for the future, but return null from this method
- return null;
- } else {
- List<PhoneAccountHandle> enabled = getEnabledPhoneAccounts();
- switch (enabled.size()) {
- case 0:
- // There are no accounts, so there can be no default
- return null;
- case 1:
- // There is only one account, which is by definition the default
- return enabled.get(0);
- default:
- // There are multiple accounts with no selected default
- return null;
- }
+ // At this point, there was a registered default but it has been deleted; proceed
+ // as though there were no default
+ }
+
+ List<PhoneAccountHandle> enabled = getEnabledPhoneAccounts();
+ switch (enabled.size()) {
+ case 0:
+ // There are no accounts, so there can be no default
+ return null;
+ case 1:
+ // There is only one account, which is by definition the default
+ return enabled.get(0);
+ default:
+ // There are multiple accounts with no selected default
+ return null;
}
}
public void setDefaultOutgoingPhoneAccount(PhoneAccountHandle accountHandle) {
- State s = read();
-
if (accountHandle == null) {
// Asking to clear the default outgoing is a valid request
- s.defaultOutgoingHandle = null;
+ mState.defaultOutgoing = null;
} else {
boolean found = false;
- for (PhoneAccount m : s.accounts) {
+ for (PhoneAccount m : mState.accounts) {
if (Objects.equals(accountHandle, m.getAccountHandle())) {
found = true;
break;
@@ -105,21 +102,51 @@
return;
}
- s.defaultOutgoingHandle = accountHandle;
+ mState.defaultOutgoing = accountHandle;
}
- write(s);
+ write();
}
+ public void setSimCallManager(PhoneAccountHandle callManager) {
+ if (callManager != null) {
+ PhoneAccount callManagerAccount = getPhoneAccount(callManager);
+ if (callManagerAccount == null) {
+ Log.d(this, "setSimCallManager: Nonexistent call manager: %s", callManager);
+ return;
+ } else if (!has(callManagerAccount, PhoneAccount.CAPABILITY_SIM_CALL_MANAGER)) {
+ Log.d(this, "setSimCallManager: Not a call manager: %s", callManagerAccount);
+ return;
+ }
+ }
+ mState.simCallManager = callManager;
+ write();
+ }
+
+ public PhoneAccountHandle getSimCallManager() {
+ return mState.simCallManager;
+ }
+
+ public List<PhoneAccountHandle> getAllPhoneAccountHandles() {
+ List<PhoneAccountHandle> accountHandles = new ArrayList<>();
+ for (PhoneAccount m : mState.accounts) {
+ accountHandles.add(m.getAccountHandle());
+ }
+ return accountHandles;
+ }
+
+ public List<PhoneAccount> getAllPhoneAccounts() {
+ return new ArrayList<>(mState.accounts);
+ }
+
+ // TODO: Rename systemwide to "getCallProviderPhoneAccounts"?
public List<PhoneAccountHandle> getEnabledPhoneAccounts() {
- State s = read();
- return simSubscriptionAccountHandles(s);
+ return getCallProviderAccountHandles();
}
- public PhoneAccount getPhoneAccount(PhoneAccountHandle accountHandle) {
- State s = read();
- for (PhoneAccount m : s.accounts) {
- if (Objects.equals(accountHandle, m.getAccountHandle())) {
+ public PhoneAccount getPhoneAccount(PhoneAccountHandle handle) {
+ for (PhoneAccount m : mState.accounts) {
+ if (Objects.equals(handle, m.getAccountHandle())) {
return m;
}
}
@@ -128,60 +155,112 @@
// TODO: Should we implement an artificial limit for # of accounts associated with a single
// ComponentName?
- public void registerPhoneAccount(PhoneAccount metadata) {
- State s = read();
-
- s.accounts.add(metadata);
+ public void registerPhoneAccount(PhoneAccount account) {
+ account = hackFixBabelAccount(account);
+ mState.accounts.add(account);
// Search for duplicates and remove any that are found.
- for (int i = 0; i < s.accounts.size() - 1; i++) {
- if (Objects.equals(metadata.getAccountHandle(), s.accounts.get(i).getAccountHandle())) {
+ for (int i = 0; i < mState.accounts.size() - 1; i++) {
+ if (Objects.equals(
+ account.getAccountHandle(), mState.accounts.get(i).getAccountHandle())) {
// replace existing entry.
- s.accounts.remove(i);
+ mState.accounts.remove(i);
break;
}
}
- write(s);
+ write();
+ }
+
+ // STOPSHIP: Hack to edit the account registered by Babel so it shows up properly
+ private PhoneAccount hackFixBabelAccount(PhoneAccount account) {
+ String pkg = account.getAccountHandle().getComponentName().getPackageName();
+ return "com.google.android.talk".equals(pkg)
+ ? new PhoneAccount(
+ account.getAccountHandle(),
+ account.getHandle(),
+ account.getSubscriptionNumber(),
+ PhoneAccount.CAPABILITY_SIM_CALL_MANAGER,
+ account.getIconResId(),
+ account.getLabel(),
+ account.getShortDescription(),
+ account.isVideoCallingSupported())
+ : account;
}
public void unregisterPhoneAccount(PhoneAccountHandle accountHandle) {
- State s = read();
-
- for (int i = 0; i < s.accounts.size(); i++) {
- if (Objects.equals(accountHandle, s.accounts.get(i).getAccountHandle())) {
- s.accounts.remove(i);
+ for (int i = 0; i < mState.accounts.size(); i++) {
+ if (Objects.equals(accountHandle, mState.accounts.get(i).getAccountHandle())) {
+ mState.accounts.remove(i);
break;
}
}
- write(s);
+ write();
}
public void clearAccounts(String packageName) {
- State s = read();
-
- for (int i = 0; i < s.accounts.size(); i++) {
+ for (int i = 0; i < mState.accounts.size(); i++) {
if (Objects.equals(
packageName,
- s.accounts.get(i).getAccountHandle().getComponentName().getPackageName())) {
- s.accounts.remove(i);
+ mState.accounts.get(i).getAccountHandle()
+ .getComponentName().getPackageName())) {
+ mState.accounts.remove(i);
}
}
- write(s);
+ write();
}
- private List<PhoneAccountHandle> simSubscriptionAccountHandles(State s) {
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+
+ // TODO: Add a corresponding has(...) method to class PhoneAccount itself and remove this one
+ // Return true iff the given account has all the specified capability flags
+ static boolean has(PhoneAccount account, int capability) {
+ return (account.getCapabilities() & capability) == capability;
+ }
+
+ private List<PhoneAccountHandle> getCallProviderAccountHandles() {
List<PhoneAccountHandle> accountHandles = new ArrayList<>();
- for (PhoneAccount m : s.accounts) {
- if ((m.getCapabilities() & PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0) {
+ for (PhoneAccount m : mState.accounts) {
+ if (has(m, PhoneAccount.CAPABILITY_CALL_PROVIDER)) {
accountHandles.add(m.getAccountHandle());
}
}
return accountHandles;
}
- private State read() {
+ /**
+ * The state of this {@code PhoneAccountRegistrar}.
+ */
+ private static class State {
+ /**
+ * The account selected by the user to be employed by default for making outgoing calls.
+ * If the user has not made such a selection, then this is null.
+ */
+ public PhoneAccountHandle defaultOutgoing = null;
+
+ /**
+ * A {@code PhoneAccount} having {@link PhoneAccount#CAPABILITY_SIM_CALL_MANAGER} which
+ * manages and optimizes a user's PSTN SIM connections.
+ */
+ public PhoneAccountHandle simCallManager;
+
+ /**
+ * The complete list of {@code PhoneAccount}s known to the Telecomm subsystem.
+ */
+ public final List<PhoneAccount> accounts = new ArrayList<>();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // State management
+ //
+
+ private void write() {
+ writeState(mState);
+ }
+
+ private State readState() {
try {
String serialized = getPreferences().getString(PREFERENCE_PHONE_ACCOUNTS, null);
Log.v(this, "read() obtained serialized state: %s", serialized);
@@ -196,7 +275,7 @@
}
}
- private boolean write(State state) {
+ private boolean writeState(State state) {
try {
Log.v(this, "write() writing state: %s", state);
String serialized = serializeState(state);
@@ -226,11 +305,7 @@
return sStateJson.fromJson(new JSONObject(new JSONTokener(s)));
}
- private static class State {
- public PhoneAccountHandle defaultOutgoingHandle = null;
- public final List<PhoneAccount> accounts = new ArrayList<>();
- }
-
+ ////////////////////////////////////////////////////////////////////////////////////////////////
//
// JSON serialization
//
@@ -243,17 +318,21 @@
private static final Json<State> sStateJson =
new Json<State>() {
private static final String DEFAULT_OUTGOING = "default_outgoing";
+ private static final String SIM_CALL_MANAGER = "sim_call_manager";
private static final String ACCOUNTS = "accounts";
@Override
public JSONObject toJson(State o) throws JSONException {
JSONObject json = new JSONObject();
- if (o.defaultOutgoingHandle != null) {
- json.put(DEFAULT_OUTGOING, sPhoneAccountJson.toJson(o.defaultOutgoingHandle));
+ if (o.defaultOutgoing != null) {
+ json.put(DEFAULT_OUTGOING, sPhoneAccountHandleJson.toJson(o.defaultOutgoing));
+ }
+ if (o.simCallManager != null) {
+ json.put(SIM_CALL_MANAGER, sPhoneAccountHandleJson.toJson(o.simCallManager));
}
JSONArray accounts = new JSONArray();
for (PhoneAccount m : o.accounts) {
- accounts.put(sPhoneAccountMetadataJson.toJson(m));
+ accounts.put(sPhoneAccountJson.toJson(m));
}
json.put(ACCOUNTS, accounts);
return json;
@@ -263,14 +342,26 @@
public State fromJson(JSONObject json) throws JSONException {
State s = new State();
if (json.has(DEFAULT_OUTGOING)) {
- s.defaultOutgoingHandle = sPhoneAccountJson.fromJson(
- (JSONObject) json.get(DEFAULT_OUTGOING));
+ try {
+ s.defaultOutgoing = sPhoneAccountHandleJson.fromJson(
+ (JSONObject) json.get(DEFAULT_OUTGOING));
+ } catch (Exception e) {
+ Log.e(this, e, "Extracting PhoneAccountHandle");
+ }
+ }
+ if (json.has(SIM_CALL_MANAGER)) {
+ try {
+ s.simCallManager = sPhoneAccountHandleJson.fromJson(
+ (JSONObject) json.get(SIM_CALL_MANAGER));
+ } catch (Exception e) {
+ Log.e(this, e, "Extracting PhoneAccountHandle");
+ }
}
if (json.has(ACCOUNTS)) {
JSONArray accounts = (JSONArray) json.get(ACCOUNTS);
for (int i = 0; i < accounts.length(); i++) {
try {
- s.accounts.add(sPhoneAccountMetadataJson.fromJson(
+ s.accounts.add(sPhoneAccountJson.fromJson(
(JSONObject) accounts.get(i)));
} catch (Exception e) {
Log.e(this, e, "Extracting phone account");
@@ -281,7 +372,7 @@
}
};
- private static final Json<PhoneAccount> sPhoneAccountMetadataJson =
+ private static final Json<PhoneAccount> sPhoneAccountJson =
new Json<PhoneAccount>() {
private static final String ACCOUNT = "account";
private static final String HANDLE = "handle";
@@ -295,7 +386,7 @@
@Override
public JSONObject toJson(PhoneAccount o) throws JSONException {
return new JSONObject()
- .put(ACCOUNT, sPhoneAccountJson.toJson(o.getAccountHandle()))
+ .put(ACCOUNT, sPhoneAccountHandleJson.toJson(o.getAccountHandle()))
.put(HANDLE, o.getHandle().toString())
.put(SUBSCRIPTION_NUMBER, o.getSubscriptionNumber())
.put(CAPABILITIES, o.getCapabilities())
@@ -308,7 +399,7 @@
@Override
public PhoneAccount fromJson(JSONObject json) throws JSONException {
return new PhoneAccount(
- sPhoneAccountJson.fromJson((JSONObject) json.get(ACCOUNT)),
+ sPhoneAccountHandleJson.fromJson((JSONObject) json.get(ACCOUNT)),
Uri.parse((String) json.get(HANDLE)),
(String) json.get(SUBSCRIPTION_NUMBER),
(int) json.get(CAPABILITIES),
@@ -319,7 +410,7 @@
}
};
- private static final Json<PhoneAccountHandle> sPhoneAccountJson =
+ private static final Json<PhoneAccountHandle> sPhoneAccountHandleJson =
new Json<PhoneAccountHandle>() {
private static final String COMPONENT_NAME = "component_name";
private static final String ID = "id";