Loading core/java/com/android/internal/os/BatteryStatsImpl.java +16 −18 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.UidTraffic; import android.compat.annotation.UnsupportedAppUsage; Loading @@ -36,7 +37,6 @@ import android.content.IntentFilter; import android.database.ContentObserver; import android.hardware.usb.UsbManager; import android.location.GnssSignalQuality; import android.net.INetworkStatsService; import android.net.NetworkStats; import android.net.Uri; import android.net.wifi.WifiManager; Loading Loading @@ -136,7 +136,9 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Queue; import java.util.Set; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; Loading Loading @@ -11539,19 +11541,11 @@ public class BatteryStatsImpl extends BatteryStats { private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1); @VisibleForTesting protected NetworkStats readNetworkStatsLocked(String[] ifaces) { try { protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager, String[] ifaces) { Objects.requireNonNull(networkStatsManager); if (!ArrayUtils.isEmpty(ifaces)) { INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); if (statsService != null) { return statsService.getDetailedUidStats(ifaces); } else { Slog.e(TAG, "Failed to get networkStatsService "); } } } catch (RemoteException e) { Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e); return networkStatsManager.getDetailedUidStats(Set.of(ifaces)); } return null; } Loading @@ -11561,7 +11555,8 @@ public class BatteryStatsImpl extends BatteryStats { * @param info The energy information from the WiFi controller. */ public void updateWifiState(@Nullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) { final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager) { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces)); } Loading @@ -11569,7 +11564,8 @@ public class BatteryStatsImpl extends BatteryStats { // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; synchronized (mWifiNetworkLock) { final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces); final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager, mWifiIfaces); if (latestStats != null) { delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null, mNetworkStatsPool.acquire()); Loading Loading @@ -11921,7 +11917,8 @@ public class BatteryStatsImpl extends BatteryStats { * Distribute Cell radio energy info and network traffic to apps. */ public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) { final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager) { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating mobile radio stats with " + activityInfo); } Loading @@ -11935,7 +11932,8 @@ public class BatteryStatsImpl extends BatteryStats { // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; synchronized (mModemNetworkLock) { final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces); final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager, mModemIfaces); if (latestStats != null) { delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null, mNetworkStatsPool.acquire()); Loading core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java +7 −2 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.usage.NetworkStatsManager; import android.net.NetworkCapabilities; import android.net.NetworkStats; import android.os.BatteryConsumer; Loading @@ -40,12 +41,15 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @RunWith(AndroidJUnit4.class) @SmallTest public class MobileRadioPowerCalculatorTest { private static final double PRECISION = 0.00001; private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42; @Mock NetworkStatsManager mNetworkStatsManager; @Rule public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() Loading Loading @@ -90,7 +94,8 @@ public class MobileRadioPowerCalculatorTest { ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000, new int[] {100, 200, 300, 400, 500}, 600); stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000); stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000, mNetworkStatsManager); mStatsRule.setTime(12_000_000, 12_000_000); Loading Loading @@ -150,7 +155,7 @@ public class MobileRadioPowerCalculatorTest { ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000, new int[] {100, 200, 300, 400, 500}, 600); stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000); stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000, mNetworkStatsManager); mStatsRule.setTime(12_000_000, 12_000_000); Loading core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +4 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.internal.os; import android.annotation.NonNull; import android.app.usage.NetworkStatsManager; import android.net.NetworkStats; import android.os.Handler; import android.os.Looper; Loading Loading @@ -105,7 +107,8 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { } @Override protected NetworkStats readNetworkStatsLocked(String[] ifaces) { protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager, String[] ifaces) { return mNetworkStats; } Loading core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java +12 −4 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE; import static com.google.common.truth.Truth.assertThat; import android.app.usage.NetworkStatsManager; import android.net.NetworkCapabilities; import android.net.NetworkStats; import android.os.BatteryConsumer; Loading @@ -35,6 +36,7 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @RunWith(AndroidJUnit4.class) @SmallTest Loading @@ -43,6 +45,9 @@ public class WifiPowerCalculatorTest { private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42; @Mock NetworkStatsManager mNetworkStatsManager; @Rule public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE, 360.0) Loading Loading @@ -80,7 +85,8 @@ public class WifiPowerCalculatorTest { final BatteryStatsImpl batteryStats = setupTestNetworkNumbers(); final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo(); batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000); batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000, mNetworkStatsManager); WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); Loading Loading @@ -113,7 +119,7 @@ public class WifiPowerCalculatorTest { final BatteryStatsImpl batteryStats = setupTestNetworkNumbers(); final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo(); batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000); batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000, mNetworkStatsManager); WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(calculator); Loading Loading @@ -160,7 +166,8 @@ public class WifiPowerCalculatorTest { // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively // on the packet counts. batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000); batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000, mNetworkStatsManager); WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); Loading @@ -180,7 +187,8 @@ public class WifiPowerCalculatorTest { // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively // on the packet counts. batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000); batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000, mNetworkStatsManager); WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(calculator); Loading packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java +26 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; import java.util.Set; /** * Provides access to network usage history and statistics. Usage data is collected in Loading Loading @@ -535,6 +536,31 @@ public class NetworkStatsManager { return result; } /** * Query realtime network usage statistics details with interfaces constrains. * Return snapshot of current UID statistics, including any {@link TrafficStats#UID_TETHERING}, * video calling data usage and count of network operations that set by * {@link TrafficStats#incrementOperationCount}. The returned data doesn't include any * statistics that is reported by {@link NetworkStatsProvider}. * * @param requiredIfaces A list of interfaces the stats should be restricted to, or * {@link NetworkStats#INTERFACES_ALL}. * * @hide */ //@SystemApi @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) @NonNull public android.net.NetworkStats getDetailedUidStats( @NonNull Set<String> requiredIfaces) { Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null"); try { return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0])); } catch (RemoteException e) { if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats"); throw e.rethrowFromSystemServer(); } } /** @hide */ public void registerUsageCallback(NetworkTemplate template, int networkType, long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { Loading Loading
core/java/com/android/internal/os/BatteryStatsImpl.java +16 −18 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; import android.app.usage.NetworkStatsManager; import android.bluetooth.BluetoothActivityEnergyInfo; import android.bluetooth.UidTraffic; import android.compat.annotation.UnsupportedAppUsage; Loading @@ -36,7 +37,6 @@ import android.content.IntentFilter; import android.database.ContentObserver; import android.hardware.usb.UsbManager; import android.location.GnssSignalQuality; import android.net.INetworkStatsService; import android.net.NetworkStats; import android.net.Uri; import android.net.wifi.WifiManager; Loading Loading @@ -136,7 +136,9 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Queue; import java.util.Set; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.ReentrantLock; Loading Loading @@ -11539,19 +11541,11 @@ public class BatteryStatsImpl extends BatteryStats { private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1); @VisibleForTesting protected NetworkStats readNetworkStatsLocked(String[] ifaces) { try { protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager, String[] ifaces) { Objects.requireNonNull(networkStatsManager); if (!ArrayUtils.isEmpty(ifaces)) { INetworkStatsService statsService = INetworkStatsService.Stub.asInterface( ServiceManager.getService(Context.NETWORK_STATS_SERVICE)); if (statsService != null) { return statsService.getDetailedUidStats(ifaces); } else { Slog.e(TAG, "Failed to get networkStatsService "); } } } catch (RemoteException e) { Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces) + e); return networkStatsManager.getDetailedUidStats(Set.of(ifaces)); } return null; } Loading @@ -11561,7 +11555,8 @@ public class BatteryStatsImpl extends BatteryStats { * @param info The energy information from the WiFi controller. */ public void updateWifiState(@Nullable final WifiActivityEnergyInfo info, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) { final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager) { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces)); } Loading @@ -11569,7 +11564,8 @@ public class BatteryStatsImpl extends BatteryStats { // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; synchronized (mWifiNetworkLock) { final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces); final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager, mWifiIfaces); if (latestStats != null) { delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null, mNetworkStatsPool.acquire()); Loading Loading @@ -11921,7 +11917,8 @@ public class BatteryStatsImpl extends BatteryStats { * Distribute Cell radio energy info and network traffic to apps. */ public void noteModemControllerActivity(@Nullable final ModemActivityInfo activityInfo, final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs) { final long consumedChargeUC, long elapsedRealtimeMs, long uptimeMs, @NonNull NetworkStatsManager networkStatsManager) { if (DEBUG_ENERGY) { Slog.d(TAG, "Updating mobile radio stats with " + activityInfo); } Loading @@ -11935,7 +11932,8 @@ public class BatteryStatsImpl extends BatteryStats { // Grab a separate lock to acquire the network stats, which may do I/O. NetworkStats delta = null; synchronized (mModemNetworkLock) { final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces); final NetworkStats latestStats = readNetworkStatsLocked(networkStatsManager, mModemIfaces); if (latestStats != null) { delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null, mNetworkStatsPool.acquire()); Loading
core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java +7 −2 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import android.app.usage.NetworkStatsManager; import android.net.NetworkCapabilities; import android.net.NetworkStats; import android.os.BatteryConsumer; Loading @@ -40,12 +41,15 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @RunWith(AndroidJUnit4.class) @SmallTest public class MobileRadioPowerCalculatorTest { private static final double PRECISION = 0.00001; private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42; @Mock NetworkStatsManager mNetworkStatsManager; @Rule public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() Loading Loading @@ -90,7 +94,8 @@ public class MobileRadioPowerCalculatorTest { ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000, new int[] {100, 200, 300, 400, 500}, 600); stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000); stats.noteModemControllerActivity(mai, POWER_DATA_UNAVAILABLE, 10000, 10000, mNetworkStatsManager); mStatsRule.setTime(12_000_000, 12_000_000); Loading Loading @@ -150,7 +155,7 @@ public class MobileRadioPowerCalculatorTest { ModemActivityInfo mai = new ModemActivityInfo(10000, 2000, 3000, new int[] {100, 200, 300, 400, 500}, 600); stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000); stats.noteModemControllerActivity(mai, 10_000_000, 10000, 10000, mNetworkStatsManager); mStatsRule.setTime(12_000_000, 12_000_000); Loading
core/tests/coretests/src/com/android/internal/os/MockBatteryStatsImpl.java +4 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.internal.os; import android.annotation.NonNull; import android.app.usage.NetworkStatsManager; import android.net.NetworkStats; import android.os.Handler; import android.os.Looper; Loading Loading @@ -105,7 +107,8 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl { } @Override protected NetworkStats readNetworkStatsLocked(String[] ifaces) { protected NetworkStats readNetworkStatsLocked(@NonNull NetworkStatsManager networkStatsManager, String[] ifaces) { return mNetworkStats; } Loading
core/tests/coretests/src/com/android/internal/os/WifiPowerCalculatorTest.java +12 −4 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE; import static com.google.common.truth.Truth.assertThat; import android.app.usage.NetworkStatsManager; import android.net.NetworkCapabilities; import android.net.NetworkStats; import android.os.BatteryConsumer; Loading @@ -35,6 +36,7 @@ import androidx.test.runner.AndroidJUnit4; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @RunWith(AndroidJUnit4.class) @SmallTest Loading @@ -43,6 +45,9 @@ public class WifiPowerCalculatorTest { private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42; @Mock NetworkStatsManager mNetworkStatsManager; @Rule public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule() .setAveragePower(PowerProfile.POWER_WIFI_CONTROLLER_IDLE, 360.0) Loading Loading @@ -80,7 +85,8 @@ public class WifiPowerCalculatorTest { final BatteryStatsImpl batteryStats = setupTestNetworkNumbers(); final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo(); batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000); batteryStats.updateWifiState(energyInfo, POWER_DATA_UNAVAILABLE, 1000, 1000, mNetworkStatsManager); WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); Loading Loading @@ -113,7 +119,7 @@ public class WifiPowerCalculatorTest { final BatteryStatsImpl batteryStats = setupTestNetworkNumbers(); final WifiActivityEnergyInfo energyInfo = setupPowerControllerBasedModelEnergyNumbersInfo(); batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000); batteryStats.updateWifiState(energyInfo, 1_000_000, 1000, 1000, mNetworkStatsManager); WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(calculator); Loading Loading @@ -160,7 +166,8 @@ public class WifiPowerCalculatorTest { // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively // on the packet counts. batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000); batteryStats.updateWifiState(/* energyInfo */ null, POWER_DATA_UNAVAILABLE, 1000, 1000, mNetworkStatsManager); WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator); Loading @@ -180,7 +187,8 @@ public class WifiPowerCalculatorTest { // Don't pass WifiActivityEnergyInfo, making WifiPowerCalculator rely exclusively // on the packet counts. batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000); batteryStats.updateWifiState(/* energyInfo */ null, 1_000_000, 1000, 1000, mNetworkStatsManager); WifiPowerCalculator calculator = new WifiPowerCalculator(mStatsRule.getPowerProfile()); mStatsRule.apply(calculator); Loading
packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java +26 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import com.android.net.module.util.NetworkIdentityUtils; import java.util.List; import java.util.Objects; import java.util.Set; /** * Provides access to network usage history and statistics. Usage data is collected in Loading Loading @@ -535,6 +536,31 @@ public class NetworkStatsManager { return result; } /** * Query realtime network usage statistics details with interfaces constrains. * Return snapshot of current UID statistics, including any {@link TrafficStats#UID_TETHERING}, * video calling data usage and count of network operations that set by * {@link TrafficStats#incrementOperationCount}. The returned data doesn't include any * statistics that is reported by {@link NetworkStatsProvider}. * * @param requiredIfaces A list of interfaces the stats should be restricted to, or * {@link NetworkStats#INTERFACES_ALL}. * * @hide */ //@SystemApi @RequiresPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK) @NonNull public android.net.NetworkStats getDetailedUidStats( @NonNull Set<String> requiredIfaces) { Objects.requireNonNull(requiredIfaces, "requiredIfaces cannot be null"); try { return mService.getDetailedUidStats(requiredIfaces.toArray(new String[0])); } catch (RemoteException e) { if (DBG) Log.d(TAG, "Remote exception when get detailed uid stats"); throw e.rethrowFromSystemServer(); } } /** @hide */ public void registerUsageCallback(NetworkTemplate template, int networkType, long thresholdBytes, UsageCallback callback, @Nullable Handler handler) { Loading