Merge "BatteryStats: Introduce Async external stats requests" into nyc-dev
am: 0d47f4b
* commit '0d47f4b6463077074abd6bed489a5f9243615c64':
BatteryStats: Introduce Async external stats requests
Change-Id: I5fbb54546528942e36293e1fbcbb03290a037823
This commit is contained in:
@@ -156,8 +156,8 @@ public final class BluetoothActivityEnergyInfo implements Parcelable {
|
|||||||
* @return if the record is valid
|
* @return if the record is valid
|
||||||
*/
|
*/
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return ((mControllerTxTimeMs !=0) ||
|
return ((mControllerTxTimeMs >=0) &&
|
||||||
(mControllerRxTimeMs !=0) ||
|
(mControllerRxTimeMs >=0) &&
|
||||||
(mControllerIdleTimeMs !=0));
|
(mControllerIdleTimeMs >=0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,11 +31,14 @@ import android.bluetooth.le.ScanRecord;
|
|||||||
import android.bluetooth.le.ScanResult;
|
import android.bluetooth.le.ScanResult;
|
||||||
import android.bluetooth.le.ScanSettings;
|
import android.bluetooth.le.ScanSettings;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.os.BatteryStats;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
|
import android.os.SynchronousResultReceiver;
|
||||||
import android.os.SystemProperties;
|
import android.os.SystemProperties;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
@@ -53,6 +56,7 @@ import java.util.Locale;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
|
* Represents the local device Bluetooth adapter. The {@link BluetoothAdapter}
|
||||||
@@ -1369,33 +1373,62 @@ public final class BluetoothAdapter {
|
|||||||
*
|
*
|
||||||
* @return a record with {@link BluetoothActivityEnergyInfo} or null if
|
* @return a record with {@link BluetoothActivityEnergyInfo} or null if
|
||||||
* report is unavailable or unsupported
|
* report is unavailable or unsupported
|
||||||
|
* @deprecated use the asynchronous
|
||||||
|
* {@link #requestControllerActivityEnergyInfo(int, ResultReceiver)} instead.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
|
public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) {
|
||||||
if (getState() != STATE_ON) return null;
|
SynchronousResultReceiver receiver = new SynchronousResultReceiver();
|
||||||
|
requestControllerActivityEnergyInfo(updateType, receiver);
|
||||||
|
try {
|
||||||
|
SynchronousResultReceiver.Result result = receiver.awaitResult(1000);
|
||||||
|
if (result.bundle != null) {
|
||||||
|
return result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
|
||||||
|
}
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
Log.e(TAG, "getControllerActivityEnergyInfo timed out");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request the record of {@link BluetoothActivityEnergyInfo} object that
|
||||||
|
* has the activity and energy info. This can be used to ascertain what
|
||||||
|
* the controller has been up to, since the last sample.
|
||||||
|
*
|
||||||
|
* A null value for the activity info object may be sent if the bluetooth service is
|
||||||
|
* unreachable or the device does not support reporting such information.
|
||||||
|
*
|
||||||
|
* @param updateType Type of info, cached vs refreshed.
|
||||||
|
* @param result The callback to which to send the activity info.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public void requestControllerActivityEnergyInfo(int updateType, ResultReceiver result) {
|
||||||
|
if (getState() != STATE_ON) {
|
||||||
|
result.send(0, null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
BluetoothActivityEnergyInfo record;
|
|
||||||
if (!mService.isActivityAndEnergyReportingSupported()) {
|
if (!mService.isActivityAndEnergyReportingSupported()) {
|
||||||
return null;
|
result.send(0, null);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
if (updateType == ACTIVITY_ENERGY_INFO_REFRESHED) {
|
if (updateType == ACTIVITY_ENERGY_INFO_REFRESHED) {
|
||||||
mService.getActivityEnergyInfoFromController();
|
mService.getActivityEnergyInfoFromController();
|
||||||
wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS);
|
wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS);
|
||||||
}
|
}
|
||||||
record = mService.reportActivityInfo();
|
mService.requestActivityInfo(result);
|
||||||
if (record.isValid()) {
|
|
||||||
return record;
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Log.e(TAG, "getControllerActivityEnergyInfoCallback wait interrupted: " + e);
|
Log.e(TAG, "getControllerActivityEnergyInfoCallback wait interrupted: " + e);
|
||||||
|
result.send(0, null);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
|
Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e);
|
||||||
|
result.send(0, null);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.bluetooth.BluetoothDevice;
|
|||||||
import android.bluetooth.OobData;
|
import android.bluetooth.OobData;
|
||||||
import android.os.ParcelUuid;
|
import android.os.ParcelUuid;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* System private API for talking with the Bluetooth service.
|
* System private API for talking with the Bluetooth service.
|
||||||
@@ -104,6 +105,15 @@ interface IBluetooth
|
|||||||
void getActivityEnergyInfoFromController();
|
void getActivityEnergyInfoFromController();
|
||||||
BluetoothActivityEnergyInfo reportActivityInfo();
|
BluetoothActivityEnergyInfo reportActivityInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the controller activity info asynchronously.
|
||||||
|
* The implementor is expected to reply with the
|
||||||
|
* {@link android.bluetooth.BluetoothActivityEnergyInfo} object placed into the Bundle with the
|
||||||
|
* key {@link android.os.BatteryStats#RESULT_RECEIVER_CONTROLLER_KEY}.
|
||||||
|
* The result code is ignored.
|
||||||
|
*/
|
||||||
|
oneway void requestActivityInfo(in ResultReceiver result);
|
||||||
|
|
||||||
void onLeServiceUp();
|
void onLeServiceUp();
|
||||||
void onBrEdrDown();
|
void onBrEdrDown();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,6 +242,8 @@ public abstract class BatteryStats implements Parcelable {
|
|||||||
private static final String VIDEO_DATA = "vid";
|
private static final String VIDEO_DATA = "vid";
|
||||||
private static final String AUDIO_DATA = "aud";
|
private static final String AUDIO_DATA = "aud";
|
||||||
|
|
||||||
|
public static final String RESULT_RECEIVER_CONTROLLER_KEY = "controller_activity";
|
||||||
|
|
||||||
private final StringBuilder mFormatBuilder = new StringBuilder(32);
|
private final StringBuilder mFormatBuilder = new StringBuilder(32);
|
||||||
private final Formatter mFormatter = new Formatter(mFormatBuilder);
|
private final Formatter mFormatter = new Formatter(mFormatBuilder);
|
||||||
|
|
||||||
|
|||||||
80
core/java/android/os/SynchronousResultReceiver.java
Normal file
80
core/java/android/os/SynchronousResultReceiver.java
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||||
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
* the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations under
|
||||||
|
* the License.
|
||||||
|
*/
|
||||||
|
package android.os;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extends ResultReceiver to allow the server end of the ResultReceiver to synchronously wait
|
||||||
|
* on the response from the client. This enables an RPC like system but with the ability to
|
||||||
|
* timeout and discard late results.
|
||||||
|
*
|
||||||
|
* NOTE: Can only be used for one response. Subsequent responses on the same instance are ignored.
|
||||||
|
* {@hide}
|
||||||
|
*/
|
||||||
|
public class SynchronousResultReceiver extends ResultReceiver {
|
||||||
|
public static class Result {
|
||||||
|
public int resultCode;
|
||||||
|
@Nullable public Bundle bundle;
|
||||||
|
|
||||||
|
public Result(int resultCode, @Nullable Bundle bundle) {
|
||||||
|
this.resultCode = resultCode;
|
||||||
|
this.bundle = bundle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final CompletableFuture<Result> mFuture = new CompletableFuture<>();
|
||||||
|
|
||||||
|
public SynchronousResultReceiver() {
|
||||||
|
super((Handler) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
final protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||||
|
super.onReceiveResult(resultCode, resultData);
|
||||||
|
mFuture.complete(new Result(resultCode, resultData));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blocks waiting for the result from the remote client.
|
||||||
|
*
|
||||||
|
* @return the Result
|
||||||
|
* @throws TimeoutException if the timeout in milliseconds expired.
|
||||||
|
*/
|
||||||
|
public @NonNull Result awaitResult(long timeoutMillis) throws TimeoutException {
|
||||||
|
final long deadline = System.currentTimeMillis() + timeoutMillis;
|
||||||
|
while (timeoutMillis >= 0) {
|
||||||
|
try {
|
||||||
|
return mFuture.get(timeoutMillis, TimeUnit.MILLISECONDS);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
// This will NEVER happen.
|
||||||
|
throw new AssertionError("Error receiving response", e);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// The thread was interrupted, try and get the value again, this time
|
||||||
|
// with the remaining time until the deadline.
|
||||||
|
timeoutMillis -= deadline - System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new TimeoutException();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -18,10 +18,13 @@ package com.android.internal.app;
|
|||||||
|
|
||||||
import com.android.internal.os.BatteryStatsImpl;
|
import com.android.internal.os.BatteryStatsImpl;
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothActivityEnergyInfo;
|
||||||
|
import android.net.wifi.WifiActivityEnergyInfo;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.WorkSource;
|
import android.os.WorkSource;
|
||||||
import android.os.health.HealthStatsParceler;
|
import android.os.health.HealthStatsParceler;
|
||||||
import android.telephony.DataConnectionRealTimeInfo;
|
import android.telephony.DataConnectionRealTimeInfo;
|
||||||
|
import android.telephony.ModemActivityInfo;
|
||||||
import android.telephony.SignalStrength;
|
import android.telephony.SignalStrength;
|
||||||
|
|
||||||
interface IBatteryStats {
|
interface IBatteryStats {
|
||||||
@@ -129,4 +132,8 @@ interface IBatteryStats {
|
|||||||
|
|
||||||
HealthStatsParceler takeUidSnapshot(int uid);
|
HealthStatsParceler takeUidSnapshot(int uid);
|
||||||
HealthStatsParceler[] takeUidSnapshots(in int[] uid);
|
HealthStatsParceler[] takeUidSnapshots(in int[] uid);
|
||||||
|
|
||||||
|
oneway void noteBluetoothControllerActivity(in BluetoothActivityEnergyInfo info);
|
||||||
|
oneway void noteModemControllerActivity(in ModemActivityInfo info);
|
||||||
|
oneway void noteWifiControllerActivity(in WifiActivityEnergyInfo info);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package com.android.server.am;
|
package com.android.server.am;
|
||||||
|
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.bluetooth.BluetoothActivityEnergyInfo;
|
import android.bluetooth.BluetoothActivityEnergyInfo;
|
||||||
import android.bluetooth.BluetoothAdapter;
|
import android.bluetooth.BluetoothAdapter;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -32,11 +33,12 @@ import android.os.Message;
|
|||||||
import android.os.Parcel;
|
import android.os.Parcel;
|
||||||
import android.os.ParcelFileDescriptor;
|
import android.os.ParcelFileDescriptor;
|
||||||
import android.os.ParcelFormatException;
|
import android.os.ParcelFormatException;
|
||||||
import android.os.PowerManager;
|
import android.os.Parcelable;
|
||||||
import android.os.PowerManagerInternal;
|
import android.os.PowerManagerInternal;
|
||||||
import android.os.Process;
|
import android.os.Process;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.os.ServiceManager;
|
import android.os.ServiceManager;
|
||||||
|
import android.os.SynchronousResultReceiver;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.os.WorkSource;
|
import android.os.WorkSource;
|
||||||
@@ -56,7 +58,6 @@ import com.android.internal.app.IBatteryStats;
|
|||||||
import com.android.internal.os.BatteryStatsHelper;
|
import com.android.internal.os.BatteryStatsHelper;
|
||||||
import com.android.internal.os.BatteryStatsImpl;
|
import com.android.internal.os.BatteryStatsImpl;
|
||||||
import com.android.internal.os.PowerProfile;
|
import com.android.internal.os.PowerProfile;
|
||||||
import com.android.internal.telephony.ITelephony;
|
|
||||||
import com.android.server.FgThread;
|
import com.android.server.FgThread;
|
||||||
import com.android.server.LocalServices;
|
import com.android.server.LocalServices;
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ import java.nio.charset.CodingErrorAction;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All information we are collecting about things that can happen that impact
|
* All information we are collecting about things that can happen that impact
|
||||||
@@ -81,15 +82,32 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
implements PowerManagerInternal.LowPowerModeListener {
|
implements PowerManagerInternal.LowPowerModeListener {
|
||||||
static final String TAG = "BatteryStatsService";
|
static final String TAG = "BatteryStatsService";
|
||||||
|
|
||||||
static IBatteryStats sService;
|
/**
|
||||||
|
* How long to wait on an individual subsystem to return its stats.
|
||||||
|
*/
|
||||||
|
private static final long EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS = 2000;
|
||||||
|
|
||||||
|
private static IBatteryStats sService;
|
||||||
|
|
||||||
final BatteryStatsImpl mStats;
|
final BatteryStatsImpl mStats;
|
||||||
final BatteryStatsHandler mHandler;
|
private final BatteryStatsHandler mHandler;
|
||||||
Context mContext;
|
private Context mContext;
|
||||||
PowerManagerInternal mPowerManagerInternal;
|
private IWifiManager mWifiManager;
|
||||||
|
private TelephonyManager mTelephony;
|
||||||
|
|
||||||
|
// Lock acquired when extracting data from external sources.
|
||||||
|
private final Object mExternalStatsLock = new Object();
|
||||||
|
|
||||||
|
// WiFi keeps an accumulated total of stats, unlike Bluetooth.
|
||||||
|
// Keep the last WiFi stats so we can compute a delta.
|
||||||
|
@GuardedBy("mExternalStatsLock")
|
||||||
|
private WifiActivityEnergyInfo mLastInfo =
|
||||||
|
new WifiActivityEnergyInfo(0, 0, 0, new long[]{0}, 0, 0, 0);
|
||||||
|
|
||||||
class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
|
class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
|
||||||
public static final int MSG_SYNC_EXTERNAL_STATS = 1;
|
public static final int MSG_SYNC_EXTERNAL_STATS = 1;
|
||||||
public static final int MSG_WRITE_TO_DISK = 2;
|
public static final int MSG_WRITE_TO_DISK = 2;
|
||||||
|
|
||||||
private int mUpdateFlags = 0;
|
private int mUpdateFlags = 0;
|
||||||
private IntArray mUidsToRemove = new IntArray();
|
private IntArray mUidsToRemove = new IntArray();
|
||||||
|
|
||||||
@@ -107,7 +125,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
updateFlags = mUpdateFlags;
|
updateFlags = mUpdateFlags;
|
||||||
mUpdateFlags = 0;
|
mUpdateFlags = 0;
|
||||||
}
|
}
|
||||||
updateExternalStats((String)msg.obj, updateFlags);
|
updateExternalStatsSync((String)msg.obj, updateFlags);
|
||||||
|
|
||||||
// other parts of the system could be calling into us
|
// other parts of the system could be calling into us
|
||||||
// from mStats in order to report of changes. We must grab the mStats
|
// from mStats in order to report of changes. We must grab the mStats
|
||||||
@@ -124,7 +142,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case MSG_WRITE_TO_DISK:
|
case MSG_WRITE_TO_DISK:
|
||||||
updateExternalStats("write", UPDATE_ALL);
|
updateExternalStatsSync("write", UPDATE_ALL);
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
mStats.writeAsyncLocked();
|
mStats.writeAsyncLocked();
|
||||||
}
|
}
|
||||||
@@ -178,16 +196,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
* initialized. So we initialize the low power observer later.
|
* initialized. So we initialize the low power observer later.
|
||||||
*/
|
*/
|
||||||
public void initPowerManagement() {
|
public void initPowerManagement() {
|
||||||
mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class);
|
final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
|
||||||
mPowerManagerInternal.registerLowPowerModeObserver(this);
|
powerMgr.registerLowPowerModeObserver(this);
|
||||||
mStats.notePowerSaveMode(mPowerManagerInternal.getLowPowerModeEnabled());
|
mStats.notePowerSaveMode(powerMgr.getLowPowerModeEnabled());
|
||||||
(new WakeupReasonThread()).start();
|
(new WakeupReasonThread()).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
Slog.w("BatteryStats", "Writing battery stats before shutdown...");
|
Slog.w("BatteryStats", "Writing battery stats before shutdown...");
|
||||||
|
|
||||||
updateExternalStats("shutdown", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
updateExternalStatsSync("shutdown", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
mStats.shutdownLocked();
|
mStats.shutdownLocked();
|
||||||
}
|
}
|
||||||
@@ -287,7 +305,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
//Slog.i("foo", "SENDING BATTERY INFO:");
|
//Slog.i("foo", "SENDING BATTERY INFO:");
|
||||||
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
|
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
|
||||||
Parcel out = Parcel.obtain();
|
Parcel out = Parcel.obtain();
|
||||||
updateExternalStats("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
updateExternalStatsSync("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
mStats.writeToParcel(out, 0);
|
mStats.writeToParcel(out, 0);
|
||||||
}
|
}
|
||||||
@@ -302,7 +320,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
//Slog.i("foo", "SENDING BATTERY INFO:");
|
//Slog.i("foo", "SENDING BATTERY INFO:");
|
||||||
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
|
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
|
||||||
Parcel out = Parcel.obtain();
|
Parcel out = Parcel.obtain();
|
||||||
updateExternalStats("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
updateExternalStatsSync("get-stats", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
mStats.writeToParcel(out, 0);
|
mStats.writeToParcel(out, 0);
|
||||||
}
|
}
|
||||||
@@ -875,6 +893,47 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noteWifiControllerActivity(WifiActivityEnergyInfo info) {
|
||||||
|
enforceCallingPermission();
|
||||||
|
|
||||||
|
if (info == null || !info.isValid()) {
|
||||||
|
Slog.e(TAG, "invalid wifi data given: " + info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (mStats) {
|
||||||
|
mStats.updateWifiStateLocked(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noteBluetoothControllerActivity(BluetoothActivityEnergyInfo info) {
|
||||||
|
enforceCallingPermission();
|
||||||
|
if (info == null || !info.isValid()) {
|
||||||
|
Slog.e(TAG, "invalid bluetooth data given: " + info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (mStats) {
|
||||||
|
mStats.updateBluetoothStateLocked(info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void noteModemControllerActivity(ModemActivityInfo info) {
|
||||||
|
enforceCallingPermission();
|
||||||
|
|
||||||
|
if (info == null || !info.isValid()) {
|
||||||
|
Slog.e(TAG, "invalid modem data given: " + info);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (mStats) {
|
||||||
|
mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isOnBattery() {
|
public boolean isOnBattery() {
|
||||||
return mStats.isOnBattery();
|
return mStats.isOnBattery();
|
||||||
}
|
}
|
||||||
@@ -901,7 +960,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
|
|
||||||
// Sync external stats first as the battery has changed states. If we don't sync
|
// Sync external stats first as the battery has changed states. If we don't sync
|
||||||
// immediately here, we may not collect the relevant data later.
|
// immediately here, we may not collect the relevant data later.
|
||||||
updateExternalStats("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
updateExternalStatsSync("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
|
mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
|
||||||
}
|
}
|
||||||
@@ -1088,9 +1147,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
pw.println("Battery stats reset.");
|
pw.println("Battery stats reset.");
|
||||||
noOutput = true;
|
noOutput = true;
|
||||||
}
|
}
|
||||||
updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
} else if ("--write".equals(arg)) {
|
} else if ("--write".equals(arg)) {
|
||||||
updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
mStats.writeSyncLocked();
|
mStats.writeSyncLocked();
|
||||||
pw.println("Battery stats written.");
|
pw.println("Battery stats written.");
|
||||||
@@ -1154,7 +1213,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
|
flags |= BatteryStats.DUMP_DEVICE_WIFI_ONLY;
|
||||||
}
|
}
|
||||||
// Fetch data from external sources and update the BatteryStatsImpl object with them.
|
// Fetch data from external sources and update the BatteryStatsImpl object with them.
|
||||||
updateExternalStats("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
updateExternalStatsSync("dump", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
@@ -1215,145 +1274,96 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Objects for extracting data from external sources.
|
private WifiActivityEnergyInfo extractDelta(WifiActivityEnergyInfo latest) {
|
||||||
private final Object mExternalStatsLock = new Object();
|
final long timePeriodMs = latest.mTimestamp - mLastInfo.mTimestamp;
|
||||||
|
final long lastIdleMs = mLastInfo.mControllerIdleTimeMs;
|
||||||
|
final long lastTxMs = mLastInfo.mControllerTxTimeMs;
|
||||||
|
final long lastRxMs = mLastInfo.mControllerRxTimeMs;
|
||||||
|
final long lastEnergy = mLastInfo.mControllerEnergyUsed;
|
||||||
|
|
||||||
@GuardedBy("mExternalStatsLock")
|
// We will modify the last info object to be the delta, and store the new
|
||||||
private IWifiManager mWifiManager;
|
// WifiActivityEnergyInfo object as our last one.
|
||||||
|
final WifiActivityEnergyInfo delta = mLastInfo;
|
||||||
|
delta.mTimestamp = latest.getTimeStamp();
|
||||||
|
delta.mStackState = latest.getStackState();
|
||||||
|
|
||||||
// WiFi keeps an accumulated total of stats, unlike Bluetooth.
|
// These times seem to be the most reliable.
|
||||||
// Keep the last WiFi stats so we can compute a delta.
|
delta.mControllerTxTimeMs = latest.mControllerTxTimeMs - lastTxMs;
|
||||||
@GuardedBy("mExternalStatsLock")
|
delta.mControllerRxTimeMs = latest.mControllerRxTimeMs - lastRxMs;
|
||||||
private WifiActivityEnergyInfo mLastInfo =
|
|
||||||
new WifiActivityEnergyInfo(0, 0, 0, new long[]{0}, 0, 0, 0);
|
|
||||||
|
|
||||||
@GuardedBy("mExternalStatsLock")
|
// WiFi calculates the idle time as a difference from the on time and the various
|
||||||
private WifiActivityEnergyInfo pullWifiEnergyInfoLocked() {
|
// Rx + Tx times. There seems to be some missing time there because this sometimes
|
||||||
if (mWifiManager == null) {
|
// becomes negative. Just cap it at 0 and move on.
|
||||||
mWifiManager = IWifiManager.Stub.asInterface(
|
// b/21613534
|
||||||
ServiceManager.getService(Context.WIFI_SERVICE));
|
delta.mControllerIdleTimeMs = Math.max(0, latest.mControllerIdleTimeMs - lastIdleMs);
|
||||||
if (mWifiManager == null) {
|
delta.mControllerEnergyUsed = Math.max(0, latest.mControllerEnergyUsed - lastEnergy);
|
||||||
return null;
|
|
||||||
}
|
if (delta.mControllerTxTimeMs < 0 || delta.mControllerRxTimeMs < 0) {
|
||||||
|
// The stats were reset by the WiFi system (which is why our delta is negative).
|
||||||
|
// Returns the unaltered stats.
|
||||||
|
delta.mControllerEnergyUsed = latest.mControllerEnergyUsed;
|
||||||
|
delta.mControllerRxTimeMs = latest.mControllerRxTimeMs;
|
||||||
|
delta.mControllerTxTimeMs = latest.mControllerTxTimeMs;
|
||||||
|
delta.mControllerIdleTimeMs = latest.mControllerIdleTimeMs;
|
||||||
|
|
||||||
|
Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// There is some accuracy error in reports so allow some slop in the results.
|
||||||
// We read the data even if we are not on battery. This is so that we keep the
|
final long SAMPLE_ERROR_MILLIS = 750;
|
||||||
// correct delta from when we should start reading (aka when we are on battery).
|
final long totalTimeMs = delta.mControllerIdleTimeMs + delta.mControllerRxTimeMs +
|
||||||
WifiActivityEnergyInfo info = mWifiManager.reportActivityInfo();
|
delta.mControllerTxTimeMs;
|
||||||
if (info != null && info.isValid()) {
|
if (totalTimeMs > timePeriodMs + SAMPLE_ERROR_MILLIS) {
|
||||||
if (info.mControllerEnergyUsed < 0 || info.mControllerIdleTimeMs < 0 ||
|
StringBuilder sb = new StringBuilder();
|
||||||
info.mControllerRxTimeMs < 0 || info.mControllerTxTimeMs < 0) {
|
sb.append("Total time ");
|
||||||
Slog.wtf(TAG, "Reported WiFi energy data is invalid: " + info);
|
TimeUtils.formatDuration(totalTimeMs, sb);
|
||||||
return null;
|
sb.append(" is longer than sample period ");
|
||||||
}
|
TimeUtils.formatDuration(timePeriodMs, sb);
|
||||||
|
sb.append(".\n");
|
||||||
final long timePeriodMs = info.mTimestamp - mLastInfo.mTimestamp;
|
sb.append("Previous WiFi snapshot: ").append("idle=");
|
||||||
final long lastIdleMs = mLastInfo.mControllerIdleTimeMs;
|
TimeUtils.formatDuration(lastIdleMs, sb);
|
||||||
final long lastTxMs = mLastInfo.mControllerTxTimeMs;
|
sb.append(" rx=");
|
||||||
final long lastRxMs = mLastInfo.mControllerRxTimeMs;
|
TimeUtils.formatDuration(lastRxMs, sb);
|
||||||
final long lastEnergy = mLastInfo.mControllerEnergyUsed;
|
sb.append(" tx=");
|
||||||
|
TimeUtils.formatDuration(lastTxMs, sb);
|
||||||
// We will modify the last info object to be the delta, and store the new
|
sb.append(" e=").append(lastEnergy);
|
||||||
// WifiActivityEnergyInfo object as our last one.
|
sb.append("\n");
|
||||||
final WifiActivityEnergyInfo result = mLastInfo;
|
sb.append("Current WiFi snapshot: ").append("idle=");
|
||||||
result.mTimestamp = info.getTimeStamp();
|
TimeUtils.formatDuration(latest.mControllerIdleTimeMs, sb);
|
||||||
result.mStackState = info.getStackState();
|
sb.append(" rx=");
|
||||||
|
TimeUtils.formatDuration(latest.mControllerRxTimeMs, sb);
|
||||||
// These times seem to be the most reliable.
|
sb.append(" tx=");
|
||||||
result.mControllerTxTimeMs = info.mControllerTxTimeMs - lastTxMs;
|
TimeUtils.formatDuration(latest.mControllerTxTimeMs, sb);
|
||||||
result.mControllerRxTimeMs = info.mControllerRxTimeMs - lastRxMs;
|
sb.append(" e=").append(latest.mControllerEnergyUsed);
|
||||||
|
Slog.wtf(TAG, sb.toString());
|
||||||
// WiFi calculates the idle time as a difference from the on time and the various
|
|
||||||
// Rx + Tx times. There seems to be some missing time there because this sometimes
|
|
||||||
// becomes negative. Just cap it at 0 and move on.
|
|
||||||
// b/21613534
|
|
||||||
result.mControllerIdleTimeMs = Math.max(0, info.mControllerIdleTimeMs - lastIdleMs);
|
|
||||||
result.mControllerEnergyUsed =
|
|
||||||
Math.max(0, info.mControllerEnergyUsed - lastEnergy);
|
|
||||||
|
|
||||||
if (result.mControllerTxTimeMs < 0 ||
|
|
||||||
result.mControllerRxTimeMs < 0) {
|
|
||||||
// The stats were reset by the WiFi system (which is why our delta is negative).
|
|
||||||
// Returns the unaltered stats.
|
|
||||||
result.mControllerEnergyUsed = info.mControllerEnergyUsed;
|
|
||||||
result.mControllerRxTimeMs = info.mControllerRxTimeMs;
|
|
||||||
result.mControllerTxTimeMs = info.mControllerTxTimeMs;
|
|
||||||
result.mControllerIdleTimeMs = info.mControllerIdleTimeMs;
|
|
||||||
|
|
||||||
Slog.v(TAG, "WiFi energy data was reset, new WiFi energy data is " + result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// There is some accuracy error in reports so allow some slop in the results.
|
|
||||||
final long SAMPLE_ERROR_MILLIS = 750;
|
|
||||||
final long totalTimeMs = result.mControllerIdleTimeMs + result.mControllerRxTimeMs +
|
|
||||||
result.mControllerTxTimeMs;
|
|
||||||
if (totalTimeMs > timePeriodMs + SAMPLE_ERROR_MILLIS) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("Total time ");
|
|
||||||
TimeUtils.formatDuration(totalTimeMs, sb);
|
|
||||||
sb.append(" is longer than sample period ");
|
|
||||||
TimeUtils.formatDuration(timePeriodMs, sb);
|
|
||||||
sb.append(".\n");
|
|
||||||
sb.append("Previous WiFi snapshot: ").append("idle=");
|
|
||||||
TimeUtils.formatDuration(lastIdleMs, sb);
|
|
||||||
sb.append(" rx=");
|
|
||||||
TimeUtils.formatDuration(lastRxMs, sb);
|
|
||||||
sb.append(" tx=");
|
|
||||||
TimeUtils.formatDuration(lastTxMs, sb);
|
|
||||||
sb.append(" e=").append(lastEnergy);
|
|
||||||
sb.append("\n");
|
|
||||||
sb.append("Current WiFi snapshot: ").append("idle=");
|
|
||||||
TimeUtils.formatDuration(info.mControllerIdleTimeMs, sb);
|
|
||||||
sb.append(" rx=");
|
|
||||||
TimeUtils.formatDuration(info.mControllerRxTimeMs, sb);
|
|
||||||
sb.append(" tx=");
|
|
||||||
TimeUtils.formatDuration(info.mControllerTxTimeMs, sb);
|
|
||||||
sb.append(" e=").append(info.mControllerEnergyUsed);
|
|
||||||
Slog.wtf(TAG, sb.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
mLastInfo = info;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
} catch (RemoteException e) {
|
|
||||||
// Nothing to report, WiFi is dead.
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
mLastInfo = latest;
|
||||||
|
return delta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GuardedBy("mExternalStatsLock")
|
/**
|
||||||
private BluetoothActivityEnergyInfo pullBluetoothEnergyInfoLocked() {
|
* Helper method to extract the Parcelable controller info from a
|
||||||
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
* SynchronousResultReceiver.
|
||||||
if (adapter != null) {
|
*/
|
||||||
BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo(
|
private static <T extends Parcelable> T awaitControllerInfo(
|
||||||
BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED);
|
@Nullable SynchronousResultReceiver receiver) throws TimeoutException {
|
||||||
if (info != null && info.isValid()) {
|
if (receiver == null) {
|
||||||
if (info.getControllerEnergyUsed() < 0 || info.getControllerIdleTimeMillis() < 0 ||
|
return null;
|
||||||
info.getControllerRxTimeMillis() < 0 || info.getControllerTxTimeMillis() < 0) {
|
|
||||||
Slog.wtf(TAG, "Bluetooth energy data is invalid: " + info);
|
|
||||||
}
|
|
||||||
return info;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GuardedBy("mExternalStatsLock")
|
final SynchronousResultReceiver.Result result =
|
||||||
private ModemActivityInfo pullModemActivityInfoLocked() {
|
receiver.awaitResult(EXTERNAL_STATS_SYNC_TIMEOUT_MILLIS);
|
||||||
ITelephony tm = ITelephony.Stub.asInterface(ServiceManager.getService(
|
if (result.bundle != null) {
|
||||||
Context.TELEPHONY_SERVICE));
|
// This is the final destination for the Bundle.
|
||||||
try {
|
result.bundle.setDefusable(true);
|
||||||
if (tm != null) {
|
|
||||||
ModemActivityInfo info = tm.getModemActivityInfo();
|
final T data = result.bundle.getParcelable(BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY);
|
||||||
if (info == null || info.isValid()) {
|
if (data != null) {
|
||||||
return info;
|
return data;
|
||||||
}
|
|
||||||
Slog.wtf(TAG, "Modem activity info is invalid: " + info);
|
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
|
||||||
// Nothing to do.
|
|
||||||
}
|
}
|
||||||
|
Slog.e(TAG, "no controller energy info supplied");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1371,58 +1381,108 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
* {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_WIFI},
|
* {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_WIFI},
|
||||||
* and {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_BT}.
|
* and {@link BatteryStatsImpl.ExternalStatsSync#UPDATE_BT}.
|
||||||
*/
|
*/
|
||||||
void updateExternalStats(final String reason, final int updateFlags) {
|
void updateExternalStatsSync(final String reason, int updateFlags) {
|
||||||
|
SynchronousResultReceiver wifiReceiver = null;
|
||||||
|
SynchronousResultReceiver bluetoothReceiver = null;
|
||||||
|
SynchronousResultReceiver modemReceiver = null;
|
||||||
|
|
||||||
synchronized (mExternalStatsLock) {
|
synchronized (mExternalStatsLock) {
|
||||||
if (mContext == null) {
|
if (mContext == null) {
|
||||||
// We haven't started yet (which means the BatteryStatsImpl object has
|
// Don't do any work yet.
|
||||||
// no power profile. Don't consume data we can't compute yet.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BatteryStatsImpl.DEBUG_ENERGY) {
|
|
||||||
Slog.d(TAG, "Updating external stats: reason=" + reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
WifiActivityEnergyInfo wifiEnergyInfo = null;
|
|
||||||
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
|
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
|
||||||
wifiEnergyInfo = pullWifiEnergyInfoLocked();
|
if (mWifiManager == null) {
|
||||||
|
mWifiManager = IWifiManager.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.WIFI_SERVICE));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mWifiManager != null) {
|
||||||
|
try {
|
||||||
|
wifiReceiver = new SynchronousResultReceiver();
|
||||||
|
mWifiManager.requestActivityInfo(wifiReceiver);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// Oh well.
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ModemActivityInfo modemActivityInfo = null;
|
|
||||||
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
|
|
||||||
modemActivityInfo = pullModemActivityInfoLocked();
|
|
||||||
}
|
|
||||||
|
|
||||||
BluetoothActivityEnergyInfo bluetoothEnergyInfo = null;
|
|
||||||
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
|
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
|
||||||
// We only pull bluetooth stats when we have to, as we are not distributing its
|
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
|
||||||
// use amongst apps and the sampling frequency does not matter.
|
if (adapter != null) {
|
||||||
bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked();
|
bluetoothReceiver = new SynchronousResultReceiver();
|
||||||
|
adapter.requestControllerActivityEnergyInfo(
|
||||||
|
BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED,
|
||||||
|
bluetoothReceiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
|
||||||
|
if (mTelephony == null) {
|
||||||
|
mTelephony = TelephonyManager.from(mContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mTelephony != null) {
|
||||||
|
modemReceiver = new SynchronousResultReceiver();
|
||||||
|
mTelephony.requestModemActivityInfo(modemReceiver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WifiActivityEnergyInfo wifiInfo = null;
|
||||||
|
BluetoothActivityEnergyInfo bluetoothInfo = null;
|
||||||
|
ModemActivityInfo modemInfo = null;
|
||||||
|
try {
|
||||||
|
wifiInfo = awaitControllerInfo(wifiReceiver);
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
Slog.w(TAG, "Timeout reading wifi stats");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
bluetoothInfo = awaitControllerInfo(bluetoothReceiver);
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
Slog.w(TAG, "Timeout reading bt stats");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
modemInfo = awaitControllerInfo(modemReceiver);
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
Slog.w(TAG, "Timeout reading modem stats");
|
||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
final long elapsedRealtime = SystemClock.elapsedRealtime();
|
mStats.addHistoryEventLocked(
|
||||||
final long uptime = SystemClock.uptimeMillis();
|
SystemClock.elapsedRealtime(),
|
||||||
if (mStats.mRecordAllHistory) {
|
SystemClock.uptimeMillis(),
|
||||||
mStats.addHistoryEventLocked(elapsedRealtime, uptime,
|
BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS,
|
||||||
BatteryStats.HistoryItem.EVENT_COLLECT_EXTERNAL_STATS, reason, 0);
|
reason, 0);
|
||||||
|
|
||||||
|
mStats.updateCpuTimeLocked();
|
||||||
|
mStats.updateKernelWakelocksLocked();
|
||||||
|
|
||||||
|
if (wifiInfo != null) {
|
||||||
|
if (wifiInfo.isValid()) {
|
||||||
|
mStats.updateWifiStateLocked(extractDelta(wifiInfo));
|
||||||
|
} else {
|
||||||
|
Slog.e(TAG, "wifi info is invalid: " + wifiInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU) != 0) {
|
if (bluetoothInfo != null) {
|
||||||
mStats.updateCpuTimeLocked();
|
if (bluetoothInfo.isValid()) {
|
||||||
mStats.updateKernelWakelocksLocked();
|
mStats.updateBluetoothStateLocked(bluetoothInfo);
|
||||||
|
} else {
|
||||||
|
Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO) != 0) {
|
if (modemInfo != null) {
|
||||||
mStats.updateMobileRadioStateLocked(elapsedRealtime, modemActivityInfo);
|
if (modemInfo.isValid()) {
|
||||||
}
|
mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(),
|
||||||
|
modemInfo);
|
||||||
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
|
} else {
|
||||||
mStats.updateWifiStateLocked(wifiEnergyInfo);
|
Slog.e(TAG, "modem info is invalid: " + modemInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_BT) != 0) {
|
|
||||||
mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1439,7 +1499,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
}
|
}
|
||||||
long ident = Binder.clearCallingIdentity();
|
long ident = Binder.clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
updateExternalStats("get-health-stats-for-uid",
|
updateExternalStatsSync("get-health-stats-for-uid",
|
||||||
BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
return getHealthStatsForUidLocked(requestUid);
|
return getHealthStatsForUidLocked(requestUid);
|
||||||
@@ -1464,7 +1524,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
long ident = Binder.clearCallingIdentity();
|
long ident = Binder.clearCallingIdentity();
|
||||||
int i=-1;
|
int i=-1;
|
||||||
try {
|
try {
|
||||||
updateExternalStats("get-health-stats-for-uids",
|
updateExternalStatsSync("get-health-stats-for-uids",
|
||||||
BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL);
|
||||||
synchronized (mStats) {
|
synchronized (mStats) {
|
||||||
final int N = requestUids.length;
|
final int N = requestUids.length;
|
||||||
@@ -1499,7 +1559,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a HealthStatsParceler for the given uid. You should probably call
|
* Gets a HealthStatsParceler for the given uid. You should probably call
|
||||||
* updateExternalStats first.
|
* updateExternalStatsSync first.
|
||||||
*/
|
*/
|
||||||
HealthStatsParceler getHealthStatsForUidLocked(int requestUid) {
|
HealthStatsParceler getHealthStatsForUidLocked(int requestUid) {
|
||||||
final HealthStatsBatteryStatsWriter writer = new HealthStatsBatteryStatsWriter();
|
final HealthStatsBatteryStatsWriter writer = new HealthStatsBatteryStatsWriter();
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import android.content.ContentResolver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
import android.os.BatteryStats;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.provider.Settings.SettingNotFoundException;
|
import android.provider.Settings.SettingNotFoundException;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
@@ -73,6 +75,14 @@ import java.util.regex.Pattern;
|
|||||||
public class TelephonyManager {
|
public class TelephonyManager {
|
||||||
private static final String TAG = "TelephonyManager";
|
private static final String TAG = "TelephonyManager";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The key to use when placing the result of {@link #requestModemActivityInfo(ResultReceiver)}
|
||||||
|
* into the ResultReceiver Bundle.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String MODEM_ACTIVITY_RESULT_KEY =
|
||||||
|
BatteryStats.RESULT_RECEIVER_CONTROLLER_KEY;
|
||||||
|
|
||||||
private static ITelephonyRegistry sRegistry;
|
private static ITelephonyRegistry sRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -5051,19 +5061,23 @@ public class TelephonyManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the modem activity info.
|
* Requests the modem activity info. The recipient will place the result
|
||||||
|
* in `result`.
|
||||||
|
* @param result The object on which the recipient will send the resulting
|
||||||
|
* {@link android.telephony.ModemActivityInfo} object.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public ModemActivityInfo getModemActivityInfo() {
|
public void requestModemActivityInfo(ResultReceiver result) {
|
||||||
try {
|
try {
|
||||||
ITelephony service = getITelephony();
|
ITelephony service = getITelephony();
|
||||||
if (service != null) {
|
if (service != null) {
|
||||||
return service.getModemActivityInfo();
|
service.requestModemActivityInfo(result);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Error calling ITelephony#getModemActivityInfo", e);
|
Log.e(TAG, "Error calling ITelephony#getModemActivityInfo", e);
|
||||||
}
|
}
|
||||||
return null;
|
result.send(0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package com.android.internal.telephony;
|
|||||||
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.telecom.PhoneAccount;
|
import android.telecom.PhoneAccount;
|
||||||
import android.telecom.PhoneAccountHandle;
|
import android.telecom.PhoneAccountHandle;
|
||||||
@@ -1027,9 +1028,13 @@ interface ITelephony {
|
|||||||
String getLocaleFromDefaultSim();
|
String getLocaleFromDefaultSim();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the modem activity info.
|
* Requests the modem activity info asynchronously.
|
||||||
|
* The implementor is expected to reply with the
|
||||||
|
* {@link android.telephony.ModemActivityInfo} object placed into the Bundle with the key
|
||||||
|
* {@link android.telephony.TelephonyManager#MODEM_ACTIVITY_RESULT_KEY}.
|
||||||
|
* The result code is ignored.
|
||||||
*/
|
*/
|
||||||
ModemActivityInfo getModemActivityInfo();
|
oneway void requestModemActivityInfo(in ResultReceiver result);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the service state on specified subscription
|
* Get the service state on specified subscription
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ import android.net.Network;
|
|||||||
|
|
||||||
import android.net.DhcpInfo;
|
import android.net.DhcpInfo;
|
||||||
|
|
||||||
|
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
import android.os.WorkSource;
|
import android.os.WorkSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,6 +42,14 @@ interface IWifiManager
|
|||||||
|
|
||||||
WifiActivityEnergyInfo reportActivityInfo();
|
WifiActivityEnergyInfo reportActivityInfo();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the controller activity info asynchronously.
|
||||||
|
* The implementor is expected to reply with the
|
||||||
|
* {@link android.net.wifi.WifiActivityEnergyInfo} object placed into the Bundle with the key
|
||||||
|
* {@link android.os.BatteryStats#RESULT_RECEIVER_CONTROLLER_KEY}. The result code is ignored.
|
||||||
|
*/
|
||||||
|
oneway void requestActivityInfo(in ResultReceiver result);
|
||||||
|
|
||||||
List<WifiConfiguration> getConfiguredNetworks();
|
List<WifiConfiguration> getConfiguredNetworks();
|
||||||
|
|
||||||
List<WifiConfiguration> getPrivilegedConfiguredNetworks();
|
List<WifiConfiguration> getPrivilegedConfiguredNetworks();
|
||||||
|
|||||||
@@ -181,8 +181,8 @@ public final class WifiActivityEnergyInfo implements Parcelable {
|
|||||||
* @return if the record is valid
|
* @return if the record is valid
|
||||||
*/
|
*/
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return ((mControllerTxTimeMs !=0) ||
|
return ((mControllerTxTimeMs >=0) &&
|
||||||
(mControllerRxTimeMs !=0) ||
|
(mControllerRxTimeMs >=0) &&
|
||||||
(mControllerIdleTimeMs !=0));
|
(mControllerIdleTimeMs >=0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user