diff options
| -rw-r--r-- | Android.bp | 3 | ||||
| -rw-r--r-- | cmds/statsd/src/atoms.proto | 70 | ||||
| -rw-r--r-- | core/java/android/app/SystemServiceRegistry.java | 8 | ||||
| -rw-r--r-- | core/java/android/bluetooth/BluetoothAdapter.java | 27 | ||||
| -rw-r--r-- | packages/Tethering/common/TetheringLib/jarjar-rules.txt | 1 | ||||
| -rw-r--r-- | packages/Tethering/common/TetheringLib/src/android/net/TetheringManager.java | 216 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/Collation.cpp | 2 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/java_writer.cpp | 60 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/java_writer.h | 5 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/java_writer_q.cpp | 25 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/java_writer_q.h | 5 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/main.cpp | 17 | ||||
| -rw-r--r-- | tools/stats_log_api_gen/utils.cpp | 9 |
13 files changed, 309 insertions, 139 deletions
diff --git a/Android.bp b/Android.bp index 9a0d542277f3..feaafa3f0ea3 100644 --- a/Android.bp +++ b/Android.bp @@ -551,7 +551,7 @@ java_library { 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 @@ filegroup { "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 c72e89b481ee..88d94ccafe25 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -75,9 +75,9 @@ message Atom { // 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 @@ message Atom { 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 @@ message Atom { 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 @@ message Atom { 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 @@ message Atom { 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 2e144461c444..86b2c06ccff2 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -356,11 +356,9 @@ final class SystemServiceRegistry { 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 8415ecd38b75..b6d096c2524a 100644 --- a/core/java/android/bluetooth/BluetoothAdapter.java +++ b/core/java/android/bluetooth/BluetoothAdapter.java @@ -2162,6 +2162,33 @@ public final class BluetoothAdapter { } /** + * 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 35e0f88e70fa..1403bba3445a 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 37ce1d57da36..53a358f29a97 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.os.ResultReceiver; 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.HashMap; 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 @@ import java.util.concurrent.Executor; 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 @@ public class TetheringManager { /** * 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 @@ public class TetheringManager { } 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 @@ public class TetheringManager { } 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 @@ public class TetheringManager { 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 @@ public class TetheringManager { 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 @@ public class TetheringManager { 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 @@ public class TetheringManager { }); } }; - 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 @@ public class TetheringManager { 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 @@ public class TetheringManager { 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 @@ public class TetheringManager { }); } }; - 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 @@ public class TetheringManager { 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 @@ public class TetheringManager { 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 @@ public class TetheringManager { 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 fa556010646c..75deb017e41b 100644 --- a/tools/stats_log_api_gen/Collation.cpp +++ b/tools/stats_log_api_gen/Collation.cpp @@ -434,7 +434,7 @@ int collate_atoms(const Descriptor *descriptor, Atoms *atoms) { 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 fef490c7e5f9..c29936b96c14 100644 --- a/tools/stats_log_api_gen/java_writer.cpp +++ b/tools/stats_log_api_gen/java_writer.cpp @@ -73,7 +73,7 @@ static int write_java_methods( 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 @@ static int write_java_methods( 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 @@ static int write_java_methods( 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 @@ static int write_java_methods( 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 @@ static int write_java_methods( 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 @@ int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attribut 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 @@ int write_stats_log_java(FILE* out, const Atoms& atoms, const AtomDecl &attribut 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 9324b23e4025..5b78f059c5b9 100644 --- a/tools/stats_log_api_gen/java_writer.h +++ b/tools/stats_log_api_gen/java_writer.h @@ -31,8 +31,9 @@ namespace stats_log_api_gen { 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 d6899f6131c6..f8661294821e 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 @@ static void write_java_method( 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 @@ static void write_java_method( } } -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 @@ int write_stats_log_java_q(FILE* out, const Atoms& atoms, const AtomDecl &attrib 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 @@ int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomD 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 @@ int write_stats_log_java_q_for_module(FILE* out, const Atoms& atoms, const AtomD 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 96ac745beef8..36df1d8edbee 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 @@ void write_java_helpers_for_q_schema_methods( 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 00a370484823..6089532e1ca4 100644 --- a/tools/stats_log_api_gen/main.cpp +++ b/tools/stats_log_api_gen/main.cpp @@ -512,6 +512,7 @@ print_usage() 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 @@ run(int argc, char const*const* argv) 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 @@ run(int argc, char const*const* argv) 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 @@ run(int argc, char const*const* argv) 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 @@ run(int argc, char const*const* argv) 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 5b830eef0603..641404280093 100644 --- a/tools/stats_log_api_gen/utils.cpp +++ b/tools/stats_log_api_gen/utils.cpp @@ -334,7 +334,7 @@ void write_java_usage(FILE* out, const string& method_name, const string& atom_c 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 @@ int write_java_work_source_methods( 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 @@ int write_java_work_source_methods( 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) { |