diff options
Diffstat (limited to 'core/java/android')
27 files changed, 771 insertions, 256 deletions
diff --git a/core/java/android/animation/Animatable.java b/core/java/android/animation/Animatable.java deleted file mode 100644 index f9ccb4d..0000000 --- a/core/java/android/animation/Animatable.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2013 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.animation; - -/** - * This interface is implemented by animation-related classes that expose - * the ability to set and get duration, startDelay, and interpolators. - */ -public interface Animatable { - - /** - * The amount of time, in milliseconds, to delay processing the animation - * after the animation is started. The {@link #setDuration(long)} of the - * animation will not begin to elapse until after the startDelay has elapsed. - * - * @return the number of milliseconds to delay running the animation - */ - long getStartDelay(); - - /** - * The amount of time, in milliseconds, to delay processing the animation - * after the animation is started. The {@link #setDuration(long)} of the - * animation will not begin to elapse until after the startDelay has elapsed. - - * @param startDelay The amount of the delay, in milliseconds - */ - void setStartDelay(long startDelay); - - /** - * Sets the length of the animation. - * - * @param duration The length of the animation, in milliseconds. - */ - Animatable setDuration(long duration); - - /** - * Gets the duration of the animation. - * - * @return The length of the animation, in milliseconds. - */ - long getDuration(); - - /** - * The time interpolator used in calculating the elapsed fraction of the - * animation. The interpolator determines whether the animation runs with - * linear or non-linear motion, such as acceleration and deceleration. - * - * @param value the interpolator to be used by this animation - */ - void setInterpolator(TimeInterpolator value); - - /** - * Returns the timing interpolator that this animation uses. - * - * @return The timing interpolator for this animation. - */ - public TimeInterpolator getInterpolator(); -} diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java index da97d72..39eb8d6 100644 --- a/core/java/android/animation/Animator.java +++ b/core/java/android/animation/Animator.java @@ -22,21 +22,13 @@ import java.util.ArrayList; * This is the superclass for classes which provide basic support for animations which can be * started, ended, and have <code>AnimatorListeners</code> added to them. */ -public abstract class Animator implements Cloneable, Animatable { +public abstract class Animator implements Cloneable { /** * The set of listeners to be sent events through the life of an animation. */ ArrayList<AnimatorListener> mListeners = null; - @Override - public abstract Animator setDuration(long duration); - - @Override - public TimeInterpolator getInterpolator() { - return null; - } - /** * Starts this animation. If the animation has a nonzero startDelay, the animation will start * running after that delay elapses. A non-delayed animation will have its initial @@ -77,6 +69,55 @@ public abstract class Animator implements Cloneable, Animatable { } /** + * The amount of time, in milliseconds, to delay processing the animation + * after {@link #start()} is called. + * + * @return the number of milliseconds to delay running the animation + */ + public abstract long getStartDelay(); + + /** + * The amount of time, in milliseconds, to delay processing the animation + * after {@link #start()} is called. + + * @param startDelay The amount of the delay, in milliseconds + */ + public abstract void setStartDelay(long startDelay); + + /** + * Sets the duration of the animation. + * + * @param duration The length of the animation, in milliseconds. + */ + public abstract Animator setDuration(long duration); + + /** + * Gets the duration of the animation. + * + * @return The length of the animation, in milliseconds. + */ + public abstract long getDuration(); + + /** + * The time interpolator used in calculating the elapsed fraction of the + * animation. The interpolator determines whether the animation runs with + * linear or non-linear motion, such as acceleration and deceleration. The + * default value is {@link android.view.animation.AccelerateDecelerateInterpolator}. + * + * @param value the interpolator to be used by this animation + */ + public abstract void setInterpolator(TimeInterpolator value); + + /** + * Returns the timing interpolator that this animation uses. + * + * @return The timing interpolator for this animation. + */ + public TimeInterpolator getInterpolator() { + return null; + } + + /** * Returns whether this Animator is currently running (having been started and gone past any * initial startDelay period and not yet ended). * diff --git a/core/java/android/app/Application.java b/core/java/android/app/Application.java index 7b07438..0d7f0a7 100644 --- a/core/java/android/app/Application.java +++ b/core/java/android/app/Application.java @@ -134,11 +134,6 @@ public class Application extends ContextWrapper implements ComponentCallbacks2 { } } - public List<RestrictionEntry> getApplicationRestrictions() { - return ((UserManager) getSystemService(USER_SERVICE)) - .getApplicationRestrictions(getPackageName(), android.os.Process.myUserHandle()); - } - public void registerComponentCallbacks(ComponentCallbacks callback) { synchronized (mComponentCallbacks) { mComponentCallbacks.add(callback); diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 03e241a..5bd28b9 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -293,15 +293,6 @@ public abstract class Context { public abstract Context getApplicationContext(); /** - * Returns the list of restrictions for the application, or null if there are no - * restrictions. - * @return - */ - public List<RestrictionEntry> getApplicationRestrictions() { - return getApplicationContext().getApplicationRestrictions(); - } - - /** * Add a new {@link ComponentCallbacks} to the base application of the * Context, which will be called at the same times as the ComponentCallbacks * methods of activities and other components are called. Note that you diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 97ad7dd..1ab1eb8 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2417,11 +2417,16 @@ public class Intent implements Parcelable, Cloneable { /** * Broadcast to a specific application to query any supported restrictions to impose - * on restricted users. The response should contain an extra {@link #EXTRA_RESTRICTIONS}, + * on restricted users. The broadcast intent contains an extra + * {@link #EXTRA_RESTRICTIONS_BUNDLE} with the currently persisted + * restrictions as a Bundle of key/value pairs. The value types can be Boolean, String or + * String[] depending on the restriction type.<p/> + * The response should contain an extra {@link #EXTRA_RESTRICTIONS_LIST}, * which is of type <code>ArrayList<RestrictionEntry></code>. It can also * contain an extra {@link #EXTRA_RESTRICTIONS_INTENT}, which is of type <code>Intent</code>. * The activity specified by that intent will be launched for a result which must contain - * the extra {@link #EXTRA_RESTRICTIONS}. The returned restrictions will be persisted. + * the extra {@link #EXTRA_RESTRICTIONS_LIST}. The keys and values of the returned restrictions + * will be persisted. * @see RestrictionEntry */ public static final String ACTION_GET_RESTRICTION_ENTRIES = @@ -3160,7 +3165,8 @@ public class Intent implements Parcelable, Cloneable { "android.intent.extra.ALLOW_MULTIPLE"; /** - * The userHandle carried with broadcast intents related to addition, removal and switching of users + * The userHandle carried with broadcast intents related to addition, removal and switching of + * users * - {@link #ACTION_USER_ADDED}, {@link #ACTION_USER_REMOVED} and {@link #ACTION_USER_SWITCHED}. * @hide */ @@ -3169,9 +3175,18 @@ public class Intent implements Parcelable, Cloneable { /** * Extra used in the response from a BroadcastReceiver that handles - * {@link #ACTION_GET_RESTRICTION_ENTRIES}. + * {@link #ACTION_GET_RESTRICTION_ENTRIES}. The type of the extra is + * <code>ArrayList<RestrictionEntry></code>. + */ + public static final String EXTRA_RESTRICTIONS_LIST = "android.intent.extra.restrictions_list"; + + /** + * Extra sent in the intent to the BroadcastReceiver that handles + * {@link #ACTION_GET_RESTRICTION_ENTRIES}. The type of the extra is a Bundle containing + * the restrictions as key/value pairs. */ - public static final String EXTRA_RESTRICTIONS = "android.intent.extra.restrictions"; + public static final String EXTRA_RESTRICTIONS_BUNDLE = + "android.intent.extra.restrictions_bundle"; /** * Extra used in the response from a BroadcastReceiver that handles diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java index 35bbb9c..e67d0d7 100644 --- a/core/java/android/hardware/location/GeofenceHardware.java +++ b/core/java/android/hardware/location/GeofenceHardware.java @@ -129,6 +129,9 @@ public final class GeofenceHardware { private HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper> mCallbacks = new HashMap<GeofenceHardwareCallback, GeofenceHardwareCallbackWrapper>(); + private HashMap<GeofenceHardwareMonitorCallback, GeofenceHardwareMonitorCallbackWrapper> + mMonitorCallbacks = new HashMap<GeofenceHardwareMonitorCallback, + GeofenceHardwareMonitorCallbackWrapper>(); /** * @hide */ @@ -137,8 +140,29 @@ public final class GeofenceHardware { } /** - * Returns all the hardware geofence monitoring systems and their status. - * Status can be one of {@link #MONITOR_CURRENTLY_AVAILABLE}, + * Returns all the hardware geofence monitoring systems which are supported + * + * <p> Call {@link #getStatusOfMonitoringType(int)} to know the current state + * of a monitoring system. + * + * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access + * geofencing in hardware. + * + * @return An array of all the monitoring types. + * An array of length 0 is returned in case of errors. + */ + public int[] getMonitoringTypes() { + try { + return mService.getMonitoringTypes(); + } catch (RemoteException e) { + } + return new int[0]; + } + + /** + * Returns current status of a hardware geofence monitoring system. + * + * <p>Status can be one of {@link #MONITOR_CURRENTLY_AVAILABLE}, * {@link #MONITOR_CURRENTLY_UNAVAILABLE} or {@link #MONITOR_UNSUPPORTED} * * <p> Some supported hardware monitoring systems might not be available @@ -147,18 +171,15 @@ public final class GeofenceHardware { * geofences and will change from {@link #MONITOR_CURRENTLY_AVAILABLE} to * {@link #MONITOR_CURRENTLY_UNAVAILABLE}. * - * <p> Requires {@link android.Manifest.permission#LOCATION_HARDWARE} permission to access - * geofencing in hardware. - * - * @return An array indexed by the various monitoring types and their status. - * An array of length 0 is returned in case of errors. + * @param monitoringType + * @return Current status of the monitoring type. */ - public int[] getMonitoringTypesAndStatus() { + public int getStatusOfMonitoringType(int monitoringType) { try { - return mService.getMonitoringTypesAndStatus(); + return mService.getStatusOfMonitoringType(monitoringType); } catch (RemoteException e) { + return MONITOR_UNSUPPORTED; } - return new int[0]; } /** @@ -167,8 +188,10 @@ public final class GeofenceHardware { * <p> When the device detects that is has entered, exited or is uncertain * about the area specified by the geofence, the given callback will be called. * - * <p> The {@link GeofenceHardwareCallback#onGeofenceChange} callback will be called, - * with the following parameters + * <p> If this call returns true, it means that the geofence has been sent to the hardware. + * {@link GeofenceHardwareCallback#onGeofenceAdd} will be called with the result of the + * add call from the hardware. The {@link GeofenceHardwareCallback#onGeofenceAdd} will be + * called with the following parameters when a transition event occurs. * <ul> * <li> The geofence Id * <li> The location object indicating the last known location. @@ -195,43 +218,46 @@ public final class GeofenceHardware { * which abstracts the hardware should be used instead. All the checks are done by the higher * level public API. Any needed locking should be handled by the higher level API. * - * @param latitude Latitude of the area to be monitored. - * @param longitude Longitude of the area to be monitored. - * @param radius Radius (in meters) of the area to be monitored. - * @param lastTransition The current state of the geofence. Can be one of - * {@link #GEOFENCE_ENTERED}, {@link #GEOFENCE_EXITED}, - * {@link #GEOFENCE_UNCERTAIN}. - * @param monitorTransitions Bitwise OR of {@link #GEOFENCE_ENTERED}, - * {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN} - * @param notificationResponsivenes Defines the best-effort description - * of how soon should the callback be called when the transition - * associated with the Geofence is triggered. For instance, if - * set to 1000 millseconds with {@link #GEOFENCE_ENTERED}, - * the callback will be called 1000 milliseconds within entering - * the geofence. This parameter is defined in milliseconds. - * @param unknownTimer The time limit after which the - * {@link #GEOFENCE_UNCERTAIN} transition - * should be triggered. This paramter is defined in milliseconds. + * <p> Create a geofence request object using the methods in {@link GeofenceHardwareRequest} to + * set all the characteristics of the geofence. Use the created GeofenceHardwareRequest object + * in this call. + * + * @param geofenceId The id associated with the geofence. * @param monitoringType The type of the hardware subsystem that should be used * to monitor the geofence. + * @param geofenceRequest The {@link GeofenceHardwareRequest} object associated with the + * geofence. * @param callback {@link GeofenceHardwareCallback} that will be use to notify the * transition. - * @return true on success. + * @return true when the geofence is successfully sent to the hardware for addition. + * @throws IllegalArgumentException when the geofence request type is not supported. */ - public boolean addCircularFence(int geofenceId, double latitude, double longitude, - double radius, int lastTransition,int monitorTransitions, int notificationResponsivenes, - int unknownTimer, int monitoringType, GeofenceHardwareCallback callback) { + public boolean addGeofence(int geofenceId, int monitoringType, GeofenceHardwareRequest + geofenceRequest, GeofenceHardwareCallback callback) { try { - return mService.addCircularFence(geofenceId, latitude, longitude, radius, - lastTransition, monitorTransitions, notificationResponsivenes, unknownTimer, - monitoringType, getCallbackWrapper(callback)); + if (geofenceRequest.getType() == GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) { + return mService.addCircularFence(geofenceId, monitoringType, + geofenceRequest.getLatitude(), + geofenceRequest.getLongitude(), geofenceRequest.getRadius(), + geofenceRequest.getLastTransition(), + geofenceRequest.getMonitorTransitions(), + geofenceRequest.getNotificationResponsiveness(), + geofenceRequest.getUnknownTimer(), + getCallbackWrapper(callback)); + } else { + throw new IllegalArgumentException("Geofence Request type not supported"); + } } catch (RemoteException e) { } return false; } /** - * Removes a geofence added by {@link #addCircularFence} call. + * Removes a geofence added by {@link #addGeofence} call. + * + * <p> If this call returns true, it means that the geofence has been sent to the hardware. + * {@link GeofenceHardwareCallback#onGeofenceRemove} will be called with the result of the + * remove call from the hardware. * * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when * {@link #MONITORING_TYPE_GPS_HARDWARE} is used. @@ -246,7 +272,7 @@ public final class GeofenceHardware { * @param geofenceId The id of the geofence. * @param monitoringType The type of the hardware subsystem that should be used * to monitor the geofence. - * @return true on success. + * @return true when the geofence is successfully sent to the hardware for removal. . */ public boolean removeGeofence(int geofenceId, int monitoringType) { try { @@ -257,7 +283,11 @@ public final class GeofenceHardware { } /** - * Pauses the monitoring of a geofence added by {@link #addCircularFence} call. + * Pauses the monitoring of a geofence added by {@link #addGeofence} call. + * + * <p> If this call returns true, it means that the geofence has been sent to the hardware. + * {@link GeofenceHardwareCallback#onGeofencePause} will be called with the result of the + * pause call from the hardware. * * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when * {@link #MONITORING_TYPE_GPS_HARDWARE} is used. @@ -272,7 +302,7 @@ public final class GeofenceHardware { * @param geofenceId The id of the geofence. * @param monitoringType The type of the hardware subsystem that should be used * to monitor the geofence. - * @return true on success. + * @return true when the geofence is successfully sent to the hardware for pausing. */ public boolean pauseGeofence(int geofenceId, int monitoringType) { try { @@ -285,6 +315,10 @@ public final class GeofenceHardware { /** * Resumes the monitoring of a geofence added by {@link #pauseGeofence} call. * + * <p> If this call returns true, it means that the geofence has been sent to the hardware. + * {@link GeofenceHardwareCallback#onGeofenceResume} will be called with the result of the + * resume call from the hardware. + * * <p> Requires {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permission when * {@link #MONITORING_TYPE_GPS_HARDWARE} is used. * @@ -296,15 +330,15 @@ public final class GeofenceHardware { * level public API. Any needed locking should be handled by the higher level API. * * @param geofenceId The id of the geofence. - * @param monitorTransition Bitwise OR of {@link #GEOFENCE_ENTERED}, - * {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN} * @param monitoringType The type of the hardware subsystem that should be used * to monitor the geofence. - * @return true on success. + * @param monitorTransition Bitwise OR of {@link #GEOFENCE_ENTERED}, + * {@link #GEOFENCE_EXITED}, {@link #GEOFENCE_UNCERTAIN} + * @return true when the geofence is successfully sent to the hardware for resumption. */ - public boolean resumeGeofence(int geofenceId, int monitorTransition, int monitoringType) { + public boolean resumeGeofence(int geofenceId, int monitoringType, int monitorTransition) { try { - return mService.resumeGeofence(geofenceId, monitorTransition, monitoringType); + return mService.resumeGeofence(geofenceId, monitoringType, monitorTransition); } catch (RemoteException e) { } return false; @@ -333,10 +367,10 @@ public final class GeofenceHardware { * @return true on success */ public boolean registerForMonitorStateChangeCallback(int monitoringType, - GeofenceHardwareCallback callback) { + GeofenceHardwareMonitorCallback callback) { try { return mService.registerForMonitorStateChangeCallback(monitoringType, - getCallbackWrapper(callback)); + getMonitorCallbackWrapper(callback)); } catch (RemoteException e) { } return false; @@ -361,12 +395,12 @@ public final class GeofenceHardware { * @return true on success */ public boolean unregisterForMonitorStateChangeCallback(int monitoringType, - GeofenceHardwareCallback callback) { + GeofenceHardwareMonitorCallback callback) { boolean result = false; try { result = mService.unregisterForMonitorStateChangeCallback(monitoringType, - getCallbackWrapper(callback)); - if (result) removeCallback(callback); + getMonitorCallbackWrapper(callback)); + if (result) removeMonitorCallback(callback); } catch (RemoteException e) { } @@ -391,24 +425,50 @@ public final class GeofenceHardware { } } - class GeofenceHardwareCallbackWrapper extends IGeofenceHardwareCallback.Stub { - private WeakReference<GeofenceHardwareCallback> mCallback; + private void removeMonitorCallback(GeofenceHardwareMonitorCallback callback) { + synchronized (mMonitorCallbacks) { + mMonitorCallbacks.remove(callback); + } + } - GeofenceHardwareCallbackWrapper(GeofenceHardwareCallback c) { - mCallback = new WeakReference<GeofenceHardwareCallback>(c); + private GeofenceHardwareMonitorCallbackWrapper getMonitorCallbackWrapper( + GeofenceHardwareMonitorCallback callback) { + synchronized (mMonitorCallbacks) { + GeofenceHardwareMonitorCallbackWrapper wrapper = mMonitorCallbacks.get(callback); + if (wrapper == null) { + wrapper = new GeofenceHardwareMonitorCallbackWrapper(callback); + mMonitorCallbacks.put(callback, wrapper); + } + return wrapper; + } + } + + class GeofenceHardwareMonitorCallbackWrapper extends IGeofenceHardwareMonitorCallback.Stub { + private WeakReference<GeofenceHardwareMonitorCallback> mCallback; + + GeofenceHardwareMonitorCallbackWrapper(GeofenceHardwareMonitorCallback c) { + mCallback = new WeakReference<GeofenceHardwareMonitorCallback>(c); } public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) { - GeofenceHardwareCallback c = mCallback.get(); + GeofenceHardwareMonitorCallback c = mCallback.get(); if (c != null) c.onMonitoringSystemChange(monitoringType, available, location); } + } + + class GeofenceHardwareCallbackWrapper extends IGeofenceHardwareCallback.Stub { + private WeakReference<GeofenceHardwareCallback> mCallback; - public void onGeofenceChange(int geofenceId, int transition, Location location, + GeofenceHardwareCallbackWrapper(GeofenceHardwareCallback c) { + mCallback = new WeakReference<GeofenceHardwareCallback>(c); + } + + public void onGeofenceTransition(int geofenceId, int transition, Location location, long timestamp, int monitoringType) { GeofenceHardwareCallback c = mCallback.get(); if (c != null) { - c.onGeofenceChange(geofenceId, transition, location, timestamp, + c.onGeofenceTransition(geofenceId, transition, location, timestamp, monitoringType); } } @@ -428,7 +488,9 @@ public final class GeofenceHardware { public void onGeofencePause(int geofenceId, int status) { GeofenceHardwareCallback c = mCallback.get(); - if (c != null) c.onGeofencePause(geofenceId, status); + if (c != null) { + c.onGeofencePause(geofenceId, status); + } } public void onGeofenceResume(int geofenceId, int status) { diff --git a/core/java/android/hardware/location/GeofenceHardwareCallback.java b/core/java/android/hardware/location/GeofenceHardwareCallback.java index 8ab582a..6cad3da 100644 --- a/core/java/android/hardware/location/GeofenceHardwareCallback.java +++ b/core/java/android/hardware/location/GeofenceHardwareCallback.java @@ -22,19 +22,6 @@ import android.location.Location; * The callback class associated with the APIs in {@link GeofenceHardware} */ public abstract class GeofenceHardwareCallback { - - /** - * The callback called when the state of a monitoring system changes. - * {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a - * monitoring system. - * - * @param monitoringType The type of the monitoring system. - * @param available Indicates whether the system is currently available or not. - * @param location The last known location according to the monitoring system. - */ - public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) { - } - /** * The callback called when there is a transition to report for the specific * geofence. @@ -47,7 +34,7 @@ public abstract class GeofenceHardwareCallback { * detected * @param monitoringType Type of the monitoring system. */ - public void onGeofenceChange(int geofenceId, int transition, Location location, + public void onGeofenceTransition(int geofenceId, int transition, Location location, long timestamp, int monitoringType) { } diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java index 21f1ea6..a62b660 100644 --- a/core/java/android/hardware/location/GeofenceHardwareImpl.java +++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java @@ -21,8 +21,10 @@ import android.content.pm.PackageManager; import android.location.IGpsGeofenceHardware; import android.location.Location; import android.location.LocationManager; +import android.os.Binder; import android.os.Bundle; import android.os.Handler; +import android.os.IBinder; import android.os.Message; import android.os.PowerManager; import android.os.RemoteException; @@ -48,8 +50,9 @@ public final class GeofenceHardwareImpl { private PowerManager.WakeLock mWakeLock; private SparseArray<IGeofenceHardwareCallback> mGeofences = new SparseArray<IGeofenceHardwareCallback>(); - private ArrayList<IGeofenceHardwareCallback>[] mCallbacks = + private ArrayList<IGeofenceHardwareMonitorCallback>[] mCallbacks = new ArrayList[GeofenceHardware.NUM_MONITORS]; + private ArrayList<Reaper> mReapers = new ArrayList<Reaper>(); private IGpsGeofenceHardware mGpsService; @@ -63,11 +66,18 @@ public final class GeofenceHardwareImpl { private static final int RESUME_GEOFENCE_CALLBACK = 5; private static final int ADD_GEOFENCE = 6; private static final int REMOVE_GEOFENCE = 7; + private static final int GEOFENCE_CALLBACK_BINDER_DIED = 8; // mCallbacksHandler message types private static final int GPS_GEOFENCE_STATUS = 1; private static final int CALLBACK_ADD = 2; private static final int CALLBACK_REMOVE = 3; + private static final int MONITOR_CALLBACK_BINDER_DIED = 4; + + // mReaperHandler message types + private static final int REAPER_GEOFENCE_ADDED = 1; + private static final int REAPER_MONITOR_CALLBACK_ADDED = 2; + private static final int REAPER_REMOVED = 3; // The following constants need to match GpsLocationFlags enum in gps.h private static final int LOCATION_INVALID = 0; @@ -151,15 +161,28 @@ public final class GeofenceHardwareImpl { } } - public int[] getMonitoringTypesAndStatus() { + public int[] getMonitoringTypes() { synchronized (mSupportedMonitorTypes) { - return mSupportedMonitorTypes; + if (mSupportedMonitorTypes[GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE] != + GeofenceHardware.MONITOR_UNSUPPORTED) { + return new int[] {GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE}; + } + return new int[0]; + } + } + + public int getStatusOfMonitoringType(int monitoringType) { + synchronized (mSupportedMonitorTypes) { + if (monitoringType >= mSupportedMonitorTypes.length || monitoringType < 0) { + throw new IllegalArgumentException("Unknown monitoring type"); + } + return mSupportedMonitorTypes[monitoringType]; } } - public boolean addCircularFence(int geofenceId, double latitude, double longitude, - double radius, int lastTransition,int monitorTransitions, int notificationResponsivenes, - int unknownTimer, int monitoringType, IGeofenceHardwareCallback callback) { + public boolean addCircularFence(int geofenceId, int monitoringType, double latitude, + double longitude, double radius, int lastTransition,int monitorTransitions, + int notificationResponsivenes, int unknownTimer, IGeofenceHardwareCallback callback) { // This API is not thread safe. Operations on the same geofence need to be serialized // by upper layers if (DEBUG) { @@ -190,7 +213,11 @@ public final class GeofenceHardwareImpl { default: result = false; } - if (!result) { + if (result) { + m = mReaperHandler.obtainMessage(REAPER_GEOFENCE_ADDED, callback); + m.arg1 = monitoringType; + mReaperHandler.sendMessage(m); + } else { m = mGeofenceHandler.obtainMessage(REMOVE_GEOFENCE); m.arg1 = geofenceId; mGeofenceHandler.sendMessage(m); @@ -245,7 +272,7 @@ public final class GeofenceHardwareImpl { } - public boolean resumeGeofence(int geofenceId, int monitorTransition, int monitoringType) { + public boolean resumeGeofence(int geofenceId, int monitoringType, int monitorTransition) { // This API is not thread safe. Operations on the same geofence need to be serialized // by upper layers if (DEBUG) Log.d(TAG, "Resume Geofence: GeofenceId: " + geofenceId); @@ -268,7 +295,12 @@ public final class GeofenceHardwareImpl { } public boolean registerForMonitorStateChangeCallback(int monitoringType, - IGeofenceHardwareCallback callback) { + IGeofenceHardwareMonitorCallback callback) { + Message reaperMessage = + mReaperHandler.obtainMessage(REAPER_MONITOR_CALLBACK_ADDED, callback); + reaperMessage.arg1 = monitoringType; + mReaperHandler.sendMessage(reaperMessage); + Message m = mCallbacksHandler.obtainMessage(CALLBACK_ADD, callback); m.arg1 = monitoringType; mCallbacksHandler.sendMessage(m); @@ -276,7 +308,7 @@ public final class GeofenceHardwareImpl { } public boolean unregisterForMonitorStateChangeCallback(int monitoringType, - IGeofenceHardwareCallback callback) { + IGeofenceHardwareMonitorCallback callback) { Message m = mCallbacksHandler.obtainMessage(CALLBACK_REMOVE, callback); m.arg1 = monitoringType; mCallbacksHandler.sendMessage(m); @@ -477,13 +509,25 @@ public final class GeofenceHardwareImpl { "Location: " + geofenceTransition.mLocation + ":" + mGeofences); try { - callback.onGeofenceChange( + callback.onGeofenceTransition( geofenceTransition.mGeofenceId, geofenceTransition.mTransition, geofenceTransition.mLocation, geofenceTransition.mTimestamp, GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE); } catch (RemoteException e) {} releaseWakeLock(); break; + case GEOFENCE_CALLBACK_BINDER_DIED: + // Find all geofences associated with this callback and remove them. + callback = (IGeofenceHardwareCallback) (msg.obj); + if (DEBUG) Log.d(TAG, "Geofence callback reaped:" + callback); + int monitoringType = msg.arg1; + for (int i = 0; i < mGeofences.size(); i++) { + if (mGeofences.valueAt(i).equals(callback)) { + geofenceId = mGeofences.keyAt(i); + removeGeofence(mGeofences.keyAt(i), monitoringType); + mGeofences.remove(geofenceId); + } + } } } }; @@ -493,8 +537,8 @@ public final class GeofenceHardwareImpl { @Override public void handleMessage(Message msg) { int monitoringType; - ArrayList<IGeofenceHardwareCallback> callbackList; - IGeofenceHardwareCallback callback; + ArrayList<IGeofenceHardwareMonitorCallback> callbackList; + IGeofenceHardwareMonitorCallback callback; switch (msg.what) { case GPS_GEOFENCE_STATUS: @@ -508,7 +552,7 @@ public final class GeofenceHardwareImpl { if (DEBUG) Log.d(TAG, "MonitoringSystemChangeCallback: GPS : " + available); - for (IGeofenceHardwareCallback c: callbackList) { + for (IGeofenceHardwareMonitorCallback c: callbackList) { try { c.onMonitoringSystemChange( GeofenceHardware.MONITORING_TYPE_GPS_HARDWARE, available, @@ -519,22 +563,71 @@ public final class GeofenceHardwareImpl { break; case CALLBACK_ADD: monitoringType = msg.arg1; - callback = (IGeofenceHardwareCallback) msg.obj; + callback = (IGeofenceHardwareMonitorCallback) msg.obj; callbackList = mCallbacks[monitoringType]; if (callbackList == null) { - callbackList = new ArrayList<IGeofenceHardwareCallback>(); + callbackList = new ArrayList<IGeofenceHardwareMonitorCallback>(); mCallbacks[monitoringType] = callbackList; } if (!callbackList.contains(callback)) callbackList.add(callback); break; case CALLBACK_REMOVE: monitoringType = msg.arg1; - callback = (IGeofenceHardwareCallback) msg.obj; + callback = (IGeofenceHardwareMonitorCallback) msg.obj; callbackList = mCallbacks[monitoringType]; if (callbackList != null) { callbackList.remove(callback); } break; + case MONITOR_CALLBACK_BINDER_DIED: + callback = (IGeofenceHardwareMonitorCallback) msg.obj; + if (DEBUG) Log.d(TAG, "Monitor callback reaped:" + callback); + callbackList = mCallbacks[msg.arg1]; + if (callbackList != null && callbackList.contains(callback)) { + callbackList.remove(callback); + } + } + } + }; + + // All operations on mReaper + private Handler mReaperHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + Reaper r; + IGeofenceHardwareCallback callback; + IGeofenceHardwareMonitorCallback monitorCallback; + int monitoringType; + + switch (msg.what) { + case REAPER_GEOFENCE_ADDED: + callback = (IGeofenceHardwareCallback) msg.obj; + monitoringType = msg.arg1; + r = new Reaper(callback, monitoringType); + if (!mReapers.contains(r)) { + mReapers.add(r); + IBinder b = callback.asBinder(); + try { + b.linkToDeath(r, 0); + } catch (RemoteException e) {} + } + break; + case REAPER_MONITOR_CALLBACK_ADDED: + monitorCallback = (IGeofenceHardwareMonitorCallback) msg.obj; + monitoringType = msg.arg1; + + r = new Reaper(monitorCallback, monitoringType); + if (!mReapers.contains(r)) { + mReapers.add(r); + IBinder b = monitorCallback.asBinder(); + try { + b.linkToDeath(r, 0); + } catch (RemoteException e) {} + } + break; + case REAPER_REMOVED: + r = (Reaper) msg.obj; + mReapers.remove(r); } } }; @@ -567,6 +660,57 @@ public final class GeofenceHardwareImpl { return RESOLUTION_LEVEL_NONE; } + class Reaper implements IBinder.DeathRecipient { + private IGeofenceHardwareMonitorCallback mMonitorCallback; + private IGeofenceHardwareCallback mCallback; + private int mMonitoringType; + + Reaper(IGeofenceHardwareCallback c, int monitoringType) { + mCallback = c; + mMonitoringType = monitoringType; + } + + Reaper(IGeofenceHardwareMonitorCallback c, int monitoringType) { + mMonitorCallback = c; + mMonitoringType = monitoringType; + } + + @Override + public void binderDied() { + Message m; + if (mCallback != null) { + m = mGeofenceHandler.obtainMessage(GEOFENCE_CALLBACK_BINDER_DIED, mCallback); + m.arg1 = mMonitoringType; + mGeofenceHandler.sendMessage(m); + } else if (mMonitorCallback != null) { + m = mCallbacksHandler.obtainMessage(MONITOR_CALLBACK_BINDER_DIED, mMonitorCallback); + m.arg1 = mMonitoringType; + mCallbacksHandler.sendMessage(m); + } + Message reaperMessage = mReaperHandler.obtainMessage(REAPER_REMOVED, this); + mReaperHandler.sendMessage(reaperMessage); + } + + @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 + mMonitoringType; + return result; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) return false; + if (obj == this) return true; + + Reaper rhs = (Reaper) obj; + return rhs.mCallback == mCallback && rhs.mMonitorCallback == mMonitorCallback && + rhs.mMonitoringType == mMonitoringType; + } + } + int getAllowedResolutionLevel(int pid, int uid) { if (mContext.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, pid, uid) == PackageManager.PERMISSION_GRANTED) { diff --git a/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java new file mode 100644 index 0000000..b8e927e --- /dev/null +++ b/core/java/android/hardware/location/GeofenceHardwareMonitorCallback.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.location; + +import android.location.Location; + +/** + * The callback class associated with the status change of hardware montiors + * in {@link GeofenceHardware} + */ +public abstract class GeofenceHardwareMonitorCallback { + /** + * The callback called when the state of a monitoring system changes. + * {@link GeofenceHardware#MONITORING_TYPE_GPS_HARDWARE} is an example of a + * monitoring system + * + * @param monitoringType The type of the monitoring system. + * @param available Indicates whether the system is currenty available or not. + * @param location The last known location according to the monitoring system. + */ + public void onMonitoringSystemChange(int monitoringType, boolean available, Location location) { + } +} diff --git a/core/java/android/hardware/location/GeofenceHardwareRequest.java b/core/java/android/hardware/location/GeofenceHardwareRequest.java new file mode 100644 index 0000000..6e7b592 --- /dev/null +++ b/core/java/android/hardware/location/GeofenceHardwareRequest.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.location; + +import android.location.Location; + +/** + * This class represents the characteristics of the geofence. + * + * <p> Use this in conjunction with {@link GeofenceHardware} APIs. + */ + +public final class GeofenceHardwareRequest { + static final int GEOFENCE_TYPE_CIRCLE = 0; + private int mType; + private double mLatitude; + private double mLongitude; + private double mRadius; + private int mLastTransition = GeofenceHardware.GEOFENCE_UNCERTAIN; + private int mUnknownTimer = 30000; // 30 secs + private int mMonitorTransitions = GeofenceHardware.GEOFENCE_UNCERTAIN | + GeofenceHardware.GEOFENCE_ENTERED | GeofenceHardware.GEOFENCE_EXITED; + private int mNotificationResponsiveness = 5000; // 5 secs + + private void setCircularGeofence(double latitude, double longitude, double radius) { + mLatitude = latitude; + mLongitude = longitude; + mRadius = radius; + mType = GEOFENCE_TYPE_CIRCLE; + } + + /** + * Create a circular geofence. + * + * @param latitude Latitude of the geofence + * @param longitude Longitude of the geofence + * @param radius Radius of the geofence (in meters) + */ + public static GeofenceHardwareRequest createCircularGeofence(double latitude, + double longitude, double radius) { + GeofenceHardwareRequest geofenceRequest = new GeofenceHardwareRequest(); + geofenceRequest.setCircularGeofence(latitude, longitude, radius); + return geofenceRequest; + } + + /** + * Set the last known transition of the geofence. + * + * @param lastTransition The current state of the geofence. Can be one of + * {@link GeofenceHardware#GEOFENCE_ENTERED}, {@link GeofenceHardware#GEOFENCE_EXITED}, + * {@link GeofenceHardware#GEOFENCE_UNCERTAIN}. + */ + public void setLastTransition(int lastTransition) { + mLastTransition = lastTransition; + } + + /** + * Set the unknown timer for this geofence. + * + * @param unknownTimer The time limit after which the + * {@link GeofenceHardware#GEOFENCE_UNCERTAIN} transition + * should be triggered. This paramter is defined in milliseconds. + */ + public void setUnknownTimer(int unknownTimer) { + mUnknownTimer = unknownTimer; + } + + /** + * Set the transitions to be monitored. + * + * @param monitorTransitions Bitwise OR of {@link GeofenceHardware#GEOFENCE_ENTERED}, + * {@link GeofenceHardware#GEOFENCE_EXITED}, {@link GeofenceHardware#GEOFENCE_UNCERTAIN} + */ + public void setMonitorTransitions(int monitorTransitions) { + mMonitorTransitions = monitorTransitions; + } + + /** + * Set the notification responsiveness of the geofence. + * + * @param notificationResponsiveness (milliseconds) Defines the best-effort description + * of how soon should the callback be called when the transition + * associated with the Geofence is triggered. For instance, if + * set to 1000 millseconds with {@link GeofenceHardware#GEOFENCE_ENTERED}, + * the callback will be called 1000 milliseconds within entering + * the geofence. + */ + public void setNotificationResponsiveness(int notificationResponsiveness) { + mNotificationResponsiveness = notificationResponsiveness; + } + + /** + * Returns the latitude of this geofence. + */ + public double getLatitude() { + return mLatitude; + } + + /** + * Returns the longitude of this geofence. + */ + public double getLongitude() { + return mLongitude; + } + + /** + * Returns the radius of this geofence. + */ + public double getRadius() { + return mRadius; + } + + /** + * Returns transitions monitored for this geofence. + */ + public int getMonitorTransitions() { + return mMonitorTransitions; + } + + /** + * Returns the unknownTimer of this geofence. + */ + public int getUnknownTimer() { + return mUnknownTimer; + } + + /** + * Returns the notification responsiveness of this geofence. + */ + public int getNotificationResponsiveness() { + return mNotificationResponsiveness; + } + + /** + * Returns the last transition of this geofence. + */ + public int getLastTransition() { + return mLastTransition; + } + + int getType() { + return mType; + } +} diff --git a/core/java/android/hardware/location/GeofenceHardwareService.java b/core/java/android/hardware/location/GeofenceHardwareService.java index 0eccee6..3bc70ee 100644 --- a/core/java/android/hardware/location/GeofenceHardwareService.java +++ b/core/java/android/hardware/location/GeofenceHardwareService.java @@ -68,23 +68,28 @@ public class GeofenceHardwareService extends Service { mGeofenceHardwareImpl.setGpsHardwareGeofence(service); } - public int[] getMonitoringTypesAndStatus() { + public int[] getMonitoringTypes() { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); - return mGeofenceHardwareImpl.getMonitoringTypesAndStatus(); + return mGeofenceHardwareImpl.getMonitoringTypes(); } - public boolean addCircularFence(int id, double lat, double longitude, double radius, - int lastTransition, int monitorTransitions, int - notificationResponsiveness, int unknownTimer, int monitoringType, - IGeofenceHardwareCallback callback) { + public int getStatusOfMonitoringType(int monitoringType) { + mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, + "Location Hardware permission not granted to access hardware geofence"); + + return mGeofenceHardwareImpl.getStatusOfMonitoringType(monitoringType); + } + public boolean addCircularFence(int id, int monitoringType, double lat, double longitude, + double radius, int lastTransition, int monitorTransitions, int + notificationResponsiveness, int unknownTimer, IGeofenceHardwareCallback callback) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType); - return mGeofenceHardwareImpl.addCircularFence(id, lat, longitude, radius, - lastTransition, monitorTransitions, notificationResponsiveness, unknownTimer, - monitoringType, callback); + return mGeofenceHardwareImpl.addCircularFence(id, monitoringType, lat, longitude, + radius, lastTransition, monitorTransitions, notificationResponsiveness, + unknownTimer, callback); } public boolean removeGeofence(int id, int monitoringType) { @@ -103,16 +108,16 @@ public class GeofenceHardwareService extends Service { return mGeofenceHardwareImpl.pauseGeofence(id, monitoringType); } - public boolean resumeGeofence(int id, int monitorTransitions, int monitoringType) { + public boolean resumeGeofence(int id, int monitoringType, int monitorTransitions) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); checkPermission(Binder.getCallingPid(), Binder.getCallingUid(), monitoringType); - return mGeofenceHardwareImpl.resumeGeofence(id, monitorTransitions, monitoringType); + return mGeofenceHardwareImpl.resumeGeofence(id, monitoringType, monitorTransitions); } public boolean registerForMonitorStateChangeCallback(int monitoringType, - IGeofenceHardwareCallback callback) { + IGeofenceHardwareMonitorCallback callback) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); @@ -122,7 +127,7 @@ public class GeofenceHardwareService extends Service { } public boolean unregisterForMonitorStateChangeCallback(int monitoringType, - IGeofenceHardwareCallback callback) { + IGeofenceHardwareMonitorCallback callback) { mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, "Location Hardware permission not granted to access hardware geofence"); diff --git a/core/java/android/hardware/location/IGeofenceHardware.aidl b/core/java/android/hardware/location/IGeofenceHardware.aidl index 4ba02b8..6900070 100644 --- a/core/java/android/hardware/location/IGeofenceHardware.aidl +++ b/core/java/android/hardware/location/IGeofenceHardware.aidl @@ -18,19 +18,21 @@ package android.hardware.location; import android.location.IGpsGeofenceHardware; import android.hardware.location.IGeofenceHardwareCallback; +import android.hardware.location.IGeofenceHardwareMonitorCallback; /** @hide */ interface IGeofenceHardware { void setGpsGeofenceHardware(in IGpsGeofenceHardware service); - int[] getMonitoringTypesAndStatus(); - boolean addCircularFence(int id, double lat, double longitude, double radius, - int lastTransition, int monitorTransitions, int notificationResponsiveness, - int unknownTimer, int monitoringType, in IGeofenceHardwareCallback callback); + int[] getMonitoringTypes(); + int getStatusOfMonitoringType(int monitoringType); + boolean addCircularFence(int id, int monitoringType, double lat, double longitude, + double radius, int lastTransition, int monitorTransitions, + int notificationResponsiveness, int unknownTimer,in IGeofenceHardwareCallback callback); boolean removeGeofence(int id, int monitoringType); boolean pauseGeofence(int id, int monitoringType); - boolean resumeGeofence(int id, int monitorTransitions, int monitoringType); + boolean resumeGeofence(int id, int monitoringType, int monitorTransitions); boolean registerForMonitorStateChangeCallback(int monitoringType, - IGeofenceHardwareCallback callback); + IGeofenceHardwareMonitorCallback callback); boolean unregisterForMonitorStateChangeCallback(int monitoringType, - IGeofenceHardwareCallback callback); + IGeofenceHardwareMonitorCallback callback); } diff --git a/core/java/android/hardware/location/IGeofenceHardwareCallback.aidl b/core/java/android/hardware/location/IGeofenceHardwareCallback.aidl index 678fc49..3a8f430 100644 --- a/core/java/android/hardware/location/IGeofenceHardwareCallback.aidl +++ b/core/java/android/hardware/location/IGeofenceHardwareCallback.aidl @@ -20,8 +20,7 @@ import android.location.Location; /** @hide */ oneway interface IGeofenceHardwareCallback { - void onMonitoringSystemChange(int monitoringType, boolean available, in Location location); - void onGeofenceChange(int geofenceId, int transition, in Location location, + void onGeofenceTransition(int geofenceId, int transition, in Location location, long timestamp, int monitoringType); void onGeofenceAdd(int geofenceId, int status); void onGeofenceRemove(int geofenceId, int status); diff --git a/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl b/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl new file mode 100644 index 0000000..0b6e04b --- /dev/null +++ b/core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2013 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.hardware.location; + +import android.location.Location; + +/** @hide */ +oneway interface IGeofenceHardwareMonitorCallback { + void onMonitoringSystemChange(int monitoringType, boolean available, in Location location); +} diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl index 2e8092a..a11358a 100644 --- a/core/java/android/os/IUserManager.aidl +++ b/core/java/android/os/IUserManager.aidl @@ -42,7 +42,8 @@ interface IUserManager { int getUserHandle(int userSerialNumber); Bundle getUserRestrictions(int userHandle); void setUserRestrictions(in Bundle restrictions, int userHandle); - void setApplicationRestrictions(in String packageName, in List<RestrictionEntry> entries, + void setApplicationRestrictions(in String packageName, in Bundle restrictions, int userHandle); - List<RestrictionEntry> getApplicationRestrictions(in String packageName, int userHandle); + Bundle getApplicationRestrictions(in String packageName); + Bundle getApplicationRestrictionsForUser(in String packageName, int userHandle); } diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java index 617f490..3307a8c 100644 --- a/core/java/android/os/Trace.java +++ b/core/java/android/os/Trace.java @@ -79,6 +79,7 @@ public final class Trace { private static native void nativeAsyncTraceBegin(long tag, String name, int cookie); private static native void nativeAsyncTraceEnd(long tag, String name, int cookie); private static native void nativeSetAppTracingAllowed(boolean allowed); + private static native void nativeSetTracingEnabled(boolean allowed); static { // We configure two separate change callbacks, one in Trace.cpp and one here. The @@ -115,10 +116,6 @@ public final class Trace { */ private static long cacheEnabledTags() { long tags = nativeGetEnabledTags(); - if (tags == TRACE_TAG_NOT_READY) { - Log.w(TAG, "Unexpected value from nativeGetEnabledTags: " + tags); - // keep going - } sEnabledTags = tags; return tags; } @@ -169,6 +166,22 @@ public final class Trace { } /** + * Set whether tracing is enabled in this process. Tracing is disabled shortly after Zygote + * initializes and re-enabled after processes fork from Zygote. This is done because Zygote + * has no way to be notified about changes to the tracing tags, and if Zygote ever reads and + * caches the tracing tags, forked processes will inherit those stale tags. + * + * @hide + */ + public static void setTracingEnabled(boolean enabled) { + nativeSetTracingEnabled(enabled); + + // Setting whether tracing is enabled may change the tags, so we update the cached tags + // here. + cacheEnabledTags(); + } + + /** * Writes a trace message to indicate that a given section of code has * begun. Must be followed by a call to {@link #traceEnd} using the same * tag. diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index e580e2b..df065e9 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -142,6 +142,7 @@ public class UserManager { private static UserManager sInstance = null; + /** @hide */ public synchronized static UserManager get(Context context) { if (sInstance == null) { sInstance = (UserManager) context.getSystemService(Context.USER_SERVICE); @@ -578,13 +579,29 @@ public class UserManager { return -1; } + /** + * Returns a Bundle containing any saved application restrictions for this user, for the + * given package name. Only an application with this package name can call this method. + * @param packageName the package name of the calling application + * @return a Bundle with the restrictions as key/value pairs, or null if there are no + * saved restrictions. The values can be of type Boolean, String or String[], depending + * on the restriction type, as defined by the application. + */ + public Bundle getApplicationRestrictions(String packageName) { + try { + return mService.getApplicationRestrictions(packageName); + } catch (RemoteException re) { + Log.w(TAG, "Could not get application restrictions for package " + packageName); + } + return null; + } /** * @hide */ - public List<RestrictionEntry> getApplicationRestrictions(String packageName, UserHandle user) { + public Bundle getApplicationRestrictions(String packageName, UserHandle user) { try { - return mService.getApplicationRestrictions(packageName, user.getIdentifier()); + return mService.getApplicationRestrictionsForUser(packageName, user.getIdentifier()); } catch (RemoteException re) { Log.w(TAG, "Could not get application restrictions for user " + user.getIdentifier()); } @@ -594,10 +611,10 @@ public class UserManager { /** * @hide */ - public void setApplicationRestrictions(String packageName, List<RestrictionEntry> entries, + public void setApplicationRestrictions(String packageName, Bundle restrictions, UserHandle user) { try { - mService.setApplicationRestrictions(packageName, entries, user.getIdentifier()); + mService.setApplicationRestrictions(packageName, restrictions, user.getIdentifier()); } catch (RemoteException re) { Log.w(TAG, "Could not set application restrictions for user " + user.getIdentifier()); } diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 88ee414..3df4e99 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3260,6 +3260,7 @@ public final class Settings { /** * This preference contains the string that shows for owner info on LockScreen. * @hide + * @deprecated */ public static final String LOCK_SCREEN_OWNER_INFO = "lock_screen_owner_info"; @@ -3287,6 +3288,7 @@ public final class Settings { /** * This preference enables showing the owner info on LockScreen. * @hide + * @deprecated */ public static final String LOCK_SCREEN_OWNER_INFO_ENABLED = "lock_screen_owner_info_enabled"; @@ -4102,9 +4104,7 @@ public final class Settings { MOUNT_UMS_AUTOSTART, MOUNT_UMS_PROMPT, MOUNT_UMS_NOTIFY_ENABLED, - UI_NIGHT_MODE, - LOCK_SCREEN_OWNER_INFO, - LOCK_SCREEN_OWNER_INFO_ENABLED + UI_NIGHT_MODE }; /** diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index edfef56..4989c3a 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -220,14 +220,14 @@ public class Surface implements Parcelable { /** * Gets a {@link Canvas} for drawing into this surface. * - * After drawing into the provided {@link Canvas}, the caller should + * After drawing into the provided {@link Canvas}, the caller must * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. * * @param inOutDirty A rectangle that represents the dirty region that the caller wants * to redraw. This function may choose to expand the dirty rectangle if for example * the surface has been resized or if the previous contents of the surface were - * not available. The caller should redraw the entire dirty region as represented - * by the contents of the dirty rect upon return from this function. + * not available. The caller must redraw the entire dirty region as represented + * by the contents of the inOutDirty rectangle upon return from this function. * The caller may also pass <code>null</code> instead, in the case where the * entire surface should be redrawn. * @return A canvas for drawing into the surface. diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java index 14fa9cb..793fb5e 100644 --- a/core/java/android/view/SurfaceView.java +++ b/core/java/android/view/SurfaceView.java @@ -755,12 +755,36 @@ public class SurfaceView extends View { mHandler.sendMessage(msg); } + /** + * Gets a {@link Canvas} for drawing into the SurfaceView's Surface + * + * After drawing into the provided {@link Canvas}, the caller must + * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. + * + * The caller must redraw the entire surface. + * @return A canvas for drawing into the surface. + */ public Canvas lockCanvas() { return internalLockCanvas(null); } - public Canvas lockCanvas(Rect dirty) { - return internalLockCanvas(dirty); + /** + * Gets a {@link Canvas} for drawing into the SurfaceView's Surface + * + * After drawing into the provided {@link Canvas}, the caller must + * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. + * + * @param inOutDirty A rectangle that represents the dirty region that the caller wants + * to redraw. This function may choose to expand the dirty rectangle if for example + * the surface has been resized or if the previous contents of the surface were + * not available. The caller must redraw the entire dirty region as represented + * by the contents of the inOutDirty rectangle upon return from this function. + * The caller may also pass <code>null</code> instead, in the case where the + * entire surface should be redrawn. + * @return A canvas for drawing into the surface. + */ + public Canvas lockCanvas(Rect inOutDirty) { + return internalLockCanvas(inOutDirty); } private final Canvas internalLockCanvas(Rect dirty) { @@ -810,6 +834,12 @@ public class SurfaceView extends View { return null; } + /** + * Posts the new contents of the {@link Canvas} to the surface and + * releases the {@link Canvas}. + * + * @param canvas The canvas previously obtained from {@link #lockCanvas}. + */ public void unlockCanvasAndPost(Canvas canvas) { mSurface.unlockCanvasAndPost(canvas); mSurfaceLock.unlock(); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 4fb2431..be26d20 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -13380,18 +13380,32 @@ public class View implements Drawable.Callback, KeyEvent.Callback, /** * Sets a rectangular area on this view to which the view will be clipped - * it is drawn. Setting the value to null will remove the clip bounds + * when it is drawn. Setting the value to null will remove the clip bounds * and the view will draw normally, using its full bounds. * * @param clipBounds The rectangular area, in the local coordinates of * this view, to which future drawing operations will be clipped. */ public void setClipBounds(Rect clipBounds) { - mClipBounds = clipBounds; if (clipBounds != null) { - invalidate(clipBounds); + if (clipBounds.equals(mClipBounds)) { + return; + } + if (mClipBounds == null) { + invalidate(); + mClipBounds = new Rect(clipBounds); + } else { + invalidate(Math.min(mClipBounds.left, clipBounds.left), + Math.min(mClipBounds.top, clipBounds.top), + Math.max(mClipBounds.right, clipBounds.right), + Math.max(mClipBounds.bottom, clipBounds.bottom)); + mClipBounds.set(clipBounds); + } } else { - invalidate(); + if (mClipBounds != null) { + invalidate(); + mClipBounds = null; + } } } diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java index 98df064..528eadd 100644 --- a/core/java/android/view/ViewPropertyAnimator.java +++ b/core/java/android/view/ViewPropertyAnimator.java @@ -16,7 +16,6 @@ package android.view; -import android.animation.Animatable; import android.animation.Animator; import android.animation.ValueAnimator; import android.animation.TimeInterpolator; diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java index c7dacf3..a324502 100644 --- a/core/java/android/webkit/WebViewClassic.java +++ b/core/java/android/webkit/WebViewClassic.java @@ -2149,7 +2149,8 @@ public final class WebViewClassic implements WebViewProvider, WebViewProvider.Sc @Override public void destroy() { if (mWebView.getViewRootImpl() != null) { - Log.e(LOGTAG, "Error: WebView.destroy() called while still attached!"); + Log.e(LOGTAG, Log.getStackTraceString( + new Throwable("Error: WebView.destroy() called while still attached!"))); } ensureFunctorDetached(); destroyJava(); diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 94dadb4..c72853f 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -2699,6 +2699,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te mLastTouchMode = touchMode; } + @Override + public void onRtlPropertiesChanged(int layoutDirection) { + super.onRtlPropertiesChanged(layoutDirection); + + if (mFastScroller != null) { + mFastScroller.setScrollbarPosition(getVerticalScrollbarPosition()); + } + } + /** * Creates the ContextMenuInfo returned from {@link #getContextMenuInfo()}. This * methods knows the view, position and ID of the item that received the diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java index d2139af..fc9c000 100644 --- a/core/java/android/widget/FastScroller.java +++ b/core/java/android/widget/FastScroller.java @@ -216,8 +216,22 @@ class FastScroller { mHandler.removeCallbacks(mScrollFade); break; case STATE_EXIT: - int viewWidth = mList.getWidth(); - mList.invalidate(viewWidth - mThumbW, mThumbY, viewWidth, mThumbY + mThumbH); + final int viewWidth = mList.getWidth(); + final int top = mThumbY; + final int bottom = mThumbY + mThumbH; + final int left; + final int right; + switch (mList.getLayoutDirection()) { + case View.LAYOUT_DIRECTION_RTL: + left = 0; + right = mThumbW; + break; + case View.LAYOUT_DIRECTION_LTR: + default: + left = viewWidth - mThumbW; + right = viewWidth; + } + mList.invalidate(left, top, right, bottom); break; } mState = state; @@ -398,10 +412,26 @@ class FastScroller { } else if (mState == STATE_EXIT) { if (alpha == 0) { // Done with exit setState(STATE_NONE); - } else if (mTrackDrawable != null) { - mList.invalidate(viewWidth - mThumbW, 0, viewWidth, mList.getHeight()); } else { - mList.invalidate(viewWidth - mThumbW, y, viewWidth, y + mThumbH); + final int left, right, top, bottom; + if (mTrackDrawable != null) { + top = 0; + bottom = mList.getHeight(); + } else { + top = y; + bottom = y + mThumbH; + } + switch (mList.getLayoutDirection()) { + case View.LAYOUT_DIRECTION_RTL: + left = 0; + right = mThumbW; + break; + case View.LAYOUT_DIRECTION_LTR: + default: + left = viewWidth - mThumbW; + right = viewWidth; + } + mList.invalidate(left, top, right, bottom); } } } diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java index 85ed8db..2309001 100644 --- a/core/java/android/widget/GridLayout.java +++ b/core/java/android/widget/GridLayout.java @@ -944,15 +944,17 @@ public class GridLayout extends ViewGroup { // Measurement + // Note: padding has already been removed from the supplied specs private void measureChildWithMargins2(View child, int parentWidthSpec, int parentHeightSpec, int childWidth, int childHeight) { int childWidthSpec = getChildMeasureSpec(parentWidthSpec, - mPaddingLeft + mPaddingRight + getTotalMargin(child, true), childWidth); + getTotalMargin(child, true), childWidth); int childHeightSpec = getChildMeasureSpec(parentHeightSpec, - mPaddingTop + mPaddingBottom + getTotalMargin(child, false), childHeight); + getTotalMargin(child, false), childHeight); child.measure(childWidthSpec, childHeightSpec); } + // Note: padding has already been removed from the supplied specs private void measureChildrenWithMargins(int widthSpec, int heightSpec, boolean firstPass) { for (int i = 0, N = getChildCount(); i < N; i++) { View c = getChildAt(i); @@ -979,6 +981,11 @@ public class GridLayout extends ViewGroup { } } + static int adjust(int measureSpec, int delta) { + return makeMeasureSpec( + MeasureSpec.getSize(measureSpec + delta), MeasureSpec.getMode(measureSpec)); + } + @Override protected void onMeasure(int widthSpec, int heightSpec) { consistencyCheck(); @@ -987,29 +994,33 @@ public class GridLayout extends ViewGroup { * is likely to have changed. We must invalidate if so. */ invalidateValues(); - measureChildrenWithMargins(widthSpec, heightSpec, true); + int hPadding = getPaddingLeft() + getPaddingRight(); + int vPadding = getPaddingTop() + getPaddingBottom(); + + int widthSpecSansPadding = adjust( widthSpec, -hPadding); + int heightSpecSansPadding = adjust(heightSpec, -vPadding); - int width, height; + measureChildrenWithMargins(widthSpecSansPadding, heightSpecSansPadding, true); + + int widthSansPadding; + int heightSansPadding; // Use the orientation property to decide which axis should be laid out first. if (orientation == HORIZONTAL) { - width = horizontalAxis.getMeasure(widthSpec); - measureChildrenWithMargins(widthSpec, heightSpec, false); - height = verticalAxis.getMeasure(heightSpec); + widthSansPadding = horizontalAxis.getMeasure(widthSpecSansPadding); + measureChildrenWithMargins(widthSpecSansPadding, heightSpecSansPadding, false); + heightSansPadding = verticalAxis.getMeasure(heightSpecSansPadding); } else { - height = verticalAxis.getMeasure(heightSpec); - measureChildrenWithMargins(widthSpec, heightSpec, false); - width = horizontalAxis.getMeasure(widthSpec); + heightSansPadding = verticalAxis.getMeasure(heightSpecSansPadding); + measureChildrenWithMargins(widthSpecSansPadding, heightSpecSansPadding, false); + widthSansPadding = horizontalAxis.getMeasure(widthSpecSansPadding); } - int hPadding = getPaddingLeft() + getPaddingRight(); - int vPadding = getPaddingTop() + getPaddingBottom(); - - int measuredWidth = Math.max(hPadding + width, getSuggestedMinimumWidth()); - int measuredHeight = Math.max(vPadding + height, getSuggestedMinimumHeight()); + int measuredWidth = Math.max(widthSansPadding + hPadding, getSuggestedMinimumWidth()); + int measuredHeight = Math.max(heightSansPadding + vPadding, getSuggestedMinimumHeight()); setMeasuredDimension( - resolveSizeAndState(measuredWidth, widthSpec, 0), + resolveSizeAndState(measuredWidth, widthSpec, 0), resolveSizeAndState(measuredHeight, heightSpec, 0)); } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 83e2e79..07e66b7 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -2108,6 +2108,8 @@ public class RemoteViews implements Parcelable, Filter { * RemoteViews. This count cannot change during the life-cycle of a given widget, so this * parameter should account for the maximum possible number of types that may appear in the * See {@link Adapter#getViewTypeCount()}. + * + * @hide */ public void setRemoteAdapter(int viewId, ArrayList<RemoteViews> list, int viewTypeCount) { addAction(new SetRemoteViewsAdapterList(viewId, list, viewTypeCount)); |