Loading core/java/android/bluetooth/BluetoothActivityEnergyInfo.java +3 −3 Original line number Diff line number Diff line Loading @@ -156,8 +156,8 @@ public final class BluetoothActivityEnergyInfo implements Parcelable { * @return if the record is valid */ public boolean isValid() { return ((mControllerTxTimeMs !=0) || (mControllerRxTimeMs !=0) || (mControllerIdleTimeMs !=0)); return ((mControllerTxTimeMs >=0) && (mControllerRxTimeMs >=0) && (mControllerIdleTimeMs >=0)); } } core/java/android/bluetooth/BluetoothAdapter.java +43 −10 Original line number Diff line number Diff line Loading @@ -31,11 +31,14 @@ import android.bluetooth.le.ScanRecord; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.content.Context; import android.os.BatteryStats; import android.os.Binder; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.SynchronousResultReceiver; import android.os.SystemProperties; import android.util.Log; import android.util.Pair; Loading @@ -53,6 +56,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeoutException; /** * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter} Loading Loading @@ -1369,33 +1373,62 @@ public final class BluetoothAdapter { * * @return a record with {@link BluetoothActivityEnergyInfo} or null if * report is unavailable or unsupported * @deprecated use the asynchronous * {@link #requestControllerActivityEnergyInfo(int, ResultReceiver)} instead. * @hide */ @Deprecated public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { if (getState() != STATE_ON) return null; SynchronousResultReceiver receiver = new SynchronousResultReceiver(); requestControllerActivityEnergyInfo(updateType, receiver); try { BluetoothActivityEnergyInfo record; if (!mService.isActivityAndEnergyReportingSupported()) { 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 { if (!mService.isActivityAndEnergyReportingSupported()) { result.send(0, null); return; } synchronized(this) { if (updateType == ACTIVITY_ENERGY_INFO_REFRESHED) { mService.getActivityEnergyInfoFromController(); wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS); } record = mService.reportActivityInfo(); if (record.isValid()) { return record; } else { return null; } mService.requestActivityInfo(result); } } catch (InterruptedException e) { Log.e(TAG, "getControllerActivityEnergyInfoCallback wait interrupted: " + e); result.send(0, null); } catch (RemoteException e) { Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); result.send(0, null); } return null; } /** Loading core/java/android/bluetooth/IBluetooth.aidl +10 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.OobData; import android.os.ParcelUuid; import android.os.ParcelFileDescriptor; import android.os.ResultReceiver; /** * System private API for talking with the Bluetooth service. Loading Loading @@ -104,6 +105,15 @@ interface IBluetooth void getActivityEnergyInfoFromController(); 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 onBrEdrDown(); } core/java/android/os/BatteryStats.java +2 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,8 @@ public abstract class BatteryStats implements Parcelable { private static final String VIDEO_DATA = "vid"; 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 Formatter mFormatter = new Formatter(mFormatBuilder); Loading core/java/android/os/SynchronousResultReceiver.java 0 → 100644 +80 −0 Original line number Diff line number Diff line /* * 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(); } } Loading
core/java/android/bluetooth/BluetoothActivityEnergyInfo.java +3 −3 Original line number Diff line number Diff line Loading @@ -156,8 +156,8 @@ public final class BluetoothActivityEnergyInfo implements Parcelable { * @return if the record is valid */ public boolean isValid() { return ((mControllerTxTimeMs !=0) || (mControllerRxTimeMs !=0) || (mControllerIdleTimeMs !=0)); return ((mControllerTxTimeMs >=0) && (mControllerRxTimeMs >=0) && (mControllerIdleTimeMs >=0)); } }
core/java/android/bluetooth/BluetoothAdapter.java +43 −10 Original line number Diff line number Diff line Loading @@ -31,11 +31,14 @@ import android.bluetooth.le.ScanRecord; import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.content.Context; import android.os.BatteryStats; import android.os.Binder; import android.os.IBinder; import android.os.ParcelUuid; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; import android.os.SynchronousResultReceiver; import android.os.SystemProperties; import android.util.Log; import android.util.Pair; Loading @@ -53,6 +56,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeoutException; /** * Represents the local device Bluetooth adapter. The {@link BluetoothAdapter} Loading Loading @@ -1369,33 +1373,62 @@ public final class BluetoothAdapter { * * @return a record with {@link BluetoothActivityEnergyInfo} or null if * report is unavailable or unsupported * @deprecated use the asynchronous * {@link #requestControllerActivityEnergyInfo(int, ResultReceiver)} instead. * @hide */ @Deprecated public BluetoothActivityEnergyInfo getControllerActivityEnergyInfo(int updateType) { if (getState() != STATE_ON) return null; SynchronousResultReceiver receiver = new SynchronousResultReceiver(); requestControllerActivityEnergyInfo(updateType, receiver); try { BluetoothActivityEnergyInfo record; if (!mService.isActivityAndEnergyReportingSupported()) { 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 { if (!mService.isActivityAndEnergyReportingSupported()) { result.send(0, null); return; } synchronized(this) { if (updateType == ACTIVITY_ENERGY_INFO_REFRESHED) { mService.getActivityEnergyInfoFromController(); wait(CONTROLLER_ENERGY_UPDATE_TIMEOUT_MILLIS); } record = mService.reportActivityInfo(); if (record.isValid()) { return record; } else { return null; } mService.requestActivityInfo(result); } } catch (InterruptedException e) { Log.e(TAG, "getControllerActivityEnergyInfoCallback wait interrupted: " + e); result.send(0, null); } catch (RemoteException e) { Log.e(TAG, "getControllerActivityEnergyInfoCallback: " + e); result.send(0, null); } return null; } /** Loading
core/java/android/bluetooth/IBluetooth.aidl +10 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.OobData; import android.os.ParcelUuid; import android.os.ParcelFileDescriptor; import android.os.ResultReceiver; /** * System private API for talking with the Bluetooth service. Loading Loading @@ -104,6 +105,15 @@ interface IBluetooth void getActivityEnergyInfoFromController(); 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 onBrEdrDown(); }
core/java/android/os/BatteryStats.java +2 −0 Original line number Diff line number Diff line Loading @@ -242,6 +242,8 @@ public abstract class BatteryStats implements Parcelable { private static final String VIDEO_DATA = "vid"; 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 Formatter mFormatter = new Formatter(mFormatBuilder); Loading
core/java/android/os/SynchronousResultReceiver.java 0 → 100644 +80 −0 Original line number Diff line number Diff line /* * 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(); } }