diff options
23 files changed, 596 insertions, 115 deletions
diff --git a/api/current.txt b/api/current.txt index ce6bbfa..6540d47 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2736,6 +2736,7 @@ package android.accounts { } public class AccountManager { + method public boolean accountAuthenticated(android.accounts.Account); method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle); method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean); @@ -2796,6 +2797,7 @@ package android.accounts { field public static final java.lang.String KEY_ERROR_CODE = "errorCode"; field public static final java.lang.String KEY_ERROR_MESSAGE = "errorMessage"; field public static final java.lang.String KEY_INTENT = "intent"; + field public static final java.lang.String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH = "lastAuthenticatedTimeMillisEpoch"; field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; @@ -11163,6 +11165,7 @@ package android.graphics { field public static final int NV21 = 17; // 0x11 field public static final int PRIVATE = 34; // 0x22 field public static final int RAW10 = 37; // 0x25 + field public static final int RAW12 = 38; // 0x26 field public static final int RAW_SENSOR = 32; // 0x20 field public static final int RGB_565 = 4; // 0x4 field public static final int UNKNOWN = 0; // 0x0 @@ -34289,8 +34292,10 @@ package android.view { method public long getTimeDelta(); method public boolean isInProgress(); method public boolean isQuickScaleEnabled(); + method public boolean isSecondaryButtonScaleEnabled(); method public boolean onTouchEvent(android.view.MotionEvent); method public void setQuickScaleEnabled(boolean); + method public void setSecondaryButtonScaleEnabled(boolean); } public static abstract interface ScaleGestureDetector.OnScaleGestureListener { diff --git a/api/system-current.txt b/api/system-current.txt index 6053603..eec0c7f 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -2815,6 +2815,7 @@ package android.accounts { } public class AccountManager { + method public boolean accountAuthenticated(android.accounts.Account); method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler); method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle); method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean); @@ -2875,6 +2876,7 @@ package android.accounts { field public static final java.lang.String KEY_ERROR_CODE = "errorCode"; field public static final java.lang.String KEY_ERROR_MESSAGE = "errorMessage"; field public static final java.lang.String KEY_INTENT = "intent"; + field public static final java.lang.String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH = "lastAuthenticatedTimeMillisEpoch"; field public static final java.lang.String KEY_PASSWORD = "password"; field public static final java.lang.String KEY_USERDATA = "userdata"; field public static final java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED"; @@ -11449,6 +11451,7 @@ package android.graphics { field public static final int NV21 = 17; // 0x11 field public static final int PRIVATE = 34; // 0x22 field public static final int RAW10 = 37; // 0x25 + field public static final int RAW12 = 38; // 0x26 field public static final int RAW_SENSOR = 32; // 0x20 field public static final int RGB_565 = 4; // 0x4 field public static final int UNKNOWN = 0; // 0x0 @@ -36831,8 +36834,10 @@ package android.view { method public long getTimeDelta(); method public boolean isInProgress(); method public boolean isQuickScaleEnabled(); + method public boolean isSecondaryButtonScaleEnabled(); method public boolean onTouchEvent(android.view.MotionEvent); method public void setQuickScaleEnabled(boolean); + method public void setSecondaryButtonScaleEnabled(boolean); } public static abstract interface ScaleGestureDetector.OnScaleGestureListener { diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 6957435..480d171 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -203,6 +203,14 @@ public class AccountManager { public static final String KEY_USERDATA = "userdata"; /** + * Bundle key used to supply the last time the credentials of the account + * were authenticated successfully. Time is specified in milliseconds since + * epoch. + */ + public static final String KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH = + "lastAuthenticatedTimeMillisEpoch"; + + /** * Authenticators using 'customTokens' option will also get the UID of the * caller */ @@ -663,6 +671,31 @@ public class AccountManager { } /** + * Informs the system that the account has been authenticated recently. This + * recency may be used by other applications to verify the account. This + * should be called only when the user has entered correct credentials for + * the account. + * <p> + * It is not safe to call this method from the main thread. As such, call it + * from another thread. + * <p> + * This method requires the caller to hold the permission + * {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and should be + * called from the account's authenticator. + * + * @param account The {@link Account} to be updated. + */ + public boolean accountAuthenticated(Account account) { + if (account == null) + throw new IllegalArgumentException("account is null"); + try { + return mService.accountAuthenticated(account); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + /** * Rename the specified {@link Account}. This is equivalent to removing * the existing account and adding a new renamed account with the old * account's user data. @@ -1544,15 +1577,20 @@ public class AccountManager { * with these fields if activity or password was supplied and * the account was successfully verified: * <ul> - * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account created + * <li> {@link #KEY_ACCOUNT_NAME} - the name of the account verified * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account * <li> {@link #KEY_BOOLEAN_RESULT} - true to indicate success * </ul> * * If no activity or password was specified, the returned Bundle contains - * only {@link #KEY_INTENT} with the {@link Intent} needed to launch the - * password prompt. If an error occurred, - * {@link AccountManagerFuture#getResult()} throws: + * {@link #KEY_INTENT} with the {@link Intent} needed to launch the + * password prompt. + * + * <p>Also the returning Bundle may contain {@link + * #KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH} indicating the last time the + * credential was validated/created. + * + * If an error occurred,{@link AccountManagerFuture#getResult()} throws: * <ul> * <li> {@link AuthenticatorException} if the authenticator failed to respond * <li> {@link OperationCanceledException} if the operation was canceled for @@ -1625,9 +1663,9 @@ public class AccountManager { * <li> {@link #KEY_ACCOUNT_TYPE} - the type of the account * </ul> * - * If no activity was specified, the returned Bundle contains only + * If no activity was specified, the returned Bundle contains * {@link #KEY_INTENT} with the {@link Intent} needed to launch the - * password prompt. If an error occurred, + * password prompt. If an error occurred, * {@link AccountManagerFuture#getResult()} throws: * <ul> * <li> {@link AuthenticatorException} if the authenticator failed to respond diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index aa41161..04b3c88 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -67,6 +67,7 @@ interface IAccountManager { boolean expectActivityLaunch); void confirmCredentialsAsUser(in IAccountManagerResponse response, in Account account, in Bundle options, boolean expectActivityLaunch, int userId); + boolean accountAuthenticated(in Account account); void getAuthTokenLabel(in IAccountManagerResponse response, String accountType, String authTokenType); diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java index a0217c2..1503bf5 100644 --- a/core/java/android/hardware/camera2/CameraCharacteristics.java +++ b/core/java/android/hardware/camera2/CameraCharacteristics.java @@ -991,7 +991,8 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <ul> * <li>Processed (but stalling): any non-RAW format with a stallDurations > 0. * Typically JPEG format (ImageFormat#JPEG).</li> - * <li>Raw formats: ImageFormat#RAW_SENSOR, ImageFormat#RAW10 and ImageFormat#RAW_OPAQUE.</li> + * <li>Raw formats: ImageFormat#RAW_SENSOR, ImageFormat#RAW10, ImageFormat#RAW12, + * and ImageFormat#RAW_OPAQUE.</li> * <li>Processed (but not-stalling): any non-RAW format without a stall duration. * Typically ImageFormat#YUV_420_888, ImageFormat#NV21, ImageFormat#YV12.</li> * </ul> @@ -1023,6 +1024,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri * <ul> * <li>ImageFormat#RAW_SENSOR</li> * <li>ImageFormat#RAW10</li> + * <li>ImageFormat#RAW12</li> * <li>Opaque <code>RAW</code></li> * </ul> * <p>LEGACY mode devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> LEGACY) diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index a0e2bf8..3abccbc 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -40,6 +40,7 @@ import android.telephony.SubscriptionManager; import android.util.ArrayMap; import android.util.Log; +import com.android.internal.net.VpnConfig; import com.android.internal.telephony.ITelephony; import com.android.internal.telephony.PhoneConstants; import com.android.internal.util.Protocol; @@ -2447,6 +2448,38 @@ public class ConnectivityManager { } /** + * Resets all connectivity manager settings back to factory defaults. + * @hide + */ + public void factoryReset() { + // Turn airplane mode off + setAirplaneMode(false); + + // Untether + for (String tether : getTetheredIfaces()) { + untether(tether); + } + + // Turn VPN off + try { + VpnConfig vpnConfig = mService.getVpnConfig(); + if (vpnConfig != null) { + if (vpnConfig.legacy) { + mService.prepareVpn(VpnConfig.LEGACY_VPN, VpnConfig.LEGACY_VPN); + } else { + // Prevent this app from initiating VPN connections in the future without + // user intervention. + mService.setVpnPackageAuthorization(false); + + mService.prepareVpn(vpnConfig.user, VpnConfig.LEGACY_VPN); + } + } + } catch (RemoteException e) { + // Well, we tried + } + } + + /** * Binds the current process to {@code network}. All Sockets created in the future * (and not explicitly bound via a bound SocketFactory from * {@link Network#getSocketFactory() Network.getSocketFactory()}) will be bound to diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java index a8e7757..a7ffee9 100644 --- a/core/java/android/net/NetworkPolicyManager.java +++ b/core/java/android/net/NetworkPolicyManager.java @@ -180,6 +180,33 @@ public class NetworkPolicyManager { } /** + * Resets network policy settings back to factory defaults. + * + * @hide + */ + public void factoryReset(String subscriber) { + // Turn mobile data limit off + NetworkPolicy[] policies = getNetworkPolicies(); + NetworkTemplate template = NetworkTemplate.buildTemplateMobileAll(subscriber); + for (NetworkPolicy policy : policies) { + if (policy.template.equals(template)) { + policy.limitBytes = NetworkPolicy.LIMIT_DISABLED; + policy.inferred = false; + policy.clearSnooze(); + } + } + setNetworkPolicies(policies); + + // Turn restrict background data off + setRestrictBackground(false); + + // Remove app's "restrict background data" flag + for (int uid : getUidsWithPolicy(POLICY_REJECT_METERED_BACKGROUND)) { + setUidPolicy(uid, NetworkPolicyManager.POLICY_NONE); + } + } + + /** * Compute the last cycle boundary for the given {@link NetworkPolicy}. For * example, if cycle day is 20th, and today is June 15th, it will return May * 20th. When cycle day doesn't exist in current month, it snaps to the 1st diff --git a/core/java/android/security/keymaster/OperationResult.java b/core/java/android/security/keymaster/OperationResult.java index 4fc9d24..9b46ad3 100644 --- a/core/java/android/security/keymaster/OperationResult.java +++ b/core/java/android/security/keymaster/OperationResult.java @@ -28,6 +28,7 @@ import android.os.Parcelable; public class OperationResult implements Parcelable { public final int resultCode; public final IBinder token; + public final long operationHandle; public final int inputConsumed; public final byte[] output; @@ -45,6 +46,7 @@ public class OperationResult implements Parcelable { protected OperationResult(Parcel in) { resultCode = in.readInt(); token = in.readStrongBinder(); + operationHandle = in.readLong(); inputConsumed = in.readInt(); output = in.createByteArray(); } @@ -58,6 +60,7 @@ public class OperationResult implements Parcelable { public void writeToParcel(Parcel out, int flags) { out.writeInt(resultCode); out.writeStrongBinder(token); + out.writeLong(operationHandle); out.writeInt(inputConsumed); out.writeByteArray(output); } diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index 6508cca..5cf2c5c 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -130,6 +130,7 @@ public class ScaleGestureDetector { private float mFocusY; private boolean mQuickScaleEnabled; + private boolean mButtonScaleEnabled; private float mCurrSpan; private float mPrevSpan; @@ -151,14 +152,17 @@ public class ScaleGestureDetector { private int mTouchHistoryDirection; private long mTouchHistoryLastAcceptedTime; private int mTouchMinMajor; - private MotionEvent mDoubleTapEvent; - private int mDoubleTapMode = DOUBLE_TAP_MODE_NONE; private final Handler mHandler; + private float mAnchoredScaleStartX; + private float mAnchoredScaleStartY; + private int mAnchoredScaleMode = ANCHORED_SCALE_MODE_NONE; + private static final long TOUCH_STABILIZE_TIME = 128; // ms - private static final int DOUBLE_TAP_MODE_NONE = 0; - private static final int DOUBLE_TAP_MODE_IN_PROGRESS = 1; private static final float SCALE_FACTOR = .5f; + private static final int ANCHORED_SCALE_MODE_NONE = 0; + private static final int ANCHORED_SCALE_MODE_DOUBLE_TAP = 1; + private static final int ANCHORED_SCALE_MODE_BUTTON = 2; /** @@ -310,8 +314,17 @@ public class ScaleGestureDetector { mGestureDetector.onTouchEvent(event); } + final int count = event.getPointerCount(); + final int toolType = event.getToolType(0); + final boolean isButtonTool = toolType == MotionEvent.TOOL_TYPE_STYLUS + || toolType == MotionEvent.TOOL_TYPE_MOUSE; + final boolean isAnchoredScaleButtonDown = isButtonTool && (count == 1) + && (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0; + + final boolean anchoredScaleCancelled = + mAnchoredScaleMode == ANCHORED_SCALE_MODE_BUTTON && !isAnchoredScaleButtonDown; final boolean streamComplete = action == MotionEvent.ACTION_UP || - action == MotionEvent.ACTION_CANCEL; + action == MotionEvent.ACTION_CANCEL || anchoredScaleCancelled; if (action == MotionEvent.ACTION_DOWN || streamComplete) { // Reset any scale in progress with the listener. @@ -321,11 +334,11 @@ public class ScaleGestureDetector { mListener.onScaleEnd(this); mInProgress = false; mInitialSpan = 0; - mDoubleTapMode = DOUBLE_TAP_MODE_NONE; - } else if (mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS && streamComplete) { + mAnchoredScaleMode = ANCHORED_SCALE_MODE_NONE; + } else if (inAnchoredScaleMode() && streamComplete) { mInProgress = false; mInitialSpan = 0; - mDoubleTapMode = DOUBLE_TAP_MODE_NONE; + mAnchoredScaleMode = ANCHORED_SCALE_MODE_NONE; } if (streamComplete) { @@ -334,25 +347,32 @@ public class ScaleGestureDetector { } } + if (!mInProgress && mButtonScaleEnabled && !inAnchoredScaleMode() + && !streamComplete && isAnchoredScaleButtonDown) { + // Start of a button scale gesture + mAnchoredScaleStartX = event.getX(); + mAnchoredScaleStartY = event.getY(); + mAnchoredScaleMode = ANCHORED_SCALE_MODE_BUTTON; + mInitialSpan = 0; + } + final boolean configChanged = action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_UP || - action == MotionEvent.ACTION_POINTER_DOWN; - + action == MotionEvent.ACTION_POINTER_DOWN || anchoredScaleCancelled; final boolean pointerUp = action == MotionEvent.ACTION_POINTER_UP; final int skipIndex = pointerUp ? event.getActionIndex() : -1; // Determine focal point float sumX = 0, sumY = 0; - final int count = event.getPointerCount(); final int div = pointerUp ? count - 1 : count; final float focusX; final float focusY; - if (mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS) { - // In double tap mode, the focal pt is always where the double tap - // gesture started - focusX = mDoubleTapEvent.getX(); - focusY = mDoubleTapEvent.getY(); + if (inAnchoredScaleMode()) { + // In anchored scale mode, the focal pt is always where the double tap + // or button down gesture started + focusX = mAnchoredScaleStartX; + focusY = mAnchoredScaleStartY; if (event.getY() < focusY) { mEventBeforeOrAboveStartingGestureEvent = true; } else { @@ -390,7 +410,7 @@ public class ScaleGestureDetector { final float spanX = devX * 2; final float spanY = devY * 2; final float span; - if (inDoubleTapMode()) { + if (inAnchoredScaleMode()) { span = spanY; } else { span = (float) Math.hypot(spanX, spanY); @@ -402,11 +422,10 @@ public class ScaleGestureDetector { final boolean wasInProgress = mInProgress; mFocusX = focusX; mFocusY = focusY; - if (!inDoubleTapMode() && mInProgress && (span < mMinSpan || configChanged)) { + if (!inAnchoredScaleMode() && mInProgress && (span < mMinSpan || configChanged)) { mListener.onScaleEnd(this); mInProgress = false; mInitialSpan = span; - mDoubleTapMode = DOUBLE_TAP_MODE_NONE; } if (configChanged) { mPrevSpanX = mCurrSpanX = spanX; @@ -414,7 +433,7 @@ public class ScaleGestureDetector { mInitialSpan = mPrevSpan = mCurrSpan = span; } - final int minSpan = inDoubleTapMode() ? mSpanSlop : mMinSpan; + final int minSpan = inAnchoredScaleMode() ? mSpanSlop : mMinSpan; if (!mInProgress && span >= minSpan && (wasInProgress || Math.abs(span - mInitialSpan) > mSpanSlop)) { mPrevSpanX = mCurrSpanX = spanX; @@ -447,9 +466,8 @@ public class ScaleGestureDetector { return true; } - - private boolean inDoubleTapMode() { - return mDoubleTapMode == DOUBLE_TAP_MODE_IN_PROGRESS; + private boolean inAnchoredScaleMode() { + return mAnchoredScaleMode != ANCHORED_SCALE_MODE_NONE; } /** @@ -466,8 +484,9 @@ public class ScaleGestureDetector { @Override public boolean onDoubleTap(MotionEvent e) { // Double tap: start watching for a swipe - mDoubleTapEvent = e; - mDoubleTapMode = DOUBLE_TAP_MODE_IN_PROGRESS; + mAnchoredScaleStartX = e.getX(); + mAnchoredScaleStartY = e.getY(); + mAnchoredScaleMode = ANCHORED_SCALE_MODE_DOUBLE_TAP; return true; } }; @@ -484,6 +503,27 @@ public class ScaleGestureDetector { } /** + * Sets whether the associates {@link OnScaleGestureListener} should receive onScale callbacks + * when the user presses a {@value MotionEvent#BUTTON_SECONDARY} (right mouse button, stylus + * first button) and drags the pointer on the screen. Note that this is enabled by default if + * the app targets API 23 and newer. + * + * @param scales true to enable stylus or mouse scaling, false to disable. + */ + public void setSecondaryButtonScaleEnabled(boolean scales) { + mButtonScaleEnabled = scales; + } + + /** + * Return whether the button scale gesture, in which the user presses a + * {@value MotionEvent#BUTTON_SECONDARY} (right mouse button, stylus first button) and drags the + * pointer on the screen, should perform scaling. {@see #setButtonScaleEnabled(boolean)}. + */ + public boolean isSecondaryButtonScaleEnabled() { + return mButtonScaleEnabled; + } + + /** * Returns {@code true} if a scale gesture is in progress. */ public boolean isInProgress() { @@ -586,7 +626,7 @@ public class ScaleGestureDetector { * @return The current scaling factor. */ public float getScaleFactor() { - if (inDoubleTapMode()) { + if (inAnchoredScaleMode()) { // Drag is moving up; the further away from the gesture // start, the smaller the span should be, the closer, // the larger the span, and therefore the larger the scale diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 82e36c3..32b99a8 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -2954,8 +2954,11 @@ public class Editor { } mSelectionHandleHeight = Math.max( mSelectHandleLeft.getMinimumHeight(), mSelectHandleRight.getMinimumHeight()); - getInsertionController().getHandle(); - mInsertionHandleHeight = mSelectHandleCenter.getMinimumHeight(); + InsertionPointCursorController insertionController = getInsertionController(); + if (insertionController != null) { + insertionController.getHandle(); + mInsertionHandleHeight = mSelectHandleCenter.getMinimumHeight(); + } } @Override diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp index c020020..87c58d6 100644 --- a/core/jni/android_text_StaticLayout.cpp +++ b/core/jni/android_text_StaticLayout.cpp @@ -48,11 +48,6 @@ struct JLineBreaksID { static jclass gLineBreaks_class; static JLineBreaksID gLineBreaks_fieldID; -static const int CHAR_SPACE = 0x20; -static const int CHAR_TAB = 0x09; -static const int CHAR_NEWLINE = 0x0a; -static const int CHAR_ZWSP = 0x200b; - // set text and set a number of parameters for creating a layout (width, tabstops, strategy) static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java index ada8c12..c63c8ba 100644 --- a/graphics/java/android/graphics/ImageFormat.java +++ b/graphics/java/android/graphics/ImageFormat.java @@ -356,6 +356,108 @@ public class ImageFormat { public static final int RAW10 = 0x25; /** + * <p> + * Android 12-bit raw format + * </p> + * <p> + * This is a single-plane, 12-bit per pixel, densely packed (in each row), + * unprocessed format, usually representing raw Bayer-pattern images coming + * from an image sensor. + * </p> + * <p> + * In an image buffer with this format, starting from the first pixel of each + * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first + * and second byte contains the top 8 bits of first and second pixel. The third + * byte contains the 4 least significant bits of the two pixels, the exact layout + * data for each two consecutive pixels is illustrated below (Pi[j] stands for + * the jth bit of the ith pixel): + * </p> + * <table> + * <thead> + * <tr> + * <th align="center"></th> + * <th align="center">bit 7</th> + * <th align="center">bit 6</th> + * <th align="center">bit 5</th> + * <th align="center">bit 4</th> + * <th align="center">bit 3</th> + * <th align="center">bit 2</th> + * <th align="center">bit 1</th> + * <th align="center">bit 0</th> + * </tr> + * </thead> <tbody> + * <tr> + * <td align="center">Byte 0:</td> + * <td align="center">P0[11]</td> + * <td align="center">P0[10]</td> + * <td align="center">P0[ 9]</td> + * <td align="center">P0[ 8]</td> + * <td align="center">P0[ 7]</td> + * <td align="center">P0[ 6]</td> + * <td align="center">P0[ 5]</td> + * <td align="center">P0[ 4]</td> + * </tr> + * <tr> + * <td align="center">Byte 1:</td> + * <td align="center">P1[11]</td> + * <td align="center">P1[10]</td> + * <td align="center">P1[ 9]</td> + * <td align="center">P1[ 8]</td> + * <td align="center">P1[ 7]</td> + * <td align="center">P1[ 6]</td> + * <td align="center">P1[ 5]</td> + * <td align="center">P1[ 4]</td> + * </tr> + * <tr> + * <td align="center">Byte 2:</td> + * <td align="center">P1[ 3]</td> + * <td align="center">P1[ 2]</td> + * <td align="center">P1[ 1]</td> + * <td align="center">P1[ 0]</td> + * <td align="center">P0[ 3]</td> + * <td align="center">P0[ 2]</td> + * <td align="center">P0[ 1]</td> + * <td align="center">P0[ 0]</td> + * </tr> + * </tbody> + * </table> + * <p> + * This format assumes + * <ul> + * <li>a width multiple of 4 pixels</li> + * <li>an even height</li> + * </ul> + * </p> + * + * <pre>size = row stride * height</pre> where the row stride is in <em>bytes</em>, + * not pixels. + * + * <p> + * Since this is a densely packed format, the pixel stride is always 0. The + * application must use the pixel data layout defined in above table to + * access each row data. When row stride is equal to {@code width * (12 / 8)}, there + * will be no padding bytes at the end of each row, the entire image data is + * densely packed. When stride is larger than {@code width * (12 / 8)}, padding + * bytes will be present at the end of each row. + * </p> + * <p> + * For example, the {@link android.media.Image} object can provide data in + * this format from a {@link android.hardware.camera2.CameraDevice} (if + * supported) through a {@link android.media.ImageReader} object. The + * {@link android.media.Image#getPlanes() Image#getPlanes()} will return a + * single plane containing the pixel data. The pixel stride is always 0 in + * {@link android.media.Image.Plane#getPixelStride()}, and the + * {@link android.media.Image.Plane#getRowStride()} describes the vertical + * neighboring pixel distance (in bytes) between adjacent rows. + * </p> + * + * @see android.media.Image + * @see android.media.ImageReader + * @see android.hardware.camera2.CameraDevice + */ + public static final int RAW12 = 0x26; + + /** * Android dense depth image format. * * Each pixel is 16 bits, representing a depth ranging measurement from @@ -445,6 +547,8 @@ public class ImageFormat { return 16; case RAW10: return 10; + case RAW12: + return 12; } return -1; } @@ -472,6 +576,7 @@ public class ImageFormat { case YUV_420_888: case RAW_SENSOR: case RAW10: + case RAW12: case DEPTH16: case DEPTH_POINT_CLOUD: case PRIVATE: diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp index 9fc7e8e..708c083 100644 --- a/media/jni/android_media_ImageReader.cpp +++ b/media/jni/android_media_ImageReader.cpp @@ -431,6 +431,19 @@ static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* bu pData = buffer->data; dataSize = buffer->stride * buffer->height; break; + case HAL_PIXEL_FORMAT_RAW12: + // Single plane 10bpp bayer data. + ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); + LOG_ALWAYS_FATAL_IF(buffer->width % 4, + "Width is not multiple of 4 %d", buffer->width); + LOG_ALWAYS_FATAL_IF(buffer->height % 2, + "Height is not even %d", buffer->height); + LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8), + "stride (%d) should be at least %d", + buffer->stride, buffer->width * 12 / 8); + pData = buffer->data; + dataSize = buffer->stride * buffer->height; + break; case HAL_PIXEL_FORMAT_RGBA_8888: case HAL_PIXEL_FORMAT_RGBX_8888: // Single plane, 32bpp. @@ -492,8 +505,10 @@ static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* bu break; case HAL_PIXEL_FORMAT_BLOB: case HAL_PIXEL_FORMAT_RAW10: - // Blob is used for JPEG data, RAW10 is used for 10-bit raw data, they are - // single plane, row and pixel strides are 0. + case HAL_PIXEL_FORMAT_RAW12: + // Blob is used for JPEG data, RAW10 and RAW12 is used for 10-bit and 12-bit raw data, + // those are single plane data with pixel stride 0 since they don't really have a + // well defined pixel stride ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); pixelStride = 0; break; @@ -549,12 +564,14 @@ static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buff rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16); break; case HAL_PIXEL_FORMAT_BLOB: - // Blob is used for JPEG data, RAW10 is used for 10-bit raw data, they are - // single plane, row and pixel strides are 0. + // Blob is used for JPEG data. It is single plane and has 0 row stride and + // 0 pixel stride ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); rowStride = 0; break; case HAL_PIXEL_FORMAT_RAW10: + case HAL_PIXEL_FORMAT_RAW12: + // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); rowStride = buffer->stride; break; diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 45b0fb2..5cc59e5 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -3938,16 +3938,6 @@ public class BackupManagerService { return; } - // Don't proceed unless we have already established package metadata - // for the current dataset via a key/value backup pass. - File stateDir = new File(mBaseStateDir, transport.transportDirName()); - File pmState = new File(stateDir, PACKAGE_MANAGER_SENTINEL); - if (pmState.length() <= 0) { - Slog.i(TAG, "Full backup requested but dataset not yet initialized " - + "via k/v backup pass; ignoring"); - return; - } - // Set up to send data to the transport final int N = mPackages.size(); for (int i = 0; i < N; i++) { @@ -4296,6 +4286,31 @@ public class BackupManagerService { writeFullBackupScheduleAsync(); } + private boolean fullBackupAllowable(IBackupTransport transport) { + if (transport == null) { + Slog.w(TAG, "Transport not present; full data backup not performed"); + return false; + } + + // Don't proceed unless we have already established package metadata + // for the current dataset via a key/value backup pass. + try { + File stateDir = new File(mBaseStateDir, transport.transportDirName()); + File pmState = new File(stateDir, PACKAGE_MANAGER_SENTINEL); + if (pmState.length() <= 0) { + if (DEBUG) { + Slog.i(TAG, "Full backup requested but dataset not yet initialized"); + } + return false; + } + } catch (Exception e) { + Slog.w(TAG, "Unable to contact transport"); + return false; + } + + return true; + } + /** * Conditions are right for a full backup operation, so run one. The model we use is * to perform one app backup per scheduled job execution, and to reschedule the job @@ -4307,6 +4322,7 @@ public class BackupManagerService { boolean beginFullBackup(FullBackupJob scheduledJob) { long now = System.currentTimeMillis(); FullBackupEntry entry = null; + long latency = MIN_FULL_BACKUP_INTERVAL; if (!mEnabled || !mProvisioned) { // Backups are globally disabled, so don't proceed. We also don't reschedule @@ -4338,17 +4354,41 @@ public class BackupManagerService { return false; } - entry = mFullBackupQueue.get(0); - long timeSinceRun = now - entry.lastBackup; - if (timeSinceRun < MIN_FULL_BACKUP_INTERVAL) { - // It's too early to back up the next thing in the queue, so bow out + // At this point we know that we have work to do, just not right now. Any + // exit without actually running backups will also require that we + // reschedule the job. + boolean runBackup = true; + + if (!fullBackupAllowable(getTransport(mCurrentTransport))) { if (MORE_DEBUG) { - Slog.i(TAG, "Device ready but too early to back up next app"); + Slog.i(TAG, "Preconditions not met; not running full backup"); + } + runBackup = false; + // Typically this means we haven't run a key/value backup yet. Back off + // full-backup operations by the key/value job's run interval so that + // next time we run, we are likely to be able to make progress. + latency = KeyValueBackupJob.BATCH_INTERVAL; + } + + if (runBackup) { + entry = mFullBackupQueue.get(0); + long timeSinceRun = now - entry.lastBackup; + runBackup = (timeSinceRun >= MIN_FULL_BACKUP_INTERVAL); + if (!runBackup) { + // It's too early to back up the next thing in the queue, so bow out + if (MORE_DEBUG) { + Slog.i(TAG, "Device ready but too early to back up next app"); + } + // Wait until the next app in the queue falls due for a full data backup + latency = MIN_FULL_BACKUP_INTERVAL - timeSinceRun; } - final long latency = MIN_FULL_BACKUP_INTERVAL - timeSinceRun; + } + + if (!runBackup) { + final long deferTime = latency; // pin for the closure mBackupHandler.post(new Runnable() { @Override public void run() { - FullBackupJob.schedule(mContext, latency); + FullBackupJob.schedule(mContext, deferTime); } }); return false; @@ -8489,27 +8529,31 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF throw new IllegalStateException("Restore supported only for the device owner"); } - if (DEBUG) { - Slog.d(TAG, "fullTransportBackup()"); - } - - CountDownLatch latch = new CountDownLatch(1); - PerformFullTransportBackupTask task = - new PerformFullTransportBackupTask(null, pkgNames, false, null, latch); - (new Thread(task, "full-transport-master")).start(); - do { - try { - latch.await(); - break; - } catch (InterruptedException e) { - // Just go back to waiting for the latch to indicate completion + if (!fullBackupAllowable(getTransport(mCurrentTransport))) { + Slog.i(TAG, "Full backup not currently possible -- key/value backup not yet run?"); + } else { + if (DEBUG) { + Slog.d(TAG, "fullTransportBackup()"); } - } while (true); - // We just ran a backup on these packages, so kick them to the end of the queue - final long now = System.currentTimeMillis(); - for (String pkg : pkgNames) { - enqueueFullBackup(pkg, now); + CountDownLatch latch = new CountDownLatch(1); + PerformFullTransportBackupTask task = + new PerformFullTransportBackupTask(null, pkgNames, false, null, latch); + (new Thread(task, "full-transport-master")).start(); + do { + try { + latch.await(); + break; + } catch (InterruptedException e) { + // Just go back to waiting for the latch to indicate completion + } + } while (true); + + // We just ran a backup on these packages, so kick them to the end of the queue + final long now = System.currentTimeMillis(); + for (String pkg : pkgNames) { + enqueueFullBackup(pkg, now); + } } if (DEBUG) { diff --git a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java index dc1c9d5..a4489c1 100644 --- a/services/backup/java/com/android/server/backup/KeyValueBackupJob.java +++ b/services/backup/java/com/android/server/backup/KeyValueBackupJob.java @@ -41,7 +41,7 @@ public class KeyValueBackupJob extends JobService { // Once someone asks for a backup, this is how long we hold off, batching // up additional requests, before running the actual backup pass. Privileged // callers can always trigger an immediate pass via BackupManager.backupNow(). - private static final long BATCH_INTERVAL = 4 * AlarmManager.INTERVAL_HOUR; + static final long BATCH_INTERVAL = 4 * AlarmManager.INTERVAL_HOUR; // Random variation in next-backup scheduling time to avoid server load spikes private static final int FUZZ_MILLIS = 10 * 60 * 1000; diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index a64e6c3..1b32f57 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -109,7 +109,7 @@ public class AccountManagerService private static final int TIMEOUT_DELAY_MS = 1000 * 60; private static final String DATABASE_NAME = "accounts.db"; - private static final int DATABASE_VERSION = 6; + private static final int DATABASE_VERSION = 7; private final Context mContext; @@ -131,6 +131,8 @@ public class AccountManagerService private static final String ACCOUNTS_TYPE_COUNT = "count(type)"; private static final String ACCOUNTS_PASSWORD = "password"; private static final String ACCOUNTS_PREVIOUS_NAME = "previous_name"; + private static final String ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS = + "last_password_entry_time_millis_epoch"; private static final String TABLE_AUTHTOKENS = "authtokens"; private static final String AUTHTOKENS_ID = "_id"; @@ -697,7 +699,8 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { new Session(fromAccounts, response, account.type, false, - false /* stripAuthTokenFromResult */) { + false /* stripAuthTokenFromResult */, account.name, + false /* authDetailsRequired */) { @Override protected String toDebugString(long now) { return super.toDebugString(now) + ", getAccountCredentialsForClone" @@ -725,12 +728,43 @@ public class AccountManagerService } } + @Override + public boolean accountAuthenticated(final Account account) { + if (account == null) { + throw new IllegalArgumentException("account is null"); + } + checkAuthenticateAccountsPermission(account); + + final UserAccounts accounts = getUserAccountsForCaller(); + int userId = Binder.getCallingUserHandle().getIdentifier(); + if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) { + return false; + } + synchronized (accounts.cacheLock) { + final ContentValues values = new ContentValues(); + values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, System.currentTimeMillis()); + final SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); + int i = db.update( + TABLE_ACCOUNTS, + values, + ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE + "=?", + new String[] { + account.name, account.type + }); + if (i > 0) { + return true; + } + } + return false; + } + private void completeCloningAccount(IAccountManagerResponse response, final Bundle accountCredentials, final Account account, final UserAccounts targetUser) { long id = clearCallingIdentity(); try { new Session(targetUser, response, account.type, false, - false /* stripAuthTokenFromResult */) { + false /* stripAuthTokenFromResult */, account.name, + false /* authDetailsRequired */) { @Override protected String toDebugString(long now) { return super.toDebugString(now) + ", getAccountCredentialsForClone" @@ -795,6 +829,7 @@ public class AccountManagerService values.put(ACCOUNTS_NAME, account.name); values.put(ACCOUNTS_TYPE, account.type); values.put(ACCOUNTS_PASSWORD, password); + values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, System.currentTimeMillis()); long accountId = db.insert(TABLE_ACCOUNTS, ACCOUNTS_NAME, values); if (accountId < 0) { Log.w(TAG, "insertAccountIntoDatabase: " + account @@ -885,7 +920,8 @@ public class AccountManagerService public TestFeaturesSession(UserAccounts accounts, IAccountManagerResponse response, Account account, String[] features) { super(accounts, response, account.type, false /* expectActivityLaunch */, - true /* stripAuthTokenFromResult */); + true /* stripAuthTokenFromResult */, account.name, + false /* authDetailsRequired */); mFeatures = features; mAccount = account; } @@ -1184,7 +1220,8 @@ public class AccountManagerService public RemoveAccountSession(UserAccounts accounts, IAccountManagerResponse response, Account account, boolean expectActivityLaunch) { super(accounts, response, account.type, expectActivityLaunch, - true /* stripAuthTokenFromResult */); + true /* stripAuthTokenFromResult */, account.name, + false /* authDetailsRequired */); mAccount = account; } @@ -1419,6 +1456,13 @@ public class AccountManagerService try { final ContentValues values = new ContentValues(); values.put(ACCOUNTS_PASSWORD, password); + long time = 0; + // Only set current time, if it is a valid password. For clear password case, it + // should not be set. + if (password != null) { + time = System.currentTimeMillis(); + } + values.put(ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS, time); final long accountId = getAccountIdLocked(db, account); if (accountId >= 0) { final String[] argsAccountId = {String.valueOf(accountId)}; @@ -1547,8 +1591,9 @@ public class AccountManagerService UserAccounts accounts = getUserAccounts(UserHandle.getUserId(callingUid)); long identityToken = clearCallingIdentity(); try { - new Session(accounts, response, accountType, false, - false /* stripAuthTokenFromResult */) { + new Session(accounts, response, accountType, false /* expectActivityLaunch */, + false /* stripAuthTokenFromResult */, null /* accountName */, + false /* authDetailsRequired */) { @Override protected String toDebugString(long now) { return super.toDebugString(now) + ", getAuthTokenLabel" @@ -1648,7 +1693,8 @@ public class AccountManagerService } new Session(accounts, response, account.type, expectActivityLaunch, - false /* stripAuthTokenFromResult */) { + false /* stripAuthTokenFromResult */, account.name, + false /* authDetailsRequired */) { @Override protected String toDebugString(long now) { if (loginOptions != null) loginOptions.keySet(); @@ -1842,7 +1888,8 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { new Session(accounts, response, accountType, expectActivityLaunch, - true /* stripAuthTokenFromResult */) { + true /* stripAuthTokenFromResult */, null /* accountName */, + false /* authDetailsRequired */) { @Override public void run() throws RemoteException { mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures, @@ -1917,7 +1964,8 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { new Session(accounts, response, accountType, expectActivityLaunch, - true /* stripAuthTokenFromResult */) { + true /* stripAuthTokenFromResult */, null /* accountName */, + false /* authDetailsRequired */) { @Override public void run() throws RemoteException { mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures, @@ -1973,7 +2021,8 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { new Session(accounts, response, account.type, expectActivityLaunch, - true /* stripAuthTokenFromResult */) { + true /* stripAuthTokenFromResult */, account.name, + true /* authDetailsRequired */) { @Override public void run() throws RemoteException { mAuthenticator.confirmCredentials(this, account, options); @@ -2009,7 +2058,8 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { new Session(accounts, response, account.type, expectActivityLaunch, - true /* stripAuthTokenFromResult */) { + true /* stripAuthTokenFromResult */, account.name, + false /* authDetailsRequired */) { @Override public void run() throws RemoteException { mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions); @@ -2045,7 +2095,8 @@ public class AccountManagerService long identityToken = clearCallingIdentity(); try { new Session(accounts, response, accountType, expectActivityLaunch, - true /* stripAuthTokenFromResult */) { + true /* stripAuthTokenFromResult */, null /* accountName */, + false /* authDetailsRequired */) { @Override public void run() throws RemoteException { mAuthenticator.editProperties(this, mAccountType); @@ -2071,7 +2122,8 @@ public class AccountManagerService public GetAccountsByTypeAndFeatureSession(UserAccounts accounts, IAccountManagerResponse response, String type, String[] features, int callingUid) { super(accounts, response, type, false /* expectActivityLaunch */, - true /* stripAuthTokenFromResult */); + true /* stripAuthTokenFromResult */, null /* accountName */, + false /* authDetailsRequired */); mCallingUid = callingUid; mFeatures = features; } @@ -2437,6 +2489,9 @@ public class AccountManagerService final String mAccountType; final boolean mExpectActivityLaunch; final long mCreationTime; + final String mAccountName; + // Indicates if we need to add auth details(like last credential time) + final boolean mAuthDetailsRequired; public int mNumResults = 0; private int mNumRequestContinued = 0; @@ -2448,7 +2503,8 @@ public class AccountManagerService protected final UserAccounts mAccounts; public Session(UserAccounts accounts, IAccountManagerResponse response, String accountType, - boolean expectActivityLaunch, boolean stripAuthTokenFromResult) { + boolean expectActivityLaunch, boolean stripAuthTokenFromResult, String accountName, + boolean authDetailsRequired) { super(); //if (response == null) throw new IllegalArgumentException("response is null"); if (accountType == null) throw new IllegalArgumentException("accountType is null"); @@ -2458,6 +2514,9 @@ public class AccountManagerService mAccountType = accountType; mExpectActivityLaunch = expectActivityLaunch; mCreationTime = SystemClock.elapsedRealtime(); + mAccountName = accountName; + mAuthDetailsRequired = authDetailsRequired; + synchronized (mSessions) { mSessions.put(toString(), this); } @@ -2592,6 +2651,16 @@ public class AccountManagerService public void onResult(Bundle result) { mNumResults++; Intent intent = null; + if (result != null && mAuthDetailsRequired) { + long lastAuthenticatedTime = DatabaseUtils.longForQuery( + mAccounts.openHelper.getReadableDatabase(), + "select " + ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS + " from " + + TABLE_ACCOUNTS + " WHERE " + ACCOUNTS_NAME + "=? AND " + + ACCOUNTS_TYPE + "=?", + new String[]{mAccountName, mAccountType}); + result.putLong(AccountManager.KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH, + lastAuthenticatedTime); + } if (result != null && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { /* @@ -2798,6 +2867,7 @@ public class AccountManagerService + ACCOUNTS_TYPE + " TEXT NOT NULL, " + ACCOUNTS_PASSWORD + " TEXT, " + ACCOUNTS_PREVIOUS_NAME + " TEXT, " + + ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS + " INTEGER DEFAULT 0, " + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))"); db.execSQL("CREATE TABLE " + TABLE_AUTHTOKENS + " ( " @@ -2833,6 +2903,11 @@ public class AccountManagerService + "UNIQUE(" + ACCOUNTS_NAME + "," + ACCOUNTS_TYPE + "))"); } + private void addLastSuccessfullAuthenticatedTimeColumn(SQLiteDatabase db) { + db.execSQL("ALTER TABLE " + TABLE_ACCOUNTS + " ADD COLUMN " + + ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS + " DEFAULT 0"); + } + private void addOldAccountNameColumn(SQLiteDatabase db) { db.execSQL("ALTER TABLE " + TABLE_ACCOUNTS + " ADD COLUMN " + ACCOUNTS_PREVIOUS_NAME); } @@ -2892,6 +2967,11 @@ public class AccountManagerService oldVersion++; } + if (oldVersion == 6) { + addLastSuccessfullAuthenticatedTimeColumn(db); + oldVersion++; + } + if (oldVersion != newVersion) { Log.e(TAG, "failed to upgrade version " + oldVersion + " to version " + newVersion); } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index dbf7def..c318370 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -17494,8 +17494,12 @@ public final class ActivityManagerService extends ActivityManagerNative mFullPssPending = true; mPendingPssProcesses.ensureCapacity(mLruProcesses.size()); mPendingPssProcesses.clear(); - for (int i=mLruProcesses.size()-1; i>=0; i--) { + for (int i = mLruProcesses.size() - 1; i >= 0; i--) { ProcessRecord app = mLruProcesses.get(i); + if (app.thread == null + || app.curProcState == ActivityManager.PROCESS_STATE_NONEXISTENT) { + continue; + } if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) { app.pssProcState = app.setProcState; app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true, @@ -17811,8 +17815,8 @@ public final class ActivityManagerService extends ActivityManagerNative } } } - if (app.setProcState < 0 || ProcessList.procStatesDifferForMem(app.curProcState, - app.setProcState)) { + if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT + || ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) { if (false && mTestPssMode && app.setProcState >= 0 && app.lastStateTime <= (now-200)) { // Experimental code to more aggressively collect pss while // running test... the problem is that this tends to collect diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 7cf3b51..7c921ac 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -16,6 +16,7 @@ package com.android.server.am; +import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -89,10 +90,10 @@ final class ProcessRecord { int curSchedGroup; // Currently desired scheduling class int setSchedGroup; // Last set to background scheduling class int trimMemoryLevel; // Last selected memory trimming level - int curProcState = -1; // Currently computed process state: ActivityManager.PROCESS_STATE_* - int repProcState = -1; // Last reported process state - int setProcState = -1; // Last set process state in process tracker - int pssProcState = -1; // The proc state we are currently requesting pss for + int curProcState = PROCESS_STATE_NONEXISTENT; // Currently computed process state + int repProcState = PROCESS_STATE_NONEXISTENT; // Last reported process state + int setProcState = PROCESS_STATE_NONEXISTENT; // Last set process state in process tracker + int pssProcState = PROCESS_STATE_NONEXISTENT; // Currently requesting pss for boolean serviceb; // Process currently is on the service B list boolean serviceHighRam; // We are forcing to service B list due to its RAM use boolean setIsForeground; // Running foreground UI when last set? diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java index d8d361b..3b34541 100644 --- a/services/core/java/com/android/server/am/TaskRecord.java +++ b/services/core/java/com/android/server/am/TaskRecord.java @@ -16,6 +16,8 @@ package com.android.server.am; +import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; +import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE; @@ -346,8 +348,8 @@ final class TaskRecord { if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) { // If the activity itself has requested auto-remove, then just always do it. autoRemoveRecents = true; - } else if ((intentFlags & (Intent.FLAG_ACTIVITY_NEW_DOCUMENT - | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS)) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT) { + } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS)) + == FLAG_ACTIVITY_NEW_DOCUMENT) { // If the caller has not asked for the document to be retained, then we may // want to turn on auto-remove, depending on whether the target has set its // own document launch mode. @@ -879,7 +881,8 @@ final class TaskRecord { for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { final ActivityRecord r = activities.get(activityNdx); if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() || - ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) && + ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT + | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) && activityNdx > 0) { // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET). break; diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java index a33ee4c..c8fd82e 100644 --- a/services/core/java/com/android/server/policy/WindowOrientationListener.java +++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java @@ -136,7 +136,9 @@ public abstract class WindowOrientationListener { public void onTouchStart() { synchronized (mLock) { - mSensorEventListener.onTouchStartLocked(); + if (mSensorEventListener != null) { + mSensorEventListener.onTouchStartLocked(); + } } } @@ -144,7 +146,9 @@ public abstract class WindowOrientationListener { long whenElapsedNanos = SystemClock.elapsedRealtimeNanos(); synchronized (mLock) { - mSensorEventListener.onTouchEndLocked(whenElapsedNanos); + if (mSensorEventListener != null) { + mSensorEventListener.onTouchEndLocked(whenElapsedNanos); + } } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index fbc70db..6bc6de63 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -3316,11 +3316,11 @@ public class TelephonyManager { * @return the preferred network type, defined in RILConstants.java. * @hide */ - public int getPreferredNetworkType() { + public int getPreferredNetworkType(int subId) { try { ITelephony telephony = getITelephony(); if (telephony != null) - return telephony.getPreferredNetworkType(); + return telephony.getPreferredNetworkType(subId); } catch (RemoteException ex) { Rlog.e(TAG, "getPreferredNetworkType RemoteException", ex); } catch (NullPointerException ex) { @@ -3330,6 +3330,27 @@ public class TelephonyManager { } /** + * Sets the network selection mode to automatic. + * <p> + * Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} + * Or the calling app has carrier privileges. @see #hasCarrierPrivileges + * + * @hide + */ + public void setNetworkSelectionModeAutomatic(int subId) { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) + telephony.setNetworkSelectionModeAutomatic(subId); + } catch (RemoteException ex) { + Rlog.e(TAG, "setNetworkSelectionModeAutomatic RemoteException", ex); + } catch (NullPointerException ex) { + Rlog.e(TAG, "setNetworkSelectionModeAutomatic NPE", ex); + } + } + + /** * Set the preferred network type. * Used for device configuration by some CDMA operators. * <p> @@ -3337,15 +3358,16 @@ public class TelephonyManager { * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} * Or the calling app has carrier privileges. @see #hasCarrierPrivileges * + * @param subId the id of the subscription to set the preferred network type for. * @param networkType the preferred network type, defined in RILConstants.java. * @return true on success; false on any failure. * @hide */ - public boolean setPreferredNetworkType(int networkType) { + public boolean setPreferredNetworkType(int subId, int networkType) { try { ITelephony telephony = getITelephony(); if (telephony != null) - return telephony.setPreferredNetworkType(networkType); + return telephony.setPreferredNetworkType(subId, networkType); } catch (RemoteException ex) { Rlog.e(TAG, "setPreferredNetworkType RemoteException", ex); } catch (NullPointerException ex) { @@ -3364,7 +3386,8 @@ public class TelephonyManager { * @return true on success; false on any failure. */ public boolean setPreferredNetworkTypeToGlobal() { - return setPreferredNetworkType(RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); + return setPreferredNetworkType(getDefaultSubscription(), + RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); } /** @@ -4448,4 +4471,22 @@ public class TelephonyManager { return retval; } + + /** + * Resets telephony manager settings back to factory defaults. + * + * @hide + */ + public void factoryReset(int subId) { + if (SubscriptionManager.isUsableSubIdValue(subId)) { + // Enable data + setDataEnabled(subId, true); + // Set network selection mode to automatic + setNetworkSelectionModeAutomatic(subId); + // Set preferred mobile network type to the best available + setPreferredNetworkType(subId, RILConstants.PREFERRED_NETWORK_MODE); + // Turn off roaming + SubscriptionManager.from(mContext).setDataRoaming(0, subId); + } + } } diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index c18e3b6..a24859b 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -653,9 +653,10 @@ interface ITelephony { * Get the preferred network type. * Used for device configuration by some CDMA operators. * + * @param subId the id of the subscription to query. * @return the preferred network type, defined in RILConstants.java. */ - int getPreferredNetworkType(); + int getPreferredNetworkType(int subId); /** * Check TETHER_DUN_REQUIRED and TETHER_DUN_APN settings, net.tethering.noprovisioning @@ -667,13 +668,21 @@ interface ITelephony { int getTetherApnRequired(); /** + * Set the network selection mode to automatic. + * + * @param subId the id of the subscription to update. + */ + void setNetworkSelectionModeAutomatic(int subId); + + /** * Set the preferred network type. * Used for device configuration by some CDMA operators. * + * @param subId the id of the subscription to update. * @param networkType the preferred network type, defined in RILConstants.java. * @return true on success; false on any failure. */ - boolean setPreferredNetworkType(int networkType); + boolean setPreferredNetworkType(int subId, int networkType); /** * User enable/disable Mobile Data. diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index e1460ef..6371891 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -2621,4 +2621,25 @@ public class WifiManager { } return false; } + + /** + * Resets all wifi manager settings back to factory defaults. + * + * @hide + */ + public void factoryReset() { + // Enable wifi + setWifiEnabled(true); + // Delete all Wifi SSIDs + List<WifiConfiguration> networks = getConfiguredNetworks(); + if (networks != null) { + for (WifiConfiguration config : networks) { + removeNetwork(config.networkId); + } + saveConfiguration(); + } + + // Turn mobile hotspot off + setWifiApEnabled(null, false); + } } |
