Merge "Purge unused native memory before Zygote fork events"
diff --git a/Android.bp b/Android.bp
index 9a0d542..feaafa3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -551,7 +551,7 @@
genrule {
name: "framework-statslog-gen",
tools: ["stats-log-api-gen"],
- cmd: "$(location stats-log-api-gen) --java $(out)",
+ cmd: "$(location stats-log-api-gen) --java $(out) --worksource",
out: ["android/util/StatsLogInternal.java"],
}
@@ -660,6 +660,7 @@
"core/java/android/annotation/RequiresPermission.java",
"core/java/android/annotation/SystemApi.java",
"core/java/android/annotation/TestApi.java",
+ "core/java/com/android/internal/annotations/GuardedBy.java",
],
}
// Build ext.jar
diff --git a/api/system-current.txt b/api/system-current.txt
index fe90410..305d571 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4538,6 +4538,27 @@
field public final int netId;
}
+ public abstract class NetworkAgent {
+ method public void onAddKeepalivePacketFilter(int, @NonNull android.net.KeepalivePacketData);
+ method public void onAutomaticReconnectDisabled();
+ method public void onBandwidthUpdateRequested();
+ method public void onNetworkUnwanted();
+ method public void onRemoveKeepalivePacketFilter(int);
+ method public void onSaveAcceptUnvalidated(boolean);
+ method public void onSignalStrengthThresholdsUpdated(@NonNull int[]);
+ method public void onStartSocketKeepalive(int, int, @NonNull android.net.KeepalivePacketData);
+ method public void onStopSocketKeepalive(int);
+ method public void onValidationStatus(int, @Nullable String);
+ method public void sendLinkProperties(@NonNull android.net.LinkProperties);
+ method public void sendNetworkCapabilities(@NonNull android.net.NetworkCapabilities);
+ method public void sendNetworkScore(int);
+ method public void sendSocketKeepaliveEvent(int, int);
+ field public static final int VALIDATION_STATUS_NOT_VALID = 2; // 0x2
+ field public static final int VALIDATION_STATUS_VALID = 1; // 0x1
+ field @NonNull public final android.net.Network network;
+ field public final int providerId;
+ }
+
public final class NetworkAgentConfig implements android.os.Parcelable {
method public int describeContents();
method @Nullable public String getSubscriberId();
@@ -8411,6 +8432,27 @@
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
}
+ public final class CallForwardingInfo implements android.os.Parcelable {
+ ctor public CallForwardingInfo(int, int, @Nullable String, int);
+ method public int describeContents();
+ method @Nullable public String getNumber();
+ method public int getReason();
+ method public int getStatus();
+ method public int getTimeoutSeconds();
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallForwardingInfo> CREATOR;
+ field public static final int REASON_ALL = 4; // 0x4
+ field public static final int REASON_ALL_CONDITIONAL = 5; // 0x5
+ field public static final int REASON_BUSY = 1; // 0x1
+ field public static final int REASON_NOT_REACHABLE = 3; // 0x3
+ field public static final int REASON_NO_REPLY = 2; // 0x2
+ field public static final int REASON_UNCONDITIONAL = 0; // 0x0
+ field public static final int STATUS_ACTIVE = 1; // 0x1
+ field public static final int STATUS_FDN_CHECK_FAILURE = 2; // 0x2
+ field public static final int STATUS_INACTIVE = 0; // 0x0
+ field public static final int STATUS_NOT_SUPPORTED = 4; // 0x4
+ field public static final int STATUS_UNKNOWN_ERROR = 3; // 0x3
+ }
+
public final class CallQuality implements android.os.Parcelable {
ctor public CallQuality(int, int, int, int, int, int, int, int, int, int, int);
method public int describeContents();
@@ -9487,6 +9529,8 @@
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getAidForAppType(int);
method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.List<android.service.carrier.CarrierIdentifier> getAllowedCarriers(int);
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getAllowedNetworkTypes();
+ method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.CallForwardingInfo getCallForwarding(int);
+ method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getCallWaitingStatus();
method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntent(android.content.Intent);
method public java.util.List<java.lang.String> getCarrierPackageNamesForIntentAndPhone(android.content.Intent, int);
@@ -9567,6 +9611,8 @@
method @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setAllowedCarriers(int, java.util.List<android.service.carrier.CarrierIdentifier>);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setAllowedNetworkTypes(long);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setAlwaysReportSignalStrength(boolean);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallForwarding(@NonNull android.telephony.CallForwardingInfo);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public boolean setCallWaitingStatus(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCarrierDataEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public int setCarrierRestrictionRules(@NonNull android.telephony.CarrierRestrictionRules);
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setDataActivationState(int);
@@ -9598,6 +9644,10 @@
field public static final String ACTION_SIM_APPLICATION_STATE_CHANGED = "android.telephony.action.SIM_APPLICATION_STATE_CHANGED";
field public static final String ACTION_SIM_CARD_STATE_CHANGED = "android.telephony.action.SIM_CARD_STATE_CHANGED";
field public static final String ACTION_SIM_SLOT_STATUS_CHANGED = "android.telephony.action.SIM_SLOT_STATUS_CHANGED";
+ field public static final int CALL_WAITING_STATUS_ACTIVE = 1; // 0x1
+ field public static final int CALL_WAITING_STATUS_INACTIVE = 2; // 0x2
+ field public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4; // 0x4
+ field public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3; // 0x3
field public static final int CARD_POWER_DOWN = 0; // 0x0
field public static final int CARD_POWER_UP = 1; // 0x1
field public static final int CARD_POWER_UP_PASS_THROUGH = 2; // 0x2
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index c72e89b..88d94cc 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -75,9 +75,9 @@
// Pushed atoms start at 2.
oneof pushed {
// For StatsLog reasons, 1 is illegal and will not work. Must start at 2.
- BleScanStateChanged ble_scan_state_changed = 2;
+ BleScanStateChanged ble_scan_state_changed = 2 [(log_from_module) = "bluetooth"];
ProcessStateChanged process_state_changed = 3;
- BleScanResultReceived ble_scan_result_received = 4;
+ BleScanResultReceived ble_scan_result_received = 4 [(log_from_module) = "bluetooth"];
SensorStateChanged sensor_state_changed = 5;
GpsScanStateChanged gps_scan_state_changed = 6;
SyncStateChanged sync_state_changed = 7;
@@ -141,7 +141,8 @@
AppDied app_died = 65;
ResourceConfigurationChanged resource_configuration_changed = 66;
BluetoothEnabledStateChanged bluetooth_enabled_state_changed = 67;
- BluetoothConnectionStateChanged bluetooth_connection_state_changed = 68;
+ BluetoothConnectionStateChanged bluetooth_connection_state_changed =
+ 68 [(log_from_module) = "bluetooth"];
GpsSignalQualityChanged gps_signal_quality_changed = 69;
UsbConnectorStateChanged usb_connector_state_changed = 70;
SpeakerImpedanceReported speaker_impedance_reported = 71;
@@ -216,9 +217,12 @@
RescuePartyResetReported rescue_party_reset_reported = 122;
SignedConfigReported signed_config_reported = 123;
GnssNiEventReported gnss_ni_event_reported = 124;
- BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event = 125;
- BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed = 126;
- BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed = 127;
+ BluetoothLinkLayerConnectionEvent bluetooth_link_layer_connection_event =
+ 125 [(log_from_module) = "bluetooth"];
+ BluetoothAclConnectionStateChanged bluetooth_acl_connection_state_changed =
+ 126 [(log_from_module) = "bluetooth"];
+ BluetoothScoConnectionStateChanged bluetooth_sco_connection_state_changed =
+ 127 [(log_from_module) = "bluetooth"];
AppDowngraded app_downgraded = 128;
AppOptimizedAfterDowngraded app_optimized_after_downgraded = 129;
LowStorageStateChanged low_storage_state_changed = 130;
@@ -242,23 +246,40 @@
BiometricSystemHealthIssueDetected biometric_system_health_issue_detected = 148;
BubbleUIChanged bubble_ui_changed = 149;
ScheduledJobConstraintChanged scheduled_job_constraint_changed = 150;
- BluetoothActiveDeviceChanged bluetooth_active_device_changed = 151;
- BluetoothA2dpPlaybackStateChanged bluetooth_a2dp_playback_state_changed = 152;
- BluetoothA2dpCodecConfigChanged bluetooth_a2dp_codec_config_changed = 153;
- BluetoothA2dpCodecCapabilityChanged bluetooth_a2dp_codec_capability_changed = 154;
- BluetoothA2dpAudioUnderrunReported bluetooth_a2dp_audio_underrun_reported = 155;
- BluetoothA2dpAudioOverrunReported bluetooth_a2dp_audio_overrun_reported = 156;
- BluetoothDeviceRssiReported bluetooth_device_rssi_reported = 157;
- BluetoothDeviceFailedContactCounterReported bluetooth_device_failed_contact_counter_reported = 158;
- BluetoothDeviceTxPowerLevelReported bluetooth_device_tx_power_level_reported = 159;
- BluetoothHciTimeoutReported bluetooth_hci_timeout_reported = 160;
- BluetoothQualityReportReported bluetooth_quality_report_reported = 161;
- BluetoothDeviceInfoReported bluetooth_device_info_reported = 162;
- BluetoothRemoteVersionInfoReported bluetooth_remote_version_info_reported = 163;
- BluetoothSdpAttributeReported bluetooth_sdp_attribute_reported = 164;
- BluetoothBondStateChanged bluetooth_bond_state_changed = 165;
- BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported = 166;
- BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported = 167;
+ BluetoothActiveDeviceChanged bluetooth_active_device_changed =
+ 151 [(log_from_module) = "bluetooth"];
+ BluetoothA2dpPlaybackStateChanged bluetooth_a2dp_playback_state_changed =
+ 152 [(log_from_module) = "bluetooth"];
+ BluetoothA2dpCodecConfigChanged bluetooth_a2dp_codec_config_changed =
+ 153 [(log_from_module) = "bluetooth"];
+ BluetoothA2dpCodecCapabilityChanged bluetooth_a2dp_codec_capability_changed =
+ 154 [(log_from_module) = "bluetooth"];
+ BluetoothA2dpAudioUnderrunReported bluetooth_a2dp_audio_underrun_reported =
+ 155 [(log_from_module) = "bluetooth"];
+ BluetoothA2dpAudioOverrunReported bluetooth_a2dp_audio_overrun_reported =
+ 156 [(log_from_module) = "bluetooth"];
+ BluetoothDeviceRssiReported bluetooth_device_rssi_reported =
+ 157 [(log_from_module) = "bluetooth"];
+ BluetoothDeviceFailedContactCounterReported
+ bluetooth_device_failed_contact_counter_reported = 158 [(log_from_module) = "bluetooth"];
+ BluetoothDeviceTxPowerLevelReported bluetooth_device_tx_power_level_reported =
+ 159 [(log_from_module) = "bluetooth"];
+ BluetoothHciTimeoutReported bluetooth_hci_timeout_reported =
+ 160 [(log_from_module) = "bluetooth"];
+ BluetoothQualityReportReported bluetooth_quality_report_reported =
+ 161 [(log_from_module) = "bluetooth"];
+ BluetoothDeviceInfoReported bluetooth_device_info_reported =
+ 162 [(log_from_module) = "bluetooth"];
+ BluetoothRemoteVersionInfoReported bluetooth_remote_version_info_reported =
+ 163 [(log_from_module) = "bluetooth"];
+ BluetoothSdpAttributeReported bluetooth_sdp_attribute_reported =
+ 164 [(log_from_module) = "bluetooth"];
+ BluetoothBondStateChanged bluetooth_bond_state_changed =
+ 165 [(log_from_module) = "bluetooth"];
+ BluetoothClassicPairingEventReported bluetooth_classic_pairing_event_reported =
+ 166 [(log_from_module) = "bluetooth"];
+ BluetoothSmpPairingEventReported bluetooth_smp_pairing_event_reported =
+ 167 [(log_from_module) = "bluetooth"];
ScreenTimeoutExtensionReported screen_timeout_extension_reported = 168;
ProcessStartTime process_start_time = 169;
PermissionGrantRequestResultReported permission_grant_request_result_reported =
@@ -280,7 +301,8 @@
BiometricEnrolled biometric_enrolled = 184;
SystemServerWatchdogOccurred system_server_watchdog_occurred = 185;
TombStoneOccurred tomb_stone_occurred = 186;
- BluetoothClassOfDeviceReported bluetooth_class_of_device_reported = 187;
+ BluetoothClassOfDeviceReported bluetooth_class_of_device_reported =
+ 187 [(log_from_module) = "bluetooth"];
IntelligenceEventReported intelligence_event_reported =
188 [(log_from_module) = "intelligence"];
ThermalThrottlingSeverityStateChanged thermal_throttling_severity_state_changed = 189;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 2e14446..86b2c06 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -356,11 +356,9 @@
registerService(Context.TETHERING_SERVICE, TetheringManager.class,
new CachedServiceFetcher<TetheringManager>() {
@Override
- public TetheringManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder b = ServiceManager.getService(Context.TETHERING_SERVICE);
- if (b == null) return null;
-
- return new TetheringManager(ctx, b);
+ public TetheringManager createService(ContextImpl ctx) {
+ return new TetheringManager(
+ ctx, () -> ServiceManager.getService(Context.TETHERING_SERVICE));
}});
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 8415ecd..b6d096c 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -2162,6 +2162,33 @@
}
/**
+ * Fetches a list of the most recently connected bluetooth devices ordered by how recently they
+ * were connected with most recently first and least recently last
+ *
+ * @return {@link List} of bonded {@link BluetoothDevice} ordered by how recently they were
+ * connected
+ *
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN)
+ public @NonNull List<BluetoothDevice> getMostRecentlyConnectedDevices() {
+ if (getState() != STATE_ON) {
+ return new ArrayList<>();
+ }
+ try {
+ mServiceLock.readLock().lock();
+ if (mService != null) {
+ return mService.getMostRecentlyConnectedDevices();
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "", e);
+ } finally {
+ mServiceLock.readLock().unlock();
+ }
+ return new ArrayList<>();
+ }
+
+ /**
* Return the set of {@link BluetoothDevice} objects that are bonded
* (paired) to the local adapter.
* <p>If Bluetooth state is not {@link #STATE_ON}, this API
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 7316dfa..aae9fd4 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -17,6 +17,8 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.os.Build;
@@ -43,7 +45,12 @@
*
* @hide
*/
+@SystemApi
public abstract class NetworkAgent {
+ /**
+ * The {@link Network} corresponding to this object.
+ */
+ @NonNull
public final Network network;
private final Handler mHandler;
@@ -55,9 +62,14 @@
private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>();
private volatile long mLastBwRefreshTime = 0;
private static final long BW_REFRESH_MIN_WIN_MS = 500;
- private boolean mPollLceScheduled = false;
- private AtomicBoolean mPollLcePending = new AtomicBoolean(false);
- public final int mProviderId;
+ private boolean mBandwidthUpdateScheduled = false;
+ private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false);
+
+ /**
+ * The ID of the {@link NetworkProvider} that created this object, or
+ * {@link NetworkProvider#ID_NONE} if unknown.
+ */
+ public final int providerId;
private static final int BASE = Protocol.BASE_NETWORK_AGENT;
@@ -65,6 +77,7 @@
* Sent by ConnectivityService to the NetworkAgent to inform it of
* suspected connectivity problems on its network. The NetworkAgent
* should take steps to verify and correct connectivity.
+ * @hide
*/
public static final int CMD_SUSPECT_BAD = BASE;
@@ -73,6 +86,7 @@
* ConnectivityService to pass the current NetworkInfo (connection state).
* Sent when the NetworkInfo changes, mainly due to change of state.
* obj = NetworkInfo
+ * @hide
*/
public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1;
@@ -80,6 +94,7 @@
* Sent by the NetworkAgent to ConnectivityService to pass the current
* NetworkCapabilties.
* obj = NetworkCapabilities
+ * @hide
*/
public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2;
@@ -87,11 +102,14 @@
* Sent by the NetworkAgent to ConnectivityService to pass the current
* NetworkProperties.
* obj = NetworkProperties
+ * @hide
*/
public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3;
- /* centralize place where base network score, and network score scaling, will be
+ /**
+ * Centralize the place where base network score, and network score scaling, will be
* stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE
+ * @hide
*/
public static final int WIFI_BASE_SCORE = 60;
@@ -99,6 +117,7 @@
* Sent by the NetworkAgent to ConnectivityService to pass the current
* network score.
* obj = network score Integer
+ * @hide
*/
public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
@@ -111,12 +130,33 @@
* obj = Bundle containing map from {@code REDIRECT_URL_KEY} to {@code String}
* representing URL that Internet probe was redirect to, if it was redirected,
* or mapping to {@code null} otherwise.
+ * @hide
*/
public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7;
+
+ /**
+ * Network validation suceeded.
+ * Corresponds to {@link NetworkCapabilities.NET_CAPABILITY_VALIDATED}.
+ */
+ public static final int VALIDATION_STATUS_VALID = 1;
+
+ /**
+ * Network validation was attempted and failed. This may be received more than once as
+ * subsequent validation attempts are made.
+ */
+ public static final int VALIDATION_STATUS_NOT_VALID = 2;
+
+ // TODO: remove.
+ /** @hide */
public static final int VALID_NETWORK = 1;
+ /** @hide */
public static final int INVALID_NETWORK = 2;
+ /**
+ * The key for the redirect URL in the Bundle argument of {@code CMD_REPORT_NETWORK_STATUS}.
+ * @hide
+ */
public static String REDIRECT_URL_KEY = "redirect URL";
/**
@@ -125,6 +165,7 @@
* CONNECTED so it can be given special treatment at that time.
*
* obj = boolean indicating whether to use this network even if unvalidated
+ * @hide
*/
public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 8;
@@ -135,12 +176,14 @@
* responsibility to remember it.
*
* arg1 = 1 if true, 0 if false
+ * @hide
*/
public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9;
/**
* Sent by ConnectivityService to the NetworkAgent to inform the agent to pull
* the underlying network connection for updated bandwidth information.
+ * @hide
*/
public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10;
@@ -153,6 +196,7 @@
* obj = KeepalivePacketData object describing the data to be sent
*
* Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
+ * @hide
*/
public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11;
@@ -162,6 +206,7 @@
* arg1 = slot number of the keepalive to stop.
*
* Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
+ * @hide
*/
public static final int CMD_STOP_SOCKET_KEEPALIVE = BASE + 12;
@@ -175,6 +220,7 @@
*
* arg1 = slot number of the keepalive
* arg2 = error code
+ * @hide
*/
public static final int EVENT_SOCKET_KEEPALIVE = BASE + 13;
@@ -183,6 +229,7 @@
* that when crossed should trigger a system wakeup and a NetworkCapabilities update.
*
* obj = int[] describing signal strength thresholds.
+ * @hide
*/
public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14;
@@ -190,6 +237,7 @@
* Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid
* automatically reconnecting to this network (e.g. via autojoin). Happens
* when user selects "No" option on the "Stay connected?" dialog box.
+ * @hide
*/
public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
@@ -202,6 +250,7 @@
* This does not happen with UDP, so this message is TCP-specific.
* arg1 = slot number of the keepalive to filter for.
* obj = the keepalive packet to send repeatedly.
+ * @hide
*/
public static final int CMD_ADD_KEEPALIVE_PACKET_FILTER = BASE + 16;
@@ -209,6 +258,7 @@
* Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See
* {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}.
* arg1 = slot number of the keepalive packet filter to remove.
+ * @hide
*/
public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17;
@@ -216,27 +266,32 @@
// of dependent changes that would conflict throughout the automerger graph. Having these
// temporarily helps with the process of going through with all these dependent changes across
// the entire tree.
+ /** @hide TODO: decide which of these to expose. */
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score) {
this(looper, context, logTag, ni, nc, lp, score, null, NetworkProvider.ID_NONE);
}
+
+ /** @hide TODO: decide which of these to expose. */
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config) {
this(looper, context, logTag, ni, nc, lp, score, config, NetworkProvider.ID_NONE);
}
+ /** @hide TODO: decide which of these to expose. */
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, int providerId) {
this(looper, context, logTag, ni, nc, lp, score, null, providerId);
}
+ /** @hide TODO: decide which of these to expose. */
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score, NetworkAgentConfig config,
int providerId) {
mHandler = new NetworkAgentHandler(looper);
LOG_TAG = logTag;
mContext = context;
- mProviderId = providerId;
+ this.providerId = providerId;
if (ni == null || nc == null || lp == null) {
throw new IllegalArgumentException();
}
@@ -284,7 +339,7 @@
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
if (DBG) log("NetworkAgent channel lost");
// let the client know CS is done with us.
- unwanted();
+ onNetworkUnwanted();
synchronized (mPreConnectedQueue) {
mAsyncChannel = null;
}
@@ -300,16 +355,16 @@
log("CMD_REQUEST_BANDWIDTH_UPDATE request received.");
}
if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) {
- mPollLceScheduled = false;
- if (!mPollLcePending.getAndSet(true)) {
- pollLceData();
+ mBandwidthUpdateScheduled = false;
+ if (!mBandwidthUpdatePending.getAndSet(true)) {
+ onBandwidthUpdateRequested();
}
} else {
// deliver the request at a later time rather than discard it completely.
- if (!mPollLceScheduled) {
+ if (!mBandwidthUpdateScheduled) {
long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS
- currentTimeMs + 1;
- mPollLceScheduled = sendEmptyMessageDelayed(
+ mBandwidthUpdateScheduled = sendEmptyMessageDelayed(
CMD_REQUEST_BANDWIDTH_UPDATE, waitTime);
}
}
@@ -322,19 +377,20 @@
+ (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ")
+ redirectUrl);
}
- networkStatus(msg.arg1, redirectUrl);
+ onValidationStatus(msg.arg1 /* status */, redirectUrl);
break;
}
case CMD_SAVE_ACCEPT_UNVALIDATED: {
- saveAcceptUnvalidated(msg.arg1 != 0);
+ onSaveAcceptUnvalidated(msg.arg1 != 0);
break;
}
case CMD_START_SOCKET_KEEPALIVE: {
- startSocketKeepalive(msg);
+ onStartSocketKeepalive(msg.arg1 /* slot */, msg.arg2 /* interval */,
+ (KeepalivePacketData) msg.obj /* packet */);
break;
}
case CMD_STOP_SOCKET_KEEPALIVE: {
- stopSocketKeepalive(msg);
+ onStopSocketKeepalive(msg.arg1 /* slot */);
break;
}
@@ -347,19 +403,20 @@
for (int i = 0; i < intThresholds.length; i++) {
intThresholds[i] = thresholds.get(i);
}
- setSignalStrengthThresholds(intThresholds);
+ onSignalStrengthThresholdsUpdated(intThresholds);
break;
}
case CMD_PREVENT_AUTOMATIC_RECONNECT: {
- preventAutomaticReconnect();
+ onAutomaticReconnectDisabled();
break;
}
case CMD_ADD_KEEPALIVE_PACKET_FILTER: {
- addKeepalivePacketFilter(msg);
+ onAddKeepalivePacketFilter(msg.arg1 /* slot */,
+ (KeepalivePacketData) msg.obj /* packet */);
break;
}
case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: {
- removeKeepalivePacketFilter(msg);
+ onRemoveKeepalivePacketFilter(msg.arg1 /* slot */);
break;
}
}
@@ -394,14 +451,16 @@
}
/**
- * Called by the bearer code when it has new LinkProperties data.
+ * Must be called by the agent when the network's {@link LinkProperties} change.
+ * @param linkProperties the new LinkProperties.
*/
- public void sendLinkProperties(LinkProperties linkProperties) {
+ public void sendLinkProperties(@NonNull LinkProperties linkProperties) {
queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties));
}
/**
- * Called by the bearer code when it has new NetworkInfo data.
+ * Must be called by the agent when it has a new NetworkInfo object.
+ * @hide TODO: expose something better.
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void sendNetworkInfo(NetworkInfo networkInfo) {
@@ -409,17 +468,19 @@
}
/**
- * Called by the bearer code when it has new NetworkCapabilities data.
+ * Must be called by the agent when the network's {@link NetworkCapabilities} change.
+ * @param networkCapabilities the new NetworkCapabilities.
*/
- public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) {
- mPollLcePending.set(false);
+ public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
+ mBandwidthUpdatePending.set(false);
mLastBwRefreshTime = System.currentTimeMillis();
queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED,
new NetworkCapabilities(networkCapabilities));
}
/**
- * Called by the bearer code when it has a new score for this network.
+ * Must be called by the agent to update the score of this network.
+ * @param score the new score.
*/
public void sendNetworkScore(int score) {
if (score < 0) {
@@ -431,14 +492,16 @@
}
/**
- * Called by the bearer code when it has a new NetworkScore for this network.
+ * Must be called by the agent when it has a new {@link NetworkScore} for this network.
+ * @param ns the new score.
+ * @hide TODO: unhide the NetworkScore class, and rename to sendNetworkScore.
*/
public void updateScore(@NonNull NetworkScore ns) {
queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new NetworkScore(ns));
}
/**
- * Called by the bearer to indicate this network was manually selected by the user.
+ * Must be called by the agent to indicate this network was manually selected by the user.
* This should be called before the NetworkInfo is marked CONNECTED so that this
* Network can be given special treatment at that time. If {@code acceptUnvalidated} is
* {@code true}, then the system will switch to this network. If it is {@code false} and the
@@ -447,15 +510,16 @@
* {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever
* calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement
* {@link #saveAcceptUnvalidated} to respect the user's choice.
+ * @hide should move to NetworkAgentConfig.
*/
public void explicitlySelected(boolean acceptUnvalidated) {
explicitlySelected(true /* explicitlySelected */, acceptUnvalidated);
}
/**
- * Called by the bearer to indicate whether the network was manually selected by the user.
- * This should be called before the NetworkInfo is marked CONNECTED so that this
- * Network can be given special treatment at that time.
+ * Must be called by the agent to indicate whether the network was manually selected by the
+ * user. This should be called before the network becomes connected, so it can be given
+ * special treatment when it does.
*
* If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true},
* then the system will switch to this network. If {@code explicitlySelected} is {@code true}
@@ -470,6 +534,7 @@
* {@code true}, the system will interpret this as the user having accepted partial connectivity
* on this network. Thus, the system will switch to the network and consider it validated even
* if it only provides partial connectivity, but the network is not otherwise treated specially.
+ * @hide should move to NetworkAgentConfig.
*/
public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED,
@@ -483,73 +548,126 @@
* as well, either canceling NetworkRequests or altering their score such that this
* network won't be immediately requested again.
*/
- abstract protected void unwanted();
+ public void onNetworkUnwanted() {
+ unwanted();
+ }
+ /** @hide TODO delete once subclasses have moved to onNetworkUnwanted. */
+ protected void unwanted() {
+ }
/**
* Called when ConnectivityService request a bandwidth update. The parent factory
* shall try to overwrite this method and produce a bandwidth update if capable.
*/
+ public void onBandwidthUpdateRequested() {
+ pollLceData();
+ }
+ /** @hide TODO delete once subclasses have moved to onBandwidthUpdateRequested. */
protected void pollLceData() {
}
/**
* Called when the system determines the usefulness of this network.
*
- * Networks claiming internet connectivity will have their internet
- * connectivity verified.
+ * The system attempts to validate Internet connectivity on networks that provide the
+ * {@link NetworkCapabilities#NET_CAPABILITY_INTERNET} capability.
*
* Currently there are two possible values:
- * {@code VALID_NETWORK} if the system is happy with the connection,
- * {@code INVALID_NETWORK} if the system is not happy.
- * TODO - add indications of captive portal-ness and related success/failure,
- * ie, CAPTIVE_SUCCESS_NETWORK, CAPTIVE_NETWORK for successful login and detection
+ * {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated,
+ * {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated.
*
- * This may be called multiple times as the network status changes and may
- * generate false negatives if we lose ip connectivity before the link is torn down.
+ * This may be called multiple times as network status changes, or if there are multiple
+ * subsequent attempts to validate connectivity that fail.
*
- * @param status one of {@code VALID_NETWORK} or {@code INVALID_NETWORK}.
- * @param redirectUrl If the Internet probe was redirected, this is the destination it was
- * redirected to, otherwise {@code null}.
+ * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}.
+ * @param redirectUrl If Internet connectivity is being redirected (e.g., on a captive portal),
+ * this is the destination the probes are being redirected to, otherwise {@code null}.
*/
+ public void onValidationStatus(int status, @Nullable String redirectUrl) {
+ networkStatus(status, redirectUrl);
+ }
+ /** @hide TODO delete once subclasses have moved to onValidationStatus */
protected void networkStatus(int status, String redirectUrl) {
}
+
/**
* Called when the user asks to remember the choice to use this network even if unvalidated.
* The transport is responsible for remembering the choice, and the next time the user connects
* to the network, should explicitlySelected with {@code acceptUnvalidated} set to {@code true}.
* This method will only be called if {@link #explicitlySelected} was called with
* {@code acceptUnvalidated} set to {@code false}.
+ * @param accept whether the user wants to use the network even if unvalidated.
*/
+ public void onSaveAcceptUnvalidated(boolean accept) {
+ saveAcceptUnvalidated(accept);
+ }
+ /** @hide TODO delete once subclasses have moved to onSaveAcceptUnvalidated */
protected void saveAcceptUnvalidated(boolean accept) {
}
/**
* Requests that the network hardware send the specified packet at the specified interval.
+ *
+ * @param slot the hardware slot on which to start the keepalive.
+ * @param intervalSeconds the interval between packets
+ * @param packet the packet to send.
*/
+ public void onStartSocketKeepalive(int slot, int intervalSeconds,
+ @NonNull KeepalivePacketData packet) {
+ Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, intervalSeconds,
+ packet);
+ startSocketKeepalive(msg);
+ msg.recycle();
+ }
+ /** @hide TODO delete once subclasses have moved to onStartSocketKeepalive */
protected void startSocketKeepalive(Message msg) {
onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED);
}
/**
- * Requests that the network hardware send the specified packet at the specified interval.
+ * Requests that the network hardware stop a previously-started keepalive.
+ *
+ * @param slot the hardware slot on which to stop the keepalive.
*/
+ public void onStopSocketKeepalive(int slot) {
+ Message msg = mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0, null);
+ stopSocketKeepalive(msg);
+ msg.recycle();
+ }
+ /** @hide TODO delete once subclasses have moved to onStopSocketKeepalive */
protected void stopSocketKeepalive(Message msg) {
onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED);
}
/**
- * Called by the network when a socket keepalive event occurs.
+ * Must be called by the agent when a socket keepalive event occurs.
+ *
+ * @param slot the hardware slot on which the event occurred.
+ * @param event the event that occurred.
*/
+ public void sendSocketKeepaliveEvent(int slot, int event) {
+ queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, event);
+ }
+ /** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */
public void onSocketKeepaliveEvent(int slot, int reason) {
- queueOrSendMessage(EVENT_SOCKET_KEEPALIVE, slot, reason);
+ sendSocketKeepaliveEvent(slot, reason);
}
/**
* Called by ConnectivityService to add specific packet filter to network hardware to block
- * ACKs matching the sent keepalive packets. Implementations that support this feature must
- * override this method.
+ * replies (e.g., TCP ACKs) matching the sent keepalive packets. Implementations that support
+ * this feature must override this method.
+ *
+ * @param slot the hardware slot on which the keepalive should be sent.
+ * @param packet the packet that is being sent.
*/
+ public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) {
+ Message msg = mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0, packet);
+ addKeepalivePacketFilter(msg);
+ msg.recycle();
+ }
+ /** @hide TODO delete once subclasses have moved to onAddKeepalivePacketFilter */
protected void addKeepalivePacketFilter(Message msg) {
}
@@ -557,14 +675,28 @@
* Called by ConnectivityService to remove a packet filter installed with
* {@link #addKeepalivePacketFilter(Message)}. Implementations that support this feature
* must override this method.
+ *
+ * @param slot the hardware slot on which the keepalive is being sent.
*/
+ public void onRemoveKeepalivePacketFilter(int slot) {
+ Message msg = mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, slot, 0, null);
+ removeKeepalivePacketFilter(msg);
+ msg.recycle();
+ }
+ /** @hide TODO delete once subclasses have moved to onRemoveKeepalivePacketFilter */
protected void removeKeepalivePacketFilter(Message msg) {
}
/**
* Called by ConnectivityService to inform this network transport of signal strength thresholds
* that when crossed should trigger a system wakeup and a NetworkCapabilities update.
+ *
+ * @param thresholds the array of thresholds that should trigger wakeups.
*/
+ public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
+ setSignalStrengthThresholds(thresholds);
+ }
+ /** @hide TODO delete once subclasses have moved to onSetSignalStrengthThresholds */
protected void setSignalStrengthThresholds(int[] thresholds) {
}
@@ -574,9 +706,14 @@
* responsible for making sure the device does not automatically reconnect to the same network
* after the {@code unwanted} call.
*/
+ public void onAutomaticReconnectDisabled() {
+ preventAutomaticReconnect();
+ }
+ /** @hide TODO delete once subclasses have moved to onAutomaticReconnectDisabled */
protected void preventAutomaticReconnect() {
}
+ /** @hide */
protected void log(String s) {
Log.d(LOG_TAG, "NetworkAgent: " + s);
}
diff --git a/core/java/android/timezone/CountryTimeZones.java b/core/java/android/timezone/CountryTimeZones.java
index e5bbdf4..5875761 100644
--- a/core/java/android/timezone/CountryTimeZones.java
+++ b/core/java/android/timezone/CountryTimeZones.java
@@ -56,7 +56,7 @@
*/
@NonNull
public String getTimeZoneId() {
- return mDelegate.timeZoneId;
+ return mDelegate.getTimeZoneId();
}
/**
@@ -187,7 +187,7 @@
* would be a good choice <em>generally</em> when there's no other information available.
*/
public boolean isDefaultTimeZoneBoosted() {
- return mDelegate.getDefaultTimeZoneBoost();
+ return mDelegate.isDefaultTimeZoneBoosted();
}
/**
@@ -220,7 +220,8 @@
mDelegate.lookupByOffsetWithBias(
totalOffsetMillis, isDst, dstOffsetMillis, whenMillis, bias);
return delegateOffsetResult == null ? null :
- new OffsetResult(delegateOffsetResult.mTimeZone, delegateOffsetResult.mOneMatch);
+ new OffsetResult(
+ delegateOffsetResult.getTimeZone(), delegateOffsetResult.isOnlyMatch());
}
/**
diff --git a/core/java/android/timezone/TzDataSetVersion.java b/core/java/android/timezone/TzDataSetVersion.java
index 605155e..efe50a0 100644
--- a/core/java/android/timezone/TzDataSetVersion.java
+++ b/core/java/android/timezone/TzDataSetVersion.java
@@ -111,23 +111,23 @@
/** Returns the major version number. See {@link TzDataSetVersion}. */
public int getFormatMajorVersion() {
- return mDelegate.formatMajorVersion;
+ return mDelegate.getFormatMajorVersion();
}
/** Returns the minor version number. See {@link TzDataSetVersion}. */
public int getFormatMinorVersion() {
- return mDelegate.formatMinorVersion;
+ return mDelegate.getFormatMinorVersion();
}
/** Returns the tzdb version string. See {@link TzDataSetVersion}. */
@NonNull
public String getRulesVersion() {
- return mDelegate.rulesVersion;
+ return mDelegate.getRulesVersion();
}
/** Returns the Android revision. See {@link TzDataSetVersion}. */
public int getRevision() {
- return mDelegate.revision;
+ return mDelegate.getRevision();
}
@Override
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index a8a579c..de5b027f 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -80,7 +80,7 @@
}
CountryTimeZones.OffsetResult offsetResult = countryTimeZones.lookupByOffsetWithBias(
offsetMillis, isDst, null /* dstOffsetMillis */, whenMillis, bias);
- return offsetResult != null ? offsetResult.mTimeZone : null;
+ return offsetResult != null ? offsetResult.getTimeZone() : null;
}
/**
@@ -108,8 +108,8 @@
List<String> timeZoneIds = new ArrayList<>();
for (TimeZoneMapping timeZoneMapping : countryTimeZones.getTimeZoneMappings()) {
- if (timeZoneMapping.showInPicker) {
- timeZoneIds.add(timeZoneMapping.timeZoneId);
+ if (timeZoneMapping.isShownInPicker()) {
+ timeZoneIds.add(timeZoneMapping.getTimeZoneId());
}
}
return Collections.unmodifiableList(timeZoneIds);
diff --git a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
index aac7fc3..d48aa24 100644
--- a/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
+++ b/packages/SettingsLib/src/com/android/settingslib/datetime/ZoneGetter.java
@@ -402,7 +402,7 @@
private static List<String> extractTimeZoneIds(List<TimeZoneMapping> timeZoneMappings) {
final List<String> zoneIds = new ArrayList<>(timeZoneMappings.size());
for (TimeZoneMapping timeZoneMapping : timeZoneMappings) {
- zoneIds.add(timeZoneMapping.timeZoneId);
+ zoneIds.add(timeZoneMapping.getTimeZoneId());
}
return Collections.unmodifiableList(zoneIds);
}
diff --git a/packages/Tethering/common/TetheringLib/jarjar-rules.txt b/packages/Tethering/common/TetheringLib/jarjar-rules.txt
index 35e0f88..1403bba 100644
--- a/packages/Tethering/common/TetheringLib/jarjar-rules.txt
+++ b/packages/Tethering/common/TetheringLib/jarjar-rules.txt
@@ -1 +1,2 @@
rule android.annotation.** com.android.networkstack.tethering.annotation.@1
+rule com.android.internal.annotations.** com.android.networkstack.tethering.annotation.@1
\ No newline at end of file
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
index 37ce1d57..53a358f 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java
@@ -30,6 +30,9 @@
import android.util.ArrayMap;
import android.util.Log;
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -37,6 +40,7 @@
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Executor;
+import java.util.function.Supplier;
/**
* This class provides the APIs to control the tethering service.
@@ -50,17 +54,23 @@
public class TetheringManager {
private static final String TAG = TetheringManager.class.getSimpleName();
private static final int DEFAULT_TIMEOUT_MS = 60_000;
+ private static final long CONNECTOR_POLL_INTERVAL_MILLIS = 200L;
- private static TetheringManager sInstance;
+ @GuardedBy("mConnectorWaitQueue")
+ @Nullable
+ private ITetheringConnector mConnector;
+ @GuardedBy("mConnectorWaitQueue")
+ @NonNull
+ private final List<ConnectorConsumer> mConnectorWaitQueue = new ArrayList<>();
+ private final Supplier<IBinder> mConnectorSupplier;
- private final ITetheringConnector mConnector;
private final TetheringCallbackInternal mCallback;
private final Context mContext;
private final ArrayMap<TetheringEventCallback, ITetheringEventCallback>
mTetheringEventCallbacks = new ArrayMap<>();
- private TetheringConfigurationParcel mTetheringConfiguration;
- private TetherStatesParcel mTetherStatesParcel;
+ private volatile TetheringConfigurationParcel mTetheringConfiguration;
+ private volatile TetherStatesParcel mTetherStatesParcel;
/**
* Broadcast Action: A tetherable connection has come or gone.
@@ -162,29 +172,139 @@
/**
* Create a TetheringManager object for interacting with the tethering service.
*
+ * @param context Context for the manager.
+ * @param connectorSupplier Supplier for the manager connector; may return null while the
+ * service is not connected.
* {@hide}
*/
- public TetheringManager(@NonNull final Context context, @NonNull final IBinder service) {
+ public TetheringManager(@NonNull final Context context,
+ @NonNull Supplier<IBinder> connectorSupplier) {
mContext = context;
- mConnector = ITetheringConnector.Stub.asInterface(service);
mCallback = new TetheringCallbackInternal();
+ mConnectorSupplier = connectorSupplier;
final String pkgName = mContext.getOpPackageName();
+
+ final IBinder connector = mConnectorSupplier.get();
+ // If the connector is available on start, do not start a polling thread. This introduces
+ // differences in the thread that sends the oneway binder calls to the service between the
+ // first few seconds after boot and later, but it avoids always having differences between
+ // the first usage of TetheringManager from a process and subsequent usages (so the
+ // difference is only on boot). On boot binder calls may be queued until the service comes
+ // up and be sent from a worker thread; later, they are always sent from the caller thread.
+ // Considering that it's just oneway binder calls, and ordering is preserved, this seems
+ // better than inconsistent behavior persisting after boot.
+ if (connector != null) {
+ mConnector = ITetheringConnector.Stub.asInterface(connector);
+ } else {
+ startPollingForConnector();
+ }
+
Log.i(TAG, "registerTetheringEventCallback:" + pkgName);
+ getConnector(c -> c.registerTetheringEventCallback(mCallback, pkgName));
+ }
+
+ private void startPollingForConnector() {
+ new Thread(() -> {
+ while (true) {
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {
+ // Not much to do here, the system needs to wait for the connector
+ }
+
+ final IBinder connector = mConnectorSupplier.get();
+ if (connector != null) {
+ onTetheringConnected(ITetheringConnector.Stub.asInterface(connector));
+ return;
+ }
+ }
+ }).start();
+ }
+
+ private interface ConnectorConsumer {
+ void onConnectorAvailable(ITetheringConnector connector) throws RemoteException;
+ }
+
+ private void onTetheringConnected(ITetheringConnector connector) {
+ // Process the connector wait queue in order, including any items that are added
+ // while processing.
+ //
+ // 1. Copy the queue to a local variable under lock.
+ // 2. Drain the local queue with the lock released (otherwise, enqueuing future commands
+ // would block on the lock).
+ // 3. Acquire the lock again. If any new tasks were queued during step 2, goto 1.
+ // If not, set mConnector to non-null so future tasks are run immediately, not queued.
+ //
+ // For this to work, all calls to the tethering service must use getConnector(), which
+ // ensures that tasks are added to the queue with the lock held.
+ //
+ // Once mConnector is set to non-null, it will never be null again. If the network stack
+ // process crashes, no recovery is possible.
+ // TODO: evaluate whether it is possible to recover from network stack process crashes
+ // (though in most cases the system will have crashed when the network stack process
+ // crashes).
+ do {
+ final List<ConnectorConsumer> localWaitQueue;
+ synchronized (mConnectorWaitQueue) {
+ localWaitQueue = new ArrayList<>(mConnectorWaitQueue);
+ mConnectorWaitQueue.clear();
+ }
+
+ // Allow more tasks to be added at the end without blocking while draining the queue.
+ for (ConnectorConsumer task : localWaitQueue) {
+ try {
+ task.onConnectorAvailable(connector);
+ } catch (RemoteException e) {
+ // Most likely the network stack process crashed, which is likely to crash the
+ // system. Keep processing other requests but report the error loudly.
+ Log.wtf(TAG, "Error processing request for the tethering connector", e);
+ }
+ }
+
+ synchronized (mConnectorWaitQueue) {
+ if (mConnectorWaitQueue.size() == 0) {
+ mConnector = connector;
+ return;
+ }
+ }
+ } while (true);
+ }
+
+ /**
+ * Asynchronously get the ITetheringConnector to execute some operation.
+ *
+ * <p>If the connector is already available, the operation will be executed on the caller's
+ * thread. Otherwise it will be queued and executed on a worker thread. The operation should be
+ * limited to performing oneway binder calls to minimize differences due to threading.
+ */
+ private void getConnector(ConnectorConsumer consumer) {
+ final ITetheringConnector connector;
+ synchronized (mConnectorWaitQueue) {
+ connector = mConnector;
+ if (connector == null) {
+ mConnectorWaitQueue.add(consumer);
+ return;
+ }
+ }
+
try {
- mConnector.registerTetheringEventCallback(mCallback, pkgName);
+ consumer.onConnectorAvailable(connector);
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
}
private interface RequestHelper {
- void runRequest(IIntResultListener listener);
+ void runRequest(ITetheringConnector connector, IIntResultListener listener);
}
+ // Used to dispatch legacy ConnectivityManager methods that expect tethering to be able to
+ // return results and perform operations synchronously.
+ // TODO: remove once there are no callers of these legacy methods.
private class RequestDispatcher {
private final ConditionVariable mWaiting;
- public int mRemoteResult;
+ public volatile int mRemoteResult;
private final IIntResultListener mListener = new IIntResultListener.Stub() {
@Override
@@ -199,7 +319,7 @@
}
int waitForResult(final RequestHelper request) {
- request.runRequest(mListener);
+ getConnector(c -> request.runRequest(c, mListener));
if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
throw new IllegalStateException("Callback timeout");
}
@@ -222,7 +342,7 @@
}
private class TetheringCallbackInternal extends ITetheringEventCallback.Stub {
- private int mError = TETHER_ERROR_NO_ERROR;
+ private volatile int mError = TETHER_ERROR_NO_ERROR;
private final ConditionVariable mWaitForCallback = new ConditionVariable();
@Override
@@ -280,9 +400,9 @@
Log.i(TAG, "tether caller:" + callerPkg);
final RequestDispatcher dispatcher = new RequestDispatcher();
- return dispatcher.waitForResult(listener -> {
+ return dispatcher.waitForResult((connector, listener) -> {
try {
- mConnector.tether(iface, callerPkg, listener);
+ connector.tether(iface, callerPkg, listener);
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
@@ -304,9 +424,9 @@
final RequestDispatcher dispatcher = new RequestDispatcher();
- return dispatcher.waitForResult(listener -> {
+ return dispatcher.waitForResult((connector, listener) -> {
try {
- mConnector.untether(iface, callerPkg, listener);
+ connector.untether(iface, callerPkg, listener);
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
@@ -330,9 +450,9 @@
final RequestDispatcher dispatcher = new RequestDispatcher();
- return dispatcher.waitForResult(listener -> {
+ return dispatcher.waitForResult((connector, listener) -> {
try {
- mConnector.setUsbTethering(enable, callerPkg, listener);
+ connector.setUsbTethering(enable, callerPkg, listener);
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
@@ -467,11 +587,7 @@
});
}
};
- try {
- mConnector.startTethering(request.getParcel(), callerPkg, listener);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
+ getConnector(c -> c.startTethering(request.getParcel(), callerPkg, listener));
}
/**
@@ -509,15 +625,15 @@
final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "stopTethering caller:" + callerPkg);
- final RequestDispatcher dispatcher = new RequestDispatcher();
-
- dispatcher.waitForResult(listener -> {
- try {
- mConnector.stopTethering(type, callerPkg, listener);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
+ getConnector(c -> c.stopTethering(type, callerPkg, new IIntResultListener.Stub() {
+ @Override
+ public void onResult(int resultCode) {
+ // TODO: provide an API to obtain result
+ // This has never been possible as stopTethering has always been void and never
+ // taken a callback object. The only indication that callers have is if the call
+ // results in a TETHER_STATE_CHANGE broadcast.
}
- });
+ }));
}
/**
@@ -591,12 +707,8 @@
final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg);
- try {
- mConnector.requestLatestTetheringEntitlementResult(type, receiver, showEntitlementUi,
- callerPkg);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
+ getConnector(c -> c.requestLatestTetheringEntitlementResult(
+ type, receiver, showEntitlementUi, callerPkg));
}
/**
@@ -832,11 +944,7 @@
});
}
};
- try {
- mConnector.registerTetheringEventCallback(remoteCallback, callerPkg);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
+ getConnector(c -> c.registerTetheringEventCallback(remoteCallback, callerPkg));
mTetheringEventCallbacks.put(callback, remoteCallback);
}
}
@@ -860,11 +968,8 @@
if (remoteCallback == null) {
throw new IllegalArgumentException("callback was not registered.");
}
- try {
- mConnector.unregisterTetheringEventCallback(remoteCallback, callerPkg);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
- }
+
+ getConnector(c -> c.unregisterTetheringEventCallback(remoteCallback, callerPkg));
}
}
@@ -1002,9 +1107,9 @@
final String callerPkg = mContext.getOpPackageName();
final RequestDispatcher dispatcher = new RequestDispatcher();
- final int ret = dispatcher.waitForResult(listener -> {
+ final int ret = dispatcher.waitForResult((connector, listener) -> {
try {
- mConnector.isTetheringSupported(callerPkg, listener);
+ connector.isTetheringSupported(callerPkg, listener);
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
@@ -1027,13 +1132,14 @@
final String callerPkg = mContext.getOpPackageName();
Log.i(TAG, "stopAllTethering caller:" + callerPkg);
- final RequestDispatcher dispatcher = new RequestDispatcher();
- dispatcher.waitForResult(listener -> {
- try {
- mConnector.stopAllTethering(callerPkg, listener);
- } catch (RemoteException e) {
- throw new IllegalStateException(e);
+ getConnector(c -> c.stopAllTethering(callerPkg, new IIntResultListener.Stub() {
+ @Override
+ public void onResult(int resultCode) {
+ // TODO: add an API parameter to send result to caller.
+ // This has never been possible as stopAllTethering has always been void and never
+ // taken a callback object. The only indication that callers have is if the call
+ // results in a TETHER_STATE_CHANGE broadcast.
}
- });
+ }));
}
}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index cdf8ea3..bbd1ae6 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -198,7 +198,7 @@
Slog.w(TAG, "Failed to read staged distro.", e);
}
}
- return new RulesState(baseVersion.rulesVersion, DISTRO_FORMAT_VERSION_SUPPORTED,
+ return new RulesState(baseVersion.getRulesVersion(), DISTRO_FORMAT_VERSION_SUPPORTED,
operationInProgress, stagedOperationStatus, stagedDistroRulesVersion,
distroStatus, installedDistroRulesVersion);
}
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 9e6dfef..db17a95 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -598,6 +598,48 @@
}
/**
+ * Call forwarding function status
+ */
+ @IntDef(prefix = { "STATUS_" }, value = {
+ CallForwardingInfo.STATUS_ACTIVE,
+ CallForwardingInfo.STATUS_INACTIVE,
+ CallForwardingInfo.STATUS_UNKNOWN_ERROR,
+ CallForwardingInfo.STATUS_NOT_SUPPORTED,
+ CallForwardingInfo.STATUS_FDN_CHECK_FAILURE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallForwardingStatus {
+ }
+
+ /**
+ * Call forwarding reason types
+ */
+ @IntDef(flag = true, prefix = { "REASON_" }, value = {
+ CallForwardingInfo.REASON_UNCONDITIONAL,
+ CallForwardingInfo.REASON_BUSY,
+ CallForwardingInfo.REASON_NO_REPLY,
+ CallForwardingInfo.REASON_NOT_REACHABLE,
+ CallForwardingInfo.REASON_ALL,
+ CallForwardingInfo.REASON_ALL_CONDITIONAL
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallForwardingReason {
+ }
+
+ /**
+ * Call waiting function status
+ */
+ @IntDef(prefix = { "CALL_WAITING_STATUS_" }, value = {
+ TelephonyManager.CALL_WAITING_STATUS_ACTIVE,
+ TelephonyManager.CALL_WAITING_STATUS_INACTIVE,
+ TelephonyManager.CALL_WAITING_STATUS_NOT_SUPPORTED,
+ TelephonyManager.CALL_WAITING_STATUS_UNKNOWN_ERROR
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CallWaitingStatus {
+ }
+
+ /**
* UICC SIM Application Types
*/
@IntDef(prefix = { "APPTYPE_" }, value = {
diff --git a/telephony/java/android/telephony/CallForwardingInfo.aidl b/telephony/java/android/telephony/CallForwardingInfo.aidl
new file mode 100644
index 0000000..2019e07
--- /dev/null
+++ b/telephony/java/android/telephony/CallForwardingInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2020, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+parcelable CallForwardingInfo;
\ No newline at end of file
diff --git a/telephony/java/android/telephony/CallForwardingInfo.java b/telephony/java/android/telephony/CallForwardingInfo.java
new file mode 100644
index 0000000..33ad5e8
--- /dev/null
+++ b/telephony/java/android/telephony/CallForwardingInfo.java
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Annotation.CallForwardingReason;
+import android.telephony.Annotation.CallForwardingStatus;
+
+import java.util.Objects;
+
+/**
+ * Defines the call forwarding information.
+ * @hide
+ */
+@SystemApi
+public final class CallForwardingInfo implements Parcelable {
+ private static final String TAG = "CallForwardingInfo";
+
+ /**
+ * Indicates the call forwarding status is inactive.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int STATUS_INACTIVE = 0;
+
+ /**
+ * Indicates the call forwarding status is active.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int STATUS_ACTIVE = 1;
+
+ /**
+ * Indicates the call forwarding could not be enabled because the recipient is not on
+ * Fixed Dialing Number (FDN) list.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int STATUS_FDN_CHECK_FAILURE = 2;
+
+ /**
+ * Indicates the call forwarding status is with an unknown error.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int STATUS_UNKNOWN_ERROR = 3;
+
+ /**
+ * Indicates the call forwarding is not supported (e.g. called via CDMA).
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int STATUS_NOT_SUPPORTED = 4;
+
+ /**
+ * Indicates the call forwarding reason is "unconditional".
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+ * and conditions +CCFC
+ * @hide
+ */
+ @SystemApi
+ public static final int REASON_UNCONDITIONAL = 0;
+
+ /**
+ * Indicates the call forwarding status is "busy".
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+ * and conditions +CCFC
+ * @hide
+ */
+ @SystemApi
+ public static final int REASON_BUSY = 1;
+
+ /**
+ * Indicates the call forwarding reason is "no reply".
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+ * and conditions +CCFC
+ * @hide
+ */
+ @SystemApi
+ public static final int REASON_NO_REPLY = 2;
+
+ /**
+ * Indicates the call forwarding reason is "not reachable".
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+ * and conditions +CCFC
+ * @hide
+ */
+ @SystemApi
+ public static final int REASON_NOT_REACHABLE = 3;
+
+ /**
+ * Indicates the call forwarding reason is "all", for setting all call forwarding reasons
+ * simultaneously (unconditional, busy, no reply, and not reachable).
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+ * and conditions +CCFC
+ * @hide
+ */
+ @SystemApi
+ public static final int REASON_ALL = 4;
+
+ /**
+ * Indicates the call forwarding reason is "all_conditional", for setting all conditional call
+ * forwarding reasons simultaneously (busy, no reply, and not reachable).
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+ * and conditions +CCFC
+ * @hide
+ */
+ @SystemApi
+ public static final int REASON_ALL_CONDITIONAL = 5;
+
+ /**
+ * The call forwarding status.
+ */
+ private @CallForwardingStatus int mStatus;
+
+ /**
+ * The call forwarding reason indicates the condition under which calls will be forwarded.
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+ * and conditions +CCFC
+ */
+ private @CallForwardingReason int mReason;
+
+ /**
+ * The phone number to which calls will be forwarded.
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10 - 7.11 Call forwarding number
+ * and conditions +CCFC
+ */
+ private String mNumber;
+
+ /**
+ * Gets the timeout (in seconds) before the forwarding is attempted.
+ */
+ private int mTimeSeconds;
+
+ /**
+ * Construct a CallForwardingInfo.
+ *
+ * @param status the call forwarding status
+ * @param reason the call forwarding reason
+ * @param number the phone number to which calls will be forwarded
+ * @param timeSeconds the timeout (in seconds) before the forwarding is attempted
+ * @hide
+ */
+ @SystemApi
+ public CallForwardingInfo(@CallForwardingStatus int status, @CallForwardingReason int reason,
+ @Nullable String number, int timeSeconds) {
+ mStatus = status;
+ mReason = reason;
+ mNumber = number;
+ mTimeSeconds = timeSeconds;
+ }
+
+ /**
+ * Returns the call forwarding status.
+ *
+ * @return the call forwarding status.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @CallForwardingStatus int getStatus() {
+ return mStatus;
+ }
+
+ /**
+ * Returns the call forwarding reason. The call forwarding reason indicates the condition
+ * under which calls will be forwarded. For example, {@link #REASON_NO_REPLY} indicates
+ * that calls will be forward to {@link #getNumber()} when the user fails to answer the call.
+ *
+ * @return the call forwarding reason.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @CallForwardingReason int getReason() {
+ return mReason;
+ }
+
+ /**
+ * Returns the phone number to which calls will be forwarded.
+ *
+ * @return the number calls will be forwarded to, or {@code null} if call forwarding
+ * is being disabled.
+ *
+ * @hide
+ */
+ @SystemApi
+ @Nullable
+ public String getNumber() {
+ return mNumber;
+ }
+
+ /**
+ * Gets the timeout (in seconds) before the forwarding is attempted. For example,
+ * if {@link #REASON_NO_REPLY} is the call forwarding reason, the device will wait this
+ * duration of time before forwarding the call to {@link #getNumber()}.
+ *
+ * Reference: 3GPP TS 27.007 version 10.3.0 Release 10
+ * 7.11 Call forwarding number and conditions +CCFC
+ *
+ * @return the timeout (in seconds) before the forwarding is attempted.
+ *
+ * @hide
+ */
+ @SystemApi
+ @SuppressLint("MethodNameUnits")
+ public int getTimeoutSeconds() {
+ return mTimeSeconds;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mNumber);
+ out.writeInt(mStatus);
+ out.writeInt(mReason);
+ out.writeInt(mTimeSeconds);
+ }
+
+ private CallForwardingInfo(Parcel in) {
+ mNumber = in.readString();
+ mStatus = in.readInt();
+ mReason = in.readInt();
+ mTimeSeconds = in.readInt();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (!(o instanceof CallForwardingInfo)) {
+ return false;
+ }
+
+ CallForwardingInfo other = (CallForwardingInfo) o;
+ return mStatus == other.mStatus
+ && mNumber == other.mNumber
+ && mReason == other.mReason
+ && mTimeSeconds == other.mTimeSeconds;
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(mStatus, mNumber, mReason, mTimeSeconds);
+ }
+
+ public static final @NonNull Parcelable.Creator<CallForwardingInfo> CREATOR =
+ new Parcelable.Creator<CallForwardingInfo>() {
+ @Override
+ public CallForwardingInfo createFromParcel(Parcel in) {
+ return new CallForwardingInfo(in);
+ }
+
+ @Override
+ public CallForwardingInfo[] newArray(int size) {
+ return new CallForwardingInfo[size];
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @Override
+ public String toString() {
+ return "[CallForwardingInfo: status=" + mStatus
+ + ", reason= " + mReason
+ + ", timeSec= " + mTimeSeconds + " seconds"
+ + ", number=" + Rlog.pii(TAG, mNumber) + "]";
+ }
+}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 58b82bf..67e036d 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -71,7 +71,9 @@
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
import android.telephony.Annotation.ApnType;
+import android.telephony.Annotation.CallForwardingReason;
import android.telephony.Annotation.CallState;
+import android.telephony.Annotation.CallWaitingStatus;
import android.telephony.Annotation.NetworkType;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
@@ -12202,6 +12204,191 @@
}
/**
+ * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward
+ * reason.
+ *
+ * @param callForwardingReason the call forwarding reasons
+ *
+ * @throws IllegalArgumentException if callForwardingReason is not any of
+ * {@link CallForwardingInfo.REASON_UNCONDITIONAL}, {@link CallForwardingInfo.REASON_BUSY},
+ * {@link CallForwardingInfo.REASON_NO_REPLY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE},
+ * {@link CallForwardingInfo.REASON_ALL}, {@link CallForwardingInfo.REASON_ALL_CONDITIONAL}
+ *
+ * @return {@link CallForwardingInfo} with the status {@link CallForwardingInfo#STATUS_ACTIVE}
+ * or {@link CallForwardingInfo#STATUS_INACTIVE} and the target phone number to forward calls
+ * to, if it's available. Otherwise, it will return a {@link CallForwardingInfo} with status
+ * {@link CallForwardingInfo#STATUS_UNKNOWN_ERROR},
+ * {@link CallForwardingInfo#STATUS_NOT_SUPPORTED},
+ * or {@link CallForwardingInfo#STATUS_FDN_CHECK_FAILURE} depending on the situation.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @NonNull
+ public CallForwardingInfo getCallForwarding(@CallForwardingReason int callForwardingReason) {
+ if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL
+ || callForwardingReason > CallForwardingInfo.REASON_ALL_CONDITIONAL) {
+ throw new IllegalArgumentException("callForwardingReason is out of range");
+ }
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getCallForwarding(getSubId(), callForwardingReason);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getCallForwarding RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "getCallForwarding NPE", ex);
+ }
+ return new CallForwardingInfo(
+ CallForwardingInfo.STATUS_UNKNOWN_ERROR, 0 /* reason */, null /* number */,
+ 0 /* timeout */);
+ }
+
+ /**
+ * Sets the voice call forwarding info including status (enable/disable), call forwarding
+ * reason, the number to forward, and the timeout before the forwarding is attempted.
+ *
+ * @param callForwardingInfo {@link CallForwardingInfo} to setup the call forwarding.
+ * Enabling if {@link CallForwardingInfo#getStatus()} returns
+ * {@link CallForwardingInfo#STATUS_ACTIVE}; Disabling if
+ * {@link CallForwardingInfo#getStatus()} returns {@link CallForwardingInfo#STATUS_INACTIVE}.
+ *
+ * @throws IllegalArgumentException if any of the following for parameter callForwardingInfo:
+ * 0) it is {@code null}.
+ * 1) {@link CallForwardingInfo#getStatus()} returns neither
+ * {@link CallForwardingInfo#STATUS_ACTIVE} nor {@link CallForwardingInfo#STATUS_INACTIVE}.
+ * 2) {@link CallForwardingInfo#getReason()} is not any of
+ * {@link CallForwardingInfo.REASON_UNCONDITIONAL}, {@link CallForwardingInfo.REASON_BUSY},
+ * {@link CallForwardingInfo.REASON_NO_REPLY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE},
+ * {@link CallForwardingInfo.REASON_ALL}, {@link CallForwardingInfo.REASON_ALL_CONDITIONAL}
+ * 3) {@link CallForwardingInfo#getNumber()} returns {@code null}.
+ * 4) {@link CallForwardingInfo#getTimeoutSeconds()} doesn't return a positive value.
+ *
+ * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public boolean setCallForwarding(@NonNull CallForwardingInfo callForwardingInfo) {
+ if (callForwardingInfo == null) {
+ throw new IllegalArgumentException("callForwardingInfo is null");
+ }
+ int callForwardingStatus = callForwardingInfo.getStatus();
+ if (callForwardingStatus != CallForwardingInfo.STATUS_ACTIVE
+ && callForwardingStatus != CallForwardingInfo.STATUS_INACTIVE) {
+ throw new IllegalArgumentException(
+ "callForwardingStatus is neither active nor inactive");
+ }
+ int callForwardingReason = callForwardingInfo.getReason();
+ if (callForwardingReason < CallForwardingInfo.REASON_UNCONDITIONAL
+ || callForwardingReason > CallForwardingInfo.REASON_ALL_CONDITIONAL) {
+ throw new IllegalArgumentException("callForwardingReason is out of range");
+ }
+ if (callForwardingInfo.getNumber() == null) {
+ throw new IllegalArgumentException("callForwarding number is null");
+ }
+ if (callForwardingInfo.getTimeoutSeconds() <= 0) {
+ throw new IllegalArgumentException("callForwarding timeout isn't positive");
+ }
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.setCallForwarding(getSubId(), callForwardingInfo);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "setCallForwarding RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "setCallForwarding NPE", ex);
+ }
+ return false;
+ }
+
+ /**
+ * Indicates the call waiting status is active.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int CALL_WAITING_STATUS_ACTIVE = 1;
+
+ /**
+ * Indicates the call waiting status is inactive.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int CALL_WAITING_STATUS_INACTIVE = 2;
+
+ /**
+ * Indicates the call waiting status is with an unknown error.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int CALL_WAITING_STATUS_UNKNOWN_ERROR = 3;
+
+ /**
+ * Indicates the call waiting is not supported (e.g. called via CDMA).
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int CALL_WAITING_STATUS_NOT_SUPPORTED = 4;
+
+ /**
+ * Gets the status of voice call waiting function. Call waiting function enables the waiting
+ * for the incoming call when it reaches the user who is busy to make another call and allows
+ * users to decide whether to switch to the incoming call.
+ *
+ * @return the status of call waiting function.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ public @CallWaitingStatus int getCallWaitingStatus() {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getCallWaitingStatus(getSubId());
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "getCallWaitingStatus RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "getCallWaitingStatus NPE", ex);
+ }
+ return CALL_WAITING_STATUS_UNKNOWN_ERROR;
+ }
+
+ /**
+ * Sets the status for voice call waiting function. Call waiting function enables the waiting
+ * for the incoming call when it reaches the user who is busy to make another call and allows
+ * users to decide whether to switch to the incoming call.
+ *
+ * @param isEnable {@code true} to enable; {@code false} to disable.
+ * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+ *
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public boolean setCallWaitingStatus(boolean isEnable) {
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.setCallWaitingStatus(getSubId(), isEnable);
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "setCallWaitingStatus RemoteException", ex);
+ } catch (NullPointerException ex) {
+ Rlog.e(TAG, "setCallWaitingStatus NPE", ex);
+ }
+ return false;
+ }
+
+ /**
* Set allowing mobile data during voice call.
*
* @param allow {@code true} if allowing using data during voice call, {@code false} if
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 1d794cd..d7fbafb 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -29,6 +29,7 @@
import android.service.carrier.CarrierIdentifier;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
+import android.telephony.CallForwardingInfo;
import android.telephony.CarrierRestrictionRules;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
@@ -1631,6 +1632,79 @@
NetworkStats getVtDataUsage(int subId, boolean perUidStats);
/**
+ * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward
+ * reason.
+ *
+ * @param callForwardingReason the call forwarding reasons which are the bitwise-OR combination
+ * of the following constants:
+ * <ol>
+ * <li>{@link CallForwardingInfo#REASON_BUSY} </li>
+ * <li>{@link CallForwardingInfo#REASON_NO_REPLY} </li>
+ * <li>{@link CallForwardingInfo#REASON_NOT_REACHABLE} </li>
+ * </ol>
+ *
+ * @throws IllegalArgumentException if callForwardingReason is not a bitwise-OR combination
+ * of {@link CallForwardingInfo.REASON_BUSY}, {@link CallForwardingInfo.REASON_BUSY},
+ * {@link CallForwardingInfo.REASON_NOT_REACHABLE}
+ *
+ * @return {@link CallForwardingInfo} with the status {@link CallForwardingInfo#STATUS_ACTIVE}
+ * or {@link CallForwardingInfo#STATUS_INACTIVE} and the target phone number to forward calls
+ * to, if it's available. Otherwise, it will return a {@link CallForwardingInfo} with status
+ * {@link CallForwardingInfo#STATUS_NOT_SUPPORTED} or
+ * {@link CallForwardingInfo#STATUS_FDN_CHECK_FAILURE} depending on the situation.
+ *
+ * @hide
+ */
+ CallForwardingInfo getCallForwarding(int subId, int callForwardingReason);
+
+ /**
+ * Sets the voice call forwarding info including status (enable/disable), call forwarding
+ * reason, the number to forward, and the timeout before the forwarding is attempted.
+ *
+ * @param callForwardingInfo {@link CallForwardingInfo} to setup the call forwarding.
+ * Enabling if {@link CallForwardingInfo#getStatus()} returns
+ * {@link CallForwardingInfo#STATUS_ACTIVE}; Disabling if
+ * {@link CallForwardingInfo#getStatus()} returns {@link CallForwardingInfo#STATUS_INACTIVE}.
+ *
+ * @throws IllegalArgumentException if any of the following:
+ * 0) callForwardingInfo is null.
+ * 1) {@link CallForwardingInfo#getStatus()} for callForwardingInfo returns neither
+ * {@link CallForwardingInfo#STATUS_ACTIVE} nor {@link CallForwardingInfo#STATUS_INACTIVE}.
+ * 2) {@link CallForwardingInfo#getReason()} for callForwardingInfo doesn't return the
+ * bitwise-OR combination of {@link CallForwardingInfo.REASON_BUSY},
+ * {@link CallForwardingInfo.REASON_BUSY}, {@link CallForwardingInfo.REASON_NOT_REACHABLE}
+ * 3) {@link CallForwardingInfo#getNumber()} for callForwardingInfo returns null.
+ * 4) {@link CallForwardingInfo#getTimeout()} for callForwardingInfo returns nagetive value.
+ *
+ * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+ *
+ * @hide
+ */
+ boolean setCallForwarding(int subId, in CallForwardingInfo callForwardingInfo);
+
+ /**
+ * Gets the status of voice call waiting function. Call waiting function enables the waiting
+ * for the incoming call when it reaches the user who is busy to make another call and allows
+ * users to decide whether to switch to the incoming call.
+ *
+ * @return the status of call waiting function.
+ * @hide
+ */
+ int getCallWaitingStatus(int subId);
+
+ /**
+ * Sets the status for voice call waiting function. Call waiting function enables the waiting
+ * for the incoming call when it reaches the user who is busy to make another call and allows
+ * users to decide whether to switch to the incoming call.
+ *
+ * @param isEnable {@code true} to enable; {@code false} to disable.
+ * @return {@code true} to indicate it was set successfully; {@code false} otherwise.
+ *
+ * @hide
+ */
+ boolean setCallWaitingStatus(int subId, boolean isEnable);
+
+ /**
* Policy control of data connection. Usually used when data limit is passed.
* @param enabled True if enabling the data, otherwise disabling.
* @param subId Subscription index
diff --git a/tests/net/TEST_MAPPING b/tests/net/TEST_MAPPING
index a7853b6..005cbe9 100644
--- a/tests/net/TEST_MAPPING
+++ b/tests/net/TEST_MAPPING
@@ -1,7 +1,12 @@
{
- "postsubmit": [
+ "presubmit": [
{
"name": "FrameworksNetIntegrationTests"
}
+ ],
+ "postsubmit": [
+ {
+ "name": "FrameworksNetDeflakeTest"
+ }
]
}
\ No newline at end of file
diff --git a/tests/net/deflake/Android.bp b/tests/net/deflake/Android.bp
index 1c48c74..b1b0171 100644
--- a/tests/net/deflake/Android.bp
+++ b/tests/net/deflake/Android.bp
@@ -26,4 +26,5 @@
"net-host-tests-utils",
],
data: [":FrameworksNetTests"],
-}
\ No newline at end of file
+ test_suites: ["device-tests"],
+}
diff --git a/tools/hiddenapi/Android.bp b/tools/hiddenapi/Android.bp
new file mode 100644
index 0000000..e0eb06cb
--- /dev/null
+++ b/tools/hiddenapi/Android.bp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+python_binary_host {
+ name: "merge_csv",
+ main: "merge_csv.py",
+ srcs: ["merge_csv.py"],
+ version: {
+ py2: {
+ enabled: false,
+ },
+ py3: {
+ enabled: true,
+ embedded_launcher: true
+ },
+ },
+}
diff --git a/tools/hiddenapi/merge_csv.py b/tools/hiddenapi/merge_csv.py
index 48c0755..9661927 100755
--- a/tools/hiddenapi/merge_csv.py
+++ b/tools/hiddenapi/merge_csv.py
@@ -21,20 +21,19 @@
import sys
csv_readers = [
- csv.DictReader(open(csv_file, 'rb'), delimiter=',', quotechar='|')
+ csv.DictReader(open(csv_file, 'r'), delimiter=',', quotechar='|')
for csv_file in sys.argv[1:]
]
# Build union of all columns from source files:
headers = set()
for reader in csv_readers:
- headers = headers.union(reader.fieldnames)
+ headers = headers.union(reader.fieldnames)
# Concatenate all files to output:
-out = csv.DictWriter(sys.stdout, delimiter=',', quotechar='|', fieldnames = sorted(headers))
+out = csv.DictWriter(sys.stdout, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL,
+ dialect='unix', fieldnames=sorted(headers))
out.writeheader()
for reader in csv_readers:
- for row in reader:
- out.writerow(row)
-
-
+ for row in reader:
+ out.writerow(row)
diff --git a/tools/stats_log_api_gen/Collation.cpp b/tools/stats_log_api_gen/Collation.cpp
index fa55601..75deb01 100644
--- a/tools/stats_log_api_gen/Collation.cpp
+++ b/tools/stats_log_api_gen/Collation.cpp
@@ -434,7 +434,7 @@
AtomDecl nonChainedAtomDecl(atomField->number(), atomField->name(), atom->name());
vector<java_type_t> nonChainedSignature;
if (get_non_chained_node(atom, &nonChainedAtomDecl, &nonChainedSignature)) {
- auto it = atoms->non_chained_signatures_to_modules.find(signature);
+ auto it = atoms->non_chained_signatures_to_modules.find(nonChainedSignature);
if (it == atoms->non_chained_signatures_to_modules.end()) {
set<string> modules_non_chained;
if (atomDecl.hasModule) {
diff --git a/tools/stats_log_api_gen/java_writer.cpp b/tools/stats_log_api_gen/java_writer.cpp
index fef490c..c29936b 100644
--- a/tools/stats_log_api_gen/java_writer.cpp
+++ b/tools/stats_log_api_gen/java_writer.cpp
@@ -73,7 +73,7 @@
java_type_name(chainField.javaType), chainField.name.c_str());
}
} else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", SparseArray<Object> valueMap");
+ fprintf(out, ", android.util.SparseArray<Object> valueMap");
} else {
fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
}
@@ -85,8 +85,9 @@
string indent("");
if (supportQ) {
// TODO(b/146235828): Use just SDK_INT check once it is incremented from Q.
- fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q ||\n");
- fprintf(out, " Build.VERSION.CODENAME.equals(\"R\")) {\n");
+ fprintf(out, " if (Build.VERSION.SDK_INT > Build.VERSION_CODES.Q\n");
+ fprintf(out, " || (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q\n");
+ fprintf(out, " && Build.VERSION.PREVIEW_SDK_INT > 0)) {\n");
indent = " ";
}
@@ -141,16 +142,16 @@
fprintf(out,
"%s final int count = valueMap.size();\n", indent.c_str());
fprintf(out,
- "%s final SparseIntArray intMap = new SparseIntArray();\n",
+ "%s android.util.SparseIntArray intMap = null;\n",
indent.c_str());
fprintf(out,
- "%s final SparseLongArray longMap = new SparseLongArray();\n",
+ "%s android.util.SparseLongArray longMap = null;\n",
indent.c_str());
fprintf(out,
- "%s final SparseArray<String> stringMap = new SparseArray<>();\n",
+ "%s android.util.SparseArray<String> stringMap = null;\n",
indent.c_str());
fprintf(out,
- "%s final SparseArray<Float> floatMap = new SparseArray<>();\n",
+ "%s android.util.SparseArray<Float> floatMap = null;\n",
indent.c_str());
fprintf(out,
"%s for (int i = 0; i < count; i++) {\n", indent.c_str());
@@ -162,18 +163,42 @@
fprintf(out,
"%s if (value instanceof Integer) {\n", indent.c_str());
fprintf(out,
+ "%s if (null == intMap) {\n", indent.c_str());
+ fprintf(out,
+ "%s intMap = new android.util.SparseIntArray();\n", indent.c_str());
+ fprintf(out,
+ "%s }\n", indent.c_str());
+ fprintf(out,
"%s intMap.put(key, (Integer) value);\n", indent.c_str());
fprintf(out,
"%s } else if (value instanceof Long) {\n", indent.c_str());
fprintf(out,
+ "%s if (null == longMap) {\n", indent.c_str());
+ fprintf(out,
+ "%s longMap = new android.util.SparseLongArray();\n", indent.c_str());
+ fprintf(out,
+ "%s }\n", indent.c_str());
+ fprintf(out,
"%s longMap.put(key, (Long) value);\n", indent.c_str());
fprintf(out,
"%s } else if (value instanceof String) {\n", indent.c_str());
fprintf(out,
+ "%s if (null == stringMap) {\n", indent.c_str());
+ fprintf(out,
+ "%s stringMap = new android.util.SparseArray<>();\n", indent.c_str());
+ fprintf(out,
+ "%s }\n", indent.c_str());
+ fprintf(out,
"%s stringMap.put(key, (String) value);\n", indent.c_str());
fprintf(out,
"%s } else if (value instanceof Float) {\n", indent.c_str());
fprintf(out,
+ "%s if (null == floatMap) {\n", indent.c_str());
+ fprintf(out,
+ "%s floatMap = new android.util.SparseArray<>();\n", indent.c_str());
+ fprintf(out,
+ "%s }\n", indent.c_str());
+ fprintf(out,
"%s floatMap.put(key, (Float) value);\n", indent.c_str());
fprintf(out,
"%s }\n", indent.c_str());
@@ -228,7 +253,8 @@
int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
const string& moduleName, const string& javaClass,
- const string& javaPackage, const bool supportQ) {
+ const string& javaPackage, const bool supportQ,
+ const bool supportWorkSource) {
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
@@ -240,25 +266,9 @@
fprintf(out, "import android.os.SystemClock;\n");
}
- if (DEFAULT_MODULE_NAME == moduleName) {
- // Mainline modules don't use WorkSource logging.
- fprintf(out, "import android.os.WorkSource;\n");
-
- // SparseArray is used for writing KeyValuePairs; not supported for Mainline modules.
- fprintf(out, "import android.util.SparseArray;\n");
- fprintf(out, "import android.util.SparseIntArray;\n");
- fprintf(out, "import android.util.SparseLongArray;\n");
- }
-
fprintf(out, "import android.util.StatsEvent;\n");
fprintf(out, "import android.util.StatsLog;\n");
- if (DEFAULT_MODULE_NAME == moduleName) {
- // List is used for WorkSource writing. Only needed for default module.
- fprintf(out, "\n");
- fprintf(out, "import java.util.ArrayList;\n");
- }
-
fprintf(out, "\n");
fprintf(out, "\n");
fprintf(out, "/**\n");
@@ -280,7 +290,7 @@
out, atoms.signatures_to_modules, attributionDecl, moduleName, supportQ);
errors += write_java_non_chained_methods(
out, atoms.non_chained_signatures_to_modules, moduleName);
- if (DEFAULT_MODULE_NAME == moduleName) {
+ if (supportWorkSource) {
errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName);
}
diff --git a/tools/stats_log_api_gen/java_writer.h b/tools/stats_log_api_gen/java_writer.h
index 9324b23..5b78f05 100644
--- a/tools/stats_log_api_gen/java_writer.h
+++ b/tools/stats_log_api_gen/java_writer.h
@@ -31,8 +31,9 @@
using namespace std;
int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& javaClass,
- const string& javaPackage, const bool supportQ);
+ const string& moduleName, const string& javaClass,
+ const string& javaPackage, const bool supportQ,
+ const bool supportWorkSource);
} // namespace stats_log_api_gen
} // namespace android
diff --git a/tools/stats_log_api_gen/java_writer_q.cpp b/tools/stats_log_api_gen/java_writer_q.cpp
index d6899f6..db766b2 100644
--- a/tools/stats_log_api_gen/java_writer_q.cpp
+++ b/tools/stats_log_api_gen/java_writer_q.cpp
@@ -361,6 +361,50 @@
}
}
+// This method is called in main.cpp to generate StatsLog for modules that's compatible with
+// Q at compile-time.
+int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
+ const AtomDecl &attributionDecl, const string& moduleName,
+ const string& javaClass, const string& javaPackage,
+ const bool supportWorkSource) {
+ // Print prelude
+ fprintf(out, "// This file is autogenerated\n");
+ fprintf(out, "\n");
+ fprintf(out, "package %s;\n", javaPackage.c_str());
+ fprintf(out, "\n");
+ fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n");
+ fprintf(out, "\n");
+ fprintf(out, "import android.util.StatsLog;\n");
+ fprintf(out, "import android.os.SystemClock;\n");
+ fprintf(out, "\n");
+ fprintf(out, "\n");
+ fprintf(out, "/**\n");
+ fprintf(out, " * Utility class for logging statistics events.\n");
+ fprintf(out, " */\n");
+ fprintf(out, "public class %s {\n", javaClass.c_str());
+
+ write_java_q_logging_constants(out, " ");
+
+ write_java_atom_codes(out, atoms, moduleName);
+
+ write_java_enum_values(out, atoms, moduleName);
+
+ int errors = 0;
+ // Print write methods
+ fprintf(out, " // Write methods\n");
+ errors += write_java_methods_q_schema(out, atoms.signatures_to_modules, attributionDecl,
+ moduleName, " ");
+ errors += write_java_non_chained_methods(out, atoms.non_chained_signatures_to_modules,
+ moduleName);
+ if (supportWorkSource) {
+ errors += write_java_work_source_methods(out, atoms.signatures_to_modules, moduleName);
+ }
+
+ fprintf(out, "}\n");
+
+ return errors;
+}
+
#if defined(STATS_SCHEMA_LEGACY)
static void write_java_method(
FILE* out,
@@ -382,7 +426,7 @@
java_type_name(chainField.javaType), chainField.name.c_str());
}
} else if (*arg == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", SparseArray<Object> value_map");
+ fprintf(out, ", android.util.SparseArray<Object> value_map");
} else {
fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
}
@@ -393,16 +437,13 @@
}
}
-int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl) {
+int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const bool supportWorkSource) {
// Print prelude
fprintf(out, "// This file is autogenerated\n");
fprintf(out, "\n");
fprintf(out, "package android.util;\n");
fprintf(out, "\n");
- fprintf(out, "import android.os.WorkSource;\n");
- fprintf(out, "import android.util.SparseArray;\n");
- fprintf(out, "import java.util.ArrayList;\n");
- fprintf(out, "\n");
fprintf(out, "\n");
fprintf(out, "/**\n");
fprintf(out, " * API For logging statistics events.\n");
@@ -418,52 +459,14 @@
write_java_method(out, "write", atoms.signatures_to_modules, attributionDecl);
write_java_method(out, "write_non_chained", atoms.non_chained_signatures_to_modules,
attributionDecl);
- write_java_work_source_methods(out, atoms.signatures_to_modules, DEFAULT_MODULE_NAME);
+ if (supportWorkSource) {
+ write_java_work_source_methods(out, atoms.signatures_to_modules, DEFAULT_MODULE_NAME);
+ }
fprintf(out, "}\n");
return 0;
}
-
-int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
- const string& moduleName, const string& javaClass,
- const string& javaPackage) {
- // Print prelude
- fprintf(out, "// This file is autogenerated\n");
- fprintf(out, "\n");
- fprintf(out, "package %s;\n", javaPackage.c_str());
- fprintf(out, "\n");
- fprintf(out, "import static java.nio.charset.StandardCharsets.UTF_8;\n");
- fprintf(out, "\n");
- fprintf(out, "import android.util.StatsLog;\n");
- fprintf(out, "import android.os.SystemClock;\n");
- fprintf(out, "\n");
- fprintf(out, "import java.util.ArrayList;\n");
- fprintf(out, "\n");
- fprintf(out, "\n");
- fprintf(out, "/**\n");
- fprintf(out, " * Utility class for logging statistics events.\n");
- fprintf(out, " */\n");
- fprintf(out, "public class %s {\n", javaClass.c_str());
-
- write_java_q_logging_constants(out, " ");
-
- write_java_atom_codes(out, atoms, moduleName);
-
- write_java_enum_values(out, atoms, moduleName);
-
- int errors = 0;
- // Print write methods
- fprintf(out, " // Write methods\n");
- errors += write_java_methods_q_schema(out, atoms.signatures_to_modules, attributionDecl,
- moduleName, " ");
- errors += write_java_non_chained_methods(out, atoms.non_chained_signatures_to_modules,
- moduleName);
-
- fprintf(out, "}\n");
-
- return errors;
-}
#endif
} // namespace stats_log_api_gen
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
index 96ac745..7d734df 100644
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ b/tools/stats_log_api_gen/java_writer_q.h
@@ -45,12 +45,13 @@
const int requiredHelpers,
const string& indent);
-#if defined(STATS_SCHEMA_LEGACY)
-int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl);
-
int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms,
const AtomDecl &attributionDecl, const string& moduleName, const string& javaClass,
- const string& javaPackage);
+ const string& javaPackage, const bool supportWorkSource);
+
+#if defined(STATS_SCHEMA_LEGACY)
+int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const bool supportWorkSource);
#endif
} // namespace stats_log_api_gen
} // namespace android
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 00a3704..ddbf22c 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -511,7 +511,10 @@
fprintf(stderr, " --javaClass CLASS the class name of the java class.\n");
fprintf(stderr, " Optional for Java with module.\n");
fprintf(stderr, " Default is \"StatsLogInternal\"\n");
- fprintf(stderr, " --supportQ Include support for Android Q.\n");
+ fprintf(stderr, " --supportQ Include runtime support for Android Q.\n");
+ fprintf(stderr, " --worksource Include support for logging WorkSource objects.\n");
+ fprintf(stderr, " --compileQ Include compile-time support for Android Q "
+ "(Java only).\n");
}
/**
@@ -534,6 +537,8 @@
string javaPackage = DEFAULT_JAVA_PACKAGE;
string javaClass = DEFAULT_JAVA_CLASS;
bool supportQ = false;
+ bool supportWorkSource = false;
+ bool compileQ = false;
int index = 1;
while (index < argc) {
@@ -626,6 +631,10 @@
atomsInfoCppHeaderImport = argv[index];
} else if (0 == strcmp("--supportQ", argv[index])) {
supportQ = true;
+ } else if (0 == strcmp("--worksource", argv[index])) {
+ supportWorkSource = true;
+ } else if (0 == strcmp("--compileQ", argv[index])) {
+ compileQ = true;
}
index++;
@@ -641,12 +650,18 @@
return 1;
}
- if (DEFAULT_MODULE_NAME == moduleName && supportQ) {
+ if (DEFAULT_MODULE_NAME == moduleName && (supportQ || compileQ)) {
// Support for Q schema is not needed for default module.
fprintf(stderr, "%s cannot support Q schema\n", moduleName.c_str());
return 1;
}
+ if (supportQ && compileQ) {
+ // Runtime Q support is redundant if compile-time Q support is required.
+ fprintf(stderr, "Cannot specify compileQ and supportQ simultaneously.\n");
+ return 1;
+ }
+
// Collate the parameters
Atoms atoms;
int errorCount = collate_atoms(Atom::descriptor(), &atoms);
@@ -728,19 +743,15 @@
fprintf(stderr, "Unable to open file for write: %s\n", javaFilename.c_str());
return 1;
}
- // If this is for a specific module, the java package must also be provided.
- if (moduleName != DEFAULT_MODULE_NAME && javaPackage== DEFAULT_JAVA_PACKAGE) {
- fprintf(stderr, "Must supply --javaPackage if supplying a specific module\n");
- return 1;
- }
#if defined(STATS_SCHEMA_LEGACY)
if (moduleName == DEFAULT_MODULE_NAME) {
errorCount = android::stats_log_api_gen::write_stats_log_java_q(
- out, atoms, attributionDecl);
+ out, atoms, attributionDecl, supportWorkSource);
} else {
errorCount = android::stats_log_api_gen::write_stats_log_java_q_for_module(
- out, atoms, attributionDecl, moduleName, javaClass, javaPackage);
+ out, atoms, attributionDecl, moduleName, javaClass, javaPackage,
+ supportWorkSource);
}
#else
@@ -748,8 +759,15 @@
javaClass = "StatsLogInternal";
javaPackage = "android.util";
}
- errorCount = android::stats_log_api_gen::write_stats_log_java(
- out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ);
+ if (compileQ) {
+ errorCount = android::stats_log_api_gen::write_stats_log_java_q_for_module(
+ out, atoms, attributionDecl, moduleName, javaClass, javaPackage,
+ supportWorkSource);
+ } else {
+ errorCount = android::stats_log_api_gen::write_stats_log_java(
+ out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ,
+ supportWorkSource);
+ }
#endif
fclose(out);
diff --git a/tools/stats_log_api_gen/utils.cpp b/tools/stats_log_api_gen/utils.cpp
index 5b830ee..6414042 100644
--- a/tools/stats_log_api_gen/utils.cpp
+++ b/tools/stats_log_api_gen/utils.cpp
@@ -334,7 +334,7 @@
if (field->javaType == JAVA_TYPE_ATTRIBUTION_CHAIN) {
fprintf(out, ", android.os.WorkSource workSource");
} else if (field->javaType == JAVA_TYPE_KEY_VALUE_PAIR) {
- fprintf(out, ", SparseArray<Object> value_map");
+ fprintf(out, ", android.util.SparseArray<Object> value_map");
} else if (field->javaType == JAVA_TYPE_BYTE_ARRAY) {
fprintf(out, ", byte[] %s", field->name.c_str());
} else {
@@ -442,7 +442,7 @@
for (vector<java_type_t>::const_iterator arg = signature.begin();
arg != signature.end(); arg++) {
if (*arg == JAVA_TYPE_ATTRIBUTION_CHAIN) {
- fprintf(out, ", WorkSource ws");
+ fprintf(out, ", android.os.WorkSource ws");
} else {
fprintf(out, ", %s arg%d", java_type_name(*arg), argIndex);
}
@@ -464,9 +464,10 @@
fprintf(out, " }\n"); // close for-loop
// write() component.
- fprintf(out, " ArrayList<WorkSource.WorkChain> workChains = ws.getWorkChains();\n");
+ fprintf(out, " java.util.ArrayList<android.os.WorkSource.WorkChain> workChains = "
+ "ws.getWorkChains();\n");
fprintf(out, " if (workChains != null) {\n");
- fprintf(out, " for (WorkSource.WorkChain wc : workChains) {\n");
+ fprintf(out, " for (android.os.WorkSource.WorkChain wc : workChains) {\n");
fprintf(out, " write(code");
for (int argIndex = 1; argIndex <= argIndexMax; argIndex++) {
if (argIndex == attributionArg) {