Loading android/app/src/com/android/bluetooth/btservice/AdapterService.java +4 −10 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.AsyncTask; import android.os.BatteryStats; import android.os.BatteryStatsManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; Loading @@ -69,7 +70,6 @@ import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; Loading Loading @@ -108,7 +108,6 @@ import com.android.bluetooth.telephony.BluetoothInCallService; import com.android.bluetooth.vc.VolumeControlService; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.google.protobuf.InvalidProtocolBufferException; Loading Loading @@ -243,7 +242,7 @@ public class AdapterService extends Service { private AlarmManager mAlarmManager; private PendingIntent mPendingAlarm; private IBatteryStats mBatteryStats; private BatteryStatsManager mBatteryStatsManager; private PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; private String mWakeLockName; Loading Loading @@ -502,8 +501,7 @@ public class AdapterService extends Service { getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE); mAlarmManager = getSystemService(AlarmManager.class); mPowerManager = getSystemService(PowerManager.class); mBatteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); mBatteryStatsManager = getSystemService(BatteryStatsManager.class); mBluetoothKeystoreService.initJni(); Loading Loading @@ -627,11 +625,7 @@ public class AdapterService extends Service { mJniCallbacks.init(mBondStateMachine, mRemoteDevices); try { mBatteryStats.noteResetBleScan(); } catch (RemoteException e) { Log.w(TAG, "RemoteException trying to send a reset to BatteryStats"); } mBatteryStatsManager.reportBleScanReset(); BluetoothStatsLog.write_non_chained(BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, -1, null, BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, false, false, false); Loading android/app/src/com/android/bluetooth/gatt/AppScanStats.java +18 −31 Original line number Diff line number Diff line Loading @@ -17,15 +17,13 @@ package com.android.bluetooth.gatt; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanSettings; import android.os.BatteryStatsManager; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.WorkSource; import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.internal.app.IBatteryStats; import java.text.DateFormat; import java.text.SimpleDateFormat; Loading Loading @@ -54,13 +52,14 @@ import java.util.Objects; static final int BALANCED_WEIGHT = 25; static final int LOW_LATENCY_WEIGHT = 100; /* ContextMap here is needed to grab Apps and Connections */ ContextMap mContextMap; // ContextMap here is needed to grab Apps and Connections ContextMap mContextMap; /* GattService is needed to add scan event protos to be dumped later */ GattService mGattService; // GattService is needed to add scan event protos to be dumped later GattService mGattService; /* Battery stats is used to keep track of scans and result stats */ IBatteryStats mBatteryStats; // Battery stats is used to keep track of scans and result stats BatteryStatsManager mBatteryStatsManager; class LastScan { public long duration; Loading Loading @@ -113,7 +112,7 @@ import java.util.Objects; static final int SCAN_TIMEOUT_MS = 30 * 60 * 1000; public String appName; public WorkSource mWorkSource; // Used for BatteryStats and BluetoothStatsLog public WorkSource mWorkSource; // Used for BatteryStatsManager and BluetoothStatsLog private int mScansStarted = 0; private int mScansStopped = 0; public boolean isRegistered = false; Loading Loading @@ -141,7 +140,7 @@ import java.util.Objects; appName = name; mContextMap = map; mGattService = service; mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batterystats")); mBatteryStatsManager = service.getSystemService(BatteryStatsManager.class); if (source == null) { // Bill the caller if the work source isn't passed through Loading @@ -158,11 +157,7 @@ import java.util.Objects; // Only update battery stats after receiving 100 new results in order // to lower the cost of the binder transaction if (scan.results % 100 == 0) { try { mBatteryStats.noteBleScanResults(mWorkSource, 100); } catch (RemoteException e) { /* ignore */ } mBatteryStatsManager.reportBleScanResults(mWorkSource, 100); BluetoothStatsLog.write( BluetoothStatsLog.BLE_SCAN_RESULT_RECEIVED, mWorkSource, 100); } Loading Loading @@ -234,13 +229,9 @@ import java.util.Objects; if (!isScanning()) { mScanStartTime = startTime; } try { boolean isUnoptimized = !(scan.isFilterScan || scan.isBackgroundScan || scan.isOpportunisticScan); mBatteryStats.noteBleScanStarted(mWorkSource, isUnoptimized); } catch (RemoteException e) { /* ignore */ } mBatteryStatsManager.reportBleScanStarted(mWorkSource, isUnoptimized); BluetoothStatsLog.write(BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, mWorkSource, BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__ON, scan.isFilterScan, scan.isBackgroundScan, scan.isOpportunisticScan); Loading Loading @@ -299,15 +290,11 @@ import java.util.Objects; break; } try { // Inform battery stats of any results it might be missing on scan stop boolean isUnoptimized = !(scan.isFilterScan || scan.isBackgroundScan || scan.isOpportunisticScan); mBatteryStats.noteBleScanResults(mWorkSource, scan.results % 100); mBatteryStats.noteBleScanStopped(mWorkSource, isUnoptimized); } catch (RemoteException e) { /* ignore */ } mBatteryStatsManager.reportBleScanResults(mWorkSource, scan.results % 100); mBatteryStatsManager.reportBleScanStopped(mWorkSource, isUnoptimized); BluetoothStatsLog.write( BluetoothStatsLog.BLE_SCAN_RESULT_RECEIVED, mWorkSource, scan.results % 100); BluetoothStatsLog.write(BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, mWorkSource, Loading android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java +11 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.media.AudioManager; import android.os.BatteryStatsManager; import android.os.Binder; import android.os.Looper; import android.os.PowerManager; Loading @@ -46,6 +47,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.Utils; import com.android.internal.app.IBatteryStats; import libcore.util.HexEncoding; Loading Loading @@ -89,6 +91,11 @@ public class AdapterServiceTest { private @Mock AudioManager mAudioManager; private @Mock android.app.Application mApplication; // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the // underlying binder calls. final BatteryStatsManager mBatteryStatsManager = new BatteryStatsManager(mock(IBatteryStats.class)); private static final int CONTEXT_SWITCH_MS = 100; private static final int PROFILE_SERVICE_TOGGLE_TIME_MS = 200; private static final int GATT_START_TIME_MS = 500; Loading Loading @@ -157,6 +164,10 @@ public class AdapterServiceTest { when(mMockContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); when(mMockContext.getSystemServiceName(AudioManager.class)) .thenReturn(Context.AUDIO_SERVICE); when(mMockContext.getSystemService(Context.BATTERY_STATS_SERVICE)) .thenReturn(mBatteryStatsManager); when(mMockContext.getSystemServiceName(BatteryStatsManager.class)) .thenReturn(Context.BATTERY_STATS_SERVICE); doAnswer(invocation -> { Object[] args = invocation.getArguments(); return InstrumentationRegistry.getTargetContext().getDatabasePath((String) args[0]); Loading Loading
android/app/src/com/android/bluetooth/btservice/AdapterService.java +4 −10 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.os.AsyncTask; import android.os.BatteryStats; import android.os.BatteryStatsManager; import android.os.Binder; import android.os.Bundle; import android.os.Handler; Loading @@ -69,7 +70,6 @@ import android.os.PowerManager; import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; Loading Loading @@ -108,7 +108,6 @@ import com.android.bluetooth.telephony.BluetoothInCallService; import com.android.bluetooth.vc.VolumeControlService; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IBatteryStats; import com.google.protobuf.InvalidProtocolBufferException; Loading Loading @@ -243,7 +242,7 @@ public class AdapterService extends Service { private AlarmManager mAlarmManager; private PendingIntent mPendingAlarm; private IBatteryStats mBatteryStats; private BatteryStatsManager mBatteryStatsManager; private PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; private String mWakeLockName; Loading Loading @@ -502,8 +501,7 @@ public class AdapterService extends Service { getAdapterPropertyNative(AbstractionLayer.BT_PROPERTY_CLASS_OF_DEVICE); mAlarmManager = getSystemService(AlarmManager.class); mPowerManager = getSystemService(PowerManager.class); mBatteryStats = IBatteryStats.Stub.asInterface( ServiceManager.getService(BatteryStats.SERVICE_NAME)); mBatteryStatsManager = getSystemService(BatteryStatsManager.class); mBluetoothKeystoreService.initJni(); Loading Loading @@ -627,11 +625,7 @@ public class AdapterService extends Service { mJniCallbacks.init(mBondStateMachine, mRemoteDevices); try { mBatteryStats.noteResetBleScan(); } catch (RemoteException e) { Log.w(TAG, "RemoteException trying to send a reset to BatteryStats"); } mBatteryStatsManager.reportBleScanReset(); BluetoothStatsLog.write_non_chained(BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, -1, null, BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__RESET, false, false, false); Loading
android/app/src/com/android/bluetooth/gatt/AppScanStats.java +18 −31 Original line number Diff line number Diff line Loading @@ -17,15 +17,13 @@ package com.android.bluetooth.gatt; import android.bluetooth.le.ScanFilter; import android.bluetooth.le.ScanSettings; import android.os.BatteryStatsManager; import android.os.Binder; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; import android.os.WorkSource; import com.android.bluetooth.BluetoothMetricsProto; import com.android.bluetooth.BluetoothStatsLog; import com.android.internal.app.IBatteryStats; import java.text.DateFormat; import java.text.SimpleDateFormat; Loading Loading @@ -54,13 +52,14 @@ import java.util.Objects; static final int BALANCED_WEIGHT = 25; static final int LOW_LATENCY_WEIGHT = 100; /* ContextMap here is needed to grab Apps and Connections */ ContextMap mContextMap; // ContextMap here is needed to grab Apps and Connections ContextMap mContextMap; /* GattService is needed to add scan event protos to be dumped later */ GattService mGattService; // GattService is needed to add scan event protos to be dumped later GattService mGattService; /* Battery stats is used to keep track of scans and result stats */ IBatteryStats mBatteryStats; // Battery stats is used to keep track of scans and result stats BatteryStatsManager mBatteryStatsManager; class LastScan { public long duration; Loading Loading @@ -113,7 +112,7 @@ import java.util.Objects; static final int SCAN_TIMEOUT_MS = 30 * 60 * 1000; public String appName; public WorkSource mWorkSource; // Used for BatteryStats and BluetoothStatsLog public WorkSource mWorkSource; // Used for BatteryStatsManager and BluetoothStatsLog private int mScansStarted = 0; private int mScansStopped = 0; public boolean isRegistered = false; Loading Loading @@ -141,7 +140,7 @@ import java.util.Objects; appName = name; mContextMap = map; mGattService = service; mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batterystats")); mBatteryStatsManager = service.getSystemService(BatteryStatsManager.class); if (source == null) { // Bill the caller if the work source isn't passed through Loading @@ -158,11 +157,7 @@ import java.util.Objects; // Only update battery stats after receiving 100 new results in order // to lower the cost of the binder transaction if (scan.results % 100 == 0) { try { mBatteryStats.noteBleScanResults(mWorkSource, 100); } catch (RemoteException e) { /* ignore */ } mBatteryStatsManager.reportBleScanResults(mWorkSource, 100); BluetoothStatsLog.write( BluetoothStatsLog.BLE_SCAN_RESULT_RECEIVED, mWorkSource, 100); } Loading Loading @@ -234,13 +229,9 @@ import java.util.Objects; if (!isScanning()) { mScanStartTime = startTime; } try { boolean isUnoptimized = !(scan.isFilterScan || scan.isBackgroundScan || scan.isOpportunisticScan); mBatteryStats.noteBleScanStarted(mWorkSource, isUnoptimized); } catch (RemoteException e) { /* ignore */ } mBatteryStatsManager.reportBleScanStarted(mWorkSource, isUnoptimized); BluetoothStatsLog.write(BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, mWorkSource, BluetoothStatsLog.BLE_SCAN_STATE_CHANGED__STATE__ON, scan.isFilterScan, scan.isBackgroundScan, scan.isOpportunisticScan); Loading Loading @@ -299,15 +290,11 @@ import java.util.Objects; break; } try { // Inform battery stats of any results it might be missing on scan stop boolean isUnoptimized = !(scan.isFilterScan || scan.isBackgroundScan || scan.isOpportunisticScan); mBatteryStats.noteBleScanResults(mWorkSource, scan.results % 100); mBatteryStats.noteBleScanStopped(mWorkSource, isUnoptimized); } catch (RemoteException e) { /* ignore */ } mBatteryStatsManager.reportBleScanResults(mWorkSource, scan.results % 100); mBatteryStatsManager.reportBleScanStopped(mWorkSource, isUnoptimized); BluetoothStatsLog.write( BluetoothStatsLog.BLE_SCAN_RESULT_RECEIVED, mWorkSource, scan.results % 100); BluetoothStatsLog.write(BluetoothStatsLog.BLE_SCAN_STATE_CHANGED, mWorkSource, Loading
android/app/tests/unit/src/com/android/bluetooth/btservice/AdapterServiceTest.java +11 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.Resources; import android.media.AudioManager; import android.os.BatteryStatsManager; import android.os.Binder; import android.os.Looper; import android.os.PowerManager; Loading @@ -46,6 +47,7 @@ import androidx.test.runner.AndroidJUnit4; import com.android.bluetooth.R; import com.android.bluetooth.TestUtils; import com.android.bluetooth.Utils; import com.android.internal.app.IBatteryStats; import libcore.util.HexEncoding; Loading Loading @@ -89,6 +91,11 @@ public class AdapterServiceTest { private @Mock AudioManager mAudioManager; private @Mock android.app.Application mApplication; // BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the // underlying binder calls. final BatteryStatsManager mBatteryStatsManager = new BatteryStatsManager(mock(IBatteryStats.class)); private static final int CONTEXT_SWITCH_MS = 100; private static final int PROFILE_SERVICE_TOGGLE_TIME_MS = 200; private static final int GATT_START_TIME_MS = 500; Loading Loading @@ -157,6 +164,10 @@ public class AdapterServiceTest { when(mMockContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager); when(mMockContext.getSystemServiceName(AudioManager.class)) .thenReturn(Context.AUDIO_SERVICE); when(mMockContext.getSystemService(Context.BATTERY_STATS_SERVICE)) .thenReturn(mBatteryStatsManager); when(mMockContext.getSystemServiceName(BatteryStatsManager.class)) .thenReturn(Context.BATTERY_STATS_SERVICE); doAnswer(invocation -> { Object[] args = invocation.getArguments(); return InstrumentationRegistry.getTargetContext().getDatabasePath((String) args[0]); Loading