diff options
Diffstat (limited to 'core/java')
27 files changed, 576 insertions, 98 deletions
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java index e18aa5c..8b70ae6 100644 --- a/core/java/android/animation/ValueAnimator.java +++ b/core/java/android/animation/ValueAnimator.java @@ -114,6 +114,15 @@ public class ValueAnimator extends Animator { private boolean mPlayingBackwards = false; /** + * Flag to indicate whether this animator is playing in reverse mode, specifically + * by being started or interrupted by a call to reverse(). This flag is different than + * mPlayingBackwards, which indicates merely whether the current iteration of the + * animator is playing in reverse. It is used in corner cases to determine proper end + * behavior. + */ + private boolean mReversing; + + /** * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the * repeatCount (if repeatCount!=INFINITE), the animation ends */ @@ -545,21 +554,51 @@ public class ValueAnimator extends Animator { * Sets the position of the animation to the specified fraction. This fraction should * be between 0 and the total fraction of the animation, including any repetition. That is, * a fraction of 0 will position the animation at the beginning, a value of 1 at the end, - * and a value of 2 at the beginning of a reversing animator that repeats once. If + * and a value of 2 at the end of a reversing animator that repeats once. If * the animation has not yet been started, then it will not advance forward after it is * set to this fraction; it will simply set the fraction to this value and perform any * appropriate actions based on that fraction. If the animation is already running, then * setCurrentFraction() will set the current fraction to this value and continue - * playing from that point. + * playing from that point. {@link Animator.AnimatorListener} events are not called + * due to changing the fraction; those events are only processed while the animation + * is running. * - * @param fraction The fraction to which the animation is advanced or rewound. + * @param fraction The fraction to which the animation is advanced or rewound. Values + * outside the range of 0 to the maximum fraction for the animator will be clamped to + * the correct range. */ public void setCurrentFraction(float fraction) { initAnimation(); + if (fraction < 0) { + fraction = 0; + } + int iteration = (int) fraction; + if (fraction == 1) { + iteration -= 1; + } else if (fraction > 1) { + if (iteration < (mRepeatCount + 1) || mRepeatCount == INFINITE) { + if (mRepeatMode == REVERSE) { + mPlayingBackwards = (iteration % 2) != 0; + } + fraction = fraction % 1f; + } else { + fraction = 1; + iteration -= 1; + } + } else { + mPlayingBackwards = mReversing; + } + mCurrentIteration = iteration; + long seekTime = (long) (mDuration * fraction); + long currentTime = AnimationUtils.currentAnimationTimeMillis(); + mStartTime = currentTime - seekTime; if (mPlayingState != RUNNING) { mSeekFraction = fraction; mPlayingState = SEEKED; } + if (mPlayingBackwards) { + fraction = 1f - fraction; + } animateValue(fraction); } @@ -962,8 +1001,30 @@ public class ValueAnimator extends Animator { if (Looper.myLooper() == null) { throw new AndroidRuntimeException("Animators may only be run on Looper threads"); } + mReversing = playBackwards; mPlayingBackwards = playBackwards; - mCurrentIteration = 0; + if (playBackwards && mSeekFraction != -1) { + if (mSeekFraction == 0 && mCurrentIteration == 0) { + // special case: reversing from seek-to-0 should act as if not seeked at all + mSeekFraction = 0; + } else if (mRepeatCount == INFINITE) { + mSeekFraction = 1 - (mSeekFraction % 1); + } else { + mSeekFraction = 1 + mRepeatCount - (mCurrentIteration + mSeekFraction); + } + mCurrentIteration = (int) mSeekFraction; + mSeekFraction = mSeekFraction % 1; + } + if (mCurrentIteration > 0 && mRepeatMode == REVERSE && + (mCurrentIteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) { + // if we were seeked to some other iteration in a reversing animator, + // figure out the correct direction to start playing based on the iteration + if (playBackwards) { + mPlayingBackwards = (mCurrentIteration % 2) == 0; + } else { + mPlayingBackwards = (mCurrentIteration % 2) != 0; + } + } int prevPlayingState = mPlayingState; mPlayingState = STOPPED; mStarted = true; @@ -1071,6 +1132,7 @@ public class ValueAnimator extends Animator { long currentPlayTime = currentTime - mStartTime; long timeLeft = mDuration - currentPlayTime; mStartTime = currentTime - timeLeft; + mReversing = !mReversing; } else if (mStarted) { end(); } else { @@ -1113,6 +1175,8 @@ public class ValueAnimator extends Animator { mStarted = false; mStartListenersCalled = false; mPlayingBackwards = false; + mReversing = false; + mCurrentIteration = 0; if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) { Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(), System.identityHashCode(this)); @@ -1201,8 +1265,16 @@ public class ValueAnimator extends Animator { case RUNNING: case SEEKED: float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f; + if (mDuration == 0 && mRepeatCount != INFINITE) { + // Skip to the end + mCurrentIteration = mRepeatCount; + if (!mReversing) { + mPlayingBackwards = false; + } + } if (fraction >= 1f) { - if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) { + if (mCurrentIteration < mRepeatCount || + (mRepeatCount == INFINITE && mDuration != 0)) { // Time to repeat if (mListeners != null) { int numListeners = mListeners.size(); @@ -1213,7 +1285,7 @@ public class ValueAnimator extends Animator { if (mRepeatMode == REVERSE) { mPlayingBackwards = !mPlayingBackwards; } - mCurrentIteration += (int)fraction; + mCurrentIteration += (int) fraction; fraction = fraction % 1f; mStartTime += mDuration; } else { @@ -1313,6 +1385,7 @@ public class ValueAnimator extends Animator { } anim.mSeekFraction = -1; anim.mPlayingBackwards = false; + anim.mReversing = false; anim.mCurrentIteration = 0; anim.mInitialized = false; anim.mPlayingState = STOPPED; diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java index 06a26ec..e8d08b8 100644 --- a/core/java/android/app/ActivityManagerNative.java +++ b/core/java/android/app/ActivityManagerNative.java @@ -2363,6 +2363,13 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM reply.writeNoException(); return true; } + + case SYSTEM_BACKUP_RESTORED: { + data.enforceInterface(IActivityManager.descriptor); + systemBackupRestored(); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -5458,5 +5465,16 @@ class ActivityManagerProxy implements IActivityManager reply.recycle(); } + @Override + public void systemBackupRestored() throws RemoteException { + Parcel data = Parcel.obtain(); + Parcel reply = Parcel.obtain(); + data.writeInterfaceToken(IActivityManager.descriptor); + mRemote.transact(SYSTEM_BACKUP_RESTORED, data, reply, 0); + reply.readException(); + data.recycle(); + reply.recycle(); + } + private IBinder mRemote; } diff --git a/core/java/android/app/ApplicationErrorReport.java b/core/java/android/app/ApplicationErrorReport.java index 49ab7c1..6c2511e 100644 --- a/core/java/android/app/ApplicationErrorReport.java +++ b/core/java/android/app/ApplicationErrorReport.java @@ -168,10 +168,20 @@ public class ApplicationErrorReport implements Parcelable { PackageManager pm = context.getPackageManager(); // look for receiver in the installer package - String candidate = pm.getInstallerPackageName(packageName); - ComponentName result = getErrorReportReceiver(pm, packageName, candidate); - if (result != null) { - return result; + String candidate = null; + ComponentName result = null; + + try { + candidate = pm.getInstallerPackageName(packageName); + } catch (IllegalArgumentException e) { + // the package could already removed + } + + if (candidate != null) { + result = getErrorReportReceiver(pm, packageName, candidate); + if (result != null) { + return result; + } } // if the error app is on the system image, look for system apps diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 1ccbd27..e505d69 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -469,6 +469,8 @@ public interface IActivityManager extends IInterface { public void notifyLaunchTaskBehindComplete(IBinder token) throws RemoteException; public void notifyEnterAnimationComplete(IBinder token) throws RemoteException; + public void systemBackupRestored() throws RemoteException; + /* * Private non-Binder interfaces */ @@ -790,4 +792,5 @@ public interface IActivityManager extends IInterface { int START_IN_PLACE_ANIMATION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+240; int CHECK_PERMISSION_WITH_TOKEN_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+241; int REGISTER_TASK_STACK_LISTENER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+242; + int SYSTEM_BACKUP_RESTORED = IBinder.FIRST_CALL_TRANSACTION+243; } diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 4753099..ead89b3 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -504,6 +504,22 @@ public class DevicePolicyManager { } return false; } + /** + * Return true if the given administrator component is currently being removed + * for the user. + * @hide + */ + public boolean isRemovingAdmin(ComponentName who, int userId) { + if (mService != null) { + try { + return mService.isRemovingAdmin(who, userId); + } catch (RemoteException e) { + Log.w(TAG, "Failed talking with device policy service", e); + } + } + return false; + } + /** * Return a list of all currently active device administrator's component diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index d144ae8..0ca60c0 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -196,4 +196,6 @@ interface IDevicePolicyManager { void setAutoTimeRequired(in ComponentName who, int userHandle, boolean required); boolean getAutoTimeRequired(); + + boolean isRemovingAdmin(in ComponentName adminReceiver, int userHandle); } diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index c203a8e..ea2dca0 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -928,7 +928,7 @@ public final class BluetoothGatt implements BluetoothProfile { BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) == 0) return false; if (VDBG) Log.d(TAG, "writeCharacteristic() - uuid: " + characteristic.getUuid()); - if (mService == null || mClientIf == 0) return false; + if (mService == null || mClientIf == 0 || characteristic.getValue() == null) return false; BluetoothGattService service = characteristic.getService(); if (service == null) return false; @@ -1015,7 +1015,7 @@ public final class BluetoothGatt implements BluetoothProfile { */ public boolean writeDescriptor(BluetoothGattDescriptor descriptor) { if (VDBG) Log.d(TAG, "writeDescriptor() - uuid: " + descriptor.getUuid()); - if (mService == null || mClientIf == 0) return false; + if (mService == null || mClientIf == 0 || descriptor.getValue() == null) return false; BluetoothGattCharacteristic characteristic = descriptor.getCharacteristic(); if (characteristic == null) return false; diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java index 353f0fb..546a50e 100644 --- a/core/java/android/bluetooth/BluetoothHeadset.java +++ b/core/java/android/bluetooth/BluetoothHeadset.java @@ -20,9 +20,10 @@ import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.content.ComponentName; import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; +import android.os.Message; import android.os.RemoteException; import android.util.Log; @@ -221,11 +222,14 @@ public final class BluetoothHeadset implements BluetoothProfile { */ public static final int STATE_AUDIO_CONNECTED = 12; + private static final int MESSAGE_HEADSET_SERVICE_CONNECTED = 100; + private static final int MESSAGE_HEADSET_SERVICE_DISCONNECTED = 101; private Context mContext; private ServiceListener mServiceListener; private IBluetoothHeadset mService; private BluetoothAdapter mAdapter; + private boolean mIsClosed; final private IBluetoothStateChangeCallback mBluetoothStateChangeCallback = new IBluetoothStateChangeCallback.Stub() { @@ -233,14 +237,7 @@ public final class BluetoothHeadset implements BluetoothProfile { if (DBG) Log.d(TAG, "onBluetoothStateChange: up=" + up); if (!up) { if (VDBG) Log.d(TAG,"Unbinding service..."); - synchronized (mConnection) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG,"",re); - } - } + doUnbind(); } else { synchronized (mConnection) { try { @@ -263,6 +260,7 @@ public final class BluetoothHeadset implements BluetoothProfile { mContext = context; mServiceListener = l; mAdapter = BluetoothAdapter.getDefaultAdapter(); + mIsClosed = false; IBluetoothManager mgr = mAdapter.getBluetoothManager(); if (mgr != null) { @@ -277,15 +275,26 @@ public final class BluetoothHeadset implements BluetoothProfile { } boolean doBind() { - Intent intent = new Intent(IBluetoothHeadset.class.getName()); - ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0); - intent.setComponent(comp); - if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0, - android.os.Process.myUserHandle())) { - Log.e(TAG, "Could not bind to Bluetooth Headset Service with " + intent); - return false; + try { + return mAdapter.getBluetoothManager().bindBluetoothProfileService( + BluetoothProfile.HEADSET, mConnection); + } catch (RemoteException e) { + Log.e(TAG, "Unable to bind HeadsetService", e); + } + return false; + } + + void doUnbind() { + synchronized (mConnection) { + if (mService != null) { + try { + mAdapter.getBluetoothManager().unbindBluetoothProfileService( + BluetoothProfile.HEADSET, mConnection); + } catch (RemoteException e) { + Log.e(TAG,"Unable to unbind HeadsetService", e); + } + } } - return true; } /** @@ -305,18 +314,8 @@ public final class BluetoothHeadset implements BluetoothProfile { Log.e(TAG,"",e); } } - - synchronized (mConnection) { - if (mService != null) { - try { - mService = null; - mContext.unbindService(mConnection); - } catch (Exception re) { - Log.e(TAG,"",re); - } - } - } - mServiceListener = null; + mIsClosed = true; + doUnbind(); } /** @@ -930,21 +929,21 @@ public final class BluetoothHeadset implements BluetoothProfile { return false; } - private final ServiceConnection mConnection = new ServiceConnection() { + private final IBluetoothProfileServiceConnection mConnection + = new IBluetoothProfileServiceConnection.Stub() { + @Override public void onServiceConnected(ComponentName className, IBinder service) { if (DBG) Log.d(TAG, "Proxy object connected"); mService = IBluetoothHeadset.Stub.asInterface(service); - - if (mServiceListener != null) { - mServiceListener.onServiceConnected(BluetoothProfile.HEADSET, BluetoothHeadset.this); - } + mHandler.sendMessage(mHandler.obtainMessage( + MESSAGE_HEADSET_SERVICE_CONNECTED)); } + @Override public void onServiceDisconnected(ComponentName className) { if (DBG) Log.d(TAG, "Proxy object disconnected"); mService = null; - if (mServiceListener != null) { - mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET); - } + mHandler.sendMessage(mHandler.obtainMessage( + MESSAGE_HEADSET_SERVICE_DISCONNECTED)); } }; @@ -968,4 +967,28 @@ public final class BluetoothHeadset implements BluetoothProfile { private static void log(String msg) { Log.d(TAG, msg); } + + private final Handler mHandler = new Handler(Looper.getMainLooper()) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MESSAGE_HEADSET_SERVICE_CONNECTED: { + if (mServiceListener != null) { + mServiceListener.onServiceConnected(BluetoothProfile.HEADSET, + BluetoothHeadset.this); + } + break; + } + case MESSAGE_HEADSET_SERVICE_DISCONNECTED: { + if (mServiceListener != null) { + mServiceListener.onServiceDisconnected(BluetoothProfile.HEADSET); + } + if (mIsClosed){ + mServiceListener = null; + } + break; + } + } + } + }; } diff --git a/core/java/android/bluetooth/BluetoothUuid.java b/core/java/android/bluetooth/BluetoothUuid.java index 1e22eb3..194a53e 100644 --- a/core/java/android/bluetooth/BluetoothUuid.java +++ b/core/java/android/bluetooth/BluetoothUuid.java @@ -66,6 +66,8 @@ public final class BluetoothUuid { ParcelUuid.fromString("00001116-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid BNEP = ParcelUuid.fromString("0000000f-0000-1000-8000-00805F9B34FB"); + public static final ParcelUuid PBAP_PCE = + ParcelUuid.fromString("0000112e-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid PBAP_PSE = ParcelUuid.fromString("0000112f-0000-1000-8000-00805F9B34FB"); public static final ParcelUuid MAP = diff --git a/core/java/android/bluetooth/IBluetoothManager.aidl b/core/java/android/bluetooth/IBluetoothManager.aidl index 493d2f8..7411d3f 100644 --- a/core/java/android/bluetooth/IBluetoothManager.aidl +++ b/core/java/android/bluetooth/IBluetoothManager.aidl @@ -19,6 +19,7 @@ package android.bluetooth; import android.bluetooth.IBluetooth; import android.bluetooth.IBluetoothGatt; import android.bluetooth.IBluetoothManagerCallback; +import android.bluetooth.IBluetoothProfileServiceConnection; import android.bluetooth.IBluetoothStateChangeCallback; /** @@ -38,6 +39,9 @@ interface IBluetoothManager boolean disable(boolean persist); IBluetoothGatt getBluetoothGatt(); + boolean bindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy); + void unbindBluetoothProfileService(int profile, IBluetoothProfileServiceConnection proxy); + String getAddress(); String getName(); } diff --git a/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl b/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl new file mode 100755 index 0000000..96c59e2 --- /dev/null +++ b/core/java/android/bluetooth/IBluetoothProfileServiceConnection.aidl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2014 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.bluetooth; + +import android.content.ComponentName; +import android.os.IBinder; + +/** + * Callback for bluetooth profile connections. + * + * {@hide} + */ +interface IBluetoothProfileServiceConnection { + void onServiceConnected(in ComponentName comp, in IBinder service); + void onServiceDisconnected(in ComponentName comp); +} diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java index 999de8a..1b10858 100644 --- a/core/java/android/hardware/camera2/CameraMetadata.java +++ b/core/java/android/hardware/camera2/CameraMetadata.java @@ -1648,11 +1648,41 @@ public abstract class CameraMetadata<TKey> { public static final int CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO = 17; /** - * <p>Turn on custom high dynamic range (HDR) mode.</p> - * <p>This is intended for LEGACY mode devices only; - * HAL3+ camera devices should not implement this mode.</p> + * <p>Turn on a device-specific high dynamic range (HDR) mode.</p> + * <p>In this scene mode, the camera device captures images + * that keep a larger range of scene illumination levels + * visible in the final image. For example, when taking a + * picture of a object in front of a bright window, both + * the object and the scene through the window may be + * visible when using HDR mode, while in normal AUTO mode, + * one or the other may be poorly exposed. As a tradeoff, + * HDR mode generally takes much longer to capture a single + * image, has no user control, and may have other artifacts + * depending on the HDR method used.</p> + * <p>Therefore, HDR captures operate at a much slower rate + * than regular captures.</p> + * <p>In this mode, on LIMITED or FULL devices, when a request + * is made with a {@link CaptureRequest#CONTROL_CAPTURE_INTENT android.control.captureIntent} of + * STILL_CAPTURE, the camera device will capture an image + * using a high dynamic range capture technique. On LEGACY + * devices, captures that target a JPEG-format output will + * be captured with HDR, and the capture intent is not + * relevant.</p> + * <p>The HDR capture may involve the device capturing a burst + * of images internally and combining them into one, or it + * may involve the device using specialized high dynamic + * range capture hardware. In all cases, a single image is + * produced in response to a capture request submitted + * while in HDR mode.</p> + * <p>Since substantial post-processing is generally needed to + * produce an HDR image, only YUV and JPEG outputs are + * supported for LIMITED/FULL device HDR captures, and only + * JPEG outputs are supported for LEGACY HDR + * captures. Using a RAW output for HDR capture is not + * supported.</p> + * + * @see CaptureRequest#CONTROL_CAPTURE_INTENT * @see CaptureRequest#CONTROL_SCENE_MODE - * @hide */ public static final int CONTROL_SCENE_MODE_HDR = 18; diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java index e89a402..0849df8 100644 --- a/core/java/android/hardware/camera2/CaptureRequest.java +++ b/core/java/android/hardware/camera2/CaptureRequest.java @@ -1294,6 +1294,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * <li>{@link #CONTROL_SCENE_MODE_CANDLELIGHT CANDLELIGHT}</li> * <li>{@link #CONTROL_SCENE_MODE_BARCODE BARCODE}</li> * <li>{@link #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}</li> + * <li>{@link #CONTROL_SCENE_MODE_HDR HDR}</li> * </ul></p> * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}</p> @@ -1322,6 +1323,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>> * @see #CONTROL_SCENE_MODE_CANDLELIGHT * @see #CONTROL_SCENE_MODE_BARCODE * @see #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO + * @see #CONTROL_SCENE_MODE_HDR */ @PublicKey public static final Key<Integer> CONTROL_SCENE_MODE = diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java index 2c3b85f..1396940 100644 --- a/core/java/android/hardware/camera2/CaptureResult.java +++ b/core/java/android/hardware/camera2/CaptureResult.java @@ -1910,6 +1910,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * <li>{@link #CONTROL_SCENE_MODE_CANDLELIGHT CANDLELIGHT}</li> * <li>{@link #CONTROL_SCENE_MODE_BARCODE BARCODE}</li> * <li>{@link #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO HIGH_SPEED_VIDEO}</li> + * <li>{@link #CONTROL_SCENE_MODE_HDR HDR}</li> * </ul></p> * <p><b>Available values for this device:</b><br> * {@link CameraCharacteristics#CONTROL_AVAILABLE_SCENE_MODES android.control.availableSceneModes}</p> @@ -1938,6 +1939,7 @@ public class CaptureResult extends CameraMetadata<CaptureResult.Key<?>> { * @see #CONTROL_SCENE_MODE_CANDLELIGHT * @see #CONTROL_SCENE_MODE_BARCODE * @see #CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO + * @see #CONTROL_SCENE_MODE_HDR */ @PublicKey public static final Key<Integer> CONTROL_SCENE_MODE = diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java index 5c7a8da..6e5d064 100644 --- a/core/java/android/hardware/location/GeofenceHardwareImpl.java +++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java @@ -23,6 +23,7 @@ import android.location.IGpsGeofenceHardware; import android.location.Location; import android.os.Handler; import android.os.IBinder; +import android.os.IInterface; import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; @@ -30,6 +31,7 @@ import android.util.Log; import android.util.SparseArray; import java.util.ArrayList; +import java.util.Iterator; /** * This class manages the geofences which are handled by hardware. @@ -558,8 +560,34 @@ public final class GeofenceHardwareImpl { try { callback.onGeofenceRemove(geofenceId, msg.arg2); } catch (RemoteException e) {} + IBinder callbackBinder = callback.asBinder(); + boolean callbackInUse = false; synchronized (mGeofences) { mGeofences.remove(geofenceId); + // Check if the underlying binder is still useful for other geofences, + // if no, unlink the DeathRecipient to avoid memory leak. + for (int i = 0; i < mGeofences.size(); i++) { + if (mGeofences.valueAt(i).asBinder() == callbackBinder) { + callbackInUse = true; + break; + } + } + } + + // Remove the reaper associated with this binder. + if (!callbackInUse) { + for (Iterator<Reaper> iterator = mReapers.iterator(); + iterator.hasNext();) { + Reaper reaper = iterator.next(); + if (reaper.mCallback != null && + reaper.mCallback.asBinder() == callbackBinder) { + iterator.remove(); + reaper.unlinkToDeath(); + if (DEBUG) Log.d(TAG, String.format("Removed reaper %s " + + "because binder %s is no longer needed.", + reaper, callbackBinder)); + } + } } } releaseWakeLock(); @@ -803,8 +831,9 @@ public final class GeofenceHardwareImpl { @Override public int hashCode() { int result = 17; - result = 31 * result + (mCallback != null ? mCallback.hashCode() : 0); - result = 31 * result + (mMonitorCallback != null ? mMonitorCallback.hashCode() : 0); + result = 31 * result + (mCallback != null ? mCallback.asBinder().hashCode() : 0); + result = 31 * result + (mMonitorCallback != null + ? mMonitorCallback.asBinder().hashCode() : 0); result = 31 * result + mMonitoringType; return result; } @@ -815,9 +844,38 @@ public final class GeofenceHardwareImpl { if (obj == this) return true; Reaper rhs = (Reaper) obj; - return rhs.mCallback == mCallback && rhs.mMonitorCallback == mMonitorCallback && + return binderEquals(rhs.mCallback, mCallback) && + binderEquals(rhs.mMonitorCallback, mMonitorCallback) && rhs.mMonitoringType == mMonitoringType; } + + /** + * Compares the underlying Binder of the given two IInterface objects and returns true if + * they equals. null values are accepted. + */ + private boolean binderEquals(IInterface left, IInterface right) { + if (left == null) { + return right == null; + } else { + return right == null ? false : left.asBinder() == right.asBinder(); + } + } + + /** + * Unlinks this DeathRecipient. + */ + private boolean unlinkToDeath() { + if (mMonitorCallback != null) { + return mMonitorCallback.asBinder().unlinkToDeath(this, 0); + } else if (mCallback != null) { + return mCallback.asBinder().unlinkToDeath(this, 0); + } + return true; + } + + private boolean callbackEquals(IGeofenceHardwareCallback cb) { + return mCallback != null && mCallback.asBinder() == cb.asBinder(); + } } int getAllowedResolutionLevel(int pid, int uid) { diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 4fe418a..4215f20 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -100,7 +100,7 @@ public class ConnectivityManager { /** * Identical to {@link #CONNECTIVITY_ACTION} broadcast, but sent without any - * historic {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY}. + * applicable {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY}. * * @hide */ @@ -428,6 +428,18 @@ public class ConnectivityManager { public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI; /** + * Default value for {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY} in + * milliseconds. This was introduced because IPv6 routes seem to take a + * moment to settle - trying network activity before the routes are adjusted + * can lead to packets using the wrong interface or having the wrong IP address. + * This delay is a bit crude, but in the future hopefully we will have kernel + * notifications letting us know when it's safe to use the new network. + * + * @hide + */ + public static final int CONNECTIVITY_CHANGE_DELAY_DEFAULT = 3000; + + /** * @hide */ public final static int REQUEST_ID_UNSET = 0; diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 11fc69e..5fd697a 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -459,6 +459,20 @@ public abstract class BatteryStats implements Parcelable { public abstract int getStarts(int which); /** + * Returns the number of times the process has crashed. + * + * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. + */ + public abstract int getNumCrashes(int which); + + /** + * Returns the number of times the process has ANRed. + * + * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. + */ + public abstract int getNumAnrs(int which); + + /** * Returns the cpu time spent in microseconds while the process was in the foreground. * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT. * @return foreground cpu time in microseconds @@ -694,8 +708,10 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_USER_RUNNING = 0x0007; // Events for foreground user. public static final int EVENT_USER_FOREGROUND = 0x0008; + // Events for connectivity changed. + public static final int EVENT_CONNECTIVITY_CHANGED = 0x0009; // Number of event types. - public static final int EVENT_COUNT = 0x0009; + public static final int EVENT_COUNT = 0x000a; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -1107,6 +1123,13 @@ public abstract class BatteryStats implements Parcelable { public abstract int getLowPowerModeEnabledCount(int which); /** + * Returns the number of times that connectivity state changed. + * + * {@hide} + */ + public abstract int getNumConnectivityChange(int which); + + /** * Returns the time in microseconds that the phone has been on while the device was * running on battery. * @@ -1306,11 +1329,11 @@ public abstract class BatteryStats implements Parcelable { }; public static final String[] HISTORY_EVENT_NAMES = new String[] { - "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg" + "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { - "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf" + "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn" }; /** @@ -1871,6 +1894,7 @@ public abstract class BatteryStats implements Parcelable { final long screenOnTime = getScreenOnTime(rawRealtime, which); final long interactiveTime = getInteractiveTime(rawRealtime, which); final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which); + final int connChanges = getNumConnectivityChange(which); final long phoneOnTime = getPhoneOnTime(rawRealtime, which); final long wifiOnTime = getWifiOnTime(rawRealtime, which); final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); @@ -1941,7 +1965,7 @@ public abstract class BatteryStats implements Parcelable { fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000, 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which) / 1000, getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000, - lowPowerModeEnabledTime / 1000); + lowPowerModeEnabledTime / 1000, connChanges); // Dump screen brightness stats Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS]; @@ -2271,12 +2295,14 @@ public abstract class BatteryStats implements Parcelable { final long userMillis = ps.getUserTime(which) * 10; final long systemMillis = ps.getSystemTime(which) * 10; final long foregroundMillis = ps.getForegroundTime(which) * 10; - final long starts = ps.getStarts(which); + final int starts = ps.getStarts(which); + final int numCrashes = ps.getNumCrashes(which); + final int numAnrs = ps.getNumAnrs(which); if (userMillis != 0 || systemMillis != 0 || foregroundMillis != 0 - || starts != 0) { + || starts != 0 || numAnrs != 0 || numCrashes != 0) { dumpLine(pw, uid, category, PROCESS_DATA, ent.getKey(), userMillis, - systemMillis, foregroundMillis, starts); + systemMillis, foregroundMillis, starts, numAnrs, numCrashes); } } } @@ -2457,6 +2483,11 @@ public abstract class BatteryStats implements Parcelable { sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime)); sb.append(") "); sb.append(getPhoneOnCount(which)); } + int connChanges = getNumConnectivityChange(which); + if (connChanges != 0) { + pw.print(prefix); + pw.print(" Connectivity changes: "); pw.println(connChanges); + } // Calculate wakelock times across all uids. long fullWakeLockTimeTotalMicros = 0; @@ -3273,11 +3304,13 @@ public abstract class BatteryStats implements Parcelable { systemTime = ps.getSystemTime(which); foregroundTime = ps.getForegroundTime(which); starts = ps.getStarts(which); + final int numCrashes = ps.getNumCrashes(which); + final int numAnrs = ps.getNumAnrs(which); numExcessive = which == STATS_SINCE_CHARGED ? ps.countExcessivePowers() : 0; if (userTime != 0 || systemTime != 0 || foregroundTime != 0 || starts != 0 - || numExcessive != 0) { + || numExcessive != 0 || numCrashes != 0 || numAnrs != 0) { sb.setLength(0); sb.append(prefix); sb.append(" Proc "); sb.append(ent.getKey()); sb.append(":\n"); @@ -3285,9 +3318,26 @@ public abstract class BatteryStats implements Parcelable { formatTime(sb, userTime); sb.append("usr + "); formatTime(sb, systemTime); sb.append("krn ; "); formatTime(sb, foregroundTime); sb.append("fg"); - if (starts != 0) { + if (starts != 0 || numCrashes != 0 || numAnrs != 0) { sb.append("\n"); sb.append(prefix); sb.append(" "); - sb.append(starts); sb.append(" proc starts"); + boolean hasOne = false; + if (starts != 0) { + hasOne = true; + sb.append(starts); sb.append(" starts"); + } + if (numCrashes != 0) { + if (hasOne) { + sb.append(", "); + } + hasOne = true; + sb.append(numCrashes); sb.append(" crashes"); + } + if (numAnrs != 0) { + if (hasOne) { + sb.append(", "); + } + sb.append(numAnrs); sb.append(" anrs"); + } } pw.println(sb.toString()); for (int e=0; e<numExcessive; e++) { diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 3bc74ae..0062eb2 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4349,6 +4349,16 @@ public final class Settings { Global.WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS; /** + * The number of milliseconds to hold on to a PendingIntent based request. This delay gives + * the receivers of the PendingIntent an opportunity to make a new network request before + * the Network satisfying the request is potentially removed. + * + * @hide + */ + public static final String CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS = + "connectivity_release_pending_intent_delay_ms"; + + /** * Whether background data usage is allowed. * * @deprecated As of {@link VERSION_CODES#ICE_CREAM_SANDWICH}, @@ -6118,7 +6128,7 @@ public final class Settings { /** * The number of milliseconds to delay before sending out - * {@link ConnectivityManager#CONNECTIVITY_ACTION} broadcasts. Ignored. + * {@link ConnectivityManager#CONNECTIVITY_ACTION} broadcasts. * * @hide */ diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 02297e3..74b7b69 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -416,7 +416,11 @@ public class StaticLayout extends Layout { currentTextWidth = widths[here - paraStart]; } - v = out(source, here, endPos, + int ellipseEnd = endPos; + if (mMaximumVisibleLineCount == 1 && ellipsize == TextUtils.TruncateAt.MIDDLE) { + ellipseEnd = paraEnd; + } + v = out(source, here, ellipseEnd, above, below, top, bottom, v, spacingmult, spacingadd, chooseHt,chooseHtv, fm, hasTabOrEmoji, needMultiply, chdirs, dir, easy, bufEnd, includepad, trackpad, @@ -704,7 +708,7 @@ public class StaticLayout extends Layout { int left = 0, right = len; float ravail = (avail - ellipsisWidth) / 2; - for (right = len; right >= 0; right--) { + for (right = len; right > 0; right--) { float w = widths[right - 1 + lineStart - widthStart]; if (w + rsum > ravail) { diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java index c1341e1..14be269 100644 --- a/core/java/android/text/util/Linkify.java +++ b/core/java/android/text/util/Linkify.java @@ -402,7 +402,7 @@ public class Linkify { } boolean hasPrefix = false; - + for (int i = 0; i < prefixes.length; i++) { if (url.regionMatches(true, 0, prefixes[i], 0, prefixes[i].length())) { @@ -450,7 +450,7 @@ public class Linkify { private static final void gatherTelLinks(ArrayList<LinkSpec> links, Spannable s) { PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); Iterable<PhoneNumberMatch> matches = phoneUtil.findNumbers(s.toString(), - Locale.getDefault().getCountry(), Leniency.POSSIBLE, Long.MAX_VALUE); + Locale.getDefault().getCountry(), Leniency.VALID, Long.MAX_VALUE); for (PhoneNumberMatch match : matches) { LinkSpec spec = new LinkSpec(); spec.url = "tel:" + PhoneNumberUtils.normalizeNumber(match.rawString()); diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java index a9b3571..121485a 100644 --- a/core/java/android/util/Log.java +++ b/core/java/android/util/Log.java @@ -295,6 +295,11 @@ public final class Log { return bytes; } + static void wtfQuiet(int logId, String tag, String msg, boolean system) { + TerribleFailure what = new TerribleFailure(msg, null); + sWtfHandler.onTerribleFailure(tag, what, system); + } + /** * Sets the terrible failure handler, for testing. * diff --git a/core/java/android/util/Slog.java b/core/java/android/util/Slog.java index e92b846..58a2703 100644 --- a/core/java/android/util/Slog.java +++ b/core/java/android/util/Slog.java @@ -83,6 +83,13 @@ public final class Slog { } /** + * Like {@link #wtf(String, String)}, but does not output anything to the log. + */ + public static void wtfQuiet(String tag, String msg) { + Log.wtfQuiet(Log.LOG_ID_SYSTEM, tag, msg, true); + } + + /** * Like {@link Log#wtfStack(String, String)}, but will never cause the caller to crash, and * will always be handled asynchronously. Primarily for use by coding running within * the system process. diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index 2e5c1e0..6944c53 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -364,7 +364,7 @@ public abstract class Window { /** * This hook is called whenever the window focus changes. See * {@link View#onWindowFocusChanged(boolean) - * View.onWindowFocusChanged(boolean)} for more information. + * View.onWindowFocusChangedNotLocked(boolean)} for more information. * * @param hasFocus Whether the window now has focus. */ diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index f4f047e..094a8a1 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -1102,6 +1102,13 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_KEYGUARD = 0x00000400; /** + * Flag that prevents the wallpaper behind the current window from receiving touch events. + * + * {@hide} + */ + public static final int PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS = 0x00000800; + + /** * Control flags that are private to the platform. * @hide */ diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 55b3ecc..87b6ed7 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -77,6 +77,7 @@ interface IBatteryStats { void noteScreenBrightness(int brightness); void noteUserActivity(int uid, int event); void noteInteractive(boolean interactive); + void noteConnectivityChanged(int type, String extra); void noteMobileRadioPowerState(int powerState, long timestampNs); void notePhoneOn(); void notePhoneOff(); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 0dfb11a..8ceee20 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -94,7 +94,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 115 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 116 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -374,6 +374,10 @@ public final class BatteryStatsImpl extends BatteryStats { private int mPhoneServiceStateRaw = -1; private int mPhoneSimStateRaw = -1; + private int mNumConnectivityChange; + private int mLoadedNumConnectivityChange; + private int mUnpluggedNumConnectivityChange; + /* * Holds a SamplingTimer associated with each kernel wakelock name being tracked. */ @@ -2540,6 +2544,22 @@ public final class BatteryStatsImpl extends BatteryStats { addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PROC_START, name, uid); } + public void noteProcessCrashLocked(String name, int uid) { + uid = mapUid(uid); + if (isOnBattery()) { + Uid u = getUidStatsLocked(uid); + u.getProcessStatsLocked(name).incNumCrashesLocked(); + } + } + + public void noteProcessAnrLocked(String name, int uid) { + uid = mapUid(uid); + if (isOnBattery()) { + Uid u = getUidStatsLocked(uid); + u.getProcessStatsLocked(name).incNumAnrsLocked(); + } + } + public void noteProcessStateLocked(String name, int uid, int state) { uid = mapUid(uid); final long elapsedRealtime = SystemClock.elapsedRealtime(); @@ -3109,6 +3129,14 @@ public final class BatteryStatsImpl extends BatteryStats { } } + public void noteConnectivityChangedLocked(int type, String extra) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_CONNECTIVITY_CHANGED, + extra, type); + mNumConnectivityChange++; + } + public void noteMobileRadioPowerState(int powerState, long timestampNs) { final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); @@ -3965,6 +3993,16 @@ public final class BatteryStatsImpl extends BatteryStats { return mLowPowerModeEnabledTimer.getCountLocked(which); } + @Override public int getNumConnectivityChange(int which) { + int val = mNumConnectivityChange; + if (which == STATS_CURRENT) { + val -= mLoadedNumConnectivityChange; + } else if (which == STATS_SINCE_UNPLUGGED) { + val -= mUnpluggedNumConnectivityChange; + } + return val; + } + @Override public long getPhoneOnTime(long elapsedRealtimeUs, int which) { return mPhoneOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } @@ -5374,6 +5412,16 @@ public final class BatteryStatsImpl extends BatteryStats { int mStarts; /** + * Number of times the process has crashed. + */ + int mNumCrashes; + + /** + * Number of times the process has had an ANR. + */ + int mNumAnrs; + + /** * The amount of user time loaded from a previous save. */ long mLoadedUserTime; @@ -5394,24 +5442,14 @@ public final class BatteryStatsImpl extends BatteryStats { int mLoadedStarts; /** - * The amount of user time loaded from the previous run. - */ - long mLastUserTime; - - /** - * The amount of system time loaded from the previous run. - */ - long mLastSystemTime; - - /** - * The amount of foreground time loaded from the previous run + * Number of times the process has crashed from a previous save. */ - long mLastForegroundTime; + int mLoadedNumCrashes; /** - * The number of times the process has started from the previous run. + * Number of times the process has had an ANR from a previous save. */ - int mLastStarts; + int mLoadedNumAnrs; /** * The amount of user time when last unplugged. @@ -5434,6 +5472,16 @@ public final class BatteryStatsImpl extends BatteryStats { int mUnpluggedStarts; /** + * Number of times the process has crashed before unplugged. + */ + int mUnpluggedNumCrashes; + + /** + * Number of times the process has had an ANR before unplugged. + */ + int mUnpluggedNumAnrs; + + /** * Current process state. */ int mProcessState = PROCESS_STATE_NONE; @@ -5453,6 +5501,8 @@ public final class BatteryStatsImpl extends BatteryStats { mUnpluggedSystemTime = mSystemTime; mUnpluggedForegroundTime = mForegroundTime; mUnpluggedStarts = mStarts; + mUnpluggedNumCrashes = mNumCrashes; + mUnpluggedNumAnrs = mNumAnrs; } public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) { @@ -5460,13 +5510,11 @@ public final class BatteryStatsImpl extends BatteryStats { void reset() { mUserTime = mSystemTime = mForegroundTime = 0; - mStarts = 0; + mStarts = mNumCrashes = mNumAnrs = 0; mLoadedUserTime = mLoadedSystemTime = mLoadedForegroundTime = 0; - mLoadedStarts = 0; - mLastUserTime = mLastSystemTime = mLastForegroundTime = 0; - mLastStarts = 0; + mLoadedStarts = mLoadedNumCrashes = mLoadedNumAnrs = 0; mUnpluggedUserTime = mUnpluggedSystemTime = mUnpluggedForegroundTime = 0; - mUnpluggedStarts = 0; + mUnpluggedStarts = mUnpluggedNumCrashes = mUnpluggedNumAnrs = 0; for (int i = 0; i < mSpeedBins.length; i++) { SamplingCounter c = mSpeedBins[i]; if (c != null) { @@ -5565,14 +5613,20 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(mSystemTime); out.writeLong(mForegroundTime); out.writeInt(mStarts); + out.writeInt(mNumCrashes); + out.writeInt(mNumAnrs); out.writeLong(mLoadedUserTime); out.writeLong(mLoadedSystemTime); out.writeLong(mLoadedForegroundTime); out.writeInt(mLoadedStarts); + out.writeInt(mLoadedNumCrashes); + out.writeInt(mLoadedNumAnrs); out.writeLong(mUnpluggedUserTime); out.writeLong(mUnpluggedSystemTime); out.writeLong(mUnpluggedForegroundTime); out.writeInt(mUnpluggedStarts); + out.writeInt(mUnpluggedNumCrashes); + out.writeInt(mUnpluggedNumAnrs); out.writeInt(mSpeedBins.length); for (int i = 0; i < mSpeedBins.length; i++) { @@ -5593,18 +5647,20 @@ public final class BatteryStatsImpl extends BatteryStats { mSystemTime = in.readLong(); mForegroundTime = in.readLong(); mStarts = in.readInt(); + mNumCrashes = in.readInt(); + mNumAnrs = in.readInt(); mLoadedUserTime = in.readLong(); mLoadedSystemTime = in.readLong(); mLoadedForegroundTime = in.readLong(); mLoadedStarts = in.readInt(); - mLastUserTime = 0; - mLastSystemTime = 0; - mLastForegroundTime = 0; - mLastStarts = 0; + mLoadedNumCrashes = in.readInt(); + mLoadedNumAnrs = in.readInt(); mUnpluggedUserTime = in.readLong(); mUnpluggedSystemTime = in.readLong(); mUnpluggedForegroundTime = in.readLong(); mUnpluggedStarts = in.readInt(); + mUnpluggedNumCrashes = in.readInt(); + mUnpluggedNumAnrs = in.readInt(); int bins = in.readInt(); int steps = getCpuSpeedSteps(); @@ -5635,6 +5691,14 @@ public final class BatteryStatsImpl extends BatteryStats { mStarts++; } + public void incNumCrashesLocked() { + mNumCrashes++; + } + + public void incNumAnrsLocked() { + mNumAnrs++; + } + @Override public boolean isActive() { return mActive; @@ -5684,6 +5748,28 @@ public final class BatteryStatsImpl extends BatteryStats { return val; } + @Override + public int getNumCrashes(int which) { + int val = mNumCrashes; + if (which == STATS_CURRENT) { + val -= mLoadedNumCrashes; + } else if (which == STATS_SINCE_UNPLUGGED) { + val -= mUnpluggedNumCrashes; + } + return val; + } + + @Override + public int getNumAnrs(int which) { + int val = mNumAnrs; + if (which == STATS_CURRENT) { + val -= mLoadedNumAnrs; + } else if (which == STATS_SINCE_UNPLUGGED) { + val -= mUnpluggedNumAnrs; + } + return val; + } + /* Called by ActivityManagerService when CPU times are updated. */ public void addSpeedStepTimes(long[] values) { for (int i = 0; i < mSpeedBins.length && i < values.length; i++) { @@ -6647,6 +6733,7 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { mBluetoothStateTimer[i].reset(false); } + mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0; for (int i=0; i<mUidStats.size(); i++) { if (mUidStats.valueAt(i).reset()) { @@ -7861,6 +7948,7 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { mBluetoothStateTimer[i].readSummaryFromParcelLocked(in); } + mNumConnectivityChange = mLoadedNumConnectivityChange = in.readInt(); mFlashlightOn = false; mFlashlightOnTimer.readSummaryFromParcelLocked(in); @@ -8022,6 +8110,8 @@ public final class BatteryStatsImpl extends BatteryStats { p.mSystemTime = p.mLoadedSystemTime = in.readLong(); p.mForegroundTime = p.mLoadedForegroundTime = in.readLong(); p.mStarts = p.mLoadedStarts = in.readInt(); + p.mNumCrashes = p.mLoadedNumCrashes = in.readInt(); + p.mNumAnrs = p.mLoadedNumAnrs = in.readInt(); int NSB = in.readInt(); if (NSB > 100) { Slog.w(TAG, "File corrupt: too many speed bins " + NSB); @@ -8143,6 +8233,7 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { mBluetoothStateTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); } + out.writeInt(mNumConnectivityChange); mFlashlightOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); out.writeInt(mKernelWakelockStats.size()); @@ -8326,6 +8417,8 @@ public final class BatteryStatsImpl extends BatteryStats { out.writeLong(ps.mSystemTime); out.writeLong(ps.mForegroundTime); out.writeInt(ps.mStarts); + out.writeInt(ps.mNumCrashes); + out.writeInt(ps.mNumAnrs); final int N = ps.mSpeedBins.length; out.writeInt(N); for (int i=0; i<N; i++) { @@ -8444,6 +8537,9 @@ public final class BatteryStatsImpl extends BatteryStats { mBluetoothStateTimer[i] = new StopwatchTimer(null, -500-i, null, mOnBatteryTimeBase, in); } + mNumConnectivityChange = in.readInt(); + mLoadedNumConnectivityChange = in.readInt(); + mUnpluggedNumConnectivityChange = in.readInt(); mAudioOnNesting = 0; mAudioOnTimer = new StopwatchTimer(null, -7, null, mOnBatteryTimeBase); mVideoOnNesting = 0; @@ -8588,6 +8684,9 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i< NUM_BLUETOOTH_STATES; i++) { mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime); } + out.writeInt(mNumConnectivityChange); + out.writeInt(mLoadedNumConnectivityChange); + out.writeInt(mUnpluggedNumConnectivityChange); mFlashlightOnTimer.writeToParcel(out, uSecRealtime); out.writeInt(mDischargeUnplugLevel); out.writeInt(mDischargePlugLevel); diff --git a/core/java/com/android/server/backup/SystemBackupAgent.java b/core/java/com/android/server/backup/SystemBackupAgent.java index ed7ce63..35a1a5a 100644 --- a/core/java/com/android/server/backup/SystemBackupAgent.java +++ b/core/java/com/android/server/backup/SystemBackupAgent.java @@ -17,6 +17,7 @@ package com.android.server.backup; +import android.app.ActivityManagerNative; import android.app.IWallpaperManager; import android.app.backup.BackupDataInput; import android.app.backup.BackupDataOutput; @@ -186,4 +187,13 @@ public class SystemBackupAgent extends BackupAgentHelper { } } } + + @Override + public void onRestoreFinished() { + try { + ActivityManagerNative.getDefault().systemBackupRestored(); + } catch (RemoteException e) { + // Not possible since this code is running in the system process. + } + } } |
