Merge "Support Call Forwarding and Call Waiting APIs for voice call."
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/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/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/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..f866129 100644
--- a/tools/stats_log_api_gen/java_writer_q.cpp
+++ b/tools/stats_log_api_gen/java_writer_q.cpp
@@ -382,7 +382,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 +393,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,16 +415,19 @@
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) {
+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");
@@ -438,8 +438,6 @@
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");
@@ -459,6 +457,9 @@
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");
diff --git a/tools/stats_log_api_gen/java_writer_q.h b/tools/stats_log_api_gen/java_writer_q.h
index 96ac745..36df1d8 100644
--- a/tools/stats_log_api_gen/java_writer_q.h
+++ b/tools/stats_log_api_gen/java_writer_q.h
@@ -46,11 +46,12 @@
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(FILE* out, const Atoms& atoms, const AtomDecl &attributionDecl,
+ const bool supportWorkSource);
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);
#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..6089532 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -512,6 +512,7 @@
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, " --worksource Include support for logging WorkSource objects.\n");
}
/**
@@ -534,6 +535,7 @@
string javaPackage = DEFAULT_JAVA_PACKAGE;
string javaClass = DEFAULT_JAVA_CLASS;
bool supportQ = false;
+ bool supportWorkSource = false;
int index = 1;
while (index < argc) {
@@ -626,6 +628,8 @@
atomsInfoCppHeaderImport = argv[index];
} else if (0 == strcmp("--supportQ", argv[index])) {
supportQ = true;
+ } else if (0 == strcmp("--worksource", argv[index])) {
+ supportWorkSource = true;
}
index++;
@@ -728,19 +732,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
@@ -749,7 +749,8 @@
javaPackage = "android.util";
}
errorCount = android::stats_log_api_gen::write_stats_log_java(
- out, atoms, attributionDecl, moduleName, javaClass, javaPackage, supportQ);
+ 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) {