diff options
9 files changed, 329 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index ad9fa40e0ab8..566ce4f48e25 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -36,6 +36,7 @@ import android.telephony.CellInfo; import android.telephony.CellLocation; import android.telephony.DisconnectCause; import android.telephony.LocationAccessPolicy; +import android.telephony.PhoneCapability; import android.telephony.PhoneStateListener; import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseCallState; @@ -47,7 +48,6 @@ import android.telephony.SignalStrength; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.VoLteServiceState; -import android.text.TextUtils; import android.util.LocalLog; import com.android.internal.app.IBatteryStats; @@ -200,6 +200,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { private boolean mCarrierNetworkChangeState = false; + private PhoneCapability mPhoneCapability = null; + private final LocalLog mLocalLog = new LocalLog(100); private PreciseDataConnectionState mPreciseDataConnectionState = @@ -658,6 +660,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { remove(r.binder); } } + if ((events & PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE) != 0) { + try { + r.callback.onPhoneCapabilityChanged(mPhoneCapability); + } catch (RemoteException ex) { + remove(r.binder); + } + } } } } else { @@ -1453,6 +1462,33 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } + public void notifyPhoneCapabilityChanged(PhoneCapability capability) { + if (!checkNotifyPermission("notifyPhoneCapabilityChanged()")) { + return; + } + + if (VDBG) { + log("notifyPhoneCapabilityChanged: capability=" + capability); + } + + synchronized (mRecords) { + mPhoneCapability = capability; + + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent( + PhoneStateListener.LISTEN_PHONE_CAPABILITY_CHANGE)) { + try { + r.callback.onPhoneCapabilityChanged(capability); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + handleRemoveListLocked(); + } + } + + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); @@ -1488,6 +1524,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { pw.println("mForegroundCallState=" + mForegroundCallState); pw.println("mBackgroundCallState=" + mBackgroundCallState); pw.println("mVoLteServiceState=" + mVoLteServiceState); + pw.println("mPhoneCapability=" + mPhoneCapability); pw.decreaseIndent(); diff --git a/telephony/java/android/telephony/ModemInfo.java b/telephony/java/android/telephony/ModemInfo.java new file mode 100644 index 000000000000..564effe05e38 --- /dev/null +++ b/telephony/java/android/telephony/ModemInfo.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Information of a single logical modem indicating + * its id, supported rats and whether it supports voice or data, etc. + * @hide + */ +public class ModemInfo implements Parcelable { + public final int modemId; + public final int rat; /* bitset */ + public final boolean isVoiceSupported; + public final boolean isDataSupported; + + public ModemInfo(int modemId, int rat, boolean isVoiceSupported, boolean isDataSupported) { + this.modemId = modemId; + this.rat = rat; + this.isVoiceSupported = isVoiceSupported; + this.isDataSupported = isDataSupported; + } + + public ModemInfo(Parcel in) { + modemId = in.readInt(); + rat = in.readInt(); + isVoiceSupported = in.readBoolean(); + isDataSupported = in.readBoolean(); + } + + @Override + public String toString() { + return "modemId=" + modemId + " rat=" + rat + " isVoiceSupported:" + isVoiceSupported + + " isDataSupported:" + isDataSupported; + } + + @Override + public int hashCode() { + return Objects.hash(modemId, rat, isVoiceSupported, isDataSupported); + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof ModemInfo) || hashCode() != o.hashCode()) { + return false; + } + + if (this == o) { + return true; + } + + ModemInfo s = (ModemInfo) o; + + return (modemId == s.modemId + && rat == s.rat + && isVoiceSupported == s.isVoiceSupported + && isDataSupported == s.isDataSupported); + } + + /** + * {@link Parcelable#describeContents} + */ + public @ContentsFlags int describeContents() { + return 0; + } + + /** + * {@link Parcelable#writeToParcel} + */ + public void writeToParcel(Parcel dest, @WriteFlags int flags) { + dest.writeInt(modemId); + dest.writeInt(rat); + dest.writeBoolean(isVoiceSupported); + dest.writeBoolean(isDataSupported); + } + + public static final Parcelable.Creator<ModemInfo> CREATOR = new Parcelable.Creator() { + public ModemInfo createFromParcel(Parcel in) { + return new ModemInfo(in); + } + + public ModemInfo[] newArray(int size) { + return new ModemInfo[size]; + } + }; +} diff --git a/telephony/java/android/telephony/PhoneCapability.aidl b/telephony/java/android/telephony/PhoneCapability.aidl new file mode 100644 index 000000000000..5de8d4a2c9e5 --- /dev/null +++ b/telephony/java/android/telephony/PhoneCapability.aidl @@ -0,0 +1,20 @@ +/* +** +** Copyright 2018, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +package android.telephony; + +parcelable PhoneCapability;
\ No newline at end of file diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java new file mode 100644 index 000000000000..2ebfa53ead23 --- /dev/null +++ b/telephony/java/android/telephony/PhoneCapability.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +/** + * Define capability of a modem group. That is, the capabilities + * are shared between those modems defined by list of modem IDs. + * @hide + */ +public class PhoneCapability implements Parcelable { + public final int maxActiveVoiceCalls; + public final int maxActiveData; + public final int max5G; + public final List<ModemInfo> logicalModemList; + + public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G, + List<ModemInfo> logicalModemList) { + this.maxActiveVoiceCalls = maxActiveVoiceCalls; + this.maxActiveData = maxActiveData; + this.max5G = max5G; + // Make sure it's not null. + this.logicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList; + } + + @Override + public String toString() { + return "maxActiveVoiceCalls=" + maxActiveVoiceCalls + " maxActiveData=" + maxActiveData + + " max5G=" + max5G + "logicalModemList:" + + Arrays.toString(logicalModemList.toArray()); + } + + private PhoneCapability(Parcel in) { + maxActiveVoiceCalls = in.readInt(); + maxActiveData = in.readInt(); + max5G = in.readInt(); + logicalModemList = new ArrayList<>(); + in.readList(logicalModemList, ModemInfo.class.getClassLoader()); + } + + @Override + public int hashCode() { + return Objects.hash(maxActiveVoiceCalls, maxActiveData, max5G, logicalModemList); + } + + @Override + public boolean equals(Object o) { + if (o == null || !(o instanceof PhoneCapability) || hashCode() != o.hashCode()) { + return false; + } + + if (this == o) { + return true; + } + + PhoneCapability s = (PhoneCapability) o; + + return (maxActiveVoiceCalls == s.maxActiveVoiceCalls + && maxActiveData == s.maxActiveData + && max5G == s.max5G + && logicalModemList.equals(s.logicalModemList)); + } + + /** + * {@link Parcelable#describeContents} + */ + public @Parcelable.ContentsFlags int describeContents() { + return 0; + } + + /** + * {@link Parcelable#writeToParcel} + */ + public void writeToParcel(Parcel dest, @Parcelable.WriteFlags int flags) { + dest.writeInt(maxActiveVoiceCalls); + dest.writeInt(maxActiveData); + dest.writeInt(max5G); + dest.writeList(logicalModemList); + } + + public static final Parcelable.Creator<PhoneCapability> CREATOR = new Parcelable.Creator() { + public PhoneCapability createFromParcel(Parcel in) { + return new PhoneCapability(in); + } + + public PhoneCapability[] newArray(int size) { + return new PhoneCapability[size]; + } + }; +} diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java index 7f7ce8e50735..bd6a59d7492c 100644 --- a/telephony/java/android/telephony/PhoneStateListener.java +++ b/telephony/java/android/telephony/PhoneStateListener.java @@ -22,12 +22,11 @@ import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Message; -import android.telecom.TelecomManager; import com.android.internal.telephony.IPhoneStateListener; -import java.util.List; import java.lang.ref.WeakReference; +import java.util.List; /** * A listener class for monitoring changes in specific telephony states @@ -273,6 +272,14 @@ public class PhoneStateListener { */ public static final int LISTEN_PHYSICAL_CHANNEL_CONFIGURATION = 0x00100000; + /** + * Listen for changes to the phone capability. + * + * @see #onPhoneCapabilityChanged + * @hide + */ + public static final int LISTEN_PHONE_CAPABILITY_CHANGE = 0x00200000; + /* * Subscription used to listen to the phone state changes * @hide @@ -395,6 +402,10 @@ public class PhoneStateListener { PhoneStateListener.this.onPhysicalChannelConfigurationChanged( (List<PhysicalChannelConfig>)msg.obj); break; + case LISTEN_PHONE_CAPABILITY_CHANGE: + PhoneStateListener.this.onPhoneCapabilityChanged( + (PhoneCapability) msg.obj); + break; } } }; @@ -625,6 +636,16 @@ public class PhoneStateListener { } /** + * Callback invoked when phone capability changes. Requires + * the READ_PRIVILEGED_PHONE_STATE permission. + * @param capability the new phone capability + * @hide + */ + public void onPhoneCapabilityChanged(PhoneCapability capability) { + // default implementation empty + } + + /** * Callback invoked when telephony has received notice from a carrier * app that a network action that could result in connectivity loss * has been requested by an app using @@ -751,6 +772,10 @@ public class PhoneStateListener { public void onPhysicalChannelConfigurationChanged(List<PhysicalChannelConfig> configs) { send(LISTEN_PHYSICAL_CHANNEL_CONFIGURATION, 0, 0, configs); } + + public void onPhoneCapabilityChanged(PhoneCapability capability) { + send(LISTEN_PHONE_CAPABILITY_CHANGE, 0, 0, capability); + } } @UnsupportedAppUsage diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 3a8dba81c984..81d0d68fd92f 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -8075,4 +8075,23 @@ public class TelephonyManager { } return UNKNOWN_CARRIER_ID_LIST_VERSION; } + + + /** + * How many modems can have simultaneous data connections. + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) + public int getNumberOfModemsWithSimultaneousDataConnections() { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.getNumberOfModemsWithSimultaneousDataConnections( + getSubId(), mContext.getOpPackageName()); + } + } catch (RemoteException ex) { + // This could happen if binder process crashes. + } + return 0; + } } diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl index 0d315e5e563e..1ebb6976b45e 100644 --- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl +++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl @@ -21,6 +21,7 @@ import android.telephony.ServiceState; import android.telephony.SignalStrength; import android.telephony.CellInfo; import android.telephony.DataConnectionRealTimeInfo; +import android.telephony.PhoneCapability; import android.telephony.PhysicalChannelConfig; import android.telephony.PreciseCallState; import android.telephony.PreciseDataConnectionState; @@ -50,5 +51,6 @@ oneway interface IPhoneStateListener { void onOemHookRawEvent(in byte[] rawData); void onCarrierNetworkChange(in boolean active); void onUserMobileDataStateChanged(in boolean enabled); + void onPhoneCapabilityChanged(in PhoneCapability capability); } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index f9c394000c83..c59a7395ebac 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1531,4 +1531,10 @@ interface ITelephony { * @hide */ void refreshUiccProfile(int subId); + + /** + * How many modems can have simultaneous data connections. + * @hide + */ + int getNumberOfModemsWithSimultaneousDataConnections(int subId, String callingPackage); } diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl index 0127db97963e..e0e1a7b87916 100644 --- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl @@ -21,6 +21,7 @@ import android.net.LinkProperties; import android.net.NetworkCapabilities; import android.os.Bundle; import android.telephony.CellInfo; +import android.telephony.PhoneCapability; import android.telephony.PhysicalChannelConfig; import android.telephony.ServiceState; import android.telephony.SignalStrength; @@ -74,4 +75,5 @@ interface ITelephonyRegistry { void notifySubscriptionInfoChanged(); void notifyCarrierNetworkChange(in boolean active); void notifyUserMobileDataStateChangedForPhoneId(in int phoneId, in int subId, in boolean state); + void notifyPhoneCapabilityChanged(in PhoneCapability capability); } |