summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/app/trust/IStrongAuthTracker.aidl26
-rw-r--r--core/java/android/app/trust/ITrustManager.aidl2
-rw-r--r--core/java/android/app/trust/TrustManager.java38
-rw-r--r--core/java/android/hardware/ICameraServiceProxy.aidl7
-rw-r--r--core/java/android/hardware/camera2/CameraCaptureSession.java42
-rw-r--r--core/java/android/hardware/camera2/ICameraDeviceUser.aidl2
-rw-r--r--core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java5
-rw-r--r--core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java5
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java27
-rw-r--r--core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java5
-rw-r--r--core/java/android/hardware/camera2/params/OutputConfiguration.java28
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java59
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl7
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl28
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl4
-rw-r--r--core/java/android/hardware/input/ITabletModeChangedListener.aidl23
-rw-r--r--core/java/android/hardware/input/InputManager.java141
-rw-r--r--core/java/android/hardware/location/ActivityRecognitionHardware.java79
-rw-r--r--core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl36
-rw-r--r--core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl4
-rw-r--r--core/java/android/net/ConnectivityManager.java146
-rw-r--r--core/java/android/net/IConnectivityManager.aidl5
-rw-r--r--core/java/android/net/NetworkAgent.java120
-rw-r--r--core/java/android/net/NetworkCapabilities.java185
-rw-r--r--core/java/android/net/NetworkRequest.java18
-rw-r--r--core/java/android/os/BatteryManager.java7
-rw-r--r--core/java/android/os/BatteryProperties.java4
-rw-r--r--core/java/android/os/BatteryStats.java1
-rw-r--r--core/java/android/os/storage/IMountService.java64
-rw-r--r--core/java/android/os/storage/StorageManager.java18
-rw-r--r--core/java/android/provider/Settings.java8
-rw-r--r--core/java/android/view/ViewRootImpl.java13
-rw-r--r--core/java/com/android/internal/logging/MetricsLogger.java15
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java2
-rw-r--r--core/java/com/android/internal/os/CpuPowerCalculator.java51
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl5
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl4
-rw-r--r--core/java/com/android/internal/widget/LockPatternUtils.java189
38 files changed, 1297 insertions, 126 deletions
diff --git a/core/java/android/app/trust/IStrongAuthTracker.aidl b/core/java/android/app/trust/IStrongAuthTracker.aidl
new file mode 100644
index 0000000..36c71bf
--- /dev/null
+++ b/core/java/android/app/trust/IStrongAuthTracker.aidl
@@ -0,0 +1,26 @@
+/*
+**
+** Copyright 2015, 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.app.trust;
+
+/**
+ * Private API to be notified about strong auth changes
+ *
+ * {@hide}
+ */
+oneway interface IStrongAuthTracker {
+ void onStrongAuthRequiredChanged(int strongAuthRequired, int userId);
+} \ No newline at end of file
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index 32951d9..2dea545 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -26,11 +26,9 @@ import android.app.trust.ITrustListener;
interface ITrustManager {
void reportUnlockAttempt(boolean successful, int userId);
void reportEnabledTrustAgentsChanged(int userId);
- void reportRequireCredentialEntry(int userId);
void registerTrustListener(in ITrustListener trustListener);
void unregisterTrustListener(in ITrustListener trustListener);
void reportKeyguardShowingChanged();
boolean isDeviceLocked(int userId);
boolean isDeviceSecure(int userId);
- boolean hasUserAuthenticatedSinceBoot(int userId);
}
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 8cab565..aff69f0 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -16,13 +16,19 @@
package android.app.trust;
+import android.annotation.IntDef;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.SparseIntArray;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* See {@link com.android.server.trust.TrustManagerService}
@@ -73,21 +79,6 @@ public class TrustManager {
}
/**
- * Reports that trust is disabled until credentials have been entered for user {@param userId}.
- *
- * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
- *
- * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
- */
- public void reportRequireCredentialEntry(int userId) {
- try {
- mService.reportRequireCredentialEntry(userId);
- } catch (RemoteException e) {
- onError(e);
- }
- }
-
- /**
* Reports that the visibility of the keyguard has changed.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
@@ -147,23 +138,6 @@ public class TrustManager {
}
}
- /**
- * Checks whether the specified user has been authenticated since the last boot.
- *
- * @param userId the user id of the user to check for
- * @return true if the user has authenticated since boot, false otherwise
- *
- * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
- */
- public boolean hasUserAuthenticatedSinceBoot(int userId) {
- try {
- return mService.hasUserAuthenticatedSinceBoot(userId);
- } catch (RemoteException e) {
- onError(e);
- return false;
- }
- }
-
private void onError(Exception e) {
Log.e(TAG, "Error while calling TrustManagerService", e);
}
diff --git a/core/java/android/hardware/ICameraServiceProxy.aidl b/core/java/android/hardware/ICameraServiceProxy.aidl
index 0bb24bc..0e654d5 100644
--- a/core/java/android/hardware/ICameraServiceProxy.aidl
+++ b/core/java/android/hardware/ICameraServiceProxy.aidl
@@ -19,6 +19,8 @@ package android.hardware;
/**
* Binder interface for the camera service proxy running in system_server.
*
+ * Keep in sync with frameworks/av/include/camera/ICameraServiceProxy.h
+ *
* @hide
*/
interface ICameraServiceProxy
@@ -27,4 +29,9 @@ interface ICameraServiceProxy
* Ping the service proxy to update the valid users for the camera service.
*/
oneway void pingForUserUpdate();
+
+ /**
+ * Update the status of a camera device
+ */
+ oneway void notifyCameraState(String cameraId, int newCameraState);
}
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 46ffe36..766868d 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -138,6 +138,48 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*/
public abstract void prepare(@NonNull Surface surface) throws CameraAccessException;
+ /**
+ * <p>Pre-allocate at most maxCount buffers for an output Surface.</p>
+ *
+ * <p>Like the {@link #prepare(Surface)} method, this method can be used to allocate output
+ * buffers for a given Surface. However, while the {@link #prepare(Surface)} method allocates
+ * the maximum possible buffer count, this method allocates at most maxCount buffers.</p>
+ *
+ * <p>If maxCount is greater than the possible maximum count (which is the sum of the buffer
+ * count requested by the creator of the Surface and the count requested by the camera device),
+ * only the possible maximum count is allocated, in which case the function acts exactly like
+ * {@link #prepare(Surface)}.</p>
+ *
+ * <p>The restrictions on when this method can be called are the same as for
+ * {@link #prepare(Surface)}.</p>
+ *
+ * <p>Repeated calls to this method are allowed, and a mix of {@link #prepare(Surface)} and
+ * this method is also allowed. Note that after the first call to {@link #prepare(Surface)},
+ * subsequent calls to either prepare method are effectively no-ops. In addition, this method
+ * is not additive in terms of buffer count. This means calling it twice with maxCount = 2
+ * will only allocate 2 buffers, not 4 (assuming the possible maximum is at least 2); to
+ * allocate two buffers on the first call and two on the second, the application needs to call
+ * prepare with prepare(surface, 2) and prepare(surface, 4).</p>
+ *
+ * @param maxCount the buffer count to try to allocate. If this is greater than the possible
+ * maximum for this output, the possible maximum is allocated instead. If
+ * maxCount buffers are already allocated, then prepare will do nothing.
+ * @param surface the output Surface for which buffers should be pre-allocated.
+ *
+ * @throws CameraAccessException if the camera device is no longer connected or has
+ * encountered a fatal error.
+ * @throws IllegalStateException if this session is no longer active, either because the
+ * session was explicitly closed, a new session has been created
+ * or the camera device has been closed.
+ * @throws IllegalArgumentException if the Surface is invalid, not part of this Session,
+ * or has already been used as a target of a CaptureRequest in
+ * this session or immediately prior sessions without an
+ * intervening tearDown call.
+ *
+ * @hide
+ */
+ public abstract void prepare(int maxCount, @NonNull Surface surface)
+ throws CameraAccessException;
/**
* <p>Free all buffers allocated for an output Surface.</p>
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
index 7cb3673..c9c9abc 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -102,4 +102,6 @@ interface ICameraDeviceUser
int prepare(int streamId);
int tearDown(int streamId);
+
+ int prepare2(int maxCount, int streamId);
}
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index d325c77..5573896 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -146,6 +146,11 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession
}
@Override
+ public void prepare(int maxCount, Surface surface) throws CameraAccessException {
+ mDeviceImpl.prepare(maxCount, surface);
+ }
+
+ @Override
public void tearDown(Surface surface) throws CameraAccessException {
mDeviceImpl.tearDown(surface);
}
diff --git a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
index a920e2b..8cd1da5 100644
--- a/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraConstrainedHighSpeedCaptureSessionImpl.java
@@ -169,6 +169,11 @@ public class CameraConstrainedHighSpeedCaptureSessionImpl
}
@Override
+ public void prepare(int maxCount, Surface surface) throws CameraAccessException {
+ mSessionImpl.prepare(maxCount, surface);
+ }
+
+ @Override
public void tearDown(Surface surface) throws CameraAccessException {
mSessionImpl.tearDown(surface);
}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 91d623e..6e02df1 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -679,6 +679,33 @@ public class CameraDeviceImpl extends CameraDevice {
}
}
+ public void prepare(int maxCount, Surface surface) throws CameraAccessException {
+ if (surface == null) throw new IllegalArgumentException("Surface is null");
+ if (maxCount <= 0) throw new IllegalArgumentException("Invalid maxCount given: " +
+ maxCount);
+
+ synchronized(mInterfaceLock) {
+ int streamId = -1;
+ for (int i = 0; i < mConfiguredOutputs.size(); i++) {
+ if (surface == mConfiguredOutputs.valueAt(i).getSurface()) {
+ streamId = mConfiguredOutputs.keyAt(i);
+ break;
+ }
+ }
+ if (streamId == -1) {
+ throw new IllegalArgumentException("Surface is not part of this session");
+ }
+ try {
+ mRemoteDevice.prepare2(maxCount, streamId);
+ } catch (CameraRuntimeException e) {
+ throw e.asChecked();
+ } catch (RemoteException e) {
+ // impossible
+ return;
+ }
+ }
+ }
+
public void tearDown(Surface surface) throws CameraAccessException {
if (surface == null) throw new IllegalArgumentException("Surface is null");
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index e20eaa7..6b8e113 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -636,6 +636,11 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
return CameraBinderDecorator.NO_ERROR;
}
+ public int prepare2(int maxCount, int streamId) {
+ // We don't support this in LEGACY mode.
+ return prepare(streamId);
+ }
+
public int tearDown(int streamId) {
if (DEBUG) {
Log.d(TAG, "tearDown called.");
diff --git a/core/java/android/hardware/camera2/params/OutputConfiguration.java b/core/java/android/hardware/camera2/params/OutputConfiguration.java
index 7aa9787..a04cdce 100644
--- a/core/java/android/hardware/camera2/params/OutputConfiguration.java
+++ b/core/java/android/hardware/camera2/params/OutputConfiguration.java
@@ -19,7 +19,9 @@ package android.hardware.camera2.params;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.utils.HashCodeHelpers;
+import android.hardware.camera2.utils.SurfaceUtils;
import android.util.Log;
+import android.util.Size;
import android.view.Surface;
import android.os.Parcel;
import android.os.Parcelable;
@@ -66,9 +68,7 @@ public final class OutputConfiguration implements Parcelable {
*
*/
public OutputConfiguration(Surface surface) {
- checkNotNull(surface, "Surface must not be null");
- mSurface = surface;
- mRotation = ROTATION_0;
+ this(surface, ROTATION_0);
}
/**
@@ -94,6 +94,9 @@ public final class OutputConfiguration implements Parcelable {
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
mSurface = surface;
mRotation = rotation;
+ mConfiguredSize = SurfaceUtils.getSurfaceSize(surface);
+ mConfiguredFormat = SurfaceUtils.getSurfaceFormat(surface);
+ mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(surface);
}
/**
@@ -106,6 +109,9 @@ public final class OutputConfiguration implements Parcelable {
checkArgumentInRange(rotation, ROTATION_0, ROTATION_270, "Rotation constant");
mSurface = surface;
mRotation = rotation;
+ mConfiguredSize = SurfaceUtils.getSurfaceSize(mSurface);
+ mConfiguredFormat = SurfaceUtils.getSurfaceFormat(mSurface);
+ mConfiguredDataspace = SurfaceUtils.getSurfaceDataspace(mSurface);
}
/**
@@ -163,8 +169,9 @@ public final class OutputConfiguration implements Parcelable {
/**
* Check if this {@link OutputConfiguration} is equal to another {@link OutputConfiguration}.
*
- * <p>Two output configurations are only equal if and only if the underlying surface and
- * all other configuration parameters are equal. </p>
+ * <p>Two output configurations are only equal if and only if the underlying surfaces, surface
+ * properties (width, height, format, dataspace) when the output configurations are created,
+ * and all other configuration parameters are equal. </p>
*
* @return {@code true} if the objects were equal, {@code false} otherwise
*/
@@ -176,7 +183,11 @@ public final class OutputConfiguration implements Parcelable {
return true;
} else if (obj instanceof OutputConfiguration) {
final OutputConfiguration other = (OutputConfiguration) obj;
- return (mSurface == other.mSurface && mRotation == other.mRotation);
+ return mSurface == other.mSurface &&
+ mRotation == other.mRotation &&
+ mConfiguredSize.equals(other.mConfiguredSize) &&
+ mConfiguredFormat == other.mConfiguredFormat &&
+ mConfiguredDataspace == other.mConfiguredDataspace;
}
return false;
}
@@ -192,4 +203,9 @@ public final class OutputConfiguration implements Parcelable {
private static final String TAG = "OutputConfiguration";
private final Surface mSurface;
private final int mRotation;
+
+ // The size, format, and dataspace of the surface when OutputConfiguration is created.
+ private final Size mConfiguredSize;
+ private final int mConfiguredFormat;
+ private final int mConfiguredDataspace;
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 6e29989..1f23c0a 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -392,6 +392,18 @@ public class FingerprintManager {
};
/**
+ * @hide
+ */
+ public static abstract class LockoutResetCallback {
+
+ /**
+ * Called when lockout period expired and clients are allowed to listen for fingerprint
+ * again.
+ */
+ public void onLockoutReset() { }
+ };
+
+ /**
* Request authentication of a crypto object. This call warms up the fingerprint hardware
* and starts scanning for a fingerprint. It terminates when
* {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
@@ -668,6 +680,52 @@ public class FingerprintManager {
return 0;
}
+ /**
+ * Reset the lockout timer when asked to do so by keyguard.
+ *
+ * @param token an opaque token returned by password confirmation.
+ *
+ * @hide
+ */
+ public void resetTimeout(byte[] token) {
+ if (mService != null) {
+ try {
+ mService.resetTimeout(token);
+ } catch (RemoteException e) {
+ Log.v(TAG, "Remote exception in resetTimeout(): ", e);
+ }
+ } else {
+ Log.w(TAG, "resetTimeout(): Service not connected!");
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void addLockoutResetCallback(final LockoutResetCallback callback) {
+ if (mService != null) {
+ try {
+ mService.addLockoutResetCallback(
+ new IFingerprintServiceLockoutResetCallback.Stub() {
+
+ @Override
+ public void onLockoutReset(long deviceId) throws RemoteException {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onLockoutReset();
+ }
+ });
+ }
+ });
+ } catch (RemoteException e) {
+ Log.v(TAG, "Remote exception in addLockoutResetCallback(): ", e);
+ }
+ } else {
+ Log.w(TAG, "addLockoutResetCallback(): Service not connected!");
+ }
+ }
+
private class MyHandler extends Handler {
private MyHandler(Context context) {
super(context.getMainLooper());
@@ -677,6 +735,7 @@ public class FingerprintManager {
super(looper);
}
+ @Override
public void handleMessage(android.os.Message msg) {
switch(msg.what) {
case MSG_ENROLL_RESULT:
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 5e233b8..690a751 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -17,6 +17,7 @@ package android.hardware.fingerprint;
import android.os.Bundle;
import android.hardware.fingerprint.IFingerprintServiceReceiver;
+import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
import android.hardware.fingerprint.Fingerprint;
import java.util.List;
@@ -68,4 +69,10 @@ interface IFingerprintService {
// Gets the authenticator ID for fingerprint
long getAuthenticatorId(String opPackageName);
+
+ // Reset the timeout when user authenticates with strong auth (e.g. PIN, pattern or password)
+ void resetTimeout(in byte [] cryptoToken);
+
+ // Add a callback which gets notified when the fingerprint lockout period expired.
+ void addLockoutResetCallback(IFingerprintServiceLockoutResetCallback callback);
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl
new file mode 100644
index 0000000..c9a5d59
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2015 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.hardware.fingerprint;
+
+import android.hardware.fingerprint.Fingerprint;
+import android.os.Bundle;
+import android.os.UserHandle;
+
+/**
+ * Callback when lockout period expired and clients are allowed to authenticate again.
+ * @hide
+ */
+oneway interface IFingerprintServiceLockoutResetCallback {
+ void onLockoutReset(long deviceId);
+}
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 465d142..c8b45c7 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -19,6 +19,7 @@ package android.hardware.input;
import android.hardware.input.InputDeviceIdentifier;
import android.hardware.input.KeyboardLayout;
import android.hardware.input.IInputDevicesChangedListener;
+import android.hardware.input.ITabletModeChangedListener;
import android.hardware.input.TouchCalibration;
import android.os.IBinder;
import android.view.InputDevice;
@@ -60,6 +61,9 @@ interface IInputManager {
// Registers an input devices changed listener.
void registerInputDevicesChangedListener(IInputDevicesChangedListener listener);
+ // Registers a tablet mode change listener
+ void registerTabletModeChangedListener(ITabletModeChangedListener listener);
+
// Input device vibrator control.
void vibrate(int deviceId, in long[] pattern, int repeat, IBinder token);
void cancelVibrate(int deviceId, IBinder token);
diff --git a/core/java/android/hardware/input/ITabletModeChangedListener.aidl b/core/java/android/hardware/input/ITabletModeChangedListener.aidl
new file mode 100644
index 0000000..a8559a7
--- /dev/null
+++ b/core/java/android/hardware/input/ITabletModeChangedListener.aidl
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2015 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.hardware.input;
+
+/** @hide */
+interface ITabletModeChangedListener {
+ /* Called when the device enters or exits tablet mode. */
+ oneway void onTabletModeChanged(long whenNanos, boolean inTabletMode);
+}
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 444f020..a754d6b 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -16,6 +16,7 @@
package android.hardware.input;
+import com.android.internal.os.SomeArgs;
import com.android.internal.util.ArrayUtils;
import android.annotation.SdkConstant;
@@ -29,6 +30,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.Vibrator;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
@@ -38,6 +40,7 @@ import android.view.InputDevice;
import android.view.InputEvent;
import java.util.ArrayList;
+import java.util.List;
/**
* Provides information about input devices and available key layouts.
@@ -67,6 +70,11 @@ public final class InputManager {
private final ArrayList<InputDeviceListenerDelegate> mInputDeviceListeners =
new ArrayList<InputDeviceListenerDelegate>();
+ // Guarded by mTabletModeLock
+ private final Object mTabletModeLock = new Object();
+ private TabletModeChangedListener mTabletModeChangedListener;
+ private List<OnTabletModeChangedListenerDelegate> mOnTabletModeChangedListeners;
+
/**
* Broadcast Action: Query available keyboard layouts.
* <p>
@@ -331,6 +339,72 @@ public final class InputManager {
}
/**
+ * Register a tablet mode changed listener.
+ *
+ * @param listener The listener to register.
+ * @param handler The handler on which the listener should be invoked, or null
+ * if the listener should be invoked on the calling thread's looper.
+ * @hide
+ */
+ public void registerOnTabletModeChangedListener(
+ OnTabletModeChangedListener listener, Handler handler) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ synchronized (mTabletModeLock) {
+ if (mOnTabletModeChangedListeners == null) {
+ initializeTabletModeListenerLocked();
+ }
+ int idx = findOnTabletModeChangedListenerLocked(listener);
+ if (idx < 0) {
+ OnTabletModeChangedListenerDelegate d =
+ new OnTabletModeChangedListenerDelegate(listener, handler);
+ mOnTabletModeChangedListeners.add(d);
+ }
+ }
+ }
+
+ /**
+ * Unregister a tablet mode changed listener.
+ *
+ * @param listener The listener to unregister.
+ * @hide
+ */
+ public void unregisterOnTabletModeChangedListener(OnTabletModeChangedListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+ synchronized (mTabletModeLock) {
+ int idx = findOnTabletModeChangedListenerLocked(listener);
+ if (idx >= 0) {
+ OnTabletModeChangedListenerDelegate d = mOnTabletModeChangedListeners.remove(idx);
+ d.removeCallbacksAndMessages(null);
+ }
+ }
+ }
+
+ private void initializeTabletModeListenerLocked() {
+ final TabletModeChangedListener listener = new TabletModeChangedListener();
+ try {
+ mIm.registerTabletModeChangedListener(listener);
+ } catch (RemoteException ex) {
+ throw new RuntimeException("Could not register tablet mode changed listener", ex);
+ }
+ mTabletModeChangedListener = listener;
+ mOnTabletModeChangedListeners = new ArrayList<>();
+ }
+
+ private int findOnTabletModeChangedListenerLocked(OnTabletModeChangedListener listener) {
+ final int N = mOnTabletModeChangedListeners.size();
+ for (int i = 0; i < N; i++) {
+ if (mOnTabletModeChangedListeners.get(i).mListener == listener) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
* Gets information about all supported keyboard layouts.
* <p>
* The input manager consults the built-in keyboard layouts as well
@@ -769,6 +843,22 @@ public final class InputManager {
return false;
}
+
+ private void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
+ if (DEBUG) {
+ Log.d(TAG, "Received tablet mode changed: "
+ + "whenNanos=" + whenNanos + ", inTabletMode=" + inTabletMode);
+ }
+ synchronized (mTabletModeLock) {
+ final int N = mOnTabletModeChangedListeners.size();
+ for (int i = 0; i < N; i++) {
+ OnTabletModeChangedListenerDelegate listener =
+ mOnTabletModeChangedListeners.get(i);
+ listener.sendTabletModeChanged(whenNanos, inTabletMode);
+ }
+ }
+ }
+
/**
* Gets a vibrator service associated with an input device, assuming it has one.
* @return The vibrator, never null.
@@ -838,6 +928,57 @@ public final class InputManager {
}
}
+ /** @hide */
+ public interface OnTabletModeChangedListener {
+ /**
+ * Called whenever the device goes into or comes out of tablet mode.
+ *
+ * @param whenNanos The time at which the device transitioned into or
+ * out of tablet mode. This is given in nanoseconds in the
+ * {@link SystemClock#uptimeMillis} time base.
+ */
+ void onTabletModeChanged(long whenNanos, boolean inTabletMode);
+ }
+
+ private final class TabletModeChangedListener extends ITabletModeChangedListener.Stub {
+ @Override
+ public void onTabletModeChanged(long whenNanos, boolean inTabletMode) {
+ InputManager.this.onTabletModeChanged(whenNanos, inTabletMode);
+ }
+ }
+
+ private static final class OnTabletModeChangedListenerDelegate extends Handler {
+ private static final int MSG_TABLET_MODE_CHANGED = 0;
+
+ public final OnTabletModeChangedListener mListener;
+
+ public OnTabletModeChangedListenerDelegate(
+ OnTabletModeChangedListener listener, Handler handler) {
+ super(handler != null ? handler.getLooper() : Looper.myLooper());
+ mListener = listener;
+ }
+
+ public void sendTabletModeChanged(long whenNanos, boolean inTabletMode) {
+ SomeArgs args = SomeArgs.obtain();
+ args.argi1 = (int) (whenNanos & 0xFFFFFFFF);
+ args.argi2 = (int) (whenNanos >> 32);
+ args.arg1 = (Boolean) inTabletMode;
+ obtainMessage(MSG_TABLET_MODE_CHANGED, args).sendToTarget();
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_TABLET_MODE_CHANGED:
+ SomeArgs args = (SomeArgs) msg.obj;
+ long whenNanos = (args.argi1 & 0xFFFFFFFFl) | ((long) args.argi2 << 32);
+ boolean inTabletMode = (boolean) args.arg1;
+ mListener.onTabletModeChanged(whenNanos, inTabletMode);
+ break;
+ }
+ }
+ }
+
private final class InputDeviceVibrator extends Vibrator {
private final int mDeviceId;
private final Binder mToken;
diff --git a/core/java/android/hardware/location/ActivityRecognitionHardware.java b/core/java/android/hardware/location/ActivityRecognitionHardware.java
index 5d3953a..8acd1ff 100644
--- a/core/java/android/hardware/location/ActivityRecognitionHardware.java
+++ b/core/java/android/hardware/location/ActivityRecognitionHardware.java
@@ -30,20 +30,34 @@ import android.util.Log;
* @hide
*/
public class ActivityRecognitionHardware extends IActivityRecognitionHardware.Stub {
- private static final String TAG = "ActivityRecognitionHardware";
+ private static final String TAG = "ActivityRecognitionHW";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
private static final String HARDWARE_PERMISSION = Manifest.permission.LOCATION_HARDWARE;
+ private static final String ENFORCE_HW_PERMISSION_MESSAGE = "Permission '"
+ + HARDWARE_PERMISSION + "' not granted to access ActivityRecognitionHardware";
+
private static final int INVALID_ACTIVITY_TYPE = -1;
private static final int NATIVE_SUCCESS_RESULT = 0;
+ private static final int EVENT_TYPE_DISABLED = 0;
+ private static final int EVENT_TYPE_ENABLED = 1;
+
+ /**
+ * Contains the number of supported Event Types.
+ *
+ * NOTE: increment this counter every time a new EVENT_TYPE_ is added to
+ * com.android.location.provider.ActivityRecognitionProvider
+ */
+ private static final int EVENT_TYPE_COUNT = 3;
- private static ActivityRecognitionHardware sSingletonInstance = null;
+ private static ActivityRecognitionHardware sSingletonInstance;
private static final Object sSingletonInstanceLock = new Object();
private final Context mContext;
+ private final int mSupportedActivitiesCount;
private final String[] mSupportedActivities;
-
- private final RemoteCallbackList<IActivityRecognitionHardwareSink> mSinks =
- new RemoteCallbackList<IActivityRecognitionHardwareSink>();
+ private final int[][] mSupportedActivitiesEnabledEvents;
+ private final SinkList mSinks = new SinkList();
private static class Event {
public int activity;
@@ -56,6 +70,8 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
mContext = context;
mSupportedActivities = fetchSupportedActivities();
+ mSupportedActivitiesCount = mSupportedActivities.length;
+ mSupportedActivitiesEnabledEvents = new int[mSupportedActivitiesCount][EVENT_TYPE_COUNT];
}
public static ActivityRecognitionHardware getInstance(Context context) {
@@ -107,7 +123,11 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
}
int result = nativeEnableActivityEvent(activityType, eventType, reportLatencyNs);
- return result == NATIVE_SUCCESS_RESULT;
+ if (result == NATIVE_SUCCESS_RESULT) {
+ mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_ENABLED;
+ return true;
+ }
+ return false;
}
@Override
@@ -120,7 +140,11 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
}
int result = nativeDisableActivityEvent(activityType, eventType);
- return result == NATIVE_SUCCESS_RESULT;
+ if (result == NATIVE_SUCCESS_RESULT) {
+ mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+ return true;
+ }
+ return false;
}
@Override
@@ -135,7 +159,7 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
*/
private void onActivityChanged(Event[] events) {
if (events == null || events.length == 0) {
- Log.d(TAG, "No events to broadcast for onActivityChanged.");
+ if (DEBUG) Log.d(TAG, "No events to broadcast for onActivityChanged.");
return;
}
@@ -161,7 +185,6 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
}
}
mSinks.finishBroadcast();
-
}
private String getActivityName(int activityType) {
@@ -193,10 +216,7 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
}
private void checkPermissions() {
- String message = String.format(
- "Permission '%s' not granted to access ActivityRecognitionHardware",
- HARDWARE_PERMISSION);
- mContext.enforceCallingPermission(HARDWARE_PERMISSION, message);
+ mContext.enforceCallingPermission(HARDWARE_PERMISSION, ENFORCE_HW_PERMISSION_MESSAGE);
}
private String[] fetchSupportedActivities() {
@@ -208,6 +228,39 @@ public class ActivityRecognitionHardware extends IActivityRecognitionHardware.St
return new String[0];
}
+ private class SinkList extends RemoteCallbackList<IActivityRecognitionHardwareSink> {
+ @Override
+ public void onCallbackDied(IActivityRecognitionHardwareSink callback) {
+ int callbackCount = mSinks.getRegisteredCallbackCount();
+ if (DEBUG) Log.d(TAG, "RegisteredCallbackCount: " + callbackCount);
+ if (callbackCount != 0) {
+ return;
+ }
+ // currently there is only one client for this, so if all its sinks have died, we clean
+ // up after them, this ensures that the AR HAL is not out of sink
+ for (int activity = 0; activity < mSupportedActivitiesCount; ++activity) {
+ for (int event = 0; event < EVENT_TYPE_COUNT; ++event) {
+ disableActivityEventIfEnabled(activity, event);
+ }
+ }
+ }
+
+ private void disableActivityEventIfEnabled(int activityType, int eventType) {
+ if (mSupportedActivitiesEnabledEvents[activityType][eventType] != EVENT_TYPE_ENABLED) {
+ return;
+ }
+
+ int result = nativeDisableActivityEvent(activityType, eventType);
+ mSupportedActivitiesEnabledEvents[activityType][eventType] = EVENT_TYPE_DISABLED;
+ String message = String.format(
+ "DisableActivityEvent: activityType=%d, eventType=%d, result=%d",
+ activityType,
+ eventType,
+ result);
+ Log.e(TAG, message);
+ }
+ }
+
// native bindings
static { nativeClassInit(); }
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
new file mode 100644
index 0000000..d2c3d75
--- /dev/null
+++ b/core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015, 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/license/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.hardware.location;
+
+import android.hardware.location.IActivityRecognitionHardware;
+
+/**
+ * Activity Recognition Hardware client interface.
+ * This interface can be used to receive interfaces to implementations of
+ * {@link IActivityRecognitionHardware}.
+ *
+ * @hide
+ */
+interface IActivityRecognitionHardwareClient {
+ /**
+ * Hardware Activity-Recognition availability event.
+ *
+ * @param isSupported whether the platform has hardware support for the feature
+ * @param instance the available instance to provide access to the feature
+ */
+ void onAvailabilityChanged(in boolean isSupported, in IActivityRecognitionHardware instance);
+}
diff --git a/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl b/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl
index 0507f52..12e3117 100644
--- a/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl
+++ b/core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl
@@ -22,6 +22,8 @@ import android.hardware.location.IActivityRecognitionHardware;
* Activity Recognition Hardware watcher. This interface can be used to receive interfaces to
* implementations of {@link IActivityRecognitionHardware}.
*
+ * @deprecated use {@link IActivityRecognitionHardwareClient} instead.
+
* @hide
*/
interface IActivityRecognitionHardwareWatcher {
@@ -29,4 +31,4 @@ interface IActivityRecognitionHardwareWatcher {
* Hardware Activity-Recognition availability event.
*/
void onInstanceChanged(in IActivityRecognitionHardware instance);
-} \ No newline at end of file
+}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 8e55736..d4e6c82 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -100,6 +100,16 @@ public class ConnectivityManager {
public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
/**
+ * A temporary hack until SUPL system can get off the legacy APIS.
+ * They do too many network requests and the long list of apps listening
+ * and waking due to the CONNECTIVITY_ACTION bcast makes it expensive.
+ * Use this bcast intent instead for SUPL requests.
+ * @hide
+ */
+ public static final String CONNECTIVITY_ACTION_SUPL =
+ "android.net.conn.CONNECTIVITY_CHANGE_SUPL";
+
+ /**
* The device has connected to a network that has presented a captive
* portal, which is blocking Internet connectivity. The user was presented
* with a notification that network sign in is required,
@@ -1181,6 +1191,142 @@ public class ConnectivityManager {
return true;
}
+ /** @hide */
+ public static class PacketKeepaliveCallback {
+ /** The requested keepalive was successfully started. */
+ public void onStarted() {}
+ /** The keepalive was successfully stopped. */
+ public void onStopped() {}
+ /** An error occurred. */
+ public void onError(int error) {}
+ }
+
+ /**
+ * Allows applications to request that the system periodically send specific packets on their
+ * behalf, using hardware offload to save battery power.
+ *
+ * To request that the system send keepalives, call one of the methods that return a
+ * {@link ConnectivityManager.PacketKeepalive} object, such as {@link #startNattKeepalive},
+ * passing in a non-null callback. If the callback is successfully started, the callback's
+ * {@code onStarted} method will be called. If an error occurs, {@code onError} will be called,
+ * specifying one of the {@code ERROR_*} constants in this class.
+ *
+ * To stop an existing keepalive, call {@link stop}. The system will call {@code onStopped} if
+ * the operation was successfull or {@code onError} if an error occurred.
+ *
+ * @hide
+ */
+ public class PacketKeepalive {
+
+ private static final String TAG = "PacketKeepalive";
+
+ /** @hide */
+ public static final int SUCCESS = 0;
+
+ /** @hide */
+ public static final int NO_KEEPALIVE = -1;
+
+ /** @hide */
+ public static final int BINDER_DIED = -10;
+
+ /** The specified {@code Network} is not connected. */
+ public static final int ERROR_INVALID_NETWORK = -20;
+ /** The specified IP addresses are invalid. For example, the specified source IP address is
+ * not configured on the specified {@code Network}. */
+ public static final int ERROR_INVALID_IP_ADDRESS = -21;
+ /** The requested port is invalid. */
+ public static final int ERROR_INVALID_PORT = -22;
+ /** The packet length is invalid (e.g., too long). */
+ public static final int ERROR_INVALID_LENGTH = -23;
+ /** The packet transmission interval is invalid (e.g., too short). */
+ public static final int ERROR_INVALID_INTERVAL = -24;
+
+ /** The hardware does not support this request. */
+ public static final int ERROR_HARDWARE_UNSUPPORTED = -30;
+
+ public static final int NATT_PORT = 4500;
+
+ private final Network mNetwork;
+ private final PacketKeepaliveCallback mCallback;
+ private final Looper mLooper;
+ private final Messenger mMessenger;
+
+ private volatile Integer mSlot;
+
+ void stopLooper() {
+ mLooper.quit();
+ }
+
+ public void stop() {
+ try {
+ mService.stopKeepalive(mNetwork, mSlot);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error stopping packet keepalive: ", e);
+ stopLooper();
+ }
+ }
+
+ private PacketKeepalive(Network network, PacketKeepaliveCallback callback) {
+ checkNotNull(network, "network cannot be null");
+ checkNotNull(callback, "callback cannot be null");
+ mNetwork = network;
+ mCallback = callback;
+ HandlerThread thread = new HandlerThread(TAG);
+ thread.start();
+ mLooper = thread.getLooper();
+ mMessenger = new Messenger(new Handler(mLooper) {
+ @Override
+ public void handleMessage(Message message) {
+ switch (message.what) {
+ case NetworkAgent.EVENT_PACKET_KEEPALIVE:
+ int error = message.arg2;
+ try {
+ if (error == SUCCESS) {
+ if (mSlot == null) {
+ mSlot = message.arg1;
+ mCallback.onStarted();
+ } else {
+ mSlot = null;
+ stopLooper();
+ mCallback.onStopped();
+ }
+ } else {
+ stopLooper();
+ mCallback.onError(error);
+ }
+ } catch (Exception e) {
+ Log.e(TAG, "Exception in keepalive callback(" + error + ")", e);
+ }
+ break;
+ default:
+ Log.e(TAG, "Unhandled message " + Integer.toHexString(message.what));
+ break;
+ }
+ }
+ });
+ }
+ }
+
+ /**
+ * Starts an IPsec NAT-T keepalive packet with the specified parameters.
+ *
+ * @hide
+ */
+ public PacketKeepalive startNattKeepalive(
+ Network network, int intervalSeconds, PacketKeepaliveCallback callback,
+ InetAddress srcAddr, int srcPort, InetAddress dstAddr) {
+ final PacketKeepalive k = new PacketKeepalive(network, callback);
+ try {
+ mService.startNattKeepalive(network, intervalSeconds, k.mMessenger, new Binder(),
+ srcAddr.getHostAddress(), srcPort, dstAddr.getHostAddress());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error starting packet keepalive: ", e);
+ k.stopLooper();
+ return null;
+ }
+ return k;
+ }
+
/**
* Ensure that a network route exists to deliver traffic to the specified
* host via the specified network interface. An attempt to add a route that
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 46c28a6..d4dd669 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -160,4 +160,9 @@ interface IConnectivityManager
boolean setUnderlyingNetworksForVpn(in Network[] networks);
void factoryReset();
+
+ void startNattKeepalive(in Network network, int intervalSeconds, in Messenger messenger,
+ in IBinder binder, String srcAddr, int srcPort, String dstAddr);
+
+ void stopKeepalive(in Network network, int slot);
}
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 808a882..20c2168 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -17,6 +17,7 @@
package android.net;
import android.content.Context;
+import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -25,6 +26,7 @@ import android.util.Log;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
+import android.net.ConnectivityManager.PacketKeepalive;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -143,17 +145,60 @@ public abstract class NetworkAgent extends Handler {
*/
public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9;
- /** Sent by ConnectivityService to the NetworkAgent to inform the agent to pull
+ /**
+ * Sent by ConnectivityService to the NetworkAgent to inform the agent to pull
* the underlying network connection for updated bandwidth information.
*/
public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10;
/**
+ * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent
+ * periodically on the given interval.
+ *
+ * arg1 = the slot number of the keepalive to start
+ * arg2 = interval in seconds
+ * obj = KeepalivePacketData object describing the data to be sent
+ *
+ * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
+ */
+ public static final int CMD_START_PACKET_KEEPALIVE = BASE + 11;
+
+ /**
+ * Requests that the specified keepalive packet be stopped.
+ *
+ * arg1 = slot number of the keepalive to stop.
+ *
+ * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
+ */
+ public static final int CMD_STOP_PACKET_KEEPALIVE = BASE + 12;
+
+ /**
+ * Sent by the NetworkAgent to ConnectivityService to provide status on a packet keepalive
+ * request. This may either be the reply to a CMD_START_PACKET_KEEPALIVE, or an asynchronous
+ * error notification.
+ *
+ * This is also sent by KeepaliveTracker to the app's ConnectivityManager.PacketKeepalive to
+ * so that the app's PacketKeepaliveCallback methods can be called.
+ *
+ * arg1 = slot number of the keepalive
+ * arg2 = error code
+ */
+ public static final int EVENT_PACKET_KEEPALIVE = BASE + 13;
+
+ /**
+ * Sent by ConnectivityService to inform this network transport of signal strength thresholds
+ * that when crossed should trigger a system wakeup and a NetworkCapabilities update.
+ *
+ * obj = int[] describing signal strength thresholds.
+ */
+ public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14;
+
+ /**
* Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid
* automatically reconnecting to this network (e.g. via autojoin). Happens
* when user selects "No" option on the "Stay connected?" dialog box.
*/
- public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 11;
+ public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
NetworkCapabilities nc, LinkProperties lp, int score) {
@@ -249,6 +294,27 @@ public abstract class NetworkAgent extends Handler {
saveAcceptUnvalidated(msg.arg1 != 0);
break;
}
+ case CMD_START_PACKET_KEEPALIVE: {
+ startPacketKeepalive(msg);
+ break;
+ }
+ case CMD_STOP_PACKET_KEEPALIVE: {
+ stopPacketKeepalive(msg);
+ break;
+ }
+
+ case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: {
+ ArrayList<Integer> thresholds =
+ ((Bundle) msg.obj).getIntegerArrayList("thresholds");
+ // TODO: Change signal strength thresholds API to use an ArrayList<Integer>
+ // rather than convert to int[].
+ int[] intThresholds = new int[(thresholds != null) ? thresholds.size() : 0];
+ for (int i = 0; i < intThresholds.length; i++) {
+ intThresholds[i] = thresholds.get(i);
+ }
+ setSignalStrengthThresholds(intThresholds);
+ break;
+ }
case CMD_PREVENT_AUTOMATIC_RECONNECT: {
preventAutomaticReconnect();
break;
@@ -257,13 +323,27 @@ public abstract class NetworkAgent extends Handler {
}
private void queueOrSendMessage(int what, Object obj) {
+ queueOrSendMessage(what, 0, 0, obj);
+ }
+
+ private void queueOrSendMessage(int what, int arg1, int arg2) {
+ queueOrSendMessage(what, arg1, arg2, null);
+ }
+
+ private void queueOrSendMessage(int what, int arg1, int arg2, Object obj) {
+ Message msg = Message.obtain();
+ msg.what = what;
+ msg.arg1 = arg1;
+ msg.arg2 = arg2;
+ msg.obj = obj;
+ queueOrSendMessage(msg);
+ }
+
+ private void queueOrSendMessage(Message msg) {
synchronized (mPreConnectedQueue) {
if (mAsyncChannel != null) {
- mAsyncChannel.sendMessage(what, obj);
+ mAsyncChannel.sendMessage(msg);
} else {
- Message msg = Message.obtain();
- msg.what = what;
- msg.obj = obj;
mPreConnectedQueue.add(msg);
}
}
@@ -378,6 +458,34 @@ public abstract class NetworkAgent extends Handler {
}
/**
+ * Requests that the network hardware send the specified packet at the specified interval.
+ */
+ protected void startPacketKeepalive(Message msg) {
+ onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
+ }
+
+ /**
+ * Requests that the network hardware send the specified packet at the specified interval.
+ */
+ protected void stopPacketKeepalive(Message msg) {
+ onPacketKeepaliveEvent(msg.arg1, PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
+ }
+
+ /**
+ * Called by the network when a packet keepalive event occurs.
+ */
+ public void onPacketKeepaliveEvent(int slot, int reason) {
+ queueOrSendMessage(EVENT_PACKET_KEEPALIVE, slot, reason);
+ }
+
+ /**
+ * Called by ConnectivityService to inform this network transport of signal strength thresholds
+ * that when crossed should trigger a system wakeup and a NetworkCapabilities update.
+ */
+ protected void setSignalStrengthThresholds(int[] thresholds) {
+ }
+
+ /**
* Called when the user asks to not stay connected to this network because it was found to not
* provide Internet access. Usually followed by call to {@code unwanted}. The transport is
* responsible for making sure the device does not automatically reconnect to the same network
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index d0e0cbe..3bd12c0 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -48,6 +48,7 @@ public final class NetworkCapabilities implements Parcelable {
mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
mNetworkSpecifier = nc.mNetworkSpecifier;
+ mSignalStrength = nc.mSignalStrength;
}
}
@@ -60,6 +61,7 @@ public final class NetworkCapabilities implements Parcelable {
mNetworkCapabilities = mTransportTypes = 0;
mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = 0;
mNetworkSpecifier = null;
+ mSignalStrength = SIGNAL_STRENGTH_UNSPECIFIED;
}
/**
@@ -184,6 +186,28 @@ public final class NetworkCapabilities implements Parcelable {
private static final int MAX_NET_CAPABILITY = NET_CAPABILITY_CAPTIVE_PORTAL;
/**
+ * Network capabilities that are expected to be mutable, i.e., can change while a particular
+ * network is connected.
+ */
+ private static final long MUTABLE_CAPABILITIES =
+ // TRUSTED can change when user explicitly connects to an untrusted network in Settings.
+ // http://b/18206275
+ (1 << NET_CAPABILITY_TRUSTED) |
+ (1 << NET_CAPABILITY_VALIDATED) |
+ (1 << NET_CAPABILITY_CAPTIVE_PORTAL);
+
+ /**
+ * Network capabilities that are not allowed in NetworkRequests. This exists because the
+ * NetworkFactory / NetworkAgent model does not deal well with the situation where a
+ * capability's presence cannot be known in advance. If such a capability is requested, then we
+ * can get into a cycle where the NetworkFactory endlessly churns out NetworkAgents that then
+ * get immediately torn down because they do not have the requested capability.
+ */
+ private static final long NON_REQUESTABLE_CAPABILITIES =
+ (1 << NET_CAPABILITY_VALIDATED) |
+ (1 << NET_CAPABILITY_CAPTIVE_PORTAL);
+
+ /**
* Capabilities that are set by default when the object is constructed.
*/
private static final long DEFAULT_CAPABILITIES =
@@ -278,8 +302,31 @@ public final class NetworkCapabilities implements Parcelable {
this.mNetworkCapabilities |= nc.mNetworkCapabilities;
}
- private boolean satisfiedByNetCapabilities(NetworkCapabilities nc) {
- return ((nc.mNetworkCapabilities & this.mNetworkCapabilities) == this.mNetworkCapabilities);
+ /**
+ * Convenience function that returns a human-readable description of the first mutable
+ * capability we find. Used to present an error message to apps that request mutable
+ * capabilities.
+ *
+ * @hide
+ */
+ public String describeFirstNonRequestableCapability() {
+ if (hasCapability(NET_CAPABILITY_VALIDATED)) return "NET_CAPABILITY_VALIDATED";
+ if (hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return "NET_CAPABILITY_CAPTIVE_PORTAL";
+ // This cannot happen unless the preceding checks are incomplete.
+ if ((mNetworkCapabilities & NON_REQUESTABLE_CAPABILITIES) != 0) {
+ return "unknown non-requestable capabilities " + Long.toHexString(mNetworkCapabilities);
+ }
+ if (mLinkUpBandwidthKbps != 0 || mLinkDownBandwidthKbps != 0) return "link bandwidth";
+ if (hasSignalStrength()) return "signalStrength";
+ return null;
+ }
+
+ private boolean satisfiedByNetCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
+ long networkCapabilities = this.mNetworkCapabilities;
+ if (onlyImmutable) {
+ networkCapabilities = networkCapabilities & ~MUTABLE_CAPABILITIES;
+ }
+ return ((nc.mNetworkCapabilities & networkCapabilities) == networkCapabilities);
}
/** @hide */
@@ -287,6 +334,11 @@ public final class NetworkCapabilities implements Parcelable {
return (nc.mNetworkCapabilities == this.mNetworkCapabilities);
}
+ private boolean equalsNetCapabilitiesImmutable(NetworkCapabilities that) {
+ return ((this.mNetworkCapabilities & ~MUTABLE_CAPABILITIES) ==
+ (that.mNetworkCapabilities & ~MUTABLE_CAPABILITIES));
+ }
+
/**
* Removes the NET_CAPABILITY_NOT_RESTRICTED capability if all the capabilities it provides are
* typically provided by restricted networks.
@@ -555,26 +607,130 @@ public final class NetworkCapabilities implements Parcelable {
}
/**
+ * Magic value that indicates no signal strength provided. A request specifying this value is
+ * always satisfied.
+ *
+ * @hide
+ */
+ public static final int SIGNAL_STRENGTH_UNSPECIFIED = Integer.MIN_VALUE;
+
+ /**
+ * Signal strength. This is a signed integer, and higher values indicate better signal.
+ * The exact units are bearer-dependent. For example, Wi-Fi uses RSSI.
+ */
+ private int mSignalStrength;
+
+ /**
+ * Sets the signal strength. This is a signed integer, with higher values indicating a stronger
+ * signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units
+ * reported by WifiManager.
+ * <p>
+ * Note that when used to register a network callback, this specifies the minimum acceptable
+ * signal strength. When received as the state of an existing network it specifies the current
+ * value. A value of code SIGNAL_STRENGTH_UNSPECIFIED} means no value when received and has no
+ * effect when requesting a callback.
+ *
+ * @param signalStrength the bearer-specific signal strength.
+ * @hide
+ */
+ public void setSignalStrength(int signalStrength) {
+ mSignalStrength = signalStrength;
+ }
+
+ /**
+ * Returns {@code true} if this object specifies a signal strength.
+ *
+ * @hide
+ */
+ public boolean hasSignalStrength() {
+ return mSignalStrength > SIGNAL_STRENGTH_UNSPECIFIED;
+ }
+
+ /**
+ * Retrieves the signal strength.
+ *
+ * @return The bearer-specific signal strength.
+ * @hide
+ */
+ public int getSignalStrength() {
+ return mSignalStrength;
+ }
+
+ private void combineSignalStrength(NetworkCapabilities nc) {
+ this.mSignalStrength = Math.max(this.mSignalStrength, nc.mSignalStrength);
+ }
+
+ private boolean satisfiedBySignalStrength(NetworkCapabilities nc) {
+ return this.mSignalStrength <= nc.mSignalStrength;
+ }
+
+ private boolean equalsSignalStrength(NetworkCapabilities nc) {
+ return this.mSignalStrength == nc.mSignalStrength;
+ }
+
+ /**
* Combine a set of Capabilities to this one. Useful for coming up with the complete set
- * {@hide}
+ * @hide
*/
public void combineCapabilities(NetworkCapabilities nc) {
combineNetCapabilities(nc);
combineTransportTypes(nc);
combineLinkBandwidths(nc);
combineSpecifiers(nc);
+ combineSignalStrength(nc);
}
/**
- * Check if our requirements are satisfied by the given Capabilities.
- * {@hide}
+ * Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
+ *
+ * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
+ * @param onlyImmutable if {@code true}, do not consider mutable requirements such as link
+ * bandwidth, signal strength, or validation / captive portal status.
+ *
+ * @hide
*/
- public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
+ private boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc, boolean onlyImmutable) {
return (nc != null &&
- satisfiedByNetCapabilities(nc) &&
+ satisfiedByNetCapabilities(nc, onlyImmutable) &&
satisfiedByTransportTypes(nc) &&
- satisfiedByLinkBandwidths(nc) &&
- satisfiedBySpecifier(nc));
+ (onlyImmutable || satisfiedByLinkBandwidths(nc)) &&
+ satisfiedBySpecifier(nc) &&
+ (onlyImmutable || satisfiedBySignalStrength(nc)));
+ }
+
+ /**
+ * Check if our requirements are satisfied by the given {@code NetworkCapabilities}.
+ *
+ * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
+ *
+ * @hide
+ */
+ public boolean satisfiedByNetworkCapabilities(NetworkCapabilities nc) {
+ return satisfiedByNetworkCapabilities(nc, false);
+ }
+
+ /**
+ * Check if our immutable requirements are satisfied by the given {@code NetworkCapabilities}.
+ *
+ * @param nc the {@code NetworkCapabilities} that may or may not satisfy our requirements.
+ *
+ * @hide
+ */
+ public boolean satisfiedByImmutableNetworkCapabilities(NetworkCapabilities nc) {
+ return satisfiedByNetworkCapabilities(nc, true);
+ }
+
+ /**
+ * Checks that our immutable capabilities are the same as those of the given
+ * {@code NetworkCapabilities}.
+ *
+ * @hide
+ */
+ public boolean equalImmutableCapabilities(NetworkCapabilities nc) {
+ if (nc == null) return false;
+ return (equalsNetCapabilitiesImmutable(nc) &&
+ equalsTransportTypes(nc) &&
+ equalsSpecifier(nc));
}
@Override
@@ -584,6 +740,7 @@ public final class NetworkCapabilities implements Parcelable {
return (equalsNetCapabilities(that) &&
equalsTransportTypes(that) &&
equalsLinkBandwidths(that) &&
+ equalsSignalStrength(that) &&
equalsSpecifier(that));
}
@@ -595,7 +752,8 @@ public final class NetworkCapabilities implements Parcelable {
((int)(mTransportTypes >> 32) * 7) +
(mLinkUpBandwidthKbps * 11) +
(mLinkDownBandwidthKbps * 13) +
- (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17));
+ (TextUtils.isEmpty(mNetworkSpecifier) ? 0 : mNetworkSpecifier.hashCode() * 17) +
+ (mSignalStrength * 19));
}
@Override
@@ -609,7 +767,9 @@ public final class NetworkCapabilities implements Parcelable {
dest.writeInt(mLinkUpBandwidthKbps);
dest.writeInt(mLinkDownBandwidthKbps);
dest.writeString(mNetworkSpecifier);
+ dest.writeInt(mSignalStrength);
}
+
public static final Creator<NetworkCapabilities> CREATOR =
new Creator<NetworkCapabilities>() {
@Override
@@ -621,6 +781,7 @@ public final class NetworkCapabilities implements Parcelable {
netCap.mLinkUpBandwidthKbps = in.readInt();
netCap.mLinkDownBandwidthKbps = in.readInt();
netCap.mNetworkSpecifier = in.readString();
+ netCap.mSignalStrength = in.readInt();
return netCap;
}
@Override
@@ -678,6 +839,8 @@ public final class NetworkCapabilities implements Parcelable {
String specifier = (mNetworkSpecifier == null ?
"" : " Specifier: <" + mNetworkSpecifier + ">");
- return "[" + transports + capabilities + upBand + dnBand + specifier + "]";
+ String signalStrength = (hasSignalStrength() ? " SignalStrength: " + mSignalStrength : "");
+
+ return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength + "]";
}
}
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index e184ec4..7da4818 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -191,6 +191,24 @@ public class NetworkRequest implements Parcelable {
mNetworkCapabilities.setNetworkSpecifier(networkSpecifier);
return this;
}
+
+ /**
+ * Sets the signal strength. This is a signed integer, with higher values indicating a
+ * stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same
+ * RSSI units reported by WifiManager.
+ * <p>
+ * Note that when used to register a network callback, this specifies the minimum acceptable
+ * signal strength. When received as the state of an existing network it specifies the
+ * current value. A value of {@code SIGNAL_STRENGTH_UNSPECIFIED} means no value when
+ * received and has no effect when requesting a callback.
+ *
+ * @param signalStrength the bearer-specific signal strength.
+ * @hide
+ */
+ public Builder setSignalStrength(int signalStrength) {
+ mNetworkCapabilities.setSignalStrength(signalStrength);
+ return this;
+ }
}
// implement the Parcelable interface
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index cccc4be..1f3e9a7 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -101,6 +101,13 @@ public class BatteryManager {
*/
public static final String EXTRA_INVALID_CHARGER = "invalid_charger";
+ /**
+ * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
+ * Int value set to the maximum charging current supported by the charger in micro amperes.
+ * {@hide}
+ */
+ public static final String EXTRA_MAX_CHARGING_CURRENT = "max_charging_current";
+
// values for "status" field in the ACTION_BATTERY_CHANGED Intent
public static final int BATTERY_STATUS_UNKNOWN = 1;
public static final int BATTERY_STATUS_CHARGING = 2;
diff --git a/core/java/android/os/BatteryProperties.java b/core/java/android/os/BatteryProperties.java
index 8f5cf8b..29e868c 100644
--- a/core/java/android/os/BatteryProperties.java
+++ b/core/java/android/os/BatteryProperties.java
@@ -22,6 +22,7 @@ public class BatteryProperties implements Parcelable {
public boolean chargerAcOnline;
public boolean chargerUsbOnline;
public boolean chargerWirelessOnline;
+ public int maxChargingCurrent;
public int batteryStatus;
public int batteryHealth;
public boolean batteryPresent;
@@ -37,6 +38,7 @@ public class BatteryProperties implements Parcelable {
chargerAcOnline = other.chargerAcOnline;
chargerUsbOnline = other.chargerUsbOnline;
chargerWirelessOnline = other.chargerWirelessOnline;
+ maxChargingCurrent = other.maxChargingCurrent;
batteryStatus = other.batteryStatus;
batteryHealth = other.batteryHealth;
batteryPresent = other.batteryPresent;
@@ -55,6 +57,7 @@ public class BatteryProperties implements Parcelable {
chargerAcOnline = p.readInt() == 1 ? true : false;
chargerUsbOnline = p.readInt() == 1 ? true : false;
chargerWirelessOnline = p.readInt() == 1 ? true : false;
+ maxChargingCurrent = p.readInt();
batteryStatus = p.readInt();
batteryHealth = p.readInt();
batteryPresent = p.readInt() == 1 ? true : false;
@@ -68,6 +71,7 @@ public class BatteryProperties implements Parcelable {
p.writeInt(chargerAcOnline ? 1 : 0);
p.writeInt(chargerUsbOnline ? 1 : 0);
p.writeInt(chargerWirelessOnline ? 1 : 0);
+ p.writeInt(maxChargingCurrent);
p.writeInt(batteryStatus);
p.writeInt(batteryHealth);
p.writeInt(batteryPresent ? 1 : 0);
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 4ad9d6d..bad94fc 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -468,6 +468,7 @@ public abstract class BatteryStats implements Parcelable {
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
* @see BatteryStats#getCpuSpeedSteps()
*/
+ @Deprecated
public abstract long getTimeAtCpuSpeed(int step, int which);
public static abstract class Sensor {
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index fce09dd..9f71ce1 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -1180,6 +1180,37 @@ public interface IMountService extends IInterface {
_data.recycle();
}
}
+
+ @Override
+ public void createNewUserDir(int userHandle, String path) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(userHandle);
+ _data.writeString(path);
+ mRemote.transact(Stub.TRANSACTION_createNewUserDir, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
+
+ @Override
+ public void deleteUserKey(int userHandle) throws RemoteException {
+ Parcel _data = Parcel.obtain();
+ Parcel _reply = Parcel.obtain();
+ try {
+ _data.writeInterfaceToken(DESCRIPTOR);
+ _data.writeInt(userHandle);
+ mRemote.transact(Stub.TRANSACTION_deleteUserKey, _data, _reply, 0);
+ _reply.readException();
+ } finally {
+ _reply.recycle();
+ _data.recycle();
+ }
+ }
}
private static final String DESCRIPTOR = "IMountService";
@@ -1295,6 +1326,9 @@ public interface IMountService extends IInterface {
static final int TRANSACTION_benchmark = IBinder.FIRST_CALL_TRANSACTION + 59;
static final int TRANSACTION_setDebugFlags = IBinder.FIRST_CALL_TRANSACTION + 60;
+ static final int TRANSACTION_createNewUserDir = IBinder.FIRST_CALL_TRANSACTION + 62;
+ static final int TRANSACTION_deleteUserKey = IBinder.FIRST_CALL_TRANSACTION + 63;
+
/**
* Cast an IBinder object into an IMountService interface, generating a
* proxy if needed.
@@ -1850,6 +1884,21 @@ public interface IMountService extends IInterface {
reply.writeNoException();
return true;
}
+ case TRANSACTION_createNewUserDir: {
+ data.enforceInterface(DESCRIPTOR);
+ int userHandle = data.readInt();
+ String path = data.readString();
+ createNewUserDir(userHandle, path);
+ reply.writeNoException();
+ return true;
+ }
+ case TRANSACTION_deleteUserKey: {
+ data.enforceInterface(DESCRIPTOR);
+ int userHandle = data.readInt();
+ deleteUserKey(userHandle);
+ reply.writeNoException();
+ return true;
+ }
}
return super.onTransact(code, data, reply, flags);
}
@@ -2159,4 +2208,19 @@ public interface IMountService extends IInterface {
public String getPrimaryStorageUuid() throws RemoteException;
public void setPrimaryStorageUuid(String volumeUuid, IPackageMoveObserver callback)
throws RemoteException;
+
+ /**
+ * Creates the user data directory, possibly encrypted
+ * @param userHandle Handle of the user whose directory we are creating
+ * @param path Path at which to create the directory.
+ */
+ public void createNewUserDir(int userHandle, String path)
+ throws RemoteException;
+
+ /**
+ * Securely delete the user's encryption key
+ * @param userHandle Handle of the user whose key we are deleting
+ */
+ public void deleteUserKey(int userHandle)
+ throws RemoteException;
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index d1f3743..1d92453 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -960,6 +960,24 @@ public class StorageManager {
}
/** {@hide} */
+ public void createNewUserDir(int userHandle, File path) {
+ try {
+ mMountService.createNewUserDir(userHandle, path.getAbsolutePath());
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** {@hide} */
+ public void deleteUserKey(int userHandle) {
+ try {
+ mMountService.deleteUserKey(userHandle);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /** {@hide} */
public static File maybeTranslateEmulatedPathToInternal(File path) {
final IMountService mountService = IMountService.Stub.asInterface(
ServiceManager.getService("mount"));
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index fe95864..78be3cd 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5712,6 +5712,13 @@ public final class Settings {
public static final String ASSISTANT = "assistant";
/**
+ * Whether the camera launch gesture should be disabled.
+ *
+ * @hide
+ */
+ public static final String CAMERA_GESTURE_DISABLED = "camera_gesture_disabled";
+
+ /**
* This are the settings to be backed up.
*
* NOTE: Settings are backed up and restored in the order they appear
@@ -5767,6 +5774,7 @@ public final class Settings {
MOUNT_UMS_NOTIFY_ENABLED,
SLEEP_TIMEOUT,
DOUBLE_TAP_TO_WAKE,
+ CAMERA_GESTURE_DISABLED,
};
/**
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 6e93a30..42402eb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -6621,6 +6621,19 @@ public final class ViewRootImpl implements ViewParent,
return false;
}
+ /**
+ * Force the window to report its next draw.
+ * <p>
+ * This method is only supposed to be used to speed up the interaction from SystemUI and window
+ * manager when waiting for the first frame to be drawn when turning on the screen. DO NOT USE
+ * unless you fully understand this interaction.
+ * @hide
+ */
+ public void setReportNextDraw() {
+ mReportNextDraw = true;
+ invalidate();
+ }
+
void changeCanvasOpacity(boolean opaque) {
Log.d(TAG, "changeCanvasOpacity: opaque=" + opaque);
if (mAttachInfo.mHardwareRenderer != null) {
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 55493c3..6da0f63 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -29,6 +29,21 @@ public class MetricsLogger implements MetricsConstants {
// Temporary constants go here, to await migration to MetricsConstants.
// next value is 239;
public static final int ACTION_ASSIST_LONG_PRESS = 239;
+ public static final int FINGERPRINT_ENROLLING = 240;
+ public static final int FINGERPRINT_FIND_SENSOR = 241;
+ public static final int FINGERPRINT_ENROLL_FINISH = 242;
+ public static final int FINGERPRINT_ENROLL_INTRO = 243;
+ public static final int FINGERPRINT_ENROLL_ONBOARD = 244;
+ public static final int FINGERPRINT_ENROLL_SIDECAR = 245;
+ public static final int FINGERPRINT_ENROLLING_SETUP = 246;
+ public static final int FINGERPRINT_FIND_SENSOR_SETUP = 247;
+ public static final int FINGERPRINT_ENROLL_FINISH_SETUP = 248;
+ public static final int FINGERPRINT_ENROLL_INTRO_SETUP = 249;
+ public static final int FINGERPRINT_ENROLL_ONBOARD_SETUP = 250;
+ public static final int ACTION_FINGERPRINT_ENROLL = 251;
+ public static final int ACTION_FINGERPRINT_AUTH = 252;
+ public static final int ACTION_FINGERPRINT_DELETE = 253;
+ public static final int ACTION_FINGERPRINT_RENAME = 254;
public static void visible(Context context, int category) throws IllegalArgumentException {
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index f178c8c..4f4d3e0 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -338,7 +338,7 @@ public final class BatteryStatsHelper {
}
if (mCpuPowerCalculator == null) {
- mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile);
+ mCpuPowerCalculator = new CpuPowerCalculator();
}
mCpuPowerCalculator.reset();
diff --git a/core/java/com/android/internal/os/CpuPowerCalculator.java b/core/java/com/android/internal/os/CpuPowerCalculator.java
index a3ef612..d62f7a6 100644
--- a/core/java/com/android/internal/os/CpuPowerCalculator.java
+++ b/core/java/com/android/internal/os/CpuPowerCalculator.java
@@ -23,54 +23,14 @@ public class CpuPowerCalculator extends PowerCalculator {
private static final String TAG = "CpuPowerCalculator";
private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
- private final double[] mPowerCpuNormal;
-
- /**
- * Reusable array for calculations.
- */
- private final long[] mSpeedStepTimes;
-
- public CpuPowerCalculator(PowerProfile profile) {
- final int speedSteps = profile.getNumSpeedSteps();
- mPowerCpuNormal = new double[speedSteps];
- mSpeedStepTimes = new long[speedSteps];
- for (int p = 0; p < speedSteps; p++) {
- mPowerCpuNormal[p] = profile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
- }
- }
-
@Override
public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
long rawUptimeUs, int statsType) {
- final int speedSteps = mSpeedStepTimes.length;
-
- long totalTimeAtSpeeds = 0;
- for (int step = 0; step < speedSteps; step++) {
- mSpeedStepTimes[step] = u.getTimeAtCpuSpeed(step, statsType);
- totalTimeAtSpeeds += mSpeedStepTimes[step];
- }
- totalTimeAtSpeeds = Math.max(totalTimeAtSpeeds, 1);
-
app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
- if (DEBUG && app.cpuTimeMs != 0) {
- Log.d(TAG, "UID " + u.getUid() + ": CPU time " + app.cpuTimeMs + " ms");
- }
-
- double cpuPowerMaMs = 0;
- for (int step = 0; step < speedSteps; step++) {
- final double ratio = (double) mSpeedStepTimes[step] / totalTimeAtSpeeds;
- final double cpuSpeedStepPower = ratio * app.cpuTimeMs * mPowerCpuNormal[step];
- if (DEBUG && ratio != 0) {
- Log.d(TAG, "UID " + u.getUid() + ": CPU step #"
- + step + " ratio=" + BatteryStatsHelper.makemAh(ratio) + " power="
- + BatteryStatsHelper.makemAh(cpuSpeedStepPower / (60 * 60 * 1000)));
- }
- cpuPowerMaMs += cpuSpeedStepPower;
- }
-
- if (DEBUG && cpuPowerMaMs != 0) {
- Log.d(TAG, "UID " + u.getUid() + ": cpu total power="
- + BatteryStatsHelper.makemAh(cpuPowerMaMs / (60 * 60 * 1000)));
+ app.cpuPowerMah = (double) u.getCpuPowerMaUs(statsType) / (60.0 * 60.0 * 1000.0 * 1000.0);
+ if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
+ Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power="
+ + BatteryStatsHelper.makemAh(app.cpuPowerMah));
}
// Keep track of the package with highest drain.
@@ -108,8 +68,5 @@ public class CpuPowerCalculator extends PowerCalculator {
// Statistics may not have been gathered yet.
app.cpuTimeMs = app.cpuFgTimeMs;
}
-
- // Convert the CPU power to mAh
- app.cpuPowerMah = cpuPowerMaMs / (60 * 60 * 1000);
}
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index c1645c3..feed3903 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -69,5 +69,10 @@ oneway interface IStatusBar
void showAssistDisclosure();
void startAssist(in Bundle args);
+
+ /**
+ * Notifies the status bar that a camera launch gesture has been detected.
+ */
+ void onCameraLaunchGestureDetected();
}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index dfb7c50..4e4552d 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -16,6 +16,7 @@
package com.android.internal.widget;
+import android.app.trust.IStrongAuthTracker;
import com.android.internal.widget.VerifyCredentialResponse;
/** {@hide} */
@@ -35,4 +36,7 @@ interface ILockSettings {
boolean checkVoldPassword(int userId);
boolean havePattern(int userId);
boolean havePassword(int userId);
+ void registerStrongAuthTracker(in IStrongAuthTracker tracker);
+ void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
+ void requireStrongAuth(int strongAuthReason, int userId);
}
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 86d11be..a3a01da 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -16,18 +16,19 @@
package com.android.internal.widget;
-import android.Manifest;
+import android.annotation.IntDef;
import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
import android.app.admin.DevicePolicyManager;
+import android.app.trust.IStrongAuthTracker;
import android.app.trust.TrustManager;
-import android.bluetooth.BluetoothClass;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.pm.PackageManager;
import android.os.AsyncTask;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -38,9 +39,12 @@ import android.os.storage.StorageManager;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+import android.util.SparseIntArray;
import com.google.android.collect.Lists;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -228,7 +232,7 @@ public class LockPatternUtils {
public void reportFailedPasswordAttempt(int userId) {
getDevicePolicyManager().reportFailedPasswordAttempt(userId);
getTrustManager().reportUnlockAttempt(false /* authenticated */, userId);
- getTrustManager().reportRequireCredentialEntry(userId);
+ requireCredentialEntry(userId);
}
public void reportSuccessfulPasswordAttempt(int userId) {
@@ -1163,10 +1167,32 @@ public class LockPatternUtils {
}
/**
- * @see android.app.trust.TrustManager#reportRequireCredentialEntry(int)
+ * Disable trust until credentials have been entered for user {@param userId}.
+ *
+ * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ *
+ * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
*/
public void requireCredentialEntry(int userId) {
- getTrustManager().reportRequireCredentialEntry(userId);
+ requireStrongAuth(StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST, userId);
+ }
+
+ /**
+ * Requests strong authentication for user {@param userId}.
+ *
+ * Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ *
+ * @param strongAuthReason a combination of {@link StrongAuthTracker.StrongAuthFlags} indicating
+ * the reason for and the strength of the requested authentication.
+ * @param userId either an explicit user id or {@link android.os.UserHandle#USER_ALL}
+ */
+ public void requireStrongAuth(@StrongAuthTracker.StrongAuthFlags int strongAuthReason,
+ int userId) {
+ try {
+ getLockSettings().requireStrongAuth(strongAuthReason, userId);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error while requesting strong auth: " + e);
+ }
}
private void onAfterChangingPassword(int userHandle) {
@@ -1198,4 +1224,153 @@ public class LockPatternUtils {
private boolean shouldEncryptWithCredentials(boolean defaultValue) {
return isCredentialRequiredToDecrypt(defaultValue) && !isDoNotAskCredentialsOnBootSet();
}
+
+
+ public void registerStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
+ try {
+ getLockSettings().registerStrongAuthTracker(strongAuthTracker.mStub);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Could not register StrongAuthTracker");
+ }
+ }
+
+ public void unregisterStrongAuthTracker(final StrongAuthTracker strongAuthTracker) {
+ try {
+ getLockSettings().unregisterStrongAuthTracker(strongAuthTracker.mStub);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Could not unregister StrongAuthTracker", e);
+ }
+ }
+
+ /**
+ * Tracks the global strong authentication state.
+ */
+ public static class StrongAuthTracker {
+
+ @IntDef(flag = true,
+ value = { STRONG_AUTH_NOT_REQUIRED,
+ STRONG_AUTH_REQUIRED_AFTER_BOOT,
+ STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW,
+ STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface StrongAuthFlags {}
+
+ /**
+ * Strong authentication is not required.
+ */
+ public static final int STRONG_AUTH_NOT_REQUIRED = 0x0;
+
+ /**
+ * Strong authentication is required because the user has not authenticated since boot.
+ */
+ public static final int STRONG_AUTH_REQUIRED_AFTER_BOOT = 0x1;
+
+ /**
+ * Strong authentication is required because a device admin has temporarily requested it.
+ */
+ public static final int STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW = 0x2;
+
+ /**
+ * Strong authentication is required because the user has temporarily requested it.
+ */
+ public static final int STRONG_AUTH_REQUIRED_AFTER_USER_REQUEST = 0x4;
+
+ /**
+ * Strong authentication is required because the user has been locked out after too many
+ * attempts.
+ */
+ public static final int STRONG_AUTH_REQUIRED_AFTER_LOCKOUT = 0x8;
+
+ public static final int DEFAULT = STRONG_AUTH_REQUIRED_AFTER_BOOT;
+
+ final SparseIntArray mStrongAuthRequiredForUser = new SparseIntArray();
+
+ private final H mHandler;
+
+ public StrongAuthTracker() {
+ this(Looper.myLooper());
+ }
+
+ /**
+ * @param looper the looper on whose thread calls to {@link #onStrongAuthRequiredChanged}
+ * will be scheduled.
+ */
+ public StrongAuthTracker(Looper looper) {
+ mHandler = new H(looper);
+ }
+
+ /**
+ * Returns {@link #STRONG_AUTH_NOT_REQUIRED} if strong authentication is not required,
+ * otherwise returns a combination of {@link StrongAuthFlags} indicating why strong
+ * authentication is required.
+ *
+ * @param userId the user for whom the state is queried.
+ */
+ public @StrongAuthFlags int getStrongAuthForUser(int userId) {
+ return mStrongAuthRequiredForUser.get(userId, DEFAULT);
+ }
+
+ /**
+ * @return true if unlocking with trust alone is allowed for {@param userId} by the current
+ * strong authentication requirements.
+ */
+ public boolean isTrustAllowedForUser(int userId) {
+ return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
+ }
+
+ /**
+ * @return true if unlocking with fingerprint alone is allowed for {@param userId} by the
+ * current strong authentication requirements.
+ */
+ public boolean isFingerprintAllowedForUser(int userId) {
+ return getStrongAuthForUser(userId) == STRONG_AUTH_NOT_REQUIRED;
+ }
+
+ /**
+ * Called when the strong authentication requirements for {@param userId} changed.
+ */
+ public void onStrongAuthRequiredChanged(int userId) {
+ }
+
+ void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
+ int userId) {
+
+ int oldValue = getStrongAuthForUser(userId);
+ if (strongAuthFlags != oldValue) {
+ if (strongAuthFlags == DEFAULT) {
+ mStrongAuthRequiredForUser.delete(userId);
+ } else {
+ mStrongAuthRequiredForUser.put(userId, strongAuthFlags);
+ }
+ onStrongAuthRequiredChanged(userId);
+ }
+ }
+
+
+ final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
+ @Override
+ public void onStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
+ int userId) {
+ mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
+ strongAuthFlags, userId).sendToTarget();
+ }
+ };
+
+ private class H extends Handler {
+ static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
+
+ public H(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
+ handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
+ break;
+ }
+ }
+ };
+ }
}