summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/animation/AnimatorInflater.java35
-rw-r--r--core/java/android/app/ActivityManager.java149
-rw-r--r--core/java/android/app/ActivityManagerNative.java89
-rw-r--r--core/java/android/app/ActivityOptions.java8
-rw-r--r--core/java/android/app/ActivityThread.java11
-rw-r--r--core/java/android/app/ActivityView.java45
-rw-r--r--core/java/android/app/AssistContent.java42
-rw-r--r--core/java/android/app/AssistStructure.java12
-rw-r--r--core/java/android/app/ContextImpl.java34
-rw-r--r--core/java/android/app/IActivityManager.java29
-rw-r--r--core/java/android/app/INotificationManager.aidl2
-rw-r--r--core/java/android/app/INotificationManagerCallback.aidl24
-rw-r--r--core/java/android/app/ISearchManager.aidl2
-rw-r--r--core/java/android/app/NotificationManager.java77
-rw-r--r--core/java/android/app/PendingIntent.java14
-rw-r--r--core/java/android/app/ResourcesManager.java20
-rw-r--r--core/java/android/app/SearchManager.java4
-rw-r--r--core/java/android/app/SystemServiceRegistry.java2
-rw-r--r--core/java/android/app/UiAutomationConnection.java7
-rw-r--r--core/java/android/app/VoiceInteractor.aidl1
-rw-r--r--core/java/android/app/VoiceInteractor.java171
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java18
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl2
-rw-r--r--core/java/android/app/usage/NetworkStats.java4
-rw-r--r--core/java/android/content/Intent.java7
-rw-r--r--core/java/android/content/pm/PackageManager.java9
-rw-r--r--core/java/android/content/res/Resources.java5
-rw-r--r--core/java/android/hardware/camera2/CaptureRequest.java46
-rw-r--r--core/java/android/hardware/camera2/ICameraDeviceUser.aidl2
-rw-r--r--core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java47
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java183
-rw-r--r--core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java13
-rw-r--r--core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java37
-rw-r--r--core/java/android/hardware/camera2/utils/SurfaceUtils.java80
-rw-r--r--core/java/android/hardware/display/DisplayManagerGlobal.java11
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java183
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl4
-rw-r--r--core/java/android/inputmethodservice/ExtractEditText.java2
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java16
-rw-r--r--core/java/android/net/Network.java44
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java19
-rw-r--r--core/java/android/nfc/cardemulation/CardEmulation.java31
-rw-r--r--core/java/android/os/BatteryStats.java16
-rw-r--r--core/java/android/os/Debug.java127
-rw-r--r--core/java/android/os/Process.java10
-rw-r--r--core/java/android/provider/AlarmClock.java2
-rw-r--r--core/java/android/provider/ContactsContract.java5
-rw-r--r--core/java/android/provider/Settings.java18
-rw-r--r--core/java/android/service/carrier/CarrierService.java8
-rw-r--r--core/java/android/service/voice/VoiceInteractionSession.java85
-rw-r--r--core/java/android/transition/Transition.java31
-rw-r--r--core/java/android/transition/Visibility.java20
-rw-r--r--core/java/android/util/LayoutDirection.java6
-rw-r--r--core/java/android/view/ActionMode.java18
-rw-r--r--core/java/android/view/Display.java5
-rw-r--r--core/java/android/view/GestureDetector.java66
-rw-r--r--core/java/android/view/GhostView.java10
-rw-r--r--core/java/android/view/HapticFeedbackConstants.java4
-rw-r--r--core/java/android/view/InputDevice.java16
-rw-r--r--core/java/android/view/ScaleGestureDetector.java4
-rw-r--r--core/java/android/view/SearchEvent.java2
-rw-r--r--core/java/android/view/View.java171
-rw-r--r--core/java/android/view/ViewConfiguration.java10
-rw-r--r--core/java/android/view/ViewStructure.java6
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java10
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java28
-rw-r--r--core/java/android/view/inputmethod/EditorInfo.java11
-rw-r--r--core/java/android/widget/AbsListView.java91
-rw-r--r--core/java/android/widget/Editor.java309
-rw-r--r--core/java/android/widget/ImageView.java10
-rw-r--r--core/java/android/widget/LinearLayout.java13
-rw-r--r--core/java/android/widget/MediaController.java39
-rw-r--r--core/java/android/widget/ScrollView.java24
-rw-r--r--core/java/android/widget/TextView.java89
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl5
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractor.aidl8
-rw-r--r--core/java/com/android/internal/logging/MetricsLogger.java1
-rw-r--r--core/java/com/android/internal/os/BatterySipper.java16
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java28
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java40
-rw-r--r--core/java/com/android/internal/os/BluetoothPowerCalculator.java20
-rw-r--r--core/java/com/android/internal/os/CameraPowerCalculator.java48
-rw-r--r--core/java/com/android/internal/os/FlashlightPowerCalculator.java46
-rw-r--r--core/java/com/android/internal/os/PowerProfile.java9
-rw-r--r--core/java/com/android/internal/os/ProcessCpuTracker.java44
-rw-r--r--core/java/com/android/internal/os/WifiPowerCalculator.java8
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java2
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java14
-rw-r--r--core/java/com/android/internal/view/FloatingActionMode.java48
89 files changed, 2146 insertions, 996 deletions
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 435d5ab..d8d2737 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -441,8 +441,12 @@ public class AnimatorInflater {
long startDelay = arrayAnimator.getInt(R.styleable.Animator_startOffset, 0);
- int valueType = arrayAnimator.getInt(R.styleable.Animator_valueType, VALUE_TYPE_FLOAT);
+ int valueType = arrayAnimator.getInt(R.styleable.Animator_valueType, VALUE_TYPE_UNDEFINED);
+ if (valueType == VALUE_TYPE_UNDEFINED) {
+ valueType = inferValueTypeFromValues(arrayAnimator, R.styleable.Animator_valueFrom,
+ R.styleable.Animator_valueTo);
+ }
PropertyValuesHolder pvh = getPVH(arrayAnimator, valueType,
R.styleable.Animator_valueFrom, R.styleable.Animator_valueTo, "");
if (pvh != null) {
@@ -520,8 +524,14 @@ public class AnimatorInflater {
ObjectAnimator oa = (ObjectAnimator) anim;
String pathData = arrayObjectAnimator.getString(R.styleable.PropertyAnimator_pathData);
- // Note that if there is a pathData defined in the Object Animator,
- // valueFrom / valueTo will be ignored.
+ // Path can be involved in an ObjectAnimator in the following 3 ways:
+ // 1) Path morphing: the property to be animated is pathData, and valueFrom and valueTo
+ // are both of pathType. valueType = pathType needs to be explicitly defined.
+ // 2) A property in X or Y dimension can be animated along a path: the property needs to be
+ // defined in propertyXName or propertyYName attribute, the path will be defined in the
+ // pathData attribute. valueFrom and valueTo will not be necessary for this animation.
+ // 3) PathInterpolator can also define a path (in pathData) for its interpolation curve.
+ // Here we are dealing with case 2:
if (pathData != null) {
String propertyXName =
arrayObjectAnimator.getString(R.styleable.PropertyAnimator_propertyXName);
@@ -805,6 +815,25 @@ public class AnimatorInflater {
return valueType;
}
+ private static int inferValueTypeFromValues(TypedArray styledAttributes, int valueFromId,
+ int valueToId) {
+ TypedValue tvFrom = styledAttributes.peekValue(valueFromId);
+ boolean hasFrom = (tvFrom != null);
+ int fromType = hasFrom ? tvFrom.type : 0;
+ TypedValue tvTo = styledAttributes.peekValue(valueToId);
+ boolean hasTo = (tvTo != null);
+ int toType = hasTo ? tvTo.type : 0;
+
+ int valueType;
+ // Check whether it's color type. If not, fall back to default type (i.e. float type)
+ if ((hasFrom && isColorType(fromType)) || (hasTo && isColorType(toType))) {
+ valueType = VALUE_TYPE_COLOR;
+ } else {
+ valueType = VALUE_TYPE_FLOAT;
+ }
+ return valueType;
+ }
+
private static void dumpKeyframes(Object[] keyframes, String header) {
if (keyframes == null || keyframes.length == 0) {
return;
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index edebc28..3892dd9 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -462,7 +462,7 @@ public class ActivityManager {
public int getMemoryClass() {
return staticGetMemoryClass();
}
-
+
/** @hide */
static public int staticGetMemoryClass() {
// Really brain dead right now -- just take this from the configured
@@ -473,7 +473,7 @@ public class ActivityManager {
}
return staticGetLargeMemoryClass();
}
-
+
/**
* Return the approximate per-application memory class of the current
* device when an application is running with a large heap. This is the
@@ -490,7 +490,7 @@ public class ActivityManager {
public int getLargeMemoryClass() {
return staticGetLargeMemoryClass();
}
-
+
/** @hide */
static public int staticGetLargeMemoryClass() {
// Really brain dead right now -- just take this from the configured
@@ -809,7 +809,7 @@ public class ActivityManager {
* The true identifier of this task, valid even if it is not running.
*/
public int persistentId;
-
+
/**
* The original Intent used to launch the task. You can use this
* Intent to re-launch the task (if it is no longer running) or bring
@@ -1014,7 +1014,7 @@ public class ActivityManager {
* user has started and the maximum number the system can remember.
* @param flags Information about what to return. May be any combination
* of {@link #RECENT_WITH_EXCLUDED} and {@link #RECENT_IGNORE_UNAVAILABLE}.
- *
+ *
* @return Returns a list of RecentTaskInfo records describing each of
* the recent tasks.
*/
@@ -1146,7 +1146,7 @@ public class ActivityManager {
numActivities = source.readInt();
numRunning = source.readInt();
}
-
+
public static final Creator<RunningTaskInfo> CREATOR = new Creator<RunningTaskInfo>() {
public RunningTaskInfo createFromParcel(Parcel source) {
return new RunningTaskInfo(source);
@@ -1469,100 +1469,100 @@ public class ActivityManager {
* If non-zero, this is the process the service is running in.
*/
public int pid;
-
+
/**
* The UID that owns this service.
*/
public int uid;
-
+
/**
* The name of the process this service runs in.
*/
public String process;
-
+
/**
* Set to true if the service has asked to run as a foreground process.
*/
public boolean foreground;
-
+
/**
* The time when the service was first made active, either by someone
* starting or binding to it. This
* is in units of {@link android.os.SystemClock#elapsedRealtime()}.
*/
public long activeSince;
-
+
/**
* Set to true if this service has been explicitly started.
*/
public boolean started;
-
+
/**
* Number of clients connected to the service.
*/
public int clientCount;
-
+
/**
* Number of times the service's process has crashed while the service
* is running.
*/
public int crashCount;
-
+
/**
* The time when there was last activity in the service (either
* explicit requests to start it or clients binding to it). This
* is in units of {@link android.os.SystemClock#uptimeMillis()}.
*/
public long lastActivityTime;
-
+
/**
* If non-zero, this service is not currently running, but scheduled to
* restart at the given time.
*/
public long restarting;
-
+
/**
* Bit for {@link #flags}: set if this service has been
* explicitly started.
*/
public static final int FLAG_STARTED = 1<<0;
-
+
/**
* Bit for {@link #flags}: set if the service has asked to
* run as a foreground process.
*/
public static final int FLAG_FOREGROUND = 1<<1;
-
+
/**
* Bit for {@link #flags): set if the service is running in a
* core system process.
*/
public static final int FLAG_SYSTEM_PROCESS = 1<<2;
-
+
/**
* Bit for {@link #flags): set if the service is running in a
* persistent process.
*/
public static final int FLAG_PERSISTENT_PROCESS = 1<<3;
-
+
/**
* Running flags.
*/
public int flags;
-
+
/**
* For special services that are bound to by system code, this is
* the package that holds the binding.
*/
public String clientPackage;
-
+
/**
* For special services that are bound to by system code, this is
* a string resource providing a user-visible label for who the
* client is.
*/
public int clientLabel;
-
+
public RunningServiceInfo() {
}
@@ -1603,7 +1603,7 @@ public class ActivityManager {
clientPackage = source.readString();
clientLabel = source.readInt();
}
-
+
public static final Creator<RunningServiceInfo> CREATOR = new Creator<RunningServiceInfo>() {
public RunningServiceInfo createFromParcel(Parcel source) {
return new RunningServiceInfo(source);
@@ -1627,7 +1627,7 @@ public class ActivityManager {
* @param maxNum The maximum number of entries to return in the list. The
* actual number returned may be smaller, depending on how many services
* are running.
- *
+ *
* @return Returns a list of RunningServiceInfo records describing each of
* the running tasks.
*/
@@ -1641,7 +1641,7 @@ public class ActivityManager {
return null;
}
}
-
+
/**
* Returns a PendingIntent you can start to show a control panel for the
* given running service. If the service does not have a control panel,
@@ -1657,7 +1657,7 @@ public class ActivityManager {
return null;
}
}
-
+
/**
* Information you can retrieve about the available memory through
* {@link ActivityManager#getMemoryInfo}.
@@ -1684,7 +1684,7 @@ public class ActivityManager {
* processes.
*/
public long threshold;
-
+
/**
* Set to true if the system considers itself to currently be in a low
* memory situation.
@@ -1717,7 +1717,7 @@ public class ActivityManager {
dest.writeLong(visibleAppThreshold);
dest.writeLong(foregroundAppThreshold);
}
-
+
public void readFromParcel(Parcel source) {
availMem = source.readLong();
totalMem = source.readLong();
@@ -1841,7 +1841,7 @@ public class ActivityManager {
*/
public boolean clearApplicationUserData(String packageName, IPackageDataObserver observer) {
try {
- return ActivityManagerNative.getDefault().clearApplicationUserData(packageName,
+ return ActivityManagerNative.getDefault().clearApplicationUserData(packageName,
observer, UserHandle.myUserId());
} catch (RemoteException e) {
return false;
@@ -1882,7 +1882,7 @@ public class ActivityManager {
* The process name in which the crash or error occurred.
*/
public String processName;
-
+
/**
* The pid of this process; 0 if none
*/
@@ -1894,7 +1894,7 @@ public class ActivityManager {
* the same uid).
*/
public int uid;
-
+
/**
* The activity name associated with the error, if known. May be null.
*/
@@ -1950,8 +1950,8 @@ public class ActivityManager {
longMsg = source.readString();
stackTrace = source.readString();
}
-
- public static final Creator<ProcessErrorStateInfo> CREATOR =
+
+ public static final Creator<ProcessErrorStateInfo> CREATOR =
new Creator<ProcessErrorStateInfo>() {
public ProcessErrorStateInfo createFromParcel(Parcel source) {
return new ProcessErrorStateInfo(source);
@@ -1965,11 +1965,11 @@ public class ActivityManager {
readFromParcel(source);
}
}
-
+
/**
- * Returns a list of any processes that are currently in an error condition. The result
+ * Returns a list of any processes that are currently in an error condition. The result
* will be null if all processes are running properly at this time.
- *
+ *
* @return Returns a list of ProcessErrorStateInfo records, or null if there are no
* current error conditions (it will not return an empty list). This list ordering is not
* specified.
@@ -1985,7 +1985,7 @@ public class ActivityManager {
/**
* Information you can retrieve about a running process.
*/
- public static class RunningAppProcessInfo implements Parcelable {
+ public static class RunningAppProcessInfo implements Parcelable {
/**
* The name of the process that this object is associated with
*/
@@ -1995,17 +1995,17 @@ public class ActivityManager {
* The pid of this process; 0 if none
*/
public int pid;
-
+
/**
* The user id of this process.
*/
public int uid;
-
+
/**
* All packages that have been loaded into the process.
*/
public String pkgList[];
-
+
/**
* Constant for {@link #flags}: this is an app that is unable to
* correctly save its state when going to the background,
@@ -2013,7 +2013,7 @@ public class ActivityManager {
* @hide
*/
public static final int FLAG_CANT_SAVE_STATE = 1<<0;
-
+
/**
* Constant for {@link #flags}: this process is associated with a
* persistent system app.
@@ -2048,7 +2048,7 @@ public class ActivityManager {
* that the user is interacting with.
*/
public static final int IMPORTANCE_FOREGROUND = 100;
-
+
/**
* Constant for {@link #importance}: This process is running a foreground
* service, for example to perform music playback even while the user is
@@ -2075,13 +2075,13 @@ public class ActivityManager {
* other services under the system's control that it inconsiders important.
*/
public static final int IMPORTANCE_VISIBLE = 200;
-
+
/**
* Constant for {@link #importance}: This process is not something the user
* is directly aware of, but is otherwise perceptable to them to some degree.
*/
public static final int IMPORTANCE_PERCEPTIBLE = 130;
-
+
/**
* Constant for {@link #importance}: This process is running an
* application that can not save its state, and thus can't be killed
@@ -2089,7 +2089,7 @@ public class ActivityManager {
* @hide
*/
public static final int IMPORTANCE_CANT_SAVE_STATE = 170;
-
+
/**
* Constant for {@link #importance}: This process is contains services
* that should remain running. These are background services apps have
@@ -2098,13 +2098,13 @@ public class ActivityManager {
* stay running as long as they want to).
*/
public static final int IMPORTANCE_SERVICE = 300;
-
+
/**
* Constant for {@link #importance}: This process process contains
* background code that is expendable.
*/
public static final int IMPORTANCE_BACKGROUND = 400;
-
+
/**
* Constant for {@link #importance}: This process is empty of any
* actively running code.
@@ -2148,7 +2148,7 @@ public class ActivityManager {
* smaller than "less important" values.
*/
public int importance;
-
+
/**
* An additional ordering within a particular {@link #importance}
* category, providing finer-grained information about the relative
@@ -2165,7 +2165,7 @@ public class ActivityManager {
* been specified for the reason for this level.
*/
public static final int REASON_UNKNOWN = 0;
-
+
/**
* Constant for {@link #importanceReasonCode}: one of the application's
* content providers is being used by another process. The pid of
@@ -2174,7 +2174,7 @@ public class ActivityManager {
* {@link #importanceReasonComponent}.
*/
public static final int REASON_PROVIDER_IN_USE = 1;
-
+
/**
* Constant for {@link #importanceReasonCode}: one of the application's
* content providers is being used by another process. The pid of
@@ -2183,25 +2183,25 @@ public class ActivityManager {
* {@link #importanceReasonComponent}.
*/
public static final int REASON_SERVICE_IN_USE = 2;
-
+
/**
* The reason for {@link #importance}, if any.
*/
public int importanceReasonCode;
-
+
/**
* For the specified values of {@link #importanceReasonCode}, this
* is the process ID of the other process that is a client of this
* process. This will be 0 if no other process is using this one.
*/
public int importanceReasonPid;
-
+
/**
* For the specified values of {@link #importanceReasonCode}, this
* is the name of the component that is being used in this process.
*/
public ComponentName importanceReasonComponent;
-
+
/**
* When {@link #importanceReasonPid} is non-0, this is the importance
* of the other pid. @hide
@@ -2219,7 +2219,7 @@ public class ActivityManager {
importanceReasonCode = REASON_UNKNOWN;
processState = PROCESS_STATE_IMPORTANT_FOREGROUND;
}
-
+
public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
processName = pProcessName;
pid = pPid;
@@ -2262,7 +2262,7 @@ public class ActivityManager {
processState = source.readInt();
}
- public static final Creator<RunningAppProcessInfo> CREATOR =
+ public static final Creator<RunningAppProcessInfo> CREATOR =
new Creator<RunningAppProcessInfo>() {
public RunningAppProcessInfo createFromParcel(Parcel source) {
return new RunningAppProcessInfo(source);
@@ -2276,7 +2276,7 @@ public class ActivityManager {
readFromParcel(source);
}
}
-
+
/**
* Returns a list of application processes installed on external media
* that are running on the device.
@@ -2297,6 +2297,23 @@ public class ActivityManager {
}
/**
+ * Sets the memory trim mode for a process and schedules a memory trim operation.
+ *
+ * <p><b>Note: this method is only intended for testing framework.</b></p>
+ *
+ * @return Returns true if successful.
+ * @hide
+ */
+ public boolean setProcessMemoryTrimLevel(String process, int userId, int level) {
+ try {
+ return ActivityManagerNative.getDefault().setProcessMemoryTrimLevel(process, userId,
+ level);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
+ /**
* Returns a list of application processes that are running on the device.
*
* <p><b>Note: this method is only intended for debugging or building
@@ -2368,7 +2385,7 @@ public class ActivityManager {
return null;
}
}
-
+
/**
* @deprecated This is now just a wrapper for
* {@link #killBackgroundProcesses(String)}; the previous behavior here
@@ -2380,17 +2397,17 @@ public class ActivityManager {
public void restartPackage(String packageName) {
killBackgroundProcesses(packageName);
}
-
+
/**
* Have the system immediately kill all background processes associated
* with the given package. This is the same as the kernel killing those
* processes to reclaim memory; the system will take care of restarting
* these processes in the future as needed.
- *
+ *
* <p>You must hold the permission
* {@link android.Manifest.permission#KILL_BACKGROUND_PROCESSES} to be able to
* call this method.
- *
+ *
* @param packageName The name of the package whose processes are to
* be killed.
*/
@@ -2426,14 +2443,14 @@ public class ActivityManager {
* removed, etc. In addition, a {@link Intent#ACTION_PACKAGE_RESTARTED}
* broadcast will be sent, so that any of its registered alarms can
* be stopped, notifications removed, etc.
- *
+ *
* <p>You must hold the permission
* {@link android.Manifest.permission#FORCE_STOP_PACKAGES} to be able to
* call this method.
- *
+ *
* @param packageName The name of the package to be stopped.
* @param userId The user for which the running package is to be stopped.
- *
+ *
* @hide This is not available to third party applications due to
* it allowing them to break other applications by stopping their
* services, removing their alarms, etc.
@@ -2697,7 +2714,7 @@ public class ActivityManager {
}
/**
- * @param userid the user's id. Zero indicates the default user
+ * @param userid the user's id. Zero indicates the default user.
* @hide
*/
public boolean switchUser(int userid) {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index b6cec60..dabcc50c 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1548,21 +1548,21 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeInt(res ? 1 : 0);
return true;
}
-
+
case STOP_APP_SWITCHES_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
stopAppSwitches();
reply.writeNoException();
return true;
}
-
+
case RESUME_APP_SWITCHES_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
resumeAppSwitches();
reply.writeNoException();
return true;
}
-
+
case PEEK_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
Intent service = Intent.CREATOR.createFromParcel(data);
@@ -1572,7 +1572,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeStrongBinder(binder);
return true;
}
-
+
case START_BACKUP_AGENT_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data);
@@ -1625,7 +1625,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
-
+
case GET_PROCESS_MEMORY_INFO_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int[] pids = data.createIntArray();
@@ -1643,7 +1643,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
-
+
case OVERRIDE_PENDING_TRANSITION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -1654,7 +1654,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
-
+
case IS_USER_A_MONKEY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
boolean areThey = isUserAMonkey();
@@ -1662,7 +1662,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeInt(areThey ? 1 : 0);
return true;
}
-
+
case SET_USER_IS_MONKEY_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
final boolean monkey = (data.readInt() == 1);
@@ -1738,7 +1738,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
-
+
case IS_TOP_ACTIVITY_IMMERSIVE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
boolean isit = isTopActivityImmersive();
@@ -1890,7 +1890,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
reply.writeNoException();
return true;
}
-
+
case SWITCH_USER_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
int userid = data.readInt();
@@ -2208,7 +2208,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
int requestType = data.readInt();
String hint = data.readString();
int userHandle = data.readInt();
- boolean res = launchAssistIntent(intent, requestType, hint, userHandle);
+ Bundle args = data.readBundle();
+ boolean res = launchAssistIntent(intent, requestType, hint, userHandle, args);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
@@ -2533,21 +2534,23 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
- case UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION: {
+ case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- ComponentName preferredActivity = ComponentName.readFromParcel(data);
- int userId = data.readInt();
- updatePreferredSetupActivity(preferredActivity, userId);
+ String pkg = data.readString();
+ int res = getPackageProcessState(pkg);
reply.writeNoException();
+ reply.writeInt(res);
return true;
}
- case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
+ case SET_PROCESS_MEMORY_TRIM_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
- String pkg = data.readString();
- int res = getPackageProcessState(pkg);
+ String process = data.readString();
+ int userId = data.readInt();
+ int level = data.readInt();
+ boolean res = setProcessMemoryTrimLevel(process, userId, level);
reply.writeNoException();
- reply.writeInt(res);
+ reply.writeInt(res ? 1 : 0);
return true;
}
}
@@ -3621,7 +3624,7 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return res;
}
-
+
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, int userId) throws RemoteException
{
@@ -3724,7 +3727,7 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
return res;
}
-
+
public void publishService(IBinder token,
Intent intent, IBinder service) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -3767,7 +3770,7 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
-
+
public IBinder peekService(Intent service, String resolvedType) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -4457,7 +4460,7 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
-
+
public void getMyMemoryState(ActivityManager.RunningAppProcessInfo outInfo)
throws RemoteException
{
@@ -4521,7 +4524,7 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
return res;
}
-
+
public void stopAppSwitches() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -4531,7 +4534,7 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
data.recycle();
}
-
+
public void resumeAppSwitches() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -4566,7 +4569,7 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
-
+
public void closeSystemDialogs(String reason) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -4577,7 +4580,7 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
-
+
public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -4603,7 +4606,7 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
-
+
public void overridePendingTransition(IBinder token, String packageName,
int enterAnim, int exitAnim) throws RemoteException {
Parcel data = Parcel.obtain();
@@ -4618,7 +4621,7 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
reply.recycle();
}
-
+
public boolean isUserAMonkey() throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
@@ -4874,7 +4877,7 @@ class ActivityManagerProxy implements IActivityManager
data.recycle();
return res;
}
-
+
public int startActivities(IApplicationThread caller, String callingPackage,
Intent[] intents, String[] resolvedTypes, IBinder resultTo,
Bundle options, int userId) throws RemoteException {
@@ -5378,8 +5381,8 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
- public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle)
- throws RemoteException {
+ public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
+ Bundle args) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
@@ -5387,6 +5390,7 @@ class ActivityManagerProxy implements IActivityManager
data.writeInt(requestType);
data.writeString(hint);
data.writeInt(userHandle);
+ data.writeBundle(args);
mRemote.transact(LAUNCH_ASSIST_INTENT_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
@@ -5855,31 +5859,34 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
- public void updatePreferredSetupActivity(ComponentName preferredActivity, int userId)
- throws RemoteException {
+ public int getPackageProcessState(String packageName) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- ComponentName.writeToParcel(preferredActivity, data);
- data.writeInt(userId);
- mRemote.transact(UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION, data, reply, 0);
+ data.writeString(packageName);
+ mRemote.transact(GET_PACKAGE_PROCESS_STATE_TRANSACTION, data, reply, 0);
reply.readException();
+ int res = reply.readInt();
data.recycle();
reply.recycle();
+ return res;
}
@Override
- public int getPackageProcessState(String packageName) throws RemoteException {
+ public boolean setProcessMemoryTrimLevel(String process, int userId, int level)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
- data.writeString(packageName);
- mRemote.transact(GET_PACKAGE_PROCESS_STATE_TRANSACTION, data, reply, 0);
+ data.writeString(process);
+ data.writeInt(userId);
+ data.writeInt(level);
+ mRemote.transact(SET_PROCESS_MEMORY_TRIM_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
- return res;
+ return res != 0;
}
private IBinder mRemote;
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 9f23b43..6fb997e 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -41,16 +41,16 @@ public class ActivityOptions {
/**
* A long in the extras delivered by {@link #requestUsageTimeReport} that contains
- * the total time (in ms) the user spent in the app.
+ * the total time (in ms) the user spent in the app flow.
*/
- public static final String EXTRA_USAGE_REPORT_TIME = "android.time";
+ public static final String EXTRA_USAGE_TIME_REPORT = "android.usage_time";
/**
* A Bundle in the extras delivered by {@link #requestUsageTimeReport} that contains
* detailed information about the time spent in each package associated with the app;
* each key is a package name, whose value is a long containing the time (in ms).
*/
- public static final String EXTRA_USAGE_REPORT_PACKAGES = "android.package";
+ public static final String EXTRA_USAGE_TIME_REPORT_PACKAGES = "android.usage_time_packages";
/**
* The package name that created the options.
@@ -915,7 +915,7 @@ public class ActivityOptions {
/**
* Ask the the system track that time the user spends in the app being launched, and
* report it back once done. The report will be sent to the given receiver, with
- * the extras {@link #EXTRA_USAGE_REPORT_TIME} and {@link #EXTRA_USAGE_REPORT_PACKAGES}
+ * the extras {@link #EXTRA_USAGE_TIME_REPORT} and {@link #EXTRA_USAGE_TIME_REPORT_PACKAGES}
* filled in.
*
* <p>The time interval tracked is from launching this activity until the user leaves
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3224d41..ffb3fb8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1640,6 +1640,10 @@ public final class ActivityThread {
return sCurrentActivityThread;
}
+ public static boolean isSystem() {
+ return (sCurrentActivityThread != null) ? sCurrentActivityThread.mSystemThread : false;
+ }
+
public static String currentOpPackageName() {
ActivityThread am = currentActivityThread();
return (am != null && am.getApplication() != null)
@@ -2440,7 +2444,8 @@ public final class ActivityThread {
&& r.packageInfo.mPackageName.contains(pkgName)) {
for (int id : dm.getDisplayIds()) {
if (id != Display.DEFAULT_DISPLAY) {
- Display display = dm.getRealDisplay(id, r.overrideConfig);
+ Display display =
+ dm.getCompatibleDisplay(id, appContext.getDisplayAdjustments(id));
baseContext = appContext.createDisplayContext(display);
break;
}
@@ -2580,9 +2585,9 @@ public final class ActivityThread {
intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
| Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
intent.removeUnsafeExtras();
- content.setIntent(intent);
+ content.setDefaultIntent(intent);
} else {
- content.setIntent(new Intent());
+ content.setDefaultIntent(new Intent());
}
r.activity.onProvideAssistContent(content);
}
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index eafcdb2..9c0d931 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -24,7 +24,10 @@ import android.content.IIntentSender;
import android.content.Intent;
import android.content.IntentSender;
import android.graphics.SurfaceTexture;
+import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
+import android.os.Message;
import android.os.OperationCanceledException;
import android.os.RemoteException;
import android.util.AttributeSet;
@@ -48,7 +51,9 @@ public class ActivityView extends ViewGroup {
private static final String TAG = "ActivityView";
private static final boolean DEBUG = false;
- DisplayMetrics mMetrics;
+ private static final int MSG_SET_SURFACE = 1;
+
+ DisplayMetrics mMetrics = new DisplayMetrics();
private final TextureView mTextureView;
private ActivityContainerWrapper mActivityContainer;
private Activity mActivity;
@@ -58,6 +63,9 @@ public class ActivityView extends ViewGroup {
private int mLastVisibility;
private ActivityViewCallback mActivityViewCallback;
+ private HandlerThread mThread = new HandlerThread("ActivityViewThread");
+ private Handler mHandler;
+
public ActivityView(Context context) {
this(context, null);
}
@@ -89,12 +97,27 @@ public class ActivityView extends ViewGroup {
+ e);
}
+ mThread.start();
+ mHandler = new Handler(mThread.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
+ super.handleMessage(msg);
+ if (msg.what == MSG_SET_SURFACE) {
+ try {
+ mActivityContainer.setSurface((Surface) msg.obj, msg.arg1, msg.arg2,
+ mMetrics.densityDpi);
+ } catch (RemoteException e) {
+ throw new RuntimeException(
+ "ActivityView: Unable to set surface of ActivityContainer. " + e);
+ }
+ }
+ }
+ };
mTextureView = new TextureView(context);
mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener());
addView(mTextureView);
WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
- mMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(mMetrics);
mLastVisibility = getVisibility();
@@ -111,18 +134,12 @@ public class ActivityView extends ViewGroup {
protected void onVisibilityChanged(View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
- if (mSurface != null) {
- try {
- if (visibility == View.GONE) {
- mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi);
- } else if (mLastVisibility == View.GONE) {
- // Don't change surface when going between View.VISIBLE and View.INVISIBLE.
- mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi);
- }
- } catch (RemoteException e) {
- throw new RuntimeException(
- "ActivityView: Unable to set surface of ActivityContainer. " + e);
- }
+ if (mSurface != null && (visibility == View.GONE || mLastVisibility == View.GONE)) {
+ Message msg = Message.obtain(mHandler, MSG_SET_SURFACE);
+ msg.obj = (visibility == View.GONE) ? null : mSurface;
+ msg.arg1 = mWidth;
+ msg.arg2 = mHeight;
+ mHandler.sendMessage(msg);
}
mLastVisibility = visibility;
}
diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java
index 4cb89a8..d23e73d 100644
--- a/core/java/android/app/AssistContent.java
+++ b/core/java/android/app/AssistContent.java
@@ -31,6 +31,7 @@ import android.os.Parcelable;
*/
@Deprecated
public class AssistContent {
+ private boolean mIsAppProvidedIntent = false;
private Intent mIntent;
private ClipData mClipData;
private Uri mUri;
@@ -55,12 +56,14 @@ public class AssistContent {
}
/**
- * Sets the Intent associated with the content, describing the current top-level context of
- * the activity. If this contains a reference to a piece of data related to the activity,
- * be sure to set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} so the accessibility
- * service can access it.
+ * @hide
+ * Called by {@link android.app.ActivityThread} to set the default Intent based on
+ * {@link android.app.Activity#getIntent Activity.getIntent}.
+ *
+ * <p>Automatically populates {@link #mUri} if that Intent is an {@link Intent#ACTION_VIEW}
+ * of a web (http or https scheme) URI.</p>
*/
- public void setIntent(Intent intent) {
+ public void setDefaultIntent(Intent intent) {
mIntent = intent;
setWebUri(null);
if (intent != null && Intent.ACTION_VIEW.equals(intent.getAction())) {
@@ -72,7 +75,19 @@ public class AssistContent {
}
/**
- * Return the current {@link #setIntent}, which you can modify in-place.
+ * Sets the Intent associated with the content, describing the current top-level context of
+ * the activity. If this contains a reference to a piece of data related to the activity,
+ * be sure to set {@link Intent#FLAG_GRANT_READ_URI_PERMISSION} so the accessibility
+ * service can access it.
+ */
+ public void setIntent(Intent intent) {
+ mIsAppProvidedIntent = true;
+ mIntent = intent;
+ }
+
+ /**
+ * Returns the current {@link #setIntent} if one is set, else the default Intent obtained from
+ * {@link android.app.Activity#getIntent Activity.getIntent}. Can be modified in-place.
* @hide
*/
public Intent getIntent() {
@@ -80,6 +95,16 @@ public class AssistContent {
}
/**
+ * Returns whether or not the current Intent was explicitly provided in
+ * {@link android.app.Activity#onProvideAssistContent Activity.onProvideAssistContent}. If not,
+ * the Intent was automatically set based on
+ * {@link android.app.Activity#getIntent Activity.getIntent}.
+ */
+ public boolean isAppProvidedIntent() {
+ return mIsAppProvidedIntent;
+ }
+
+ /**
* Optional additional content items that are involved with
* the current UI. Access to this content will be granted to the assistant as if you
* are sending it through an Intent with {@link Intent#FLAG_GRANT_READ_URI_PERMISSION}.
@@ -103,9 +128,6 @@ public class AssistContent {
* off the device into other environments to acesss the same data as is currently
* being shown in the app; if the app does not have such a representation, it should
* leave the null and only report the local intent and clip data.
- *
- * <p>This will be automatically populated for you from {@link #setIntent} if that Intent
- * is an {@link Intent#ACTION_VIEW} of a web (http or https scheme) URI.</p>
*/
public void setWebUri(Uri uri) {
mUri = uri;
@@ -130,6 +152,7 @@ public class AssistContent {
if (in.readInt() != 0) {
mUri = Uri.CREATOR.createFromParcel(in);
}
+ mIsAppProvidedIntent = in.readInt() == 1;
}
/** @hide */
@@ -152,5 +175,6 @@ public class AssistContent {
} else {
dest.writeInt(0);
}
+ dest.writeInt(mIsAppProvidedIntent ? 1 : 0);
}
}
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index ef7fde4..0f69817 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -235,7 +235,7 @@ public class AssistStructure {
static final int FLAGS_CHECKED = 0x00000200;
static final int FLAGS_CLICKABLE = 0x00004000;
static final int FLAGS_LONG_CLICKABLE = 0x00200000;
- static final int FLAGS_STYLUS_BUTTON_PRESSABLE = 0x00400000;
+ static final int FLAGS_CONTEXT_CLICKABLE = 0x00400000;
int mFlags;
@@ -413,8 +413,8 @@ public class AssistStructure {
return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
}
- public boolean isStylusButtonPressable() {
- return (mFlags&ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE) != 0;
+ public boolean isContextClickable() {
+ return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
}
public String getClassName() {
@@ -529,9 +529,9 @@ public class AssistStructure {
}
@Override
- public void setStylusButtonPressable(boolean state) {
- mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE)
- | (state ? ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE : 0);
+ public void setContextClickable(boolean state) {
+ mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_CONTEXT_CLICKABLE)
+ | (state ? ViewNode.FLAGS_CONTEXT_CLICKABLE : 0);
}
@Override
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 3b1ccd2..829b098 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1597,7 +1597,7 @@ class ContextImpl extends Context {
final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
new UserHandle(UserHandle.getUserId(application.uid)), restricted,
- mDisplay, null);
+ mDisplay, null, Display.INVALID_DISPLAY);
if (c.mResources != null) {
return c;
}
@@ -1620,14 +1620,14 @@ class ContextImpl extends Context {
final boolean restricted = (flags & CONTEXT_RESTRICTED) == CONTEXT_RESTRICTED;
if (packageName.equals("system") || packageName.equals("android")) {
return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
- user, restricted, mDisplay, null);
+ user, restricted, mDisplay, null, Display.INVALID_DISPLAY);
}
LoadedApk pi = mMainThread.getPackageInfo(packageName, mResources.getCompatibilityInfo(),
flags | CONTEXT_REGISTER_PACKAGE, user.getIdentifier());
if (pi != null) {
ContextImpl c = new ContextImpl(this, mMainThread, pi, mActivityToken,
- user, restricted, mDisplay, null);
+ user, restricted, mDisplay, null, Display.INVALID_DISPLAY);
if (c.mResources != null) {
return c;
}
@@ -1645,7 +1645,7 @@ class ContextImpl extends Context {
}
return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
- mUser, mRestricted, mDisplay, overrideConfiguration);
+ mUser, mRestricted, mDisplay, overrideConfiguration, Display.INVALID_DISPLAY);
}
@Override
@@ -1655,15 +1655,15 @@ class ContextImpl extends Context {
}
return new ContextImpl(this, mMainThread, mPackageInfo, mActivityToken,
- mUser, mRestricted, display, null);
+ mUser, mRestricted, display, null, Display.INVALID_DISPLAY);
}
Display getDisplay() {
if (mDisplay != null) {
return mDisplay;
}
- DisplayManager dm = getSystemService(DisplayManager.class);
- return dm.getDisplay(Display.DEFAULT_DISPLAY);
+ return ResourcesManager.getInstance().getAdjustedDisplay(
+ Display.DEFAULT_DISPLAY, mDisplayAdjustments);
}
private int getDisplayId() {
@@ -1708,7 +1708,7 @@ class ContextImpl extends Context {
static ContextImpl createSystemContext(ActivityThread mainThread) {
LoadedApk packageInfo = new LoadedApk(mainThread);
ContextImpl context = new ContextImpl(null, mainThread,
- packageInfo, null, null, false, null, null);
+ packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
context.mResources.updateConfiguration(context.mResourcesManager.getConfiguration(),
context.mResourcesManager.getDisplayMetricsLocked());
return context;
@@ -1717,21 +1717,19 @@ class ContextImpl extends Context {
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread,
- packageInfo, null, null, false, null, null);
+ packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
}
static ContextImpl createActivityContext(ActivityThread mainThread,
LoadedApk packageInfo, int displayId, Configuration overrideConfiguration) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
- final Display display = ResourcesManager.getInstance().getAdjustedDisplay(
- displayId, overrideConfiguration);
- return new ContextImpl(null, mainThread, packageInfo, null, null, false, display,
- overrideConfiguration);
+ return new ContextImpl(null, mainThread, packageInfo, null, null, false,
+ null, overrideConfiguration, displayId);
}
private ContextImpl(ContextImpl container, ActivityThread mainThread,
LoadedApk packageInfo, IBinder activityToken, UserHandle user, boolean restricted,
- Display display, Configuration overrideConfiguration) {
+ Display display, Configuration overrideConfiguration, int createDisplayWithId) {
mOuterContext = this;
mMainThread = mainThread;
@@ -1745,9 +1743,10 @@ class ContextImpl extends Context {
mPackageInfo = packageInfo;
mResourcesManager = ResourcesManager.getInstance();
- mDisplay = display;
- final int displayId = getDisplayId();
+ final int displayId = (createDisplayWithId != Display.INVALID_DISPLAY)
+ ? createDisplayWithId : getDisplayId();
+
CompatibilityInfo compatInfo = null;
if (container != null) {
compatInfo = container.getDisplayAdjustments(displayId).getCompatibilityInfo();
@@ -1760,6 +1759,9 @@ class ContextImpl extends Context {
mDisplayAdjustments.setCompatibilityInfo(compatInfo);
mDisplayAdjustments.setConfiguration(overrideConfiguration);
+ mDisplay = (createDisplayWithId == Display.INVALID_DISPLAY) ? display
+ : ResourcesManager.getInstance().getAdjustedDisplay(displayId, mDisplayAdjustments);
+
Resources resources = packageInfo.getResources(mainThread);
if (resources != null) {
if (displayId != Display.DEFAULT_DISPLAY
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 249cdb2..0d5e1c7 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -242,14 +242,14 @@ public interface IActivityManager extends IInterface {
public void showWaitingForDebugger(IApplicationThread who, boolean waiting)
throws RemoteException;
-
+
public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) throws RemoteException;
-
+
public void killBackgroundProcesses(final String packageName, int userId)
throws RemoteException;
public void killAllBackgroundProcesses() throws RemoteException;
public void forceStopPackage(final String packageName, int userId) throws RemoteException;
-
+
// Note: probably don't want to allow applications access to these.
public void setLockScreenShown(boolean shown) throws RemoteException;
@@ -263,7 +263,7 @@ public interface IActivityManager extends IInterface {
throws RemoteException;
public void enterSafeMode() throws RemoteException;
-
+
public void noteWakeupAlarm(IIntentSender sender, int sourceUid, String sourcePkg, String tag)
throws RemoteException;
public void noteAlarmStart(IIntentSender sender, int sourceUid, String tag)
@@ -318,9 +318,9 @@ public interface IActivityManager extends IInterface {
public void killApplicationWithAppId(String pkg, int appid, String reason)
throws RemoteException;
-
+
public void closeSystemDialogs(String reason) throws RemoteException;
-
+
public Debug.MemoryInfo[] getProcessMemoryInfo(int[] pids)
throws RemoteException;
@@ -438,8 +438,8 @@ public interface IActivityManager extends IInterface {
public void reportAssistContextExtras(IBinder token, Bundle extras,
AssistStructure structure, AssistContent content) throws RemoteException;
- public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle)
- throws RemoteException;
+ public boolean launchAssistIntent(Intent intent, int requestType, String hint, int userHandle,
+ Bundle args) throws RemoteException;
public void killUid(int uid, String reason) throws RemoteException;
@@ -502,11 +502,12 @@ public interface IActivityManager extends IInterface {
throws RemoteException;
public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
public void updateDeviceOwner(String packageName) throws RemoteException;
- public void updatePreferredSetupActivity(ComponentName preferredActivity, int userId)
- throws RemoteException;
public int getPackageProcessState(String packageName) throws RemoteException;
+ public boolean setProcessMemoryTrimLevel(String process, int uid, int level)
+ throws RemoteException;
+
/*
* Private non-Binder interfaces
*/
@@ -792,6 +793,7 @@ public interface IActivityManager extends IInterface {
// Available
int GET_ACTIVITY_DISPLAY_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184;
int DELETE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+185;
+ int SET_PROCESS_MEMORY_TRIM_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+186;
// Start of L transactions
@@ -846,8 +848,7 @@ public interface IActivityManager extends IInterface {
int GET_PACKAGE_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+293;
int SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+294;
int UPDATE_DEVICE_OWNER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+295;
- int UPDATE_PREFERRED_SETUP_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296;
- int KEYGUARD_GOING_AWAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+297;
- int REGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298;
- int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+299;
+ int KEYGUARD_GOING_AWAY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+296;
+ int REGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+297;
+ int UNREGISTER_UID_OBSERVER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+298;
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 63ff005..f78fb47 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -17,7 +17,6 @@
package android.app;
-import android.app.INotificationManagerCallback;
import android.app.ITransientNotification;
import android.app.Notification;
import android.app.NotificationManager;
@@ -87,7 +86,6 @@ interface INotificationManager
oneway void setZenMode(int mode, in Uri conditionId, String reason);
oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
oneway void requestZenModeConditions(in IConditionListener callback, int relevance);
- oneway void requestNotificationPolicyAccess(String pkg, in INotificationManagerCallback callback);
boolean isNotificationPolicyAccessGranted(String pkg);
NotificationManager.Policy getNotificationPolicy(String pkg);
void setNotificationPolicy(String pkg, in NotificationManager.Policy policy);
diff --git a/core/java/android/app/INotificationManagerCallback.aidl b/core/java/android/app/INotificationManagerCallback.aidl
deleted file mode 100644
index 9929745..0000000
--- a/core/java/android/app/INotificationManagerCallback.aidl
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Copyright (c) 2015, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app;
-
-import android.app.NotificationManager;
-
-/** @hide */
-oneway interface INotificationManagerCallback {
- void onPolicyRequestResult(boolean granted);
-}
diff --git a/core/java/android/app/ISearchManager.aidl b/core/java/android/app/ISearchManager.aidl
index 6d27910..6094012 100644
--- a/core/java/android/app/ISearchManager.aidl
+++ b/core/java/android/app/ISearchManager.aidl
@@ -31,5 +31,5 @@ interface ISearchManager {
ComponentName getGlobalSearchActivity();
ComponentName getWebSearchActivity();
ComponentName getAssistIntent(int userHandle);
- boolean launchAssistAction(String hint, int userHandle);
+ boolean launchAssistAction(String hint, int userHandle, in Bundle args);
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 557964b..0904e21 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -101,6 +101,16 @@ public class NotificationManager
= "android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED";
/**
+ * Intent that is broadcast when the state of {@link #isNotificationPolicyAccessGranted()}
+ * changes.
+ *
+ * This broadcast is only sent to registered receivers, and only to the apps that have changed.
+ */
+ @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED
+ = "android.app.action.NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED";
+
+ /**
* Intent that is broadcast when the state of getNotificationPolicy() changes.
* This broadcast is only sent to registered receivers.
*/
@@ -403,55 +413,18 @@ public class NotificationManager
}
/**
- * Requests the ability to read/modify notification policy for the calling package.
- *
- * @param callback required, used to receive the granted or the denied signal.
- * @param handler The handler used when receiving the result.
- * If null, the current thread is used.
- */
- public void requestPolicyAccess(@NonNull final NotificationPolicyAccessRequestCallback callback,
- @Nullable Handler handler) {
- checkRequired("callback", callback);
- final Handler h = handler != null ? handler : new Handler();
- INotificationManager service = getService();
- try {
- service.requestNotificationPolicyAccess(mContext.getOpPackageName(),
- new INotificationManagerCallback.Stub() {
- @Override
- public void onPolicyRequestResult(final boolean granted) throws RemoteException {
- h.post(new Runnable() {
- @Override
- public void run() {
- if (granted) {
- callback.onAccessGranted();
- } else {
- callback.onAccessDenied();
- }
- }
- });
- }
- });
- } catch (RemoteException e) {
- }
- }
-
- /** Callback for receiving the result of a policy access request. */
- public static abstract class NotificationPolicyAccessRequestCallback {
- /**
- * Received if the request was granted for this package.
- */
- public abstract void onAccessGranted();
-
- /**
- * Received if the request was denied for this package.
- */
- public abstract void onAccessDenied();
- }
-
- /**
* Checks the ability to read/modify notification policy for the calling package.
*
+ * <p>
* Returns true if the calling package can read/modify notification policy.
+ *
+ * <p>
+ * Request policy access by sending the user to the activity that matches the system intent
+ * action {@link android.provider.Settings#ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS}.
+ *
+ * <p>
+ * Use {@link #ACTION_NOTIFICATION_POLICY_ACCESS_GRANTED_CHANGED} to listen for
+ * user grant or denial of this access.
*/
public boolean isNotificationPolicyAccessGranted() {
INotificationManager service = getService();
@@ -476,7 +449,8 @@ public class NotificationManager
* Gets the current notification policy.
*
* <p>
- * Only available if policy access is granted.
+ * Only available if policy access is granted to this package.
+ * See {@link #isNotificationPolicyAccessGranted}.
*/
public Policy getNotificationPolicy() {
INotificationManager service = getService();
@@ -491,7 +465,8 @@ public class NotificationManager
* Sets the current notification policy.
*
* <p>
- * Only available if policy access is granted.
+ * Only available if policy access is granted to this package.
+ * See {@link #isNotificationPolicyAccessGranted}.
*
* @param policy The new desired policy.
*/
@@ -716,7 +691,8 @@ public class NotificationManager
* unavailable.
*
* <p>
- * Only available if policy access is granted.
+ * Only available if policy access is granted to this package.
+ * See {@link #isNotificationPolicyAccessGranted}.
*/
public final int getCurrentInterruptionFilter() {
final INotificationManager service = getService();
@@ -738,7 +714,8 @@ public class NotificationManager
* unavailable.
*
* <p>
- * Only available if policy access is granted.
+ * Only available if policy access is granted to this package.
+ * See {@link #isNotificationPolicyAccessGranted}.
*/
public final void setInterruptionFilter(int interruptionFilter) {
final INotificationManager service = getService();
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 2cfc1fa4..031854a 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -25,11 +25,13 @@ import android.content.IIntentReceiver;
import android.content.IIntentSender;
import android.content.IntentSender;
import android.os.Bundle;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.Handler;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.Process;
import android.os.UserHandle;
import android.util.AndroidException;
@@ -206,10 +208,20 @@ public final class PendingIntent implements Parcelable {
private int mResultCode;
private String mResultData;
private Bundle mResultExtras;
+ private static Handler sDefaultSystemHandler;
FinishedDispatcher(PendingIntent pi, OnFinished who, Handler handler) {
mPendingIntent = pi;
mWho = who;
- mHandler = handler;
+ if (handler == null && ActivityThread.isSystem()) {
+ // We assign a default handler for the system process to avoid deadlocks when
+ // processing receivers in various components that hold global service locks.
+ if (sDefaultSystemHandler == null) {
+ sDefaultSystemHandler = new Handler(Looper.getMainLooper());
+ }
+ mHandler = sDefaultSystemHandler;
+ } else {
+ mHandler = handler;
+ }
}
public void performReceive(Intent intent, int resultCode, String data,
Bundle extras, boolean serialized, boolean sticky, int sendingUser) {
diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java
index 79797c9..2117597 100644
--- a/core/java/android/app/ResourcesManager.java
+++ b/core/java/android/app/ResourcesManager.java
@@ -31,6 +31,8 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.view.Display;
+import android.view.DisplayAdjustments;
+
import java.lang.ref.WeakReference;
import java.util.Locale;
@@ -42,7 +44,7 @@ public class ResourcesManager {
private static ResourcesManager sResourcesManager;
private final ArrayMap<ResourcesKey, WeakReference<Resources> > mActiveResources =
new ArrayMap<>();
- private final ArrayMap<Pair<Integer, Configuration>, WeakReference<Display>> mDisplays =
+ private final ArrayMap<Pair<Integer, DisplayAdjustments>, WeakReference<Display>> mDisplays =
new ArrayMap<>();
CompatibilityInfo mResCompatibilityInfo;
@@ -68,7 +70,8 @@ public class ResourcesManager {
DisplayMetrics getDisplayMetricsLocked(int displayId) {
DisplayMetrics dm = new DisplayMetrics();
- final Display display = getAdjustedDisplay(displayId, Configuration.EMPTY);
+ final Display display =
+ getAdjustedDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
if (display != null) {
display.getMetrics(dm);
} else {
@@ -113,12 +116,13 @@ public class ResourcesManager {
* available.
*
* @param displayId display Id.
- * @param overrideConfiguration override configurations.
+ * @param displayAdjustments display adjustments.
*/
- public Display getAdjustedDisplay(final int displayId, Configuration overrideConfiguration) {
- final Configuration configCopy = (overrideConfiguration != null)
- ? new Configuration(overrideConfiguration) : new Configuration();
- final Pair<Integer, Configuration> key = Pair.create(displayId, configCopy);
+ public Display getAdjustedDisplay(final int displayId, DisplayAdjustments displayAdjustments) {
+ final DisplayAdjustments displayAdjustmentsCopy = (displayAdjustments != null)
+ ? new DisplayAdjustments(displayAdjustments) : new DisplayAdjustments();
+ final Pair<Integer, DisplayAdjustments> key =
+ Pair.create(displayId, displayAdjustmentsCopy);
synchronized (this) {
WeakReference<Display> wd = mDisplays.get(key);
if (wd != null) {
@@ -132,7 +136,7 @@ public class ResourcesManager {
// may be null early in system startup
return null;
}
- final Display display = dm.getRealDisplay(displayId, key.second);
+ final Display display = dm.getCompatibleDisplay(displayId, key.second);
if (display != null) {
mDisplays.put(key, new WeakReference<>(display));
}
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index fa27631..45799a1 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -985,12 +985,12 @@ public class SearchManager
* Launch an assist action for the current top activity.
* @hide
*/
- public boolean launchAssistAction(String hint, int userHandle) {
+ public boolean launchAssistAction(String hint, int userHandle, Bundle args) {
try {
if (mService == null) {
return false;
}
- return mService.launchAssistAction(hint, userHandle);
+ return mService.launchAssistAction(hint, userHandle, args);
} catch (RemoteException re) {
Log.e(TAG, "launchAssistAction() failed: " + re);
return false;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 0d00908..10e8a53 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -691,7 +691,7 @@ final class SystemServiceRegistry {
@Override
public MidiManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.MIDI_SERVICE);
- return new MidiManager(ctx, IMidiManager.Stub.asInterface(b));
+ return new MidiManager(IMidiManager.Stub.asInterface(b));
}});
registerService(Context.RADIO_SERVICE, RadioManager.class,
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 9ba6a8e..39cd3bc 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -239,9 +239,10 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
public void run() {
InputStream in = null;
OutputStream out = null;
+ java.lang.Process process = null;
try {
- java.lang.Process process = Runtime.getRuntime().exec(command);
+ process = Runtime.getRuntime().exec(command);
in = process.getInputStream();
out = new FileOutputStream(sink.getFileDescriptor());
@@ -257,7 +258,9 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
} catch (IOException ioe) {
throw new RuntimeException("Error running shell command", ioe);
} finally {
- IoUtils.closeQuietly(in);
+ if (process != null) {
+ process.destroy();
+ }
IoUtils.closeQuietly(out);
IoUtils.closeQuietly(sink);
}
diff --git a/core/java/android/app/VoiceInteractor.aidl b/core/java/android/app/VoiceInteractor.aidl
index 40a4a0e..949605c 100644
--- a/core/java/android/app/VoiceInteractor.aidl
+++ b/core/java/android/app/VoiceInteractor.aidl
@@ -17,3 +17,4 @@
package android.app;
parcelable VoiceInteractor.PickOptionRequest.Option;
+parcelable VoiceInteractor.Prompt;
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index ba27c54..eccd9dc 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -16,6 +16,8 @@
package android.app;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
@@ -257,7 +259,7 @@ public class VoiceInteractor {
* so the user can give a confirmation.
*/
public static class ConfirmationRequest extends Request {
- final CharSequence mPrompt;
+ final Prompt mPrompt;
final Bundle mExtras;
/**
@@ -266,11 +268,23 @@ public class VoiceInteractor {
* should be spoken.
* @param extras Additional optional information or null.
*/
- public ConfirmationRequest(CharSequence prompt, Bundle extras) {
+ public ConfirmationRequest(@Nullable Prompt prompt, @Nullable Bundle extras) {
mPrompt = prompt;
mExtras = extras;
}
+ /**
+ * Create a new confirmation request.
+ * @param prompt Optional confirmation to speak to the user or null if nothing
+ * should be spoken.
+ * @param extras Additional optional information or null.
+ * @deprecated Prefer the version that takes a {@link Prompt}.
+ */
+ public ConfirmationRequest(CharSequence prompt, Bundle extras) {
+ mPrompt = (prompt != null ? new Prompt(prompt) : null);
+ mExtras = extras;
+ }
+
public void onConfirmationResult(boolean confirmed, Bundle result) {
}
@@ -288,7 +302,7 @@ public class VoiceInteractor {
* either {@link #onPickOptionResult} or {@link #onCancel()}.
*/
public static class PickOptionRequest extends Request {
- final CharSequence mPrompt;
+ final Prompt mPrompt;
final Option[] mOptions;
final Bundle mExtras;
@@ -417,13 +431,28 @@ public class VoiceInteractor {
* @param options The set of {@link Option}s the user is selecting from.
* @param extras Additional optional information or null.
*/
- public PickOptionRequest(CharSequence prompt, Option[] options, Bundle extras) {
+ public PickOptionRequest(@Nullable Prompt prompt, Option[] options,
+ @Nullable Bundle extras) {
mPrompt = prompt;
mOptions = options;
mExtras = extras;
}
/**
+ * Create a new pick option request.
+ * @param prompt Optional question to be asked of the user when the options are
+ * presented or null if nothing should be asked.
+ * @param options The set of {@link Option}s the user is selecting from.
+ * @param extras Additional optional information or null.
+ * @deprecated Prefer the version that takes a {@link Prompt}.
+ */
+ public PickOptionRequest(CharSequence prompt, Option[] options, Bundle extras) {
+ mPrompt = (prompt != null ? new Prompt(prompt) : null);
+ mOptions = options;
+ mExtras = extras;
+ }
+
+ /**
* Called when a single option is confirmed or narrowed to one of several options.
* @param finished True if the voice interaction has finished making a selection, in
* which case {@code selections} contains the final result. If false, this request is
@@ -451,17 +480,29 @@ public class VoiceInteractor {
* interaction task.
*/
public static class CompleteVoiceRequest extends Request {
- final CharSequence mMessage;
+ final Prompt mPrompt;
final Bundle mExtras;
/**
* Create a new completed voice interaction request.
+ * @param prompt Optional message to speak to the user about the completion status of
+ * the task or null if nothing should be spoken.
+ * @param extras Additional optional information or null.
+ */
+ public CompleteVoiceRequest(@Nullable Prompt prompt, @Nullable Bundle extras) {
+ mPrompt = prompt;
+ mExtras = extras;
+ }
+
+ /**
+ * Create a new completed voice interaction request.
* @param message Optional message to speak to the user about the completion status of
* the task or null if nothing should be spoken.
* @param extras Additional optional information or null.
+ * @deprecated Prefer the version that takes a {@link Prompt}.
*/
public CompleteVoiceRequest(CharSequence message, Bundle extras) {
- mMessage = message;
+ mPrompt = (message != null ? new Prompt(message) : null);
mExtras = extras;
}
@@ -470,7 +511,7 @@ public class VoiceInteractor {
IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
IVoiceInteractorCallback callback) throws RemoteException {
- return interactor.startCompleteVoice(packageName, callback, mMessage, mExtras);
+ return interactor.startCompleteVoice(packageName, callback, mPrompt, mExtras);
}
}
@@ -486,17 +527,29 @@ public class VoiceInteractor {
* interaction task.
*/
public static class AbortVoiceRequest extends Request {
- final CharSequence mMessage;
+ final Prompt mPrompt;
final Bundle mExtras;
/**
* Create a new voice abort request.
+ * @param prompt Optional message to speak to the user indicating why the task could
+ * not be completed by voice or null if nothing should be spoken.
+ * @param extras Additional optional information or null.
+ */
+ public AbortVoiceRequest(@Nullable Prompt prompt, @Nullable Bundle extras) {
+ mPrompt = prompt;
+ mExtras = extras;
+ }
+
+ /**
+ * Create a new voice abort request.
* @param message Optional message to speak to the user indicating why the task could
* not be completed by voice or null if nothing should be spoken.
* @param extras Additional optional information or null.
+ * @deprecated Prefer the version that takes a {@link Prompt}.
*/
public AbortVoiceRequest(CharSequence message, Bundle extras) {
- mMessage = message;
+ mPrompt = (message != null ? new Prompt(message) : null);
mExtras = extras;
}
@@ -505,7 +558,7 @@ public class VoiceInteractor {
IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
IVoiceInteractorCallback callback) throws RemoteException {
- return interactor.startAbortVoice(packageName, callback, mMessage, mExtras);
+ return interactor.startAbortVoice(packageName, callback, mPrompt, mExtras);
}
}
@@ -550,7 +603,101 @@ public class VoiceInteractor {
IVoiceInteractorCallback callback) throws RemoteException {
return interactor.startCommand(packageName, callback, mCommand, mArgs);
}
- }
+ }
+
+ /**
+ * A set of voice prompts to use with the voice interaction system to confirm an action, select
+ * an option, or do similar operations. Multiple voice prompts may be provided for variety. A
+ * visual prompt must be provided, which might not match the spoken version. For example, the
+ * confirmation "Are you sure you want to purchase this item?" might use a visual label like
+ * "Purchase item".
+ */
+ public static class Prompt implements Parcelable {
+ // Mandatory voice prompt. Must contain at least one item, which must not be null.
+ private final CharSequence[] mVoicePrompts;
+
+ // Mandatory visual prompt.
+ private final CharSequence mVisualPrompt;
+
+ /**
+ * Constructs a prompt set.
+ * @param voicePrompts An array of one or more voice prompts. Must not be empty or null.
+ * @param visualPrompt A prompt to display on the screen. Must not be null.
+ */
+ public Prompt(@NonNull CharSequence[] voicePrompts, @NonNull CharSequence visualPrompt) {
+ if (voicePrompts == null) {
+ throw new NullPointerException("voicePrompts must not be null");
+ }
+ if (voicePrompts.length == 0) {
+ throw new IllegalArgumentException("voicePrompts must not be empty");
+ }
+ if (visualPrompt == null) {
+ throw new NullPointerException("visualPrompt must not be null");
+ }
+ this.mVoicePrompts = voicePrompts;
+ this.mVisualPrompt = visualPrompt;
+ }
+
+ /**
+ * Constructs a prompt set with single prompt used for all interactions. This is most useful
+ * in test apps. Non-trivial apps should prefer the detailed constructor.
+ */
+ public Prompt(@NonNull CharSequence prompt) {
+ this.mVoicePrompts = new CharSequence[] { prompt };
+ this.mVisualPrompt = prompt;
+ }
+
+ /**
+ * Returns a prompt to use for voice interactions.
+ */
+ @NonNull
+ public CharSequence getVoicePromptAt(int index) {
+ return mVoicePrompts[index];
+ }
+
+ /**
+ * Returns the number of different voice prompts.
+ */
+ public int countVoicePrompts() {
+ return mVoicePrompts.length;
+ }
+
+ /**
+ * Returns the prompt to use for visual display.
+ */
+ @NonNull
+ public CharSequence getVisualPrompt() {
+ return mVisualPrompt;
+ }
+
+ /** Constructor to support Parcelable behavior. */
+ Prompt(Parcel in) {
+ mVoicePrompts = in.readCharSequenceArray();
+ mVisualPrompt = in.readCharSequence();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeCharSequenceArray(mVoicePrompts);
+ dest.writeCharSequence(mVisualPrompt);
+ }
+
+ public static final Creator<Prompt> CREATOR
+ = new Creator<Prompt>() {
+ public Prompt createFromParcel(Parcel in) {
+ return new Prompt(in);
+ }
+
+ public Prompt[] newArray(int size) {
+ return new Prompt[size];
+ }
+ };
+ }
VoiceInteractor(IVoiceInteractor interactor, Context context, Activity activity,
Looper looper) {
@@ -631,7 +778,7 @@ public class VoiceInteractor {
}
/**
- * Queries the supported commands available from the VoiceinteractionService.
+ * Queries the supported commands available from the VoiceInteractionService.
* The command is a string that describes the generic operation to be performed.
* An example might be "org.example.commands.PICK_DATE" to ask the user to pick
* a date. (Note: This is not an actual working example.)
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 55eaf27..3ab0e01 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -4404,24 +4404,6 @@ public class DevicePolicyManager {
}
/**
- * Called by a device initializer to set the activity to be launched on device boot or after a
- * user switch during user setup. This activity will be started regardless of the priority of
- * other 'home' activities. Once user setup is complete, the preferred setup activity will be
- * ignored.
- *
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param activity The Activity to be started by default during user setup.
- */
- public void setPreferredSetupActivity(@NonNull ComponentName admin,
- @NonNull ComponentName activity) {
- try {
- mService.setPreferredSetupActivity(admin, activity);
- } catch (RemoteException re) {
- Log.w(TAG, "Failed talking with device policy service", re);
- }
- }
-
- /**
* Called by profile or device owners to set the default response for future runtime permission
* requests by applications. The policy can allow for normal operation which prompts the
* user to grant a permission, or can allow automatic granting or denying of runtime
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 477a338..8c7b20a 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -218,8 +218,6 @@ interface IDevicePolicyManager {
String getDeviceInitializer();
ComponentName getDeviceInitializerComponent();
- void setPreferredSetupActivity(in ComponentName admin, in ComponentName activity);
-
void setUserIcon(in ComponentName admin, in Bitmap icon);
void sendDeviceInitializerStatus(int statusCode, String description);
diff --git a/core/java/android/app/usage/NetworkStats.java b/core/java/android/app/usage/NetworkStats.java
index 5193563..1079f1a 100644
--- a/core/java/android/app/usage/NetworkStats.java
+++ b/core/java/android/app/usage/NetworkStats.java
@@ -29,11 +29,11 @@ import android.util.Log;
import dalvik.system.CloseGuard;
/**
- * Class providing enumeration over buckets of network usage statistics. NetworkUsageStats objects
+ * Class providing enumeration over buckets of network usage statistics. {@link NetworkStats} objects
* are returned as results to various queries in {@link NetworkStatsManager}.
*/
public final class NetworkStats implements AutoCloseable {
- private final static String TAG = "NetworkUsageStats";
+ private final static String TAG = "NetworkStats";
private final CloseGuard mCloseGuard = CloseGuard.get();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index c01ce4f..5c23204 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1274,6 +1274,13 @@ public class Intent implements Parcelable, Cloneable {
"android.intent.extra.ASSIST_INPUT_HINT_KEYBOARD";
/**
+ * An optional field on {@link #ACTION_ASSIST} containing the InputDevice id
+ * that was used to invoke the assist.
+ */
+ public static final String EXTRA_ASSIST_INPUT_DEVICE_ID =
+ "android.intent.extra.ASSIST_INPUT_DEVICE_ID";
+
+ /**
* Activity Action: List all available applications
* <p>Input: Nothing.
* <p>Output: nothing.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 45245e4..c016ac3 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3274,10 +3274,11 @@ public abstract class PackageManager {
throws NameNotFoundException;
/**
- * If the target user is a managed profile of the calling user or the caller
- * is itself a managed profile, then this returns a badged copy of the given
- * icon to be able to distinguish it from the original icon. For badging an
- * arbitrary drawable use {@link #getUserBadgedDrawableForDensity(
+ * If the target user is a managed profile of the calling user or if the
+ * target user is the caller and is itself a managed profile, then this
+ * returns a badged copy of the given icon to be able to distinguish it from
+ * the original icon. For badging an arbitrary drawable use
+ * {@link #getUserBadgedDrawableForDensity(
* android.graphics.drawable.Drawable, UserHandle, android.graphics.Rect, int)}.
* <p>
* If the original drawable is a BitmapDrawable and the backing bitmap is
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index a572590..9a99a46 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -2486,7 +2486,8 @@ public class Resources {
return true;
}
- /*package*/ Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
+ @Nullable
+ Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
if (TRACE_FOR_PRELOAD) {
// Log only framework resources
if ((id >>> 24) == 0x1) {
@@ -2541,7 +2542,7 @@ public class Resources {
// Determine if the drawable has unresolved theme attributes. If it
// does, we'll need to apply a theme and store it in a theme-specific
// cache.
- final boolean canApplyTheme = dr.canApplyTheme();
+ final boolean canApplyTheme = dr != null && dr.canApplyTheme();
if (canApplyTheme && theme != null) {
dr = dr.mutate();
dr.applyTheme(theme);
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index b2c1c71..bc625dd 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -169,6 +169,9 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
private final HashSet<Surface> mSurfaceSet;
private final CameraMetadataNative mSettings;
private boolean mIsReprocess;
+ // If this request is part of constrained high speed request list that was created by
+ // {@link CameraDevice#createConstrainedHighSpeedRequestList}.
+ private boolean mIsPartOfCHSRequestList = false;
// Each reprocess request must be tied to a reprocessable session ID.
// Valid only for reprocess requests (mIsReprocess == true).
private int mReprocessableSessionId;
@@ -197,6 +200,7 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
mSettings = new CameraMetadataNative(source.mSettings);
mSurfaceSet = (HashSet<Surface>) source.mSurfaceSet.clone();
mIsReprocess = source.mIsReprocess;
+ mIsPartOfCHSRequestList = source.mIsPartOfCHSRequestList;
mReprocessableSessionId = source.mReprocessableSessionId;
mUserTag = source.mUserTag;
}
@@ -321,6 +325,35 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
}
/**
+ * <p>Determine if this request is part of a constrained high speed request list that was
+ * created by {@link CameraDevice#createConstrainedHighSpeedRequestList}. A constrained high
+ * speed request list contains some constrained high speed capture requests with certain
+ * interleaved pattern that is suitable for high speed preview/video streaming. An active
+ * constrained high speed capture session only accepts constrained high speed request lists.
+ * This method can be used to do the sanity check when a constrained high speed capture session
+ * receives a request list via {@link CameraCaptureSession#setRepeatingBurst} or
+ * {@link CameraCaptureSession#captureBurst}.
+ * </p>
+ *
+ *
+ * @return {@code true} if this request is part of a constrained high speed request list,
+ * {@code false} otherwise.
+ *
+ * @hide
+ */
+ public boolean isPartOfCRequestList() {
+ return mIsPartOfCHSRequestList;
+ }
+
+ /**
+ * Returns a copy of the underlying {@link CameraMetadataNative}.
+ * @hide
+ */
+ public CameraMetadataNative getNativeCopy() {
+ return new CameraMetadataNative(mSettings);
+ }
+
+ /**
* Get the reprocessable session ID this reprocess capture request is associated with.
*
* @return the reprocessable session ID this reprocess capture request is associated with
@@ -547,6 +580,18 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
}
/**
+ * <p>Mark this request as part of a constrained high speed request list created by
+ * {@link CameraDevice#createConstrainedHighSpeedRequestList}. A constrained high speed
+ * request list contains some constrained high speed capture requests with certain
+ * interleaved pattern that is suitable for high speed preview/video streaming.</p>
+ *
+ * @hide
+ */
+ public void setPartOfCHSRequestList(boolean partOfCHSList) {
+ mRequest.mIsPartOfCHSRequestList = partOfCHSList;
+ }
+
+ /**
* Build a request using the current target Surfaces and settings.
* <p>Note that, although it is possible to create a {@code CaptureRequest} with no target
* {@link Surface}s, passing such a request into {@link CameraCaptureSession#capture},
@@ -563,7 +608,6 @@ public final class CaptureRequest extends CameraMetadata<CaptureRequest.Key<?>>
return new CaptureRequest(mRequest);
}
-
/**
* @hide
*/
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
index 375b310..1574f93 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -61,7 +61,7 @@ interface ICameraDeviceUser
* must be called before any requests can be submitted.
* <p>
*/
- int endConfigure();
+ int endConfigure(boolean isConstrainedHighSpeed);
int deleteStream(int streamId);
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
index ab0f607..3d261dd 100644
--- a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -60,6 +60,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
private final android.hardware.camera2.impl.CameraDeviceImpl mDeviceImpl;
/** Internal handler; used for all incoming events to preserve total order */
private final Handler mDeviceHandler;
+ private final boolean mIsConstrainedHighSpeedSession;
/** Drain Sequence IDs which have been queued but not yet finished with aborted/completed */
private final TaskDrainer<Integer> mSequenceDrainer;
@@ -88,13 +89,14 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
CameraCaptureSessionImpl(int id, Surface input, List<Surface> outputs,
CameraCaptureSession.StateCallback callback, Handler stateHandler,
android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
- Handler deviceStateHandler, boolean configureSuccess) {
+ Handler deviceStateHandler, boolean configureSuccess, boolean isConstrainedHighSpeed) {
if (outputs == null || outputs.isEmpty()) {
throw new IllegalArgumentException("outputs must be a non-null, non-empty list");
} else if (callback == null) {
throw new IllegalArgumentException("callback must not be null");
}
+ mIsConstrainedHighSpeedSession = isConstrainedHighSpeed;
mId = id;
mIdString = String.format("Session %d: ", mId);
@@ -134,6 +136,30 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
}
}
+
+ private boolean isConstrainedHighSpeedRequestList(List<CaptureRequest> requestList) {
+ checkCollectionNotEmpty(requestList, "High speed request list");
+ for (CaptureRequest request : requestList) {
+ if (!request.isPartOfCRequestList()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * If the session is constrained high speed session, it only accept constrained high speed
+ * request list.
+ */
+ private void checkConstrainedHighSpeedRequestSanity(List<CaptureRequest> requestList) {
+ if (mIsConstrainedHighSpeedSession) {
+ if (!isConstrainedHighSpeedRequestList(requestList)) {
+ throw new IllegalArgumentException("It is only allowed to submit a constrained "
+ + "high speed request list to a constrained high speed session!!!");
+ }
+ }
+ }
+
@Override
public CameraDevice getDevice() {
return mDeviceImpl;
@@ -155,6 +181,10 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
} else if (request.isReprocess() && request.getReprocessableSessionId() != mId) {
throw new IllegalArgumentException("capture request was created for another session");
}
+ if (mIsConstrainedHighSpeedSession) {
+ throw new UnsupportedOperationException("Constrained high speed session doesn't support"
+ + " this method");
+ }
checkNotClosed();
@@ -178,6 +208,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
throw new IllegalArgumentException("Requests must have at least one element");
}
+ checkConstrainedHighSpeedRequestSanity(requests);
+
for (CaptureRequest request : requests) {
if (request.isReprocess()) {
if (!isReprocessable()) {
@@ -212,7 +244,10 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
} else if (request.isReprocess()) {
throw new IllegalArgumentException("repeating reprocess requests are not supported");
}
-
+ if (mIsConstrainedHighSpeedSession) {
+ throw new UnsupportedOperationException("Constrained high speed session doesn't support"
+ + " this method");
+ }
checkNotClosed();
@@ -236,6 +271,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
throw new IllegalArgumentException("requests must have at least one element");
}
+ checkConstrainedHighSpeedRequestSanity(requests);
+
for (CaptureRequest r : requests) {
if (r.isReprocess()) {
throw new IllegalArgumentException("repeating reprocess burst requests are not " +
@@ -704,7 +741,8 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
// everything is idle.
try {
// begin transition to unconfigured
- mDeviceImpl.configureStreamsChecked(null, null);
+ mDeviceImpl.configureStreamsChecked(/*inputConfig*/null, /*outputs*/null,
+ /*isConstrainedHighSpeed*/false);
} catch (CameraAccessException e) {
// OK: do not throw checked exceptions.
Log.e(TAG, mIdString + "Exception while unconfiguring outputs: ", e);
@@ -723,8 +761,7 @@ public class CameraCaptureSessionImpl extends CameraCaptureSession {
@Override
public boolean isConstrainedHighSpeed() {
- // TODO: to be implemented
- return false;
+ return mIsConstrainedHighSpeedSession;
}
}
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index ad0cd0f..c073ba5 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -18,6 +18,7 @@ package android.hardware.camera2.impl;
import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
+import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
@@ -35,17 +36,22 @@ import android.hardware.camera2.params.StreamConfigurationMap;
import android.hardware.camera2.utils.CameraBinderDecorator;
import android.hardware.camera2.utils.CameraRuntimeException;
import android.hardware.camera2.utils.LongParcelable;
+import android.hardware.camera2.utils.SurfaceUtils;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
+import android.util.Range;
import android.util.Size;
import android.util.SparseArray;
import android.view.Surface;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -326,7 +332,8 @@ public class CameraDeviceImpl extends CameraDevice {
for (Surface s : outputs) {
outputConfigs.add(new OutputConfiguration(s));
}
- configureStreamsChecked(/*inputConfig*/null, outputConfigs);
+ configureStreamsChecked(/*inputConfig*/null, outputConfigs,
+ /*isConstrainedHighSpeed*/false);
}
@@ -344,12 +351,14 @@ public class CameraDeviceImpl extends CameraDevice {
*
* @param inputConfig input configuration or {@code null} for no input
* @param outputs a list of one or more surfaces, or {@code null} to unconfigure
+ * @param isConstrainedHighSpeed If the streams configuration is for constrained high speed output.
* @return whether or not the configuration was successful
*
* @throws CameraAccessException if there were any unexpected problems during configuration
*/
public boolean configureStreamsChecked(InputConfiguration inputConfig,
- List<OutputConfiguration> outputs) throws CameraAccessException {
+ List<OutputConfiguration> outputs, boolean isConstrainedHighSpeed)
+ throws CameraAccessException {
// Treat a null input the same an empty list
if (outputs == null) {
outputs = new ArrayList<OutputConfiguration>();
@@ -422,7 +431,7 @@ public class CameraDeviceImpl extends CameraDevice {
}
try {
- mRemoteDevice.endConfigure();
+ mRemoteDevice.endConfigure(isConstrainedHighSpeed);
}
catch (IllegalArgumentException e) {
// OK. camera service can reject stream config if it's not supported by HAL
@@ -463,7 +472,8 @@ public class CameraDeviceImpl extends CameraDevice {
for (Surface surface : outputs) {
outConfigurations.add(new OutputConfiguration(surface));
}
- createCaptureSessionInternal(null, outConfigurations, callback, handler);
+ createCaptureSessionInternal(null, outConfigurations, callback, handler,
+ /*isConstrainedHighSpeed*/false);
}
@Override
@@ -475,7 +485,8 @@ public class CameraDeviceImpl extends CameraDevice {
Log.d(TAG, "createCaptureSessionByOutputConfiguration");
}
- createCaptureSessionInternal(null, outputConfigurations, callback, handler);
+ createCaptureSessionInternal(null, outputConfigurations, callback, handler,
+ /*isConstrainedHighSpeed*/false);
}
@Override
@@ -494,13 +505,14 @@ public class CameraDeviceImpl extends CameraDevice {
for (Surface surface : outputs) {
outConfigurations.add(new OutputConfiguration(surface));
}
- createCaptureSessionInternal(inputConfig, outConfigurations, callback, handler);
+ createCaptureSessionInternal(inputConfig, outConfigurations, callback, handler,
+ /*isConstrainedHighSpeed*/false);
}
private void createCaptureSessionInternal(InputConfiguration inputConfig,
List<OutputConfiguration> outputConfigurations,
- CameraCaptureSession.StateCallback callback, Handler handler)
- throws CameraAccessException {
+ CameraCaptureSession.StateCallback callback, Handler handler,
+ boolean isConstrainedHighSpeed) throws CameraAccessException {
synchronized(mInterfaceLock) {
if (DEBUG) {
Log.d(TAG, "createCaptureSessionInternal");
@@ -508,6 +520,11 @@ public class CameraDeviceImpl extends CameraDevice {
checkIfCameraClosedOrInError();
+ if (isConstrainedHighSpeed && inputConfig != null) {
+ throw new IllegalArgumentException("Constrained high speed session doesn't support"
+ + " input configuration yet.");
+ }
+
// Notify current session that it's going away, before starting camera operations
// After this call completes, the session is not allowed to call into CameraDeviceImpl
if (mCurrentSession != null) {
@@ -520,7 +537,8 @@ public class CameraDeviceImpl extends CameraDevice {
Surface input = null;
try {
// configure streams and then block until IDLE
- configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations);
+ configureSuccess = configureStreamsChecked(inputConfig, outputConfigurations,
+ isConstrainedHighSpeed);
if (inputConfig != null) {
input = new Surface();
mRemoteDevice.getInputSurface(/*out*/input);
@@ -545,7 +563,7 @@ public class CameraDeviceImpl extends CameraDevice {
CameraCaptureSessionImpl newSession =
new CameraCaptureSessionImpl(mNextSessionId++, input,
outSurfaces, callback, handler, this, mDeviceHandler,
- configureSuccess);
+ configureSuccess, isConstrainedHighSpeed);
// TODO: wait until current session closes, then create the new session
mCurrentSession = newSession;
@@ -1906,17 +1924,156 @@ public class CameraDeviceImpl extends CameraDevice {
return mCharacteristics;
}
+ private void checkConstrainedHighSpeedSurfaces(Collection<Surface> surfaces,
+ Range<Integer> fpsRange) {
+ if (surfaces == null || surfaces.size() == 0 || surfaces.size() > 2) {
+ throw new IllegalArgumentException("Output target surface list must not be null and"
+ + " the size must be 1 or 2");
+ }
+
+ StreamConfigurationMap config =
+ getCharacteristics().get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+ List<Size> highSpeedSizes = null;
+ if (fpsRange == null) {
+ highSpeedSizes = Arrays.asList(config.getHighSpeedVideoSizes());
+ } else {
+ // Check the FPS range first if provided
+ Range<Integer>[] highSpeedFpsRanges = config.getHighSpeedVideoFpsRanges();
+ if(!Arrays.asList(highSpeedFpsRanges).contains(fpsRange)) {
+ throw new IllegalArgumentException("Fps range " + fpsRange.toString() + " in the"
+ + " request is not a supported high speed fps range " +
+ Arrays.toString(highSpeedFpsRanges));
+ }
+ highSpeedSizes = Arrays.asList(config.getHighSpeedVideoSizesFor(fpsRange));
+ }
+
+ for (Surface surface : surfaces) {
+ // Surface size must be supported high speed sizes.
+ Size surfaceSize = SurfaceUtils.getSurfaceSize(surface);
+ int surfaceFormat = SurfaceUtils.getSurfaceFormat(surface);
+
+ if (surfaceFormat != ImageFormat.PRIVATE) {
+ throw new IllegalArgumentException("Surface format is not for preview or"
+ + " hardware video encoding" + surfaceFormat);
+ }
+
+ if (!highSpeedSizes.contains(surfaceSize)) {
+ throw new IllegalArgumentException("Surface size " + surfaceSize.toString() + " is"
+ + " not part of the high speed supported size list " +
+ Arrays.toString(highSpeedSizes.toArray()));
+ }
+ // Each output surface must be either preview surface or recording surface.
+ if (!SurfaceUtils.isSurfaceForPreview(surface) &&
+ !SurfaceUtils.isSurfaceForHwVideoEncoder(surface)) {
+ throw new IllegalArgumentException("This output surface is neither preview nor "
+ + "hardware video encoding surface");
+ }
+ if (SurfaceUtils.isSurfaceForPreview(surface) &&
+ SurfaceUtils.isSurfaceForHwVideoEncoder(surface)) {
+ throw new IllegalArgumentException("This output surface can not be both preview"
+ + " and hardware video encoding surface");
+ }
+ }
+
+ // For 2 output surface case, they shouldn't be same type.
+ if (surfaces.size() == 2) {
+ // Up to here, each surface can only be either preview or recording.
+ Iterator<Surface> iterator = surfaces.iterator();
+ boolean isFirstSurfacePreview =
+ SurfaceUtils.isSurfaceForPreview(iterator.next());
+ boolean isSecondSurfacePreview =
+ SurfaceUtils.isSurfaceForPreview(iterator.next());
+ if (isFirstSurfacePreview == isSecondSurfacePreview) {
+ throw new IllegalArgumentException("The 2 output surfaces must have different"
+ + " type");
+ }
+ }
+ }
+
@Override
public void createConstrainedHighSpeedCaptureSession(List<Surface> outputs,
android.hardware.camera2.CameraCaptureSession.StateCallback callback, Handler handler)
throws CameraAccessException {
- // TODO: to be implemented
- throw new UnsupportedOperationException("To be implemented!!!!");
+ if (outputs == null || outputs.size() == 0 || outputs.size() > 2) {
+ throw new IllegalArgumentException(
+ "Output surface list must not be null and the size must be no more than 2");
+ }
+ checkConstrainedHighSpeedSurfaces(outputs, /*fpsRange*/null);
+
+ List<OutputConfiguration> outConfigurations = new ArrayList<>(outputs.size());
+ for (Surface surface : outputs) {
+ outConfigurations.add(new OutputConfiguration(surface));
+ }
+ createCaptureSessionInternal(null, outConfigurations, callback, handler,
+ /*isConstrainedHighSpeed*/true);
}
@Override
public List<CaptureRequest> createConstrainedHighSpeedRequestList(CaptureRequest request)
throws CameraAccessException {
- throw new UnsupportedOperationException("To be implemented!!!!");
+ if (request == null) {
+ throw new IllegalArgumentException("Input capture request must not be null");
+ }
+ Collection<Surface> outputSurfaces = request.getTargets();
+ Range<Integer> fpsRange = request.get(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE);
+ checkConstrainedHighSpeedSurfaces(outputSurfaces, fpsRange);
+
+ // Request list size: to limit the preview to 30fps, need use maxFps/30; to maximize
+ // the preview frame rate, should use maxBatch size for that high speed stream
+ // configuration. We choose the former for now.
+ int requestListSize = fpsRange.getUpper() / 30;
+ List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+
+ // Prepare the Request builders: need carry over the request controls.
+ // First, create a request builder that will only include preview or recording target.
+ CameraMetadataNative requestMetadata = new CameraMetadataNative(request.getNativeCopy());
+ CaptureRequest.Builder singleTargetRequestBuilder = new CaptureRequest.Builder(
+ requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
+
+ // Overwrite the capture intent to make sure a good value is set.
+ Surface[] surfaces = (Surface[])outputSurfaces.toArray();
+ if (outputSurfaces.size() == 1 && SurfaceUtils.isSurfaceForHwVideoEncoder(surfaces[0])) {
+ singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
+ CaptureRequest.CONTROL_CAPTURE_INTENT_PREVIEW);
+ } else {
+ // Video only, or preview + video
+ singleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
+ CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
+ }
+ singleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
+
+ // Second, Create a request builder that will include both preview and recording targets.
+ CaptureRequest.Builder doubleTargetRequestBuilder = null;
+ if (outputSurfaces.size() == 2) {
+ doubleTargetRequestBuilder = new CaptureRequest.Builder(
+ requestMetadata, /*reprocess*/false, CameraCaptureSession.SESSION_ID_NONE);
+ doubleTargetRequestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT,
+ CaptureRequest.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
+ doubleTargetRequestBuilder.addTarget(surfaces[0]);
+ doubleTargetRequestBuilder.addTarget(surfaces[1]);
+ doubleTargetRequestBuilder.setPartOfCHSRequestList(/*partOfCHSList*/true);
+ // Make sure singleTargetRequestBuilder contains only recording surface for
+ // preview + recording case.
+ Surface recordingSurface = surfaces[0];
+ if (!SurfaceUtils.isSurfaceForHwVideoEncoder(recordingSurface)) {
+ recordingSurface = surfaces[1];
+ }
+ singleTargetRequestBuilder.addTarget(recordingSurface);
+ } else {
+ // Single output case: either recording or preview.
+ singleTargetRequestBuilder.addTarget(surfaces[0]);
+ }
+
+ // Generate the final request list.
+ for (int i = 0; i < requestListSize; i++) {
+ if (i == 0 && doubleTargetRequestBuilder != null) {
+ // First request should be recording + preview request
+ requestList.add(doubleTargetRequestBuilder.build());
+ } else {
+ requestList.add(singleTargetRequestBuilder.build());
+ }
+ }
+
+ return Collections.unmodifiableList(requestList);
}
}
diff --git a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
index bc0a3a8..f5314da 100644
--- a/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
+++ b/core/java/android/hardware/camera2/legacy/CameraDeviceUserShim.java
@@ -88,15 +88,6 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
mSurfaceIdCounter = 0;
}
- private static int translateErrorsFromCamera1(int errorCode) {
- switch (errorCode) {
- case CameraBinderDecorator.EACCES:
- return CameraBinderDecorator.PERMISSION_DENIED;
- default:
- return errorCode;
- }
- }
-
/**
* Create a separate looper/thread for the camera to run on; open the camera.
*
@@ -140,7 +131,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
// Save the looper so that we can terminate this thread
// after we are done with it.
mLooper = Looper.myLooper();
- mInitErrors = translateErrorsFromCamera1(mCamera.cameraInitUnspecified(mCameraId));
+ mInitErrors = mCamera.cameraInitUnspecified(mCameraId);
mStartDone.open();
Looper.loop(); // Blocks forever until #close is called.
}
@@ -465,7 +456,7 @@ public class CameraDeviceUserShim implements ICameraDeviceUser {
}
@Override
- public int endConfigure() {
+ public int endConfigure(boolean isConstrainedHighSpeed) {
if (DEBUG) {
Log.d(TAG, "endConfigure called.");
}
diff --git a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
index 098c2d8..cc9d496 100644
--- a/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
+++ b/core/java/android/hardware/camera2/legacy/LegacyCameraDevice.java
@@ -82,6 +82,7 @@ public class LegacyCameraDevice implements AutoCloseable {
private static final int GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003;
private static final int GRALLOC_USAGE_HW_TEXTURE = 0x00000100;
private static final int GRALLOC_USAGE_HW_COMPOSER = 0x00000800;
+ private static final int GRALLOC_USAGE_HW_RENDER = 0x00000200;
private static final int GRALLOC_USAGE_HW_VIDEO_ENCODER = 0x00010000;
public static final int MAX_DIMEN_FOR_ROUNDING = 1080; // maximum allowed width for rounding
@@ -549,6 +550,42 @@ public class LegacyCameraDevice implements AutoCloseable {
return flexibleConsumer;
}
+ public static boolean isPreviewConsumer(Surface output) {
+ int usageFlags = detectSurfaceUsageFlags(output);
+ int disallowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER | GRALLOC_USAGE_RENDERSCRIPT |
+ GRALLOC_USAGE_SW_READ_OFTEN;
+ int allowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER |
+ GRALLOC_USAGE_HW_RENDER;
+ boolean previewConsumer = ((usageFlags & disallowedFlags) == 0 &&
+ (usageFlags & allowedFlags) != 0);
+ int surfaceFormat = ImageFormat.UNKNOWN;
+ try {
+ surfaceFormat = detectSurfaceType(output);
+ } catch(BufferQueueAbandonedException e) {
+ throw new IllegalArgumentException("Surface was abandoned", e);
+ }
+
+ return previewConsumer && (surfaceFormat == ImageFormat.PRIVATE);
+ }
+
+ public static boolean isVideoEncoderConsumer(Surface output) {
+ int usageFlags = detectSurfaceUsageFlags(output);
+ int disallowedFlags = GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_HW_COMPOSER |
+ GRALLOC_USAGE_RENDERSCRIPT | GRALLOC_USAGE_SW_READ_OFTEN;
+ int allowedFlags = GRALLOC_USAGE_HW_VIDEO_ENCODER;
+ boolean videoEncoderConsumer = ((usageFlags & disallowedFlags) == 0 &&
+ (usageFlags & allowedFlags) != 0);
+
+ int surfaceFormat = ImageFormat.UNKNOWN;
+ try {
+ surfaceFormat = detectSurfaceType(output);
+ } catch(BufferQueueAbandonedException e) {
+ throw new IllegalArgumentException("Surface was abandoned", e);
+ }
+
+ return videoEncoderConsumer && (surfaceFormat == ImageFormat.PRIVATE);
+ }
+
/**
* Query the surface for its currently configured usage flags
*/
diff --git a/core/java/android/hardware/camera2/utils/SurfaceUtils.java b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
new file mode 100644
index 0000000..32e74e2
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/SurfaceUtils.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera2.utils;
+
+import android.hardware.camera2.legacy.LegacyCameraDevice;
+import android.hardware.camera2.legacy.LegacyExceptionUtils.BufferQueueAbandonedException;
+import android.util.Size;
+import android.view.Surface;
+
+/**
+ * Various Surface utilities.
+ */
+public class SurfaceUtils {
+
+ /**
+ * Check if a surface is for preview consumer.
+ *
+ * @param surface The surface to be checked.
+ * @return true if the surface is for preview consumer, false otherwise.
+ */
+ public static boolean isSurfaceForPreview(Surface surface) {
+ return LegacyCameraDevice.isPreviewConsumer(surface);
+ }
+
+ /**
+ * Check if the surface is for hardware video encoder consumer.
+ *
+ * @param surface The surface to be checked.
+ * @return true if the surface is for hardware video encoder consumer, false otherwise.
+ */
+ public static boolean isSurfaceForHwVideoEncoder(Surface surface) {
+ return LegacyCameraDevice.isVideoEncoderConsumer(surface);
+ }
+
+ /**
+ * Get the Surface size.
+ *
+ * @param surface The surface to be queried for size.
+ * @return Size of the surface.
+ *
+ * @throws IllegalArgumentException if the surface is already abandoned.
+ */
+ public static Size getSurfaceSize(Surface surface) {
+ try {
+ return LegacyCameraDevice.getSurfaceSize(surface);
+ } catch (BufferQueueAbandonedException e) {
+ throw new IllegalArgumentException("Surface was abandoned", e);
+ }
+ }
+
+ /**
+ * Get the Surface format.
+ *
+ * @param surface The surface to be queried for format.
+ * @return format of the surface.
+ *
+ * @throws IllegalArgumentException if the surface is already abandoned.
+ */
+ public static int getSurfaceFormat(Surface surface) {
+ try {
+ return LegacyCameraDevice.detectSurfaceType(surface);
+ } catch (BufferQueueAbandonedException e) {
+ throw new IllegalArgumentException("Surface was abandoned", e);
+ }
+ }
+}
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index d9f9c1e..21ba7bd 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -192,17 +192,6 @@ public final class DisplayManagerGlobal {
return getCompatibleDisplay(displayId, DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
}
- /**
- * Gets information about a logical display without applying any compatibility metrics.
- *
- * @param displayId The logical display id.
- * @param configuration the configuration.
- * @return The display object, or null if there is no display with the given id.
- */
- public Display getRealDisplay(int displayId, Configuration configuration) {
- return getCompatibleDisplay(displayId, new DisplayAdjustments(configuration));
- }
-
public void registerDisplayListener(DisplayListener listener, Handler handler) {
if (listener == null) {
throw new IllegalArgumentException("listener must not be null");
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index caf21d5..e61813c 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -18,32 +18,30 @@ package android.hardware.fingerprint;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.ActivityManagerNative;
-import android.content.ContentResolver;
import android.content.Context;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.CancellationSignal.OnCancelListener;
import android.os.Handler;
import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.provider.Settings;
-import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
import android.security.keystore.AndroidKeyStoreProvider;
import android.util.Log;
import android.util.Slog;
import java.security.Signature;
-import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
import javax.crypto.Cipher;
import javax.crypto.Mac;
+import static android.Manifest.permission.USE_FINGERPRINT;
+import static android.Manifest.permission.MANAGE_FINGERPRINT;
+
/**
* A class that coordinates access to the fingerprint hardware.
* <p>
@@ -57,9 +55,10 @@ public class FingerprintManager {
private static final boolean DEBUG = true;
private static final int MSG_ENROLL_RESULT = 100;
private static final int MSG_ACQUIRED = 101;
- private static final int MSG_AUTHENTICATED = 102;
- private static final int MSG_ERROR = 103;
- private static final int MSG_REMOVED = 104;
+ private static final int MSG_AUTHENTICATION_SUCCEEDED = 102;
+ private static final int MSG_AUTHENTICATION_FAILED = 103;
+ private static final int MSG_ERROR = 104;
+ private static final int MSG_REMOVED = 105;
//
// Error messages from fingerprint hardware during initilization, enrollment, authentication or
@@ -112,6 +111,7 @@ public class FingerprintManager {
/**
* Hardware vendors may extend this list if there are conditions that do not fall under one of
* the above categories. Vendors are responsible for providing error strings for these errors.
+ * @hide
*/
public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000;
@@ -162,6 +162,7 @@ public class FingerprintManager {
/**
* Hardware vendors may extend this list if there are conditions that do not fall under one of
* the above categories. Vendors are responsible for providing error strings for these errors.
+ * @hide
*/
public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
@@ -173,6 +174,7 @@ public class FingerprintManager {
private RemovalCallback mRemovalCallback;
private CryptoObject mCryptoObject;
private Fingerprint mRemovalFingerprint;
+ private Handler mHandler;
private class OnEnrollCancelListener implements OnCancelListener {
@Override
@@ -198,72 +200,71 @@ public class FingerprintManager {
* A wrapper class for the crypto objects supported by FingerprintManager. Currently the
* framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects.
*/
- public static class CryptoObject {
+ public static final class CryptoObject {
public CryptoObject(@NonNull Signature signature) {
- mSignature = signature;
- mCipher = null;
- mMac = null;
+ mCrypto = signature;
}
public CryptoObject(@NonNull Cipher cipher) {
- mCipher = cipher;
- mSignature = null;
- mMac = null;
+ mCrypto = cipher;
}
public CryptoObject(@NonNull Mac mac) {
- mMac = mac;
- mCipher = null;
- mSignature = null;
+ mCrypto = mac;
}
/**
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
*/
- public Signature getSignature() { return mSignature; }
+ public Signature getSignature() {
+ return mCrypto instanceof Signature ? (Signature) mCrypto : null;
+ }
/**
* Get {@link Cipher} object.
* @return {@link Cipher} object or null if this doesn't contain one.
*/
- public Cipher getCipher() { return mCipher; }
+ public Cipher getCipher() {
+ return mCrypto instanceof Cipher ? (Cipher) mCrypto : null;
+ }
/**
* Get {@link Mac} object.
* @return {@link Mac} object or null if this doesn't contain one.
*/
- public Mac getMac() { return mMac; }
+ public Mac getMac() {
+ return mCrypto instanceof Mac ? (Mac) mCrypto : null;
+ }
/**
* @hide
* @return the opId associated with this object or 0 if none
*/
public long getOpId() {
- if (mSignature != null) {
- return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mSignature);
- } else if (mCipher != null) {
- return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCipher);
- } else if (mMac != null) {
- return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mMac);
- }
- return 0;
+ return mCrypto != null ?
+ AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0;
}
- private final Signature mSignature;
- private final Cipher mCipher;
- private final Mac mMac;
+ private final Object mCrypto;
};
/**
* Container for callback data from {@link FingerprintManager#authenticate(CryptoObject,
- * CancellationSignal, AuthenticationCallback, int)}.
+ * CancellationSignal, int, AuthenticationCallback, Handler)}.
*/
public static final class AuthenticationResult {
private Fingerprint mFingerprint;
private CryptoObject mCryptoObject;
+ /**
+ * Authentication result
+ *
+ * @param crypto the crypto object
+ * @param fingerprint the recognized fingerprint data, if allowed.
+ * @hide
+ */
public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) {
mCryptoObject = crypto;
mFingerprint = fingerprint;
@@ -272,7 +273,7 @@ public class FingerprintManager {
/**
* Obtain the crypto object associated with this transaction
* @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject,
- * CancellationSignal, AuthenticationCallback, int)}.
+ * CancellationSignal, int, AuthenticationCallback, Handler)}.
*/
public CryptoObject getCryptoObject() { return mCryptoObject; }
@@ -287,28 +288,28 @@ public class FingerprintManager {
/**
* Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject,
- * CancellationSignal, AuthenticationCallback, int)}. Users of {@link
+ * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link
* FingerprintManager#authenticate(CryptoObject, CancellationSignal,
- * AuthenticationCallback, int) } must provide an implementation of this for listening to
+ * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to
* fingerprint events.
*/
public static abstract class AuthenticationCallback {
/**
* Called when an unrecoverable error has been encountered and the operation is complete.
* No further callbacks will be made on this object.
- * @param errMsgId An integer identifying the error message
+ * @param errorCode An integer identifying the error message
* @param errString A human-readable error string that can be shown in UI
*/
- public void onAuthenticationError(int errMsgId, CharSequence errString) { }
+ public void onAuthenticationError(int errorCode, CharSequence errString) { }
/**
* Called when a recoverable error has been encountered during authentication. The help
* string is provided to give the user guidance for what went wrong, such as
* "Sensor dirty, please clean it."
- * @param helpMsgId An integer identifying the error message
+ * @param helpCode An integer identifying the error message
* @param helpString A human-readable string that can be shown in UI
*/
- public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { }
+ public void onAuthenticationHelp(int helpCode, CharSequence helpString) { }
/**
* Called when a fingerprint is recognized.
@@ -326,7 +327,7 @@ public class FingerprintManager {
* Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback,
* CancellationSignal, int). Users of {@link #FingerprintManager()}
* must provide an implementation of this to {@link FingerprintManager#enroll(long,
- * CancellationSignal, EnrollmentCallback, int) for listening to fingerprint events.
+ * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events.
*
* @hide
*/
@@ -392,31 +393,35 @@ public class FingerprintManager {
*
* @param crypto object associated with the call or null if none required.
* @param cancel an object that can be used to cancel authentication
- * @param callback an object to receive authentication events
* @param flags optional flags; should be 0
+ * @param callback an object to receive authentication events
+ * @param handler an optional handler to handle callback events
*/
+ @RequiresPermission(USE_FINGERPRINT)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- @NonNull AuthenticationCallback callback, int flags) {
- authenticate(crypto, cancel, callback, flags, UserHandle.myUserId());
+ int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) {
+ authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId());
}
/**
- * Request authentication of a crypto object. This call warms up the fingerprint hardware
- * and starts scanning for a fingerprint. It terminates when
- * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
- * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at
- * which point the object is no longer valid. The operation can be canceled by using the
- * provided cancel object.
- *
- * @param crypto object associated with the call or null if none required.
- * @param cancel an object that can be used to cancel authentication
- * @param callback an object to receive authentication events
- * @param flags optional flags; should be 0
- * @param userId the userId the fingerprint belongs to
+ * Use the provided handler thread for events.
+ * @param handler
+ */
+ private void useHandler(Handler handler) {
+ if (handler != null) {
+ mHandler = new MyHandler(handler.getLooper());
+ } else if (mHandler.getLooper() != mContext.getMainLooper()){
+ mHandler = new MyHandler(mContext.getMainLooper());
+ }
+ }
+
+ /**
+ * Per-user version
* @hide
*/
+ @RequiresPermission(USE_FINGERPRINT)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- @NonNull AuthenticationCallback callback, int flags, int userId) {
+ int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
@@ -431,6 +436,7 @@ public class FingerprintManager {
}
if (mService != null) try {
+ useHandler(handler);
mAuthenticationCallback = callback;
mCryptoObject = crypto;
long sessionId = crypto != null ? crypto.getOpId() : 0;
@@ -458,12 +464,13 @@ public class FingerprintManager {
* @param token a unique token provided by a recent creation or verification of device
* credentials (e.g. pin, pattern or password).
* @param cancel an object that can be used to cancel enrollment
- * @param callback an object to receive enrollment events
* @param flags optional flags
+ * @param callback an object to receive enrollment events
* @hide
*/
- public void enroll(byte [] token, CancellationSignal cancel, EnrollmentCallback callback,
- int flags) {
+ @RequiresPermission(MANAGE_FINGERPRINT)
+ public void enroll(byte [] token, CancellationSignal cancel, int flags,
+ EnrollmentCallback callback) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an enrollment callback");
}
@@ -496,6 +503,7 @@ public class FingerprintManager {
* existing device credentials (e.g. pin/pattern/password).
* @hide
*/
+ @RequiresPermission(MANAGE_FINGERPRINT)
public long preEnroll() {
long result = 0;
if (mService != null) try {
@@ -514,6 +522,7 @@ public class FingerprintManager {
*
* @hide
*/
+ @RequiresPermission(MANAGE_FINGERPRINT)
public void remove(Fingerprint fp, RemovalCallback callback) {
if (mService != null) try {
mRemovalCallback = callback;
@@ -535,6 +544,7 @@ public class FingerprintManager {
*
* @hide
*/
+ @RequiresPermission(MANAGE_FINGERPRINT)
public void rename(int fpId, String newName) {
// Renames the given fpId
if (mService != null) {
@@ -554,6 +564,7 @@ public class FingerprintManager {
*
* @hide
*/
+ @RequiresPermission(USE_FINGERPRINT)
public List<Fingerprint> getEnrolledFingerprints(int userId) {
if (mService != null) try {
return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName());
@@ -569,6 +580,7 @@ public class FingerprintManager {
*
* @hide
*/
+ @RequiresPermission(USE_FINGERPRINT)
public List<Fingerprint> getEnrolledFingerprints() {
return getEnrolledFingerprints(UserHandle.myUserId());
}
@@ -578,6 +590,7 @@ public class FingerprintManager {
*
* @return true if at least one fingerprint is enrolled, false otherwise
*/
+ @RequiresPermission(USE_FINGERPRINT)
public boolean hasEnrolledFingerprints() {
if (mService != null) try {
return mService.hasEnrolledFingerprints(UserHandle.myUserId(),
@@ -593,6 +606,7 @@ public class FingerprintManager {
*
* @return true if hardware is present and functional, false otherwise.
*/
+ @RequiresPermission(USE_FINGERPRINT)
public boolean isHardwareDetected() {
if (mService != null) {
try {
@@ -626,13 +640,15 @@ public class FingerprintManager {
return 0;
}
- private Handler mHandler;
-
private class MyHandler extends Handler {
private MyHandler(Context context) {
super(context.getMainLooper());
}
+ private MyHandler(Looper looper) {
+ super(looper);
+ }
+
public void handleMessage(android.os.Message msg) {
switch(msg.what) {
case MSG_ENROLL_RESULT:
@@ -641,8 +657,11 @@ public class FingerprintManager {
case MSG_ACQUIRED:
sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */);
break;
- case MSG_AUTHENTICATED:
- sendAuthenticatedResult((Fingerprint) msg.obj);
+ case MSG_AUTHENTICATION_SUCCEEDED:
+ sendAuthenticatedSucceeded((Fingerprint) msg.obj);
+ break;
+ case MSG_AUTHENTICATION_FAILED:
+ sendAuthenticatedFailed();
break;
case MSG_ERROR:
sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */);
@@ -684,15 +703,16 @@ public class FingerprintManager {
}
}
- private void sendAuthenticatedResult(Fingerprint fp) {
+ private void sendAuthenticatedSucceeded(Fingerprint fp) {
if (mAuthenticationCallback != null) {
- if (fp.getFingerId() == 0) {
- // Fingerprint template valid but doesn't match one in database
- mAuthenticationCallback.onAuthenticationFailed();
- } else {
- final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
- mAuthenticationCallback.onAuthenticationSucceeded(result);
- }
+ final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp);
+ mAuthenticationCallback.onAuthenticationSucceeded(result);
+ }
+ }
+
+ private void sendAuthenticatedFailed() {
+ if (mAuthenticationCallback != null) {
+ mAuthenticationCallback.onAuthenticationFailed();
}
}
@@ -809,24 +829,33 @@ public class FingerprintManager {
private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() {
+ @Override // binder call
public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0,
new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
}
+ @Override // binder call
public void onAcquired(long deviceId, int acquireInfo) {
mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget();
}
- public void onAuthenticated(long deviceId, int fingerId, int groupId) {
- mHandler.obtainMessage(MSG_AUTHENTICATED,
- new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget();
+ @Override // binder call
+ public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) {
+ mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget();
+ }
+
+ @Override // binder call
+ public void onAuthenticationFailed(long deviceId) {
+ mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();;
}
+ @Override // binder call
public void onError(long deviceId, int error) {
mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget();
}
+ @Override // binder call
public void onRemoved(long deviceId, int fingerId, int groupId) {
mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget();
}
diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
index a2d74b8..57a429f 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
@@ -15,6 +15,7 @@
*/
package android.hardware.fingerprint;
+import android.hardware.fingerprint.Fingerprint;
import android.os.Bundle;
import android.os.UserHandle;
@@ -25,7 +26,8 @@ import android.os.UserHandle;
oneway interface IFingerprintServiceReceiver {
void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);
void onAcquired(long deviceId, int acquiredInfo);
- void onAuthenticated(long deviceId, int fingerId, int groupId);
+ void onAuthenticationSucceeded(long deviceId, in Fingerprint fp);
+ void onAuthenticationFailed(long deviceId);
void onError(long deviceId, int error);
void onRemoved(long deviceId, int fingerId, int groupId);
}
diff --git a/core/java/android/inputmethodservice/ExtractEditText.java b/core/java/android/inputmethodservice/ExtractEditText.java
index 48b604c..f965f54 100644
--- a/core/java/android/inputmethodservice/ExtractEditText.java
+++ b/core/java/android/inputmethodservice/ExtractEditText.java
@@ -106,7 +106,7 @@ public class ExtractEditText extends EditText {
if (mIME != null && mIME.onExtractTextContextMenuItem(id)) {
// Mode was started on Extracted, needs to be stopped here.
// Cut and paste will change the text, which stops selection mode.
- if (id == android.R.id.copy) stopSelectionActionMode();
+ if (id == android.R.id.copy) stopTextActionMode();
return true;
}
return super.onTextContextMenuItem(id);
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 81a65f8..a7afa91 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1565,11 +1565,17 @@ public class InputMethodService extends AbstractInputMethodService {
if (DEBUG) Log.v(TAG, "clearInsetOfPreviousIme() "
+ " mShouldClearInsetOfPreviousIme=" + mShouldClearInsetOfPreviousIme);
if (!mShouldClearInsetOfPreviousIme || mWindow == null) return;
- // We do not call onWindowShown() and onWindowHidden() so as not to make the IME author
- // confused.
- // TODO: Find out a better way which has less side-effect.
- mWindow.show();
- mWindow.hide();
+ try {
+ // We do not call onWindowShown() and onWindowHidden() so as not to make the IME author
+ // confused.
+ // TODO: Find out a better way which has less side-effect.
+ mWindow.show();
+ mWindow.hide();
+ } catch (WindowManager.BadTokenException e) {
+ if (DEBUG) Log.v(TAG, "clearInsetOfPreviousIme: BadTokenException: IME is done.");
+ mWindowVisible = false;
+ mWindowAdded = false;
+ }
mShouldClearInsetOfPreviousIme = false;
}
diff --git a/core/java/android/net/Network.java b/core/java/android/net/Network.java
index 754c6b3..9628bae 100644
--- a/core/java/android/net/Network.java
+++ b/core/java/android/net/Network.java
@@ -19,6 +19,8 @@ package android.net;
import android.os.Parcelable;
import android.os.Parcel;
import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -64,7 +66,7 @@ public class Network implements Parcelable {
// maybeInitHttpClient() must be called prior to reading either variable.
private volatile ConnectionPool mConnectionPool = null;
private volatile com.android.okhttp.internal.Network mNetwork = null;
- private Object mLock = new Object();
+ private final Object mLock = new Object();
// Default connection pool values. These are evaluated at startup, just
// like the OkHttp code. Also like the OkHttp code, we will throw parse
@@ -300,14 +302,10 @@ public class Network implements Parcelable {
* connected.
*/
public void bindSocket(DatagramSocket socket) throws IOException {
- // Apparently, the kernel doesn't update a connected UDP socket's routing upon mark changes.
- if (socket.isConnected()) {
- throw new SocketException("Socket is connected");
- }
// Query a property of the underlying socket to ensure that the socket's file descriptor
// exists, is available to bind to a network and is not closed.
socket.getReuseAddress();
- bindSocketFd(socket.getFileDescriptor$());
+ bindSocket(socket.getFileDescriptor$());
}
/**
@@ -316,18 +314,38 @@ public class Network implements Parcelable {
* {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected.
*/
public void bindSocket(Socket socket) throws IOException {
- // Apparently, the kernel doesn't update a connected TCP socket's routing upon mark changes.
- if (socket.isConnected()) {
- throw new SocketException("Socket is connected");
- }
// Query a property of the underlying socket to ensure that the socket's file descriptor
// exists, is available to bind to a network and is not closed.
socket.getReuseAddress();
- bindSocketFd(socket.getFileDescriptor$());
+ bindSocket(socket.getFileDescriptor$());
}
- private void bindSocketFd(FileDescriptor fd) throws IOException {
- int err = NetworkUtils.bindSocketToNetwork(fd.getInt$(), netId);
+ /**
+ * Binds the specified {@link FileDescriptor} to this {@code Network}. All data traffic on the
+ * socket represented by this file descriptor will be sent on this {@code Network},
+ * irrespective of any process-wide network binding set by
+ * {@link ConnectivityManager#bindProcessToNetwork}. The socket must not be connected.
+ */
+ public void bindSocket(FileDescriptor fd) throws IOException {
+ try {
+ final SocketAddress peer = Os.getpeername(fd);
+ final InetAddress inetPeer = ((InetSocketAddress) peer).getAddress();
+ if (!inetPeer.isAnyLocalAddress()) {
+ // Apparently, the kernel doesn't update a connected UDP socket's
+ // routing upon mark changes.
+ throw new SocketException("Socket is connected");
+ }
+ } catch (ErrnoException e) {
+ // getpeername() failed.
+ if (e.errno != OsConstants.ENOTCONN) {
+ throw e.rethrowAsSocketException();
+ }
+ } catch (ClassCastException e) {
+ // Wasn't an InetSocketAddress.
+ throw new SocketException("Only AF_INET/AF_INET6 sockets supported");
+ }
+
+ final int err = NetworkUtils.bindSocketToNetwork(fd.getInt$(), netId);
if (err != 0) {
// bindSocketToNetwork returns negative errno.
throw new ErrnoException("Binding socket to network " + netId, -err)
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 3d065e3..7678678 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -92,11 +92,6 @@ public final class ApduServiceInfo implements Parcelable {
final int mUid;
/**
- * Whether this service has dynamic resources
- */
- final boolean mHasDynamicResources;
-
- /**
* Settings Activity for this service
*/
final String mSettingsActivityName;
@@ -106,7 +101,7 @@ public final class ApduServiceInfo implements Parcelable {
*/
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
- boolean requiresUnlock, int bannerResource, int uid, boolean hasDynamicResources,
+ boolean requiresUnlock, int bannerResource, int uid,
String settingsActivityName) {
this.mService = info;
this.mDescription = description;
@@ -122,7 +117,6 @@ public final class ApduServiceInfo implements Parcelable {
}
this.mBannerResourceId = bannerResource;
this.mUid = uid;
- this.mHasDynamicResources = hasDynamicResources;
this.mSettingsActivityName = settingsActivityName;
}
@@ -172,8 +166,6 @@ public final class ApduServiceInfo implements Parcelable {
false);
mBannerResourceId = sa.getResourceId(
com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1);
- mHasDynamicResources = sa.getBoolean(
- com.android.internal.R.styleable.HostApduService_dynamicResources, false);
mSettingsActivityName = sa.getString(
com.android.internal.R.styleable.HostApduService_settingsActivity);
sa.recycle();
@@ -186,8 +178,6 @@ public final class ApduServiceInfo implements Parcelable {
mRequiresDeviceUnlock = false;
mBannerResourceId = sa.getResourceId(
com.android.internal.R.styleable.OffHostApduService_apduServiceBanner, -1);
- mHasDynamicResources = sa.getBoolean(
- com.android.internal.R.styleable.OffHostApduService_dynamicResources, false);
mSettingsActivityName = sa.getString(
com.android.internal.R.styleable.HostApduService_settingsActivity);
sa.recycle();
@@ -410,9 +400,6 @@ public final class ApduServiceInfo implements Parcelable {
return null;
}
}
- public boolean hasDynamicResources() {
- return mHasDynamicResources;
- }
public String getSettingsActivityName() { return mSettingsActivityName; }
@@ -468,7 +455,6 @@ public final class ApduServiceInfo implements Parcelable {
dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
dest.writeInt(mBannerResourceId);
dest.writeInt(mUid);
- dest.writeInt(mHasDynamicResources ? 1 : 0);
dest.writeString(mSettingsActivityName);
};
@@ -492,10 +478,9 @@ public final class ApduServiceInfo implements Parcelable {
boolean requiresUnlock = source.readInt() != 0;
int bannerResource = source.readInt();
int uid = source.readInt();
- boolean dynamicResources = source.readInt() != 0;
String settingsActivityName = source.readString();
return new ApduServiceInfo(info, onHost, description, staticAidGroups,
- dynamicAidGroups, requiresUnlock, bannerResource, uid, dynamicResources,
+ dynamicAidGroups, requiresUnlock, bannerResource, uid,
settingsActivityName);
}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index b94d4a6..64c2bc2 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -90,37 +90,6 @@ public final class CardEmulation {
public static final String CATEGORY_OTHER = "other";
/**
- * Ordered broadcast that can be sent to your app to
- * request a description and banner to be shown in
- * Android Settings UI.
- * When sent to you, this broadcast will contain the
- * {@link #EXTRA_SERVICE_COMPONENT} extra to identify
- * the service.
- *
- * Note that this broadcast will only be sent to your
- * app, if a card emulation service in your app has requested
- * its resources to be loaded dynamically.
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_REQUEST_SERVICE_RESOURCES =
- "android.nfc.cardemulation.action.REQUEST_SERVICE_RESOURCES";
-
- /**
- * The description of the service. Note that this must
- * be localized by your app, as the String will be shown
- * as is.
- */
- public static final String EXTRA_DESCRIPTION =
- "android.nfc.cardemulation.extra.DESCRIPTION";
-
- /**
- * The resource ID of the service banner to be shown
- * for this service.
- */
- public static final String EXTRA_BANNER_RES_ID =
- "android.nfc.cardemulation.extra.BANNER_RES_ID";
-
- /**
* Return value for {@link #getSelectionModeForCategory(String)}.
*
* <p>In this mode, the user has set a default service for this
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 0a45b8b..c9609e5 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1940,6 +1940,15 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getFlashlightOnCount(int which);
+ /**
+ * Returns the time in microseconds that the camera has been on while the device was
+ * running on battery.
+ *
+ * {@hide}
+ */
+ public abstract long getCameraOnTime(long elapsedRealtimeUs, int which);
+
+
public static final int NETWORK_MOBILE_RX_DATA = 0;
public static final int NETWORK_MOBILE_TX_DATA = 1;
public static final int NETWORK_WIFI_RX_DATA = 2;
@@ -2735,6 +2744,9 @@ public abstract class BatteryStats implements Parcelable {
case OVERCOUNTED:
label = "over";
break;
+ case CAMERA:
+ label = "camera";
+ break;
default:
label = "???";
}
@@ -3523,6 +3535,10 @@ public abstract class BatteryStats implements Parcelable {
pw.print(prefix); pw.print(" Over-counted: "); printmAh(pw, bs.totalPowerMah);
pw.println();
break;
+ case CAMERA:
+ pw.print(prefix); pw.print(" Camera: "); printmAh(pw, bs.totalPowerMah);
+ pw.println();
+ break;
}
}
pw.println();
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index 19c8fa9..87e8c5e 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -34,6 +34,7 @@ import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.HashMap;
import java.util.Map;
import org.apache.harmony.dalvik.ddmc.Chunk;
@@ -389,6 +390,132 @@ public final class Debug
}
}
+ /**
+ * Returns the value of a particular memory statistic or {@code null} if no
+ * such memory statistic exists.
+ *
+ * <p>The following table lists the memory statistics that are supported.
+ * Note that memory statistics may be added or removed in a future API level.</p>
+ *
+ * <table>
+ * <thead>
+ * <tr>
+ * <th>Memory statistic name</th>
+ * <th>Meaning</th>
+ * <th>Example</th>
+ * <th>Supported (API Levels)</th>
+ * </tr>
+ * </thead>
+ * <tbody>
+ * <tr>
+ * <td>summary.java-heap</td>
+ * <td>The private Java Heap usage in kB. This corresponds to the Java Heap field
+ * in the App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.native-heap</td>
+ * <td>The private Native Heap usage in kB. This corresponds to the Native Heap
+ * field in the App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.code</td>
+ * <td>The memory usage for static code and resources in kB. This corresponds to
+ * the Code field in the App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.stack</td>
+ * <td>The stack usage in kB. This corresponds to the Stack field in the
+ * App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.graphics</td>
+ * <td>The graphics usage in kB. This corresponds to the Graphics field in the
+ * App Summary section output by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.private-other</td>
+ * <td>Other private memory usage in kB. This corresponds to the Private Other
+ * field output in the App Summary section by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.system</td>
+ * <td>Shared and system memory usage in kB. This corresponds to the System
+ * field output in the App Summary section by dumpsys meminfo.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.total-pss</td>
+ * <td>Total PPS memory usage in kB.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * <tr>
+ * <td>summary.total-swap</td>
+ * <td>Total swap usage in kB.</td>
+ * <td>{@code 1442}</td>
+ * <td>23</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ */
+ public String getMemoryStat(String statName) {
+ switch(statName) {
+ case "summary.java-heap":
+ return Integer.toString(getSummaryJavaHeap());
+ case "summary.native-heap":
+ return Integer.toString(getSummaryNativeHeap());
+ case "summary.code":
+ return Integer.toString(getSummaryCode());
+ case "summary.stack":
+ return Integer.toString(getSummaryStack());
+ case "summary.graphics":
+ return Integer.toString(getSummaryGraphics());
+ case "summary.private-other":
+ return Integer.toString(getSummaryPrivateOther());
+ case "summary.system":
+ return Integer.toString(getSummarySystem());
+ case "summary.total-pss":
+ return Integer.toString(getSummaryTotalPss());
+ case "summary.total-swap":
+ return Integer.toString(getSummaryTotalSwap());
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns a map of the names/values of the memory statistics
+ * that {@link #getMemoryStat(String)} supports.
+ *
+ * @return a map of the names/values of the supported memory statistics.
+ */
+ public Map<String, String> getMemoryStats() {
+ Map<String, String> stats = new HashMap<String, String>();
+ stats.put("summary.java-heap", Integer.toString(getSummaryJavaHeap()));
+ stats.put("summary.native-heap", Integer.toString(getSummaryNativeHeap()));
+ stats.put("summary.code", Integer.toString(getSummaryCode()));
+ stats.put("summary.stack", Integer.toString(getSummaryStack()));
+ stats.put("summary.graphics", Integer.toString(getSummaryGraphics()));
+ stats.put("summary.private-other", Integer.toString(getSummaryPrivateOther()));
+ stats.put("summary.system", Integer.toString(getSummarySystem()));
+ stats.put("summary.total-pss", Integer.toString(getSummaryTotalPss()));
+ stats.put("summary.total-swap", Integer.toString(getSummaryTotalSwap()));
+ return stats;
+ }
+
/**
* Pss of Java Heap bytes in KB due to the application.
* Notes:
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 009649f..dbb5146 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -21,6 +21,7 @@ import android.net.LocalSocketAddress;
import android.system.Os;
import android.util.Log;
import com.android.internal.os.Zygote;
+import dalvik.system.VMRuntime;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.IOException;
@@ -744,7 +745,14 @@ public class Process {
* @return Returns the number of milliseconds this process has return.
*/
public static final native long getElapsedCpuTime();
-
+
+ /**
+ * Returns true if the current process is a 64-bit runtime.
+ */
+ public static final boolean is64Bit() {
+ return VMRuntime.getRuntime().is64Bit();
+ }
+
/**
* Returns the identifier of this process, which can be used with
* {@link #killProcess} and {@link #sendSignal}.
diff --git a/core/java/android/provider/AlarmClock.java b/core/java/android/provider/AlarmClock.java
index be37293..63ae9a9 100644
--- a/core/java/android/provider/AlarmClock.java
+++ b/core/java/android/provider/AlarmClock.java
@@ -86,7 +86,7 @@ public final class AlarmClock {
* If the extra {@link #EXTRA_ALARM_SEARCH_MODE} is used, and the search results contain two or
* more matching alarms, then the implementation should show an UI with the results and allow
* the user to select the alarm to dismiss. If the implementation supports
- * {@link android.content.Intent.CATEGORY_VOICE} and the activity is started in Voice
+ * {@link android.content.Intent#CATEGORY_VOICE} and the activity is started in Voice
* Interaction mode (i.e. check {@link android.app.Activity#isVoiceInteraction}), then the
* implementation should additionally use {@link android.app.VoiceInteractor.PickOptionRequest}
* to start a voice interaction follow-on flow to help the user disambiguate the alarm by voice.
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index df2e5f9..d9c412b 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -4079,9 +4079,8 @@ public final class ContactsContract {
public static final String CARRIER_PRESENCE = "carrier_presence";
/**
- * Bitmask flags for CARRIER_PRESENCE column. Each value represents
- * a bit (or a set of bits) which may be set independently of each
- * other.
+ * Indicates that the entry is Video Telephony (VT) capable on the
+ * current carrier. An allowed bitmask of {@link #CARRIER_PRESENCE}.
*/
public static final int CARRIER_PRESENCE_VT_CAPABLE = 0x01;
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 37645b5..cac4a53 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -811,14 +811,17 @@ public final class Settings {
/**
* Activity Action: Show Do Not Disturb access settings.
* <p>
- * In some cases, a matching Activity may not exist, so ensure you safeguard against this.
+ * Users can grant and deny access to Do Not Disturb configuration from here.
+ * See {@link android.app.NotificationManager#isNotificationPolicyAccessGranted()} for more
+ * details.
* <p>
* Input: Nothing.
* <p>
* Output: Nothing.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_ZEN_ACCESS_SETTINGS = "android.settings.ZEN_ACCESS_SETTINGS";
+ public static final String ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS
+ = "android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS";
/**
* @hide
@@ -5425,7 +5428,7 @@ public final class Settings {
public static final String ASSIST_STRUCTURE_ENABLED = "assist_structure_enabled";
/**
- * Names of the packages that the current user has explicitly allowed to
+ * Names of the service components that the current user has explicitly allowed to
* see all of the user's notifications, separated by ':'.
*
* @hide
@@ -5433,6 +5436,15 @@ public final class Settings {
public static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
/**
+ * Names of the packages that the current user has explicitly allowed to
+ * manage notification policy configuration, separated by ':'.
+ *
+ * @hide
+ */
+ public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES =
+ "enabled_notification_policy_access_packages";
+
+ /**
* @hide
*/
public static final String ENABLED_CONDITION_PROVIDERS = "enabled_condition_providers";
diff --git a/core/java/android/service/carrier/CarrierService.java b/core/java/android/service/carrier/CarrierService.java
index 4a4a375..5f83452 100644
--- a/core/java/android/service/carrier/CarrierService.java
+++ b/core/java/android/service/carrier/CarrierService.java
@@ -59,16 +59,16 @@ public abstract class CarrierService extends Service {
* <ol>
* <li>The carrier app package is updated, or</li>
* <li>The carrier app requests a reload with
- * {@link android.telephony.CarrierConfigManager#reloadCarrierConfigForSubId
- * reloadCarrierConfigForSubId}.</li>
+ * {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
+ * notifyConfigChangedForSubId}.</li>
* </ol>
* This method can be called after a SIM card loads, which may be before or after boot.
* </p>
* <p>
* This method should not block for a long time. If expensive operations (e.g. network access)
* are required, this method can schedule the work and return null. Then, use
- * {@link android.telephony.CarrierConfigManager#reloadCarrierConfigForSubId
- * reloadCarrierConfigForSubId} to trigger a reload when the config is ready.
+ * {@link android.telephony.CarrierConfigManager#notifyConfigChangedForSubId
+ * notifyConfigChangedForSubId} to trigger a reload when the config is ready.
* </p>
* <p>
* Implementations should use the keys defined in {@link android.telephony.CarrierConfigManager
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 33fef62..d5ee7e7 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -16,6 +16,7 @@
package android.service.voice;
+import android.annotation.Nullable;
import android.app.Dialog;
import android.app.Instrumentation;
import android.app.VoiceInteractor;
@@ -122,7 +123,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
final IVoiceInteractor mInteractor = new IVoiceInteractor.Stub() {
@Override
public IVoiceInteractorRequest startConfirmation(String callingPackage,
- IVoiceInteractorCallback callback, CharSequence prompt, Bundle extras) {
+ IVoiceInteractorCallback callback, VoiceInteractor.Prompt prompt, Bundle extras) {
ConfirmationRequest request = new ConfirmationRequest(callingPackage,
Binder.getCallingUid(), callback, VoiceInteractionSession.this,
prompt, extras);
@@ -134,7 +135,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
@Override
public IVoiceInteractorRequest startPickOption(String callingPackage,
- IVoiceInteractorCallback callback, CharSequence prompt,
+ IVoiceInteractorCallback callback, VoiceInteractor.Prompt prompt,
VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras) {
PickOptionRequest request = new PickOptionRequest(callingPackage,
Binder.getCallingUid(), callback, VoiceInteractionSession.this,
@@ -147,7 +148,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
@Override
public IVoiceInteractorRequest startCompleteVoice(String callingPackage,
- IVoiceInteractorCallback callback, CharSequence message, Bundle extras) {
+ IVoiceInteractorCallback callback, VoiceInteractor.Prompt message, Bundle extras) {
CompleteVoiceRequest request = new CompleteVoiceRequest(callingPackage,
Binder.getCallingUid(), callback, VoiceInteractionSession.this,
message, extras);
@@ -159,7 +160,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
@Override
public IVoiceInteractorRequest startAbortVoice(String callingPackage,
- IVoiceInteractorCallback callback, CharSequence message, Bundle extras) {
+ IVoiceInteractorCallback callback, VoiceInteractor.Prompt message, Bundle extras) {
AbortVoiceRequest request = new AbortVoiceRequest(callingPackage,
Binder.getCallingUid(), callback, VoiceInteractionSession.this,
message, extras);
@@ -404,10 +405,10 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* VoiceInteractor.ConfirmationRequest}.
*/
public static final class ConfirmationRequest extends Request {
- final CharSequence mPrompt;
+ final VoiceInteractor.Prompt mPrompt;
ConfirmationRequest(String packageName, int uid, IVoiceInteractorCallback callback,
- VoiceInteractionSession session, CharSequence prompt, Bundle extras) {
+ VoiceInteractionSession session, VoiceInteractor.Prompt prompt, Bundle extras) {
super(packageName, uid, callback, session, extras);
mPrompt = prompt;
}
@@ -417,11 +418,23 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* {@link android.app.VoiceInteractor.ConfirmationRequest
* VoiceInteractor.ConfirmationRequest}.
*/
- public CharSequence getPrompt() {
+ @Nullable
+ public VoiceInteractor.Prompt getVoicePrompt() {
return mPrompt;
}
/**
+ * Return the prompt informing the user of what will happen, as per
+ * {@link android.app.VoiceInteractor.ConfirmationRequest
+ * VoiceInteractor.ConfirmationRequest}.
+ * @deprecated Prefer {@link #getVoicePrompt()} which allows multiple voice prompts.
+ */
+ @Nullable
+ public CharSequence getPrompt() {
+ return (mPrompt != null ? mPrompt.getVoicePromptAt(0) : null);
+ }
+
+ /**
* Report that the voice interactor has confirmed the operation with the user, resulting
* in a call to
* {@link android.app.VoiceInteractor.ConfirmationRequest#onConfirmationResult
@@ -437,11 +450,11 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
*/
public static final class PickOptionRequest extends Request {
- final CharSequence mPrompt;
+ final VoiceInteractor.Prompt mPrompt;
final VoiceInteractor.PickOptionRequest.Option[] mOptions;
PickOptionRequest(String packageName, int uid, IVoiceInteractorCallback callback,
- VoiceInteractionSession session, CharSequence prompt,
+ VoiceInteractionSession session, VoiceInteractor.Prompt prompt,
VoiceInteractor.PickOptionRequest.Option[] options, Bundle extras) {
super(packageName, uid, callback, session, extras);
mPrompt = prompt;
@@ -452,11 +465,22 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* Return the prompt informing the user of what they are picking, as per
* {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
*/
- public CharSequence getPrompt() {
+ @Nullable
+ public VoiceInteractor.Prompt getVoicePrompt() {
return mPrompt;
}
/**
+ * Return the prompt informing the user of what they are picking, as per
+ * {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
+ * @deprecated Prefer {@link #getVoicePrompt()} which allows multiple voice prompts.
+ */
+ @Nullable
+ public CharSequence getPrompt() {
+ return (mPrompt != null ? mPrompt.getVoicePromptAt(0) : null);
+ }
+
+ /**
* Return the set of options the user is picking from, as per
* {@link android.app.VoiceInteractor.PickOptionRequest VoiceInteractor.PickOptionRequest}.
*/
@@ -494,12 +518,12 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* VoiceInteractor.CompleteVoiceRequest}.
*/
public static final class CompleteVoiceRequest extends Request {
- final CharSequence mMessage;
+ final VoiceInteractor.Prompt mPrompt;
CompleteVoiceRequest(String packageName, int uid, IVoiceInteractorCallback callback,
- VoiceInteractionSession session, CharSequence message, Bundle extras) {
+ VoiceInteractionSession session, VoiceInteractor.Prompt prompt, Bundle extras) {
super(packageName, uid, callback, session, extras);
- mMessage = message;
+ mPrompt = prompt;
}
/**
@@ -507,8 +531,20 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* {@link android.app.VoiceInteractor.CompleteVoiceRequest
* VoiceInteractor.CompleteVoiceRequest}.
*/
+ @Nullable
+ public VoiceInteractor.Prompt getVoicePrompt() {
+ return mPrompt;
+ }
+
+ /**
+ * Return the message informing the user of the completion, as per
+ * {@link android.app.VoiceInteractor.CompleteVoiceRequest
+ * VoiceInteractor.CompleteVoiceRequest}.
+ * @deprecated Prefer {@link #getVoicePrompt()} which allows a separate visual message.
+ */
+ @Nullable
public CharSequence getMessage() {
- return mMessage;
+ return (mPrompt != null ? mPrompt.getVoicePromptAt(0) : null);
}
/**
@@ -527,20 +563,31 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* {@link android.app.VoiceInteractor.AbortVoiceRequest VoiceInteractor.AbortVoiceRequest}.
*/
public static final class AbortVoiceRequest extends Request {
- final CharSequence mMessage;
+ final VoiceInteractor.Prompt mPrompt;
AbortVoiceRequest(String packageName, int uid, IVoiceInteractorCallback callback,
- VoiceInteractionSession session, CharSequence message, Bundle extras) {
+ VoiceInteractionSession session, VoiceInteractor.Prompt prompt, Bundle extras) {
super(packageName, uid, callback, session, extras);
- mMessage = message;
+ mPrompt = prompt;
}
/**
* Return the message informing the user of the problem, as per
* {@link android.app.VoiceInteractor.AbortVoiceRequest VoiceInteractor.AbortVoiceRequest}.
*/
+ @Nullable
+ public VoiceInteractor.Prompt getVoicePrompt() {
+ return mPrompt;
+ }
+
+ /**
+ * Return the message informing the user of the problem, as per
+ * {@link android.app.VoiceInteractor.AbortVoiceRequest VoiceInteractor.AbortVoiceRequest}.
+ * @deprecated Prefer {@link #getVoicePrompt()} which allows a separate visual message.
+ */
+ @Nullable
public CharSequence getMessage() {
- return mMessage;
+ return (mPrompt != null ? mPrompt.getVoicePromptAt(0) : null);
}
/**
@@ -1035,7 +1082,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
public void onCreate(Bundle args) {
doOnCreate();
}
-
+
/** @hide */
public void onCreate(Bundle args, int showFlags) {
doOnCreate();
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 1b25505..c61ca4e 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -19,6 +19,7 @@ package android.transition;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TimeInterpolator;
+import android.annotation.Nullable;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Path;
@@ -700,7 +701,7 @@ public abstract class Transition implements Cloneable {
continue;
}
// Only bother trying to animate with values that differ between start/end
- boolean isChanged = start == null || end == null || areValuesChanged(start, end);
+ boolean isChanged = start == null || end == null || isTransitionRequired(start, end);
if (isChanged) {
if (DBG) {
View view = (end != null) ? end.view : start.view;
@@ -1747,7 +1748,7 @@ public abstract class Transition implements Cloneable {
endValues = mEndValues.viewValues.get(oldView);
}
boolean cancel = (startValues != null || endValues != null) &&
- oldInfo.transition.areValuesChanged(oldValues, endValues);
+ oldInfo.transition.isTransitionRequired(oldValues, endValues);
if (cancel) {
if (anim.isRunning() || anim.isStarted()) {
if (DBG) {
@@ -1770,32 +1771,36 @@ public abstract class Transition implements Cloneable {
}
/**
- * Returns whether transition values have changed between the start scene and the end scene
- * (thus determining whether animation is required). The default implementation compares the
+ * Returns whether or not the transition should create an Animator, based on the values
+ * captured during {@link #captureStartValues(TransitionValues)} and
+ * {@link #captureEndValues(TransitionValues)}. The default implementation compares the
* property values returned from {@link #getTransitionProperties()}, or all property values if
* {@code getTransitionProperties()} returns null. Subclasses may override this method to
- * provide logic more specific to their transition implementation.
+ * provide logic more specific to the transition implementation.
*
- * @param oldValues the first set of values, may be {@code null}
- * @param newValues the second set of values, may be {@code null}
+ * @param startValues the values from captureStartValues, This may be {@code null} if the
+ * View did not exist in the start state.
+ * @param endValues the values from captureEndValues. This may be {@code null} if the View
+ * did not exist in the end state.
*/
- protected boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
+ public boolean isTransitionRequired(@Nullable TransitionValues startValues,
+ @Nullable TransitionValues endValues) {
boolean valuesChanged = false;
- // if oldValues null, then transition didn't care to stash values,
+ // if startValues null, then transition didn't care to stash values,
// and won't get canceled
- if (oldValues != null && newValues != null) {
+ if (startValues != null && endValues != null) {
String[] properties = getTransitionProperties();
if (properties != null) {
int count = properties.length;
for (int i = 0; i < count; i++) {
- if (isValueChanged(oldValues, newValues, properties[i])) {
+ if (isValueChanged(startValues, endValues, properties[i])) {
valuesChanged = true;
break;
}
}
} else {
- for (String key : oldValues.values.keySet()) {
- if (isValueChanged(oldValues, newValues, key)) {
+ for (String key : startValues.values.keySet()) {
+ if (isValueChanged(startValues, endValues, key)) {
valuesChanged = true;
break;
}
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index ed7fd86..bac668a 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -445,7 +445,7 @@ public abstract class Visibility extends Transition {
mForcedEndVisibility != -1;
if (!isForcedVisibility) {
originalVisibility = viewToKeep.getVisibility();
- viewToKeep.setVisibility(View.VISIBLE);
+ viewToKeep.setTransitionVisibility(View.VISIBLE);
}
Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
if (animator != null) {
@@ -454,7 +454,7 @@ public abstract class Visibility extends Transition {
animator.addListener(disappearListener);
addListener(disappearListener);
} else if (!isForcedVisibility) {
- viewToKeep.setVisibility(originalVisibility);
+ viewToKeep.setTransitionVisibility(originalVisibility);
}
return animator;
}
@@ -462,18 +462,18 @@ public abstract class Visibility extends Transition {
}
@Override
- protected boolean areValuesChanged(TransitionValues oldValues, TransitionValues newValues) {
- if (oldValues == null && newValues == null) {
+ public boolean isTransitionRequired(TransitionValues startValues, TransitionValues newValues) {
+ if (startValues == null && newValues == null) {
return false;
}
- if (oldValues != null && newValues != null &&
+ if (startValues != null && newValues != null &&
newValues.values.containsKey(PROPNAME_VISIBILITY) !=
- oldValues.values.containsKey(PROPNAME_VISIBILITY)) {
+ startValues.values.containsKey(PROPNAME_VISIBILITY)) {
// The transition wasn't targeted in either the start or end, so it couldn't
// have changed.
return false;
}
- VisibilityInfo changeInfo = getVisibilityChangeInfo(oldValues, newValues);
+ VisibilityInfo changeInfo = getVisibilityChangeInfo(startValues, newValues);
return changeInfo.visibilityChange && (changeInfo.startVisibility == View.VISIBLE ||
changeInfo.endVisibility == View.VISIBLE);
}
@@ -516,14 +516,14 @@ public abstract class Visibility extends Transition {
@Override
public void onAnimationPause(Animator animation) {
if (!mCanceled && !mIsForcedVisibility) {
- mView.setVisibility(mFinalVisibility);
+ mView.setTransitionVisibility(mFinalVisibility);
}
}
@Override
public void onAnimationResume(Animator animation) {
if (!mCanceled && !mIsForcedVisibility) {
- mView.setVisibility(View.VISIBLE);
+ mView.setTransitionVisibility(View.VISIBLE);
}
}
@@ -557,7 +557,7 @@ public abstract class Visibility extends Transition {
if (mIsForcedVisibility) {
mView.setTransitionAlpha(0);
} else {
- mView.setVisibility(mFinalVisibility);
+ mView.setTransitionVisibility(mFinalVisibility);
}
}
}
diff --git a/core/java/android/util/LayoutDirection.java b/core/java/android/util/LayoutDirection.java
index 20af20b..03077e4 100644
--- a/core/java/android/util/LayoutDirection.java
+++ b/core/java/android/util/LayoutDirection.java
@@ -27,6 +27,12 @@ public final class LayoutDirection {
private LayoutDirection() {}
/**
+ * An undefined layout direction.
+ * @hide
+ */
+ public static final int UNDEFINED = -1;
+
+ /**
* Horizontal layout direction is from Left to Right.
*/
public static final int LTR = 0;
diff --git a/core/java/android/view/ActionMode.java b/core/java/android/view/ActionMode.java
index 4b9b590..80dcecc 100644
--- a/core/java/android/view/ActionMode.java
+++ b/core/java/android/view/ActionMode.java
@@ -45,10 +45,10 @@ public abstract class ActionMode {
public static final int TYPE_FLOATING = 1;
/**
- * Default snooze time.
+ * Default value to hide the action mode for
+ * {@link ViewConfiguration#getDefaultActionModeHideDuration()}.
*/
- public static final int SNOOZE_TIME_DEFAULT =
- ViewConfiguration.getDefaultActionModeSnoozeTime();
+ public static final int DEFAULT_HIDE_DURATION = -1;
private Object mTag;
private boolean mTitleOptionalHint;
@@ -213,17 +213,17 @@ public abstract class ActionMode {
public void invalidateContentRect() {}
/**
- * Hide the action mode view from obstructing the content below for a short period.
+ * Hide the action mode view from obstructing the content below for a short duration.
* This only makes sense for action modes that support dynamic positioning on the screen.
- * If this method is called again before the snooze time expires, the later snooze will
+ * If this method is called again before the hide duration expires, the later hide call will
* cancel the former and then take effect.
- * NOTE that there is an internal limit to how long the mode can be snoozed for. It's typically
+ * NOTE that there is an internal limit to how long the mode can be hidden for. It's typically
* about a few seconds.
*
- * @param snoozeTime The number of milliseconds to snooze for.
- * @see #SNOOZE_TIME_DEFAULT
+ * @param duration The number of milliseconds to hide for.
+ * @see #DEFAULT_HIDE_DURATION
*/
- public void snooze(int snoozeTime) {}
+ public void hide(long duration) {}
/**
* Finish and close this action mode. The action mode's {@link ActionMode.Callback} will
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 5a587fe..35c4192 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -89,6 +89,11 @@ public final class Display {
public static final int DEFAULT_DISPLAY = 0;
/**
+ * Invalid display id.
+ */
+ public static final int INVALID_DISPLAY = -1;
+
+ /**
* Display flag: Indicates that the display supports compositing content
* that is stored in protected graphics buffers.
* <p>
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index ff0af6b..b705cf1 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -32,7 +32,7 @@ import android.os.Message;
* <li>In the {@link View#onTouchEvent(MotionEvent)} method ensure you call
* {@link #onTouchEvent(MotionEvent)}. The methods defined in your callback
* will be executed when the events occur.
- * <li>If listening for {@link OnStylusButtonPressListener#onStylusButtonPress(MotionEvent)}
+ * <li>If listening for {@link OnContextClickListener#onContextClick(MotionEvent)}
* you must call {@link #onGenericMotionEvent(MotionEvent)}
* in {@link View#onGenericMotionEvent(MotionEvent)}.
* </ul>
@@ -152,31 +152,28 @@ public class GestureDetector {
}
/**
- * The listener that is used to notify when a stylus button press occurs. When listening for a
- * stylus button press ensure that you call {@link #onGenericMotionEvent(MotionEvent)} in
+ * The listener that is used to notify when a context click occurs. When listening for a
+ * context click ensure that you call {@link #onGenericMotionEvent(MotionEvent)} in
* {@link View#onGenericMotionEvent(MotionEvent)}.
*/
- public interface OnStylusButtonPressListener {
+ public interface OnContextClickListener {
/**
- * Notified when a stylus button press occurs. This is when the stylus
- * is touching the screen and the {@value MotionEvent#BUTTON_STYLUS_PRIMARY}
- * is pressed.
+ * Notified when a context click occurs.
*
- * @param e The motion event that occurred during the stylus button
- * press.
+ * @param e The motion event that occurred during the context click.
* @return true if the event is consumed, else false
*/
- boolean onStylusButtonPress(MotionEvent e);
+ boolean onContextClick(MotionEvent e);
}
/**
* A convenience class to extend when you only want to listen for a subset
* of all the gestures. This implements all methods in the
- * {@link OnGestureListener}, {@link OnDoubleTapListener}, and {@link OnStylusButtonPressListener}
+ * {@link OnGestureListener}, {@link OnDoubleTapListener}, and {@link OnContextClickListener}
* but does nothing and return {@code false} for all applicable methods.
*/
public static class SimpleOnGestureListener implements OnGestureListener, OnDoubleTapListener,
- OnStylusButtonPressListener {
+ OnContextClickListener {
public boolean onSingleTapUp(MotionEvent e) {
return false;
@@ -214,7 +211,7 @@ public class GestureDetector {
return false;
}
- public boolean onStylusButtonPress(MotionEvent e) {
+ public boolean onContextClick(MotionEvent e) {
return false;
}
}
@@ -238,12 +235,12 @@ public class GestureDetector {
private final Handler mHandler;
private final OnGestureListener mListener;
private OnDoubleTapListener mDoubleTapListener;
- private OnStylusButtonPressListener mStylusButtonListener;
+ private OnContextClickListener mContextClickListener;
private boolean mStillDown;
private boolean mDeferConfirmSingleTap;
private boolean mInLongPress;
- private boolean mInStylusButtonPress;
+ private boolean mInContextClick;
private boolean mAlwaysInTapRegion;
private boolean mAlwaysInBiggerTapRegion;
private boolean mIgnoreNextUpEvent;
@@ -388,8 +385,8 @@ public class GestureDetector {
if (listener instanceof OnDoubleTapListener) {
setOnDoubleTapListener((OnDoubleTapListener) listener);
}
- if (listener instanceof OnStylusButtonPressListener) {
- setOnStylusButtonPressListener((OnStylusButtonPressListener) listener);
+ if (listener instanceof OnContextClickListener) {
+ setContextClickListener((OnContextClickListener) listener);
}
init(context);
}
@@ -453,16 +450,13 @@ public class GestureDetector {
}
/**
- * Sets the listener which will be called for stylus button related
- * gestures.
+ * Sets the listener which will be called for context clicks.
*
- * @param onStylusButtonPressListener the listener invoked for all the
- * callbacks, or null to stop listening for stylus button
- * gestures.
+ * @param onContextClickListener the listener invoked for all the callbacks, or null to stop
+ * listening for context clicks.
*/
- public void setOnStylusButtonPressListener(
- OnStylusButtonPressListener onStylusButtonPressListener) {
- mStylusButtonListener = onStylusButtonPressListener;
+ public void setContextClickListener(OnContextClickListener onContextClickListener) {
+ mContextClickListener = onContextClickListener;
}
/**
@@ -597,7 +591,7 @@ public class GestureDetector {
break;
case MotionEvent.ACTION_MOVE:
- if (mInLongPress || mInStylusButtonPress) {
+ if (mInLongPress || mInContextClick) {
break;
}
final float scrollX = mLastFocusX - focusX;
@@ -698,12 +692,14 @@ public class GestureDetector {
mInputEventConsistencyVerifier.onGenericMotionEvent(ev, 0);
}
+ final int actionButton = ev.getActionButton();
switch (ev.getActionMasked()) {
case MotionEvent.ACTION_BUTTON_PRESS:
- if (mStylusButtonListener != null && !mInStylusButtonPress && !mInLongPress
- && ev.getActionButton() == MotionEvent.BUTTON_STYLUS_PRIMARY) {
- if (mStylusButtonListener.onStylusButtonPress(ev)) {
- mInStylusButtonPress = true;
+ if (mContextClickListener != null && !mInContextClick && !mInLongPress
+ && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
+ || actionButton == MotionEvent.BUTTON_SECONDARY)) {
+ if (mContextClickListener.onContextClick(ev)) {
+ mInContextClick = true;
mHandler.removeMessages(LONG_PRESS);
mHandler.removeMessages(TAP);
return true;
@@ -712,9 +708,9 @@ public class GestureDetector {
break;
case MotionEvent.ACTION_BUTTON_RELEASE:
- if (mInStylusButtonPress
- && ev.getActionButton() == MotionEvent.BUTTON_STYLUS_PRIMARY) {
- mInStylusButtonPress = false;
+ if (mInContextClick && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
+ || actionButton == MotionEvent.BUTTON_SECONDARY)) {
+ mInContextClick = false;
mIgnoreNextUpEvent = true;
}
break;
@@ -734,7 +730,7 @@ public class GestureDetector {
mAlwaysInBiggerTapRegion = false;
mDeferConfirmSingleTap = false;
mInLongPress = false;
- mInStylusButtonPress = false;
+ mInContextClick = false;
mIgnoreNextUpEvent = false;
}
@@ -747,7 +743,7 @@ public class GestureDetector {
mAlwaysInBiggerTapRegion = false;
mDeferConfirmSingleTap = false;
mInLongPress = false;
- mInStylusButtonPress = false;
+ mInContextClick = false;
mIgnoreNextUpEvent = false;
}
diff --git a/core/java/android/view/GhostView.java b/core/java/android/view/GhostView.java
index 41502b6..d1b96ba 100644
--- a/core/java/android/view/GhostView.java
+++ b/core/java/android/view/GhostView.java
@@ -39,7 +39,7 @@ public class GhostView extends View {
mView = view;
mView.mGhostView = this;
final ViewGroup parent = (ViewGroup) mView.getParent();
- setGhostedVisibility(View.INVISIBLE);
+ mView.setTransitionVisibility(View.INVISIBLE);
parent.invalidate();
}
@@ -66,19 +66,15 @@ public class GhostView extends View {
super.setVisibility(visibility);
if (mView.mGhostView == this) {
int inverseVisibility = (visibility == View.VISIBLE) ? View.INVISIBLE : View.VISIBLE;
- setGhostedVisibility(inverseVisibility);
+ mView.setTransitionVisibility(inverseVisibility);
}
}
- private void setGhostedVisibility(int visibility) {
- mView.mViewFlags = (mView.mViewFlags & ~View.VISIBILITY_MASK) | visibility;
- }
-
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (!mBeingMoved) {
- setGhostedVisibility(View.VISIBLE);
+ mView.setTransitionVisibility(View.VISIBLE);
mView.mGhostView = null;
final ViewGroup parent = (ViewGroup) mView.getParent();
if (parent != null) {
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 6651b83..2f87d2e 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -52,9 +52,9 @@ public class HapticFeedbackConstants {
public static final int CALENDAR_DATE = 5;
/**
- * The user has touched the screen with a stylus and pressed the stylus button.
+ * The user has performed a context click on an object.
*/
- public static final int STYLUS_BUTTON_PRESS = 6;
+ public static final int CONTEXT_CLICK = 6;
/**
* This is a private constant. Feel free to renumber as desired.
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 1ee4780..f39d1f5 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -56,7 +56,7 @@ public final class InputDevice implements Parcelable {
private final int mKeyboardType;
private final KeyCharacterMap mKeyCharacterMap;
private final boolean mHasVibrator;
- private final boolean mHasMic;
+ private final boolean mHasMicrophone;
private final boolean mHasButtonUnderPad;
private final ArrayList<MotionRange> mMotionRanges = new ArrayList<MotionRange>();
@@ -358,7 +358,7 @@ public final class InputDevice implements Parcelable {
// Called by native code.
private InputDevice(int id, int generation, int controllerNumber, String name, int vendorId,
int productId, String descriptor, boolean isExternal, int sources, int keyboardType,
- KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMic,
+ KeyCharacterMap keyCharacterMap, boolean hasVibrator, boolean hasMicrophone,
boolean hasButtonUnderPad) {
mId = id;
mGeneration = generation;
@@ -372,7 +372,7 @@ public final class InputDevice implements Parcelable {
mKeyboardType = keyboardType;
mKeyCharacterMap = keyCharacterMap;
mHasVibrator = hasVibrator;
- mHasMic = hasMic;
+ mHasMicrophone = hasMicrophone;
mHasButtonUnderPad = hasButtonUnderPad;
mIdentifier = new InputDeviceIdentifier(descriptor, vendorId, productId);
}
@@ -390,7 +390,7 @@ public final class InputDevice implements Parcelable {
mKeyboardType = in.readInt();
mKeyCharacterMap = KeyCharacterMap.CREATOR.createFromParcel(in);
mHasVibrator = in.readInt() != 0;
- mHasMic = in.readInt() != 0;
+ mHasMicrophone = in.readInt() != 0;
mHasButtonUnderPad = in.readInt() != 0;
mIdentifier = new InputDeviceIdentifier(mDescriptor, mVendorId, mProductId);
@@ -723,8 +723,8 @@ public final class InputDevice implements Parcelable {
* Reports whether the device has a built-in microphone.
* @return Whether the device has a built-in microphone.
*/
- public boolean hasMic() {
- return mHasMic;
+ public boolean hasMicrophone() {
+ return mHasMicrophone;
}
/**
@@ -861,7 +861,7 @@ public final class InputDevice implements Parcelable {
out.writeInt(mKeyboardType);
mKeyCharacterMap.writeToParcel(out, flags);
out.writeInt(mHasVibrator ? 1 : 0);
- out.writeInt(mHasMic ? 1 : 0);
+ out.writeInt(mHasMicrophone ? 1 : 0);
out.writeInt(mHasButtonUnderPad ? 1 : 0);
final int numRanges = mMotionRanges.size();
@@ -907,7 +907,7 @@ public final class InputDevice implements Parcelable {
description.append(" Has Vibrator: ").append(mHasVibrator).append("\n");
- description.append(" Has mic: ").append(mHasMic).append("\n");
+ description.append(" Has mic: ").append(mHasMicrophone).append("\n");
description.append(" Sources: 0x").append(Integer.toHexString(mSources)).append(" (");
appendSourceDescriptionIfApplicable(description, SOURCE_KEYBOARD, "keyboard");
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 7b0f1fb..37e4000 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -516,8 +516,8 @@ public class ScaleGestureDetector {
}
/**
- * Return whether the stylus scale gesture, in which the user uses a stylus
- * and presses the button, should preform scaling. {@see #setButtonScaleEnabled(boolean)}.
+ * Return whether the stylus scale gesture, in which the user uses a stylus and presses the
+ * button, should perform scaling. {@see #setStylusScaleEnabled(boolean)}
*/
public boolean isStylusScaleEnabled() {
return mStylusScaleEnabled;
diff --git a/core/java/android/view/SearchEvent.java b/core/java/android/view/SearchEvent.java
index ef51e7d..643cc3e 100644
--- a/core/java/android/view/SearchEvent.java
+++ b/core/java/android/view/SearchEvent.java
@@ -25,7 +25,7 @@ public class SearchEvent {
private InputDevice mInputDevice;
- /** @hide */
+ /** Create a new search event. */
public SearchEvent(InputDevice inputDevice) {
mInputDevice = inputDevice;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 126540f..5dd5ab8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -990,13 +990,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
/**
* <p>
- * Indicates this view can be stylus button pressed. When stylus button
- * pressable, a View reacts to stylus button presses by notifiying
- * the OnStylusButtonPressListener.
+ * Indicates this view can be context clicked. When context clickable, a View reacts to a
+ * context click (e.g. a primary stylus button press or right mouse click) by notifying the
+ * OnContextClickListener.
* </p>
* {@hide}
*/
- static final int STYLUS_BUTTON_PRESSABLE = 0x00800000;
+ static final int CONTEXT_CLICKABLE = 0x00800000;
/** @hide */
@@ -1872,6 +1872,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public @interface ResolvedLayoutDir {}
/**
+ * A flag to indicate that the layout direction of this view has not been defined yet.
+ * @hide
+ */
+ public static final int LAYOUT_DIRECTION_UNDEFINED = LayoutDirection.UNDEFINED;
+
+ /**
* Horizontal layout direction of this view is from Left to Right.
* Use with {@link #setLayoutDirection}.
*/
@@ -3418,11 +3424,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
protected OnLongClickListener mOnLongClickListener;
/**
- * Listener used to dispatch stylus touch and button press events. This field should be made
- * private, so it is hidden from the SDK.
+ * Listener used to dispatch context click events. This field should be made private, so it
+ * is hidden from the SDK.
* {@hide}
*/
- protected OnStylusButtonPressListener mOnStylusButtonPressListener;
+ protected OnContextClickListener mOnContextClickListener;
/**
* Listener used to build the context menu.
@@ -3515,11 +3521,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private boolean mHasPerformedLongPress;
/**
- * Whether the stylus button is currently pressed down. This is true when
- * the stylus is touching the screen and the button has been pressed, this
- * is false once the stylus has been lifted.
+ * Whether a context click button is currently pressed down. This is true when the stylus is
+ * touching the screen and the primary button has been pressed, or if a mouse's right button is
+ * pressed. This is false once the button is released or if the stylus has been lifted.
*/
- private boolean mInStylusButtonPress;
+ private boolean mInContextButtonPress;
/**
* Whether the next up event should be ignored for the purposes of gesture recognition. This is
@@ -4045,10 +4051,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
viewFlagMasks |= LONG_CLICKABLE;
}
break;
- case com.android.internal.R.styleable.View_stylusButtonPressable:
+ case com.android.internal.R.styleable.View_contextClickable:
if (a.getBoolean(attr, false)) {
- viewFlagValues |= STYLUS_BUTTON_PRESSABLE;
- viewFlagMasks |= STYLUS_BUTTON_PRESSABLE;
+ viewFlagValues |= CONTEXT_CLICKABLE;
+ viewFlagMasks |= CONTEXT_CLICKABLE;
}
break;
case com.android.internal.R.styleable.View_saveEnabled:
@@ -4537,7 +4543,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
- out.append((mViewFlags & STYLUS_BUTTON_PRESSABLE) != 0 ? 'S' : '.');
+ out.append((mViewFlags&CONTEXT_CLICKABLE) != 0 ? 'X' : '.');
out.append(' ');
out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
@@ -5125,17 +5131,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Register a callback to be invoked when this view is touched with a stylus and the button is
- * pressed.
+ * Register a callback to be invoked when this view is context clicked. If the view is not
+ * context clickable, it becomes context clickable.
*
* @param l The callback that will run
- * @see #setStylusButtonPressable(boolean)
+ * @see #setContextClickable(boolean)
*/
- public void setOnStylusButtonPressListener(@Nullable OnStylusButtonPressListener l) {
- if (!isStylusButtonPressable()) {
- setStylusButtonPressable(true);
+ public void setOnContextClickListener(@Nullable OnContextClickListener l) {
+ if (!isContextClickable()) {
+ setContextClickable(true);
}
- getListenerInfo().mOnStylusButtonPressListener = l;
+ getListenerInfo().mOnContextClickListener = l;
}
/**
@@ -5216,21 +5222,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Call this view's OnStylusButtonPressListener, if it is defined.
+ * Call this view's OnContextClickListener, if it is defined.
*
- * @return True if there was an assigned OnStylusButtonPressListener that consumed the event,
- * false otherwise.
+ * @return True if there was an assigned OnContextClickListener that consumed the event, false
+ * otherwise.
*/
- public boolean performStylusButtonPress() {
- sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_STYLUS_BUTTON_PRESSED);
+ public boolean performContextClick() {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
boolean handled = false;
ListenerInfo li = mListenerInfo;
- if (li != null && li.mOnStylusButtonPressListener != null) {
- handled = li.mOnStylusButtonPressListener.onStylusButtonPress(View.this);
+ if (li != null && li.mOnContextClickListener != null) {
+ handled = li.mOnContextClickListener.onContextClick(View.this);
}
if (handled) {
- performHapticFeedback(HapticFeedbackConstants.STYLUS_BUTTON_PRESS);
+ performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
}
return handled;
}
@@ -6025,7 +6031,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
* <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
* <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
- * <li>{@link AccessibilityNodeInfo#setStylusButtonPressable(boolean)}</li>
+ * <li>{@link AccessibilityNodeInfo#setContextClickable(boolean)}</li>
* </ul>
* <p>
* Subclasses should override this method, call the super implementation,
@@ -6177,8 +6183,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setChecked(true);
}
}
- if (isStylusButtonPressable()) {
- structure.setStylusButtonPressable(true);
+ if (isContextClickable()) {
+ structure.setContextClickable(true);
}
structure.setClassName(getAccessibilityClassName().toString());
structure.setContentDescription(getContentDescription());
@@ -6247,8 +6253,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setChecked(true);
}
}
- if (info.isStylusButtonPressable()) {
- structure.setStylusButtonPressable(true);
+ if (info.isContextClickable()) {
+ structure.setContextClickable(true);
}
CharSequence cname = info.getClassName();
structure.setClassName(cname != null ? cname.toString() : null);
@@ -6379,7 +6385,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
info.setAccessibilityFocused(isAccessibilityFocused());
info.setSelected(isSelected());
info.setLongClickable(isLongClickable());
- info.setStylusButtonPressable(isStylusButtonPressable());
+ info.setContextClickable(isContextClickable());
info.setLiveRegion(getAccessibilityLiveRegion());
// TODO: These make sense only if we are in an AdapterView but all
@@ -6410,8 +6416,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
}
- if (isStylusButtonPressable() && isEnabled()) {
- info.addAction(AccessibilityAction.ACTION_STYLUS_BUTTON_PRESS);
+ if (isContextClickable() && isEnabled()) {
+ info.addAction(AccessibilityAction.ACTION_CONTEXT_CLICK);
}
CharSequence text = getIterableTextForAccessibility();
@@ -7801,28 +7807,25 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Indicates whether this view reacts to stylus button press events or not.
+ * Indicates whether this view reacts to context clicks or not.
*
- * @return true if the view is stylus button pressable, false otherwise
- * @see #setStylusButtonPressable(boolean)
- * @attr ref android.R.styleable#View_stylusButtonPressable
+ * @return true if the view is context clickable, false otherwise
+ * @see #setContextClickable(boolean)
+ * @attr ref android.R.styleable#View_contextClickable
*/
- public boolean isStylusButtonPressable() {
- return (mViewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE;
+ public boolean isContextClickable() {
+ return (mViewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
}
/**
- * Enables or disables stylus button press events for this view. When a view is stylus button
- * pressable it reacts to the user touching the screen with a stylus and pressing the first
- * stylus button. This event can launch the listener.
+ * Enables or disables context clicking for this view. This event can launch the listener.
*
- * @param stylusButtonPressable true to make the view react to a stylus button press, false
- * otherwise
- * @see #isStylusButtonPressable()
- * @attr ref android.R.styleable#View_stylusButtonPressable
+ * @param contextClickable true to make the view react to a context click, false otherwise
+ * @see #isContextClickable()
+ * @attr ref android.R.styleable#View_contextClickable
*/
- public void setStylusButtonPressable(boolean stylusButtonPressable) {
- setFlags(stylusButtonPressable ? STYLUS_BUTTON_PRESSABLE : 0, STYLUS_BUTTON_PRESSABLE);
+ public void setContextClickable(boolean contextClickable) {
+ setFlags(contextClickable ? CONTEXT_CLICKABLE : 0, CONTEXT_CLICKABLE);
}
/**
@@ -8243,7 +8246,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final int viewFlags = mViewFlags;
if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
- || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE)
+ || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE)
&& (viewFlags & ENABLED_MASK) == ENABLED) {
views.add(this);
}
@@ -8786,6 +8789,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Change the visibility of the View without triggering any other changes. This is
+ * important for transitions, where visibility changes should not adjust focus or
+ * trigger a new layout. This is only used when the visibility has already been changed
+ * and we need a transient value during an animation. When the animation completes,
+ * the original visibility value is always restored.
+ *
+ * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
+ * @hide
+ */
+ public void setTransitionVisibility(@Visibility int visibility) {
+ mViewFlags = (mViewFlags & ~View.VISIBILITY_MASK) | visibility;
+ }
+
+ /**
* Reset the flag indicating the accessibility state of the subtree rooted
* at this view changed.
*/
@@ -8962,9 +8979,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return requestRectangleOnScreen(r, true);
}
} break;
- case R.id.accessibilityActionStylusButtonPress: {
- if (isStylusButtonPressable()) {
- performStylusButtonPress();
+ case R.id.accessibilityActionContextClick: {
+ if (isContextClickable()) {
+ performContextClick();
return true;
}
} break;
@@ -9369,12 +9386,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return true;
}
+ final int actionButton = event.getActionButton();
switch (event.getActionMasked()) {
case MotionEvent.ACTION_BUTTON_PRESS:
- if (isStylusButtonPressable() && !mInStylusButtonPress && !mHasPerformedLongPress
- && event.getActionButton() == MotionEvent.BUTTON_STYLUS_PRIMARY) {
- if (performStylusButtonPress()) {
- mInStylusButtonPress = true;
+ if (isContextClickable() && !mInContextButtonPress && !mHasPerformedLongPress
+ && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
+ || actionButton == MotionEvent.BUTTON_SECONDARY)) {
+ if (performContextClick()) {
+ mInContextButtonPress = true;
setPressed(true, event.getX(), event.getY());
removeTapCallback();
removeLongPressCallback();
@@ -9384,9 +9403,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
break;
case MotionEvent.ACTION_BUTTON_RELEASE:
- if (mInStylusButtonPress
- && event.getActionButton() == MotionEvent.BUTTON_STYLUS_PRIMARY) {
- mInStylusButtonPress = false;
+ if (mInContextButtonPress && (actionButton == MotionEvent.BUTTON_STYLUS_PRIMARY
+ || actionButton == MotionEvent.BUTTON_SECONDARY)) {
+ mInContextButtonPress = false;
mIgnoreNextUpEvent = true;
}
break;
@@ -10145,7 +10164,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return (viewFlags & CLICKABLE) == CLICKABLE
|| (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
- || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE;
+ || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE;
}
/**
@@ -10238,7 +10257,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// events, it just doesn't respond to them.
return (((viewFlags & CLICKABLE) == CLICKABLE
|| (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
- || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE);
+ || (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE);
}
if (mTouchDelegate != null) {
@@ -10249,7 +10268,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
- (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE) {
+ (viewFlags & CONTEXT_CLICKABLE) == CONTEXT_CLICKABLE) {
switch (action) {
case MotionEvent.ACTION_UP:
boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
@@ -10335,7 +10354,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setPressed(false);
removeTapCallback();
removeLongPressCallback();
- mInStylusButtonPress = false;
+ mInContextButtonPress = false;
mHasPerformedLongPress = false;
mIgnoreNextUpEvent = false;
break;
@@ -10643,7 +10662,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (accessibilityEnabled) {
if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
|| (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
- || (changed & STYLUS_BUTTON_PRESSABLE) != 0) {
+ || (changed & CONTEXT_CLICKABLE) != 0) {
if (oldIncludeForAccessibility != includeForAccessibility()) {
notifySubtreeAccessibilityStateChangedIfNeeded();
} else {
@@ -17148,6 +17167,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* drawable.
*
* @return The color of the ColorDrawable background, if set, otherwise 0.
+ * @hide
*/
@ColorInt
public int getBackgroundColor() {
@@ -21301,17 +21321,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
- * Interface definition for a callback to be invoked when a view is touched with a stylus while
- * the stylus button is pressed.
+ * Interface definition for a callback to be invoked when a view is context clicked.
*/
- public interface OnStylusButtonPressListener {
+ public interface OnContextClickListener {
/**
- * Called when a view is touched with a stylus while the stylus button is pressed.
+ * Called when a view is context clicked.
*
- * @param v The view that was touched.
- * @return true if the callback consumed the stylus button press, false otherwise.
+ * @param v The view that has been context clicked.
+ * @return true if the callback consumed the context click, false otherwise.
*/
- boolean onStylusButtonPress(View v);
+ boolean onContextClick(View v);
}
/**
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index 8c6fa3f..4d584a3 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -213,9 +213,9 @@ public class ViewConfiguration {
private static final int OVERFLING_DISTANCE = 6;
/**
- * Default time to snooze an action mode for.
+ * Default duration to hide an action mode for.
*/
- private static final int ACTION_MODE_SNOOZE_TIME_DEFAULT = 2000;
+ private static final long ACTION_MODE_HIDE_DURATION_DEFAULT = 2000;
/**
* Configuration values for overriding {@link #hasPermanentMenuKey()} behavior.
@@ -737,10 +737,10 @@ public class ViewConfiguration {
}
/**
- * @return the default duration in milliseconds for {@link ActionMode#snooze(int)}.
+ * @return the default duration in milliseconds for {@link ActionMode#hide(long)}.
*/
- public static int getDefaultActionModeSnoozeTime() {
- return ACTION_MODE_SNOOZE_TIME_DEFAULT;
+ public static long getDefaultActionModeHideDuration() {
+ return ACTION_MODE_HIDE_DURATION_DEFAULT;
}
/**
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index e525474..8ceb166 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -75,10 +75,10 @@ public abstract class ViewStructure {
public abstract void setLongClickable(boolean state);
/**
- * Set the stylus button pressable state of this view, as per
- * {@link View#isStylusButtonPressable View.isStylusButtonPressable()}.
+ * Set the context clickable state of this view, as per
+ * {@link View#isContextClickable View.isContextClickable()}.
*/
- public abstract void setStylusButtonPressable(boolean state);
+ public abstract void setContextClickable(boolean state);
/**
* Set the focusable state of this view, as per {@link View#isFocusable View.isFocusable()}.
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index b0dbeca..ab793e0 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -684,9 +684,9 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
/**
- * Represents the event of a stylus button press on a {@link android.view.View}.
+ * Represents the event of a context click on a {@link android.view.View}.
*/
- public static final int TYPE_VIEW_STYLUS_BUTTON_PRESSED = 0x00800000;
+ public static final int TYPE_VIEW_CONTEXT_CLICKED = 0x00800000;
/**
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
@@ -736,7 +736,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* @see #TYPE_TOUCH_INTERACTION_START
* @see #TYPE_TOUCH_INTERACTION_END
* @see #TYPE_WINDOWS_CHANGED
- * @see #TYPE_VIEW_STYLUS_BUTTON_PRESSED
+ * @see #TYPE_VIEW_CONTEXT_CLICKED
*/
public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
@@ -1402,11 +1402,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
builder.append("TYPE_WINDOWS_CHANGED");
eventTypeCount++;
} break;
- case TYPE_VIEW_STYLUS_BUTTON_PRESSED: {
+ case TYPE_VIEW_CONTEXT_CLICKED: {
if (eventTypeCount > 0) {
builder.append(", ");
}
- builder.append("TYPE_VIEW_STYLUS_BUTTON_PRESSED");
+ builder.append("TYPE_VIEW_CONTEXT_CLICKED");
eventTypeCount++;
}
break;
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index b454d1c..36de8f3 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -520,7 +520,7 @@ public class AccessibilityNodeInfo implements Parcelable {
private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
- private static final int BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE = 0x00020000;
+ private static final int BOOLEAN_PROPERTY_CONTEXT_CLICKABLE = 0x00020000;
/**
* Bits that provide the id of a virtual descendant of a view.
@@ -1945,27 +1945,27 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
- * Gets whether this node is stylus button pressable.
+ * Gets whether this node is context clickable.
*
- * @return True if the node is stylus button pressable.
+ * @return True if the node is context clickable.
*/
- public boolean isStylusButtonPressable() {
- return getBooleanProperty(BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE);
+ public boolean isContextClickable() {
+ return getBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE);
}
/**
- * Sets whether this node is stylus button pressable.
+ * Sets whether this node is context clickable.
* <p>
* <strong>Note:</strong> Cannot be called from an
* {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
* before being delivered to an AccessibilityService.
* </p>
*
- * @param stylusButtonPressable True if the node is stylus button pressable.
+ * @param contextClickable True if the node is context clickable.
* @throws IllegalStateException If called from an AccessibilityService.
*/
- public void setStylusButtonPressable(boolean stylusButtonPressable) {
- setBooleanProperty(BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE, stylusButtonPressable);
+ public void setContextClickable(boolean contextClickable) {
+ setBooleanProperty(BOOLEAN_PROPERTY_CONTEXT_CLICKABLE, contextClickable);
}
/**
@@ -3156,7 +3156,7 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("; selected: ").append(isSelected());
builder.append("; clickable: ").append(isClickable());
builder.append("; longClickable: ").append(isLongClickable());
- builder.append("; stylusButtonPressable: ").append(isStylusButtonPressable());
+ builder.append("; contextClickable: ").append(isContextClickable());
builder.append("; enabled: ").append(isEnabled());
builder.append("; password: ").append(isPassword());
builder.append("; scrollable: ").append(isScrollable());
@@ -3537,10 +3537,10 @@ public class AccessibilityNodeInfo implements Parcelable {
new AccessibilityAction(R.id.accessibilityActionScrollRight, null);
/**
- * Action that stylus button presses the node.
+ * Action that context clicks the node.
*/
- public static final AccessibilityAction ACTION_STYLUS_BUTTON_PRESS =
- new AccessibilityAction(R.id.accessibilityActionStylusButtonPress, null);
+ public static final AccessibilityAction ACTION_CONTEXT_CLICK =
+ new AccessibilityAction(R.id.accessibilityActionContextClick, null);
private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
static {
@@ -3572,7 +3572,7 @@ public class AccessibilityNodeInfo implements Parcelable {
sStandardActions.add(ACTION_SCROLL_LEFT);
sStandardActions.add(ACTION_SCROLL_DOWN);
sStandardActions.add(ACTION_SCROLL_RIGHT);
- sStandardActions.add(ACTION_STYLUS_BUTTON_PRESS);
+ sStandardActions.add(ACTION_CONTEXT_CLICK);
}
private final int mActionId;
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index c0395cf..76c8fbd 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -298,6 +298,17 @@ public class EditorInfo implements InputType, Parcelable {
/**
* Name of the package that owns this editor.
+ *
+ * <p><strong>IME authors:</strong> In API level 22
+ * {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and prior, do not trust this package
+ * name. The system had not verified the consistency between the package name here and
+ * application's uid. Consider to use {@link InputBinding#getUid()}, which is trustworthy.
+ * Starting from Android MNC, the system verifies the consistency between this package name
+ * and application uid before {@link EditorInfo} is passed to the input method.</p>
+ *
+ * <p><strong>Editor authors:</strong> Starting from Android MNC, the application is no longer
+ * able to establish input connections if the package name provided here is inconsistent with
+ * application's uid.</p>
*/
public String packageName;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index a0d1930..0001860 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -694,9 +694,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*/
private boolean mForceTranscriptScroll;
- private int mGlowPaddingLeft;
- private int mGlowPaddingRight;
-
/**
* Used for interacting with list items from an accessibility service.
*/
@@ -3489,17 +3486,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (!mEdgeGlowBottom.isFinished()) {
mEdgeGlowBottom.onRelease();
}
- invalidate(0, 0, getWidth(),
- mEdgeGlowTop.getMaxHeight() + getPaddingTop());
+ invalidateTopGlow();
} else if (incrementalDeltaY < 0) {
mEdgeGlowBottom.onPull((float) overscroll / getHeight(),
1.f - (float) x / getWidth());
if (!mEdgeGlowTop.isFinished()) {
mEdgeGlowTop.onRelease();
}
- invalidate(0, getHeight() - getPaddingBottom() -
- mEdgeGlowBottom.getMaxHeight(), getWidth(),
- getHeight());
+ invalidateBottomGlow();
}
}
}
@@ -3539,17 +3533,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (!mEdgeGlowBottom.isFinished()) {
mEdgeGlowBottom.onRelease();
}
- invalidate(0, 0, getWidth(),
- mEdgeGlowTop.getMaxHeight() + getPaddingTop());
+ invalidateTopGlow();
} else if (rawDeltaY < 0) {
mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight(),
1.f - (float) x / getWidth());
if (!mEdgeGlowTop.isFinished()) {
mEdgeGlowTop.onRelease();
}
- invalidate(0, getHeight() - getPaddingBottom() -
- mEdgeGlowBottom.getMaxHeight(), getWidth(),
- getHeight());
+ invalidateBottomGlow();
}
}
}
@@ -3581,6 +3572,28 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
+ private void invalidateTopGlow() {
+ if (mEdgeGlowTop == null) {
+ return;
+ }
+ final boolean clipToPadding = getClipToPadding();
+ final int top = clipToPadding ? mPaddingTop : 0;
+ final int left = clipToPadding ? mPaddingLeft : 0;
+ final int right = clipToPadding ? getWidth() - mPaddingRight : getWidth();
+ invalidate(left, top, right, top + mEdgeGlowTop.getMaxHeight());
+ }
+
+ private void invalidateBottomGlow() {
+ if (mEdgeGlowBottom == null) {
+ return;
+ }
+ final boolean clipToPadding = getClipToPadding();
+ final int bottom = clipToPadding ? getHeight() - mPaddingBottom : getHeight();
+ final int left = clipToPadding ? mPaddingLeft : 0;
+ final int right = clipToPadding ? getWidth() - mPaddingRight : getWidth();
+ invalidate(left, bottom - mEdgeGlowBottom.getMaxHeight(), right, bottom);
+ }
+
@Override
public void onTouchModeChanged(boolean isInTouchMode) {
if (isInTouchMode) {
@@ -4142,47 +4155,53 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
super.draw(canvas);
if (mEdgeGlowTop != null) {
final int scrollY = mScrollY;
+ final boolean clipToPadding = getClipToPadding();
+ final int width;
+ final int height;
+ final int translateX;
+ final int translateY;
+
+ if (clipToPadding) {
+ width = getWidth() - mPaddingLeft - mPaddingRight;
+ height = getHeight() - mPaddingTop - mPaddingBottom;
+ translateX = mPaddingLeft;
+ translateY = mPaddingTop;
+ } else {
+ width = getWidth();
+ height = getHeight();
+ translateX = 0;
+ translateY = 0;
+ }
if (!mEdgeGlowTop.isFinished()) {
final int restoreCount = canvas.save();
- final int width = getWidth();
-
- int edgeY = Math.min(0, scrollY + mFirstPositionDistanceGuess);
- canvas.translate(0, edgeY);
- mEdgeGlowTop.setSize(width, getHeight());
+ canvas.clipRect(translateX, translateY,
+ translateX + width ,translateY + mEdgeGlowTop.getMaxHeight());
+ final int edgeY = Math.min(0, scrollY + mFirstPositionDistanceGuess) + translateY;
+ canvas.translate(translateX, edgeY);
+ mEdgeGlowTop.setSize(width, height);
if (mEdgeGlowTop.draw(canvas)) {
- invalidate(0, 0, getWidth(),
- mEdgeGlowTop.getMaxHeight() + getPaddingTop());
+ invalidateTopGlow();
}
canvas.restoreToCount(restoreCount);
}
if (!mEdgeGlowBottom.isFinished()) {
final int restoreCount = canvas.save();
- final int width = getWidth();
- final int height = getHeight();
-
- int edgeX = -width;
- int edgeY = Math.max(height, scrollY + mLastPositionDistanceGuess);
+ canvas.clipRect(translateX, translateY + height - mEdgeGlowBottom.getMaxHeight(),
+ translateX + width, translateY + height);
+ final int edgeX = -width + translateX;
+ final int edgeY = Math.max(getHeight(), scrollY + mLastPositionDistanceGuess)
+ - (clipToPadding ? mPaddingBottom : 0);
canvas.translate(edgeX, edgeY);
canvas.rotate(180, width, 0);
mEdgeGlowBottom.setSize(width, height);
if (mEdgeGlowBottom.draw(canvas)) {
- invalidate(0, getHeight() - getPaddingBottom() -
- mEdgeGlowBottom.getMaxHeight(), getWidth(),
- getHeight());
+ invalidateBottomGlow();
}
canvas.restoreToCount(restoreCount);
}
}
}
- /**
- * @hide
- */
- public void setOverScrollEffectPadding(int leftPadding, int rightPadding) {
- mGlowPaddingLeft = leftPadding;
- mGlowPaddingRight = rightPadding;
- }
-
private void initOrResetVelocityTracker() {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 56f9b5c..cd110b7 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -125,6 +125,15 @@ public class Editor {
// Tag used when the Editor maintains its own separate UndoManager.
private static final String UNDO_OWNER_TAG = "Editor";
+ // Ordering constants used to place the Action Mode items in their menu.
+ private static final int MENU_ITEM_ORDER_CUT = 1;
+ private static final int MENU_ITEM_ORDER_COPY = 2;
+ private static final int MENU_ITEM_ORDER_PASTE = 3;
+ private static final int MENU_ITEM_ORDER_SHARE = 4;
+ private static final int MENU_ITEM_ORDER_SELECT_ALL = 5;
+ private static final int MENU_ITEM_ORDER_REPLACE = 6;
+ private static final int MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START = 10;
+
// Each Editor manages its own undo stack.
private final UndoManager mUndoManager = new UndoManager();
private UndoOwner mUndoOwner = mUndoManager.getOwner(UNDO_OWNER_TAG, this);
@@ -134,7 +143,8 @@ public class Editor {
// Cursor Controllers.
InsertionPointCursorController mInsertionPointCursorController;
SelectionModifierCursorController mSelectionModifierCursorController;
- ActionMode mSelectionActionMode;
+ // Action mode used when text is selected or when actions on an insertion cursor are triggered.
+ ActionMode mTextActionMode;
boolean mInsertionControllerEnabled;
boolean mSelectionControllerEnabled;
@@ -205,13 +215,14 @@ public class Editor {
float mLastDownPositionX, mLastDownPositionY;
Callback mCustomSelectionActionModeCallback;
+ Callback mCustomInsertionActionModeCallback;
// Set when this TextView gained focus with some text selected. Will start selection mode.
boolean mCreatedWithASelection;
boolean mDoubleTap = false;
- private Runnable mSelectionModeWithoutSelectionRunnable;
+ private Runnable mInsertionActionModeRunnable;
// The span controller helps monitoring the changes to which the Editor needs to react:
// - EasyEditSpans, for which we have some UI to display on attach and on hide
@@ -236,8 +247,8 @@ public class Editor {
private final Runnable mHideFloatingToolbar = new Runnable() {
@Override
public void run() {
- if (mSelectionActionMode != null) {
- mSelectionActionMode.snooze(ActionMode.SNOOZE_TIME_DEFAULT);
+ if (mTextActionMode != null) {
+ mTextActionMode.hide(ActionMode.DEFAULT_HIDE_DURATION);
}
}
};
@@ -245,8 +256,8 @@ public class Editor {
private final Runnable mShowFloatingToolbar = new Runnable() {
@Override
public void run() {
- if (mSelectionActionMode != null) {
- mSelectionActionMode.snooze(0); // snooze off.
+ if (mTextActionMode != null) {
+ mTextActionMode.hide(0); // hide off.
}
}
};
@@ -310,7 +321,7 @@ public class Editor {
void replace() {
int middle = (mTextView.getSelectionStart() + mTextView.getSelectionEnd()) / 2;
- stopSelectionActionMode();
+ stopTextActionMode();
Selection.setSelection((Spannable) mTextView.getText(), middle);
showSuggestions();
}
@@ -343,7 +354,7 @@ public class Editor {
mTextView.setHasTransientState(false);
// We had an active selection from before, start the selection mode.
- startSelectionActionModeWithSelection();
+ startSelectionActionMode();
}
getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true);
@@ -372,8 +383,8 @@ public class Editor {
}
// Cancel the single tap delayed runnable.
- if (mSelectionModeWithoutSelectionRunnable != null) {
- mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
+ if (mInsertionActionModeRunnable != null) {
+ mTextView.removeCallbacks(mInsertionActionModeRunnable);
}
mTextView.removeCallbacks(mHideFloatingToolbar);
@@ -390,7 +401,7 @@ public class Editor {
mPreserveDetachedSelection = true;
hideControllers();
- stopSelectionActionMode();
+ stopTextActionMode();
mPreserveDetachedSelection = false;
mTemporaryDetach = false;
}
@@ -586,7 +597,7 @@ public class Editor {
}
if (!mSelectionControllerEnabled) {
- stopSelectionActionMode();
+ stopTextActionMode();
if (mSelectionModifierCursorController != null) {
mSelectionModifierCursorController.onDetached();
mSelectionModifierCursorController = null;
@@ -984,14 +995,14 @@ public class Editor {
mInsertionControllerEnabled) {
final int offset = mTextView.getOffsetForPosition(mLastDownPositionX,
mLastDownPositionY);
- stopSelectionActionMode();
+ stopTextActionMode();
Selection.setSelection((Spannable) mTextView.getText(), offset);
getInsertionController().show();
- startSelectionActionModeWithoutSelection();
+ startInsertionActionMode();
handled = true;
}
- if (!handled && mSelectionActionMode != null) {
+ if (!handled && mTextActionMode != null) {
if (touchPositionIsInSelection()) {
// Start a drag
final int start = mTextView.getSelectionStart();
@@ -1001,9 +1012,9 @@ public class Editor {
DragLocalState localState = new DragLocalState(mTextView, start, end);
mTextView.startDrag(data, getTextThumbnailBuilder(selectedText), localState,
View.DRAG_FLAG_GLOBAL);
- stopSelectionActionMode();
+ stopTextActionMode();
} else {
- stopSelectionActionMode();
+ stopTextActionMode();
selectCurrentWordAndStartDrag();
}
handled = true;
@@ -1101,12 +1112,12 @@ public class Editor {
final int selStart = mTextView.getSelectionStart();
final int selEnd = mTextView.getSelectionEnd();
hideControllers();
- stopSelectionActionMode();
+ stopTextActionMode();
Selection.setSelection((Spannable) mTextView.getText(), selStart, selEnd);
} else {
if (mTemporaryDetach) mPreserveDetachedSelection = true;
hideControllers();
- stopSelectionActionMode();
+ stopTextActionMode();
if (mTemporaryDetach) mPreserveDetachedSelection = false;
downgradeEasyCorrectionSpans();
}
@@ -1149,7 +1160,7 @@ public class Editor {
// We do not hide the span controllers, since they can be added when a new text is
// inserted into the text view (voice IME).
hideCursorControllers();
- stopSelectionActionMode();
+ stopTextActionMode();
}
private int getLastTapPosition() {
@@ -1216,7 +1227,7 @@ public class Editor {
}
private void updateFloatingToolbarVisibility(MotionEvent event) {
- if (mSelectionActionMode != null) {
+ if (mTextActionMode != null) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_MOVE:
hideFloatingToolbar();
@@ -1229,7 +1240,7 @@ public class Editor {
}
private void hideFloatingToolbar() {
- if (mSelectionActionMode != null) {
+ if (mTextActionMode != null) {
mTextView.removeCallbacks(mShowFloatingToolbar);
// Delay the "hide" a little bit just in case a "show" will happen almost immediately.
mTextView.postDelayed(mHideFloatingToolbar, 100);
@@ -1237,7 +1248,7 @@ public class Editor {
}
private void showFloatingToolbar() {
- if (mSelectionActionMode != null) {
+ if (mTextActionMode != null) {
mTextView.removeCallbacks(mHideFloatingToolbar);
// Delay "show" so it doesn't interfere with click confirmations
// or double-clicks that could "dismiss" the floating toolbar.
@@ -1701,26 +1712,20 @@ public class Editor {
/**
* @return true if the selection mode was actually started.
*/
- private boolean startSelectionActionModeWithoutSelection() {
+ private boolean startInsertionActionMode() {
+ if (mInsertionActionModeRunnable != null) {
+ mTextView.removeCallbacks(mInsertionActionModeRunnable);
+ }
if (extractedTextModeWillBeStarted()) {
- // Cancel the single tap delayed runnable.
- if (mSelectionModeWithoutSelectionRunnable != null) {
- mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
- }
-
return false;
}
+ stopTextActionMode();
- if (mSelectionActionMode != null) {
- // Selection action mode is already started
- // TODO: revisit invocations to minimize this case.
- mSelectionActionMode.invalidate();
- return false;
- }
- ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
- mSelectionActionMode = mTextView.startActionMode(
+ ActionMode.Callback actionModeCallback =
+ new TextActionModeCallback(false /* hasSelection */);
+ mTextActionMode = mTextView.startActionMode(
actionModeCallback, ActionMode.TYPE_FLOATING);
- return mSelectionActionMode != null;
+ return mTextActionMode != null;
}
/**
@@ -1730,8 +1735,8 @@ public class Editor {
*
* @return true if the selection mode was actually started.
*/
- boolean startSelectionActionModeWithSelection() {
- boolean selectionStarted = startSelectionActionModeWithSelectionInternal();
+ boolean startSelectionActionMode() {
+ boolean selectionStarted = startSelectionActionModeInternal();
if (selectionStarted) {
getSelectionController().show();
} else if (getInsertionController() != null) {
@@ -1747,19 +1752,24 @@ public class Editor {
* @return true if the drag was started.
*/
private boolean selectCurrentWordAndStartDrag() {
+ if (mInsertionActionModeRunnable != null) {
+ mTextView.removeCallbacks(mInsertionActionModeRunnable);
+ }
if (extractedTextModeWillBeStarted()) {
- // Cancel the single tap delayed runnable.
- if (mSelectionModeWithoutSelectionRunnable != null) {
- mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
- }
return false;
}
- if (mSelectionActionMode != null) {
- mSelectionActionMode.finish();
+ if (mTextActionMode != null) {
+ mTextActionMode.finish();
}
if (!checkFieldAndSelectCurrentWord()) {
return false;
}
+
+ // Avoid dismissing the selection if it exists.
+ mPreserveDetachedSelection = true;
+ stopTextActionMode();
+ mPreserveDetachedSelection = false;
+
getSelectionController().enterDrag();
return true;
}
@@ -1784,10 +1794,10 @@ public class Editor {
return true;
}
- private boolean startSelectionActionModeWithSelectionInternal() {
- if (mSelectionActionMode != null) {
+ private boolean startSelectionActionModeInternal() {
+ if (mTextActionMode != null) {
// Selection action mode is already started
- mSelectionActionMode.invalidate();
+ mTextActionMode.invalidate();
return false;
}
@@ -1800,12 +1810,13 @@ public class Editor {
// Do not start the action mode when extracted text will show up full screen, which would
// immediately hide the newly created action bar and would be visually distracting.
if (!willExtract) {
- ActionMode.Callback actionModeCallback = new SelectionActionModeCallback();
- mSelectionActionMode = mTextView.startActionMode(
+ ActionMode.Callback actionModeCallback =
+ new TextActionModeCallback(true /* hasSelection */);
+ mTextActionMode = mTextView.startActionMode(
actionModeCallback, ActionMode.TYPE_FLOATING);
}
- final boolean selectionStarted = mSelectionActionMode != null || willExtract;
+ final boolean selectionStarted = mTextActionMode != null || willExtract;
if (selectionStarted && !mTextView.isTextSelectable() && mShowSoftInputOnFocus) {
// Show the IME to be able to replace text, except when selecting non editable text.
final InputMethodManager imm = InputMethodManager.peekInstance();
@@ -1906,7 +1917,7 @@ public class Editor {
void onTouchUpEvent(MotionEvent event) {
boolean selectAllGotFocus = mSelectAllOnFocus && mTextView.didTouchFocusSelect();
hideControllers();
- stopSelectionActionMode();
+ stopTextActionMode();
CharSequence text = mTextView.getText();
if (!selectAllGotFocus && text.length() > 0) {
// Move cursor
@@ -1920,8 +1931,8 @@ public class Editor {
if (!extractedTextModeWillBeStarted()) {
if (isCursorInsideEasyCorrectionSpan()) {
// Cancel the single tap delayed runnable.
- if (mSelectionModeWithoutSelectionRunnable != null) {
- mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
+ if (mInsertionActionModeRunnable != null) {
+ mTextView.removeCallbacks(mInsertionActionModeRunnable);
}
mShowSuggestionRunnable = new Runnable() {
@@ -1939,10 +1950,10 @@ public class Editor {
}
}
- protected void stopSelectionActionMode() {
- if (mSelectionActionMode != null) {
+ protected void stopTextActionMode() {
+ if (mTextActionMode != null) {
// This will hide the mSelectionModifierCursorController
- mSelectionActionMode.finish();
+ mTextActionMode.finish();
}
}
@@ -2027,7 +2038,7 @@ public class Editor {
mSuggestionsPopupWindow = new SuggestionsPopupWindow();
}
hideControllers();
- stopSelectionActionMode();
+ stopTextActionMode();
mSuggestionsPopupWindow.show();
}
@@ -2035,8 +2046,8 @@ public class Editor {
if (mPositionListener != null) {
mPositionListener.onScrollChanged();
}
- if (mSelectionActionMode != null) {
- mSelectionActionMode.invalidateContentRect();
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidateContentRect();
}
}
@@ -3087,46 +3098,54 @@ public class Editor {
}
/**
- * An ActionMode Callback class that is used to provide actions while in text selection mode.
+ * An ActionMode Callback class that is used to provide actions while in text insertion or
+ * selection mode.
*
- * The default callback provides a subset of Select All, Cut, Copy and Paste actions, depending
- * on which of these this TextView supports.
+ * The default callback provides a subset of Select All, Cut, Copy, Paste, Share and Replace
+ * actions, depending on which of these this TextView supports and the current selection.
*/
- private class SelectionActionModeCallback extends ActionMode.Callback2 {
+ private class TextActionModeCallback extends ActionMode.Callback2 {
private final Path mSelectionPath = new Path();
private final RectF mSelectionBounds = new RectF();
-
- private int mSelectionHandleHeight;
- private int mInsertionHandleHeight;
-
- public SelectionActionModeCallback() {
- SelectionModifierCursorController selectionController = getSelectionController();
- if (selectionController.mStartHandle == null) {
- // As these are for initializing selectionController, hide() must be called.
- selectionController.initDrawables();
- selectionController.initHandles();
- selectionController.hide();
- }
- mSelectionHandleHeight = Math.max(
- mSelectHandleLeft.getMinimumHeight(), mSelectHandleRight.getMinimumHeight());
- InsertionPointCursorController insertionController = getInsertionController();
- if (insertionController != null) {
- insertionController.getHandle();
- mInsertionHandleHeight = mSelectHandleCenter.getMinimumHeight();
+ private final boolean mHasSelection;
+
+ private int mHandleHeight;
+
+ public TextActionModeCallback(boolean hasSelection) {
+ mHasSelection = hasSelection;
+ if (mHasSelection) {
+ SelectionModifierCursorController selectionController = getSelectionController();
+ if (selectionController.mStartHandle == null) {
+ // As these are for initializing selectionController, hide() must be called.
+ selectionController.initDrawables();
+ selectionController.initHandles();
+ selectionController.hide();
+ }
+ mHandleHeight = Math.max(
+ mSelectHandleLeft.getMinimumHeight(),
+ mSelectHandleRight.getMinimumHeight());
+ } else {
+ InsertionPointCursorController insertionController = getInsertionController();
+ if (insertionController != null) {
+ insertionController.getHandle();
+ mHandleHeight = mSelectHandleCenter.getMinimumHeight();
+ }
}
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
- mode.setTitle(mTextView.getContext().getString(
- com.android.internal.R.string.textSelectionCABTitle));
+ mode.setTitle(null);
mode.setSubtitle(null);
mode.setTitleOptionalHint(true);
populateMenuWithItems(menu);
- if (mCustomSelectionActionModeCallback != null) {
- if (!mCustomSelectionActionModeCallback.onCreateActionMode(mode, menu)) {
- // The custom mode can choose to cancel the action mode
+ Callback customCallback = getCustomCallback();
+ if (customCallback != null) {
+ if (!customCallback.onCreateActionMode(mode, menu)) {
+ // The custom mode can choose to cancel the action mode, dismiss selection.
+ Selection.setSelection((Spannable) mTextView.getText(),
+ mTextView.getSelectionEnd());
return false;
}
}
@@ -3141,36 +3160,41 @@ public class Editor {
}
}
+ private Callback getCustomCallback() {
+ return mHasSelection
+ ? mCustomSelectionActionModeCallback
+ : mCustomInsertionActionModeCallback;
+ }
+
private void populateMenuWithItems(Menu menu) {
if (mTextView.canCut()) {
- menu.add(0, TextView.ID_CUT, 0, com.android.internal.R.string.cut).
+ menu.add(Menu.NONE, TextView.ID_CUT, MENU_ITEM_ORDER_CUT,
+ com.android.internal.R.string.cut).
setAlphabeticShortcut('x').
setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
if (mTextView.canCopy()) {
- menu.add(0, TextView.ID_COPY, 0, com.android.internal.R.string.copy).
+ menu.add(Menu.NONE, TextView.ID_COPY, MENU_ITEM_ORDER_COPY,
+ com.android.internal.R.string.copy).
setAlphabeticShortcut('c').
setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
if (mTextView.canPaste()) {
- menu.add(0, TextView.ID_PASTE, 0, com.android.internal.R.string.paste).
- setAlphabeticShortcut('v').
- setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ menu.add(Menu.NONE, TextView.ID_PASTE, MENU_ITEM_ORDER_PASTE,
+ com.android.internal.R.string.paste).
+ setAlphabeticShortcut('v').
+ setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
}
if (mTextView.canShare()) {
- menu.add(0, TextView.ID_SHARE, 0, com.android.internal.R.string.share).
- setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- }
-
- if (mTextView.canSelectAllText()) {
- menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
- setAlphabeticShortcut('a').
- setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ menu.add(Menu.NONE, TextView.ID_SHARE, MENU_ITEM_ORDER_SHARE,
+ com.android.internal.R.string.share).
+ setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
+ updateSelectAllItem(menu);
updateReplaceItem(menu);
}
@@ -3179,8 +3203,11 @@ public class Editor {
PackageManager packageManager = mTextView.getContext().getPackageManager();
List<ResolveInfo> supportedActivities =
packageManager.queryIntentActivities(createProcessTextIntent(), 0);
- for (ResolveInfo info : supportedActivities) {
- menu.add(info.loadLabel(packageManager))
+ for (int i = 0; i < supportedActivities.size(); ++i) {
+ ResolveInfo info = supportedActivities.get(i);
+ menu.add(Menu.NONE, Menu.NONE,
+ MENU_ITEM_ORDER_PROCESS_TEXT_INTENT_ACTIONS_START + i,
+ info.loadLabel(packageManager))
.setIntent(createProcessTextIntentForResolveInfo(info))
.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
}
@@ -3201,20 +3228,35 @@ public class Editor {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ updateSelectAllItem(menu);
updateReplaceItem(menu);
- if (mCustomSelectionActionModeCallback != null) {
- return mCustomSelectionActionModeCallback.onPrepareActionMode(mode, menu);
+ Callback customCallback = getCustomCallback();
+ if (customCallback != null) {
+ return customCallback.onPrepareActionMode(mode, menu);
}
return true;
}
+ private void updateSelectAllItem(Menu menu) {
+ boolean canSelectAll = mTextView.canSelectAllText();
+ boolean selectAllItemExists = menu.findItem(TextView.ID_SELECT_ALL) != null;
+ if (canSelectAll && !selectAllItemExists) {
+ menu.add(Menu.NONE, TextView.ID_SELECT_ALL, MENU_ITEM_ORDER_SELECT_ALL,
+ com.android.internal.R.string.selectAll)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ } else if (!canSelectAll && selectAllItemExists) {
+ menu.removeItem(TextView.ID_SELECT_ALL);
+ }
+ }
+
private void updateReplaceItem(Menu menu) {
boolean canReplace = mTextView.isSuggestionsEnabled() && shouldOfferToShowSuggestions();
boolean replaceItemExists = menu.findItem(TextView.ID_REPLACE) != null;
if (canReplace && !replaceItemExists) {
- menu.add(0, TextView.ID_REPLACE, 0, com.android.internal.R.string.replace).
- setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+ menu.add(Menu.NONE, TextView.ID_REPLACE, MENU_ITEM_ORDER_REPLACE,
+ com.android.internal.R.string.replace)
+ .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
} else if (!canReplace && replaceItemExists) {
menu.removeItem(TextView.ID_REPLACE);
}
@@ -3230,8 +3272,8 @@ public class Editor {
item.getIntent(), TextView.PROCESS_TEXT_REQUEST_CODE);
return true;
}
- if (mCustomSelectionActionModeCallback != null &&
- mCustomSelectionActionModeCallback.onActionItemClicked(mode, item)) {
+ Callback customCallback = getCustomCallback();
+ if (customCallback != null && customCallback.onActionItemClicked(mode, item)) {
return true;
}
return mTextView.onTextContextMenuItem(item.getItemId());
@@ -3239,8 +3281,9 @@ public class Editor {
@Override
public void onDestroyActionMode(ActionMode mode) {
- if (mCustomSelectionActionModeCallback != null) {
- mCustomSelectionActionModeCallback.onDestroyActionMode(mode);
+ Callback customCallback = getCustomCallback();
+ if (customCallback != null) {
+ customCallback.onDestroyActionMode(mode);
}
/*
@@ -3259,7 +3302,7 @@ public class Editor {
mSelectionModifierCursorController.resetTouchOffsets();
}
- mSelectionActionMode = null;
+ mTextActionMode = null;
}
@Override
@@ -3274,7 +3317,7 @@ public class Editor {
mTextView.getLayout().getSelectionPath(
mTextView.getSelectionStart(), mTextView.getSelectionEnd(), mSelectionPath);
mSelectionPath.computeBounds(mSelectionBounds, true);
- mSelectionBounds.bottom += mSelectionHandleHeight;
+ mSelectionBounds.bottom += mHandleHeight;
} else if (mCursorCount == 2) {
// We have a split cursor. In this case, we take the rectangle that includes both
// parts of the cursor to ensure we don't obscure either of them.
@@ -3285,7 +3328,7 @@ public class Editor {
Math.min(firstCursorBounds.top, secondCursorBounds.top),
Math.max(firstCursorBounds.right, secondCursorBounds.right),
Math.max(firstCursorBounds.bottom, secondCursorBounds.bottom)
- + mInsertionHandleHeight);
+ + mHandleHeight);
} else {
// We have a single cursor.
int line = mTextView.getLayout().getLineForOffset(mTextView.getSelectionStart());
@@ -3295,7 +3338,7 @@ public class Editor {
primaryHorizontal,
mTextView.getLayout().getLineTop(line),
primaryHorizontal + 1,
- mTextView.getLayout().getLineTop(line + 1) + mInsertionHandleHeight);
+ mTextView.getLayout().getLineTop(line + 1) + mHandleHeight);
}
// Take TextView's padding and scroll into account.
int textHorizontalOffset = mTextView.viewportToContentHorizontalOffset();
@@ -3847,25 +3890,25 @@ public class Editor {
SystemClock.uptimeMillis() - TextView.sLastCutCopyOrTextChangedTime;
// Cancel the single tap delayed runnable.
- if (mSelectionModeWithoutSelectionRunnable != null
+ if (mInsertionActionModeRunnable != null
&& (mDoubleTap || isCursorInsideEasyCorrectionSpan())) {
- mTextView.removeCallbacks(mSelectionModeWithoutSelectionRunnable);
+ mTextView.removeCallbacks(mInsertionActionModeRunnable);
}
// Prepare and schedule the single tap runnable to run exactly after the double tap
// timeout has passed.
if (!mDoubleTap && !isCursorInsideEasyCorrectionSpan()
&& (durationSinceCutOrCopy < RECENT_CUT_COPY_DURATION)) {
- if (mSelectionModeWithoutSelectionRunnable == null) {
- mSelectionModeWithoutSelectionRunnable = new Runnable() {
+ if (mInsertionActionModeRunnable == null) {
+ mInsertionActionModeRunnable = new Runnable() {
public void run() {
- startSelectionActionModeWithoutSelection();
+ startInsertionActionMode();
}
};
}
mTextView.postDelayed(
- mSelectionModeWithoutSelectionRunnable,
+ mInsertionActionModeRunnable,
ViewConfiguration.getDoubleTapTimeout() + 1);
}
@@ -3934,15 +3977,15 @@ public class Editor {
if (distanceSquared < touchSlop * touchSlop) {
// Tapping on the handle toggles the selection action mode.
- if (mSelectionActionMode != null) {
- mSelectionActionMode.finish();
+ if (mTextActionMode != null) {
+ mTextActionMode.finish();
} else {
- startSelectionActionModeWithoutSelection();
+ startInsertionActionMode();
}
}
} else {
- if (mSelectionActionMode != null) {
- mSelectionActionMode.invalidateContentRect();
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidateContentRect();
}
}
hideAfterDelay();
@@ -3972,8 +4015,8 @@ public class Editor {
@Override
public void updatePosition(float x, float y) {
positionAtCursorOffset(mTextView.getOffsetForPosition(x, y), false);
- if (mSelectionActionMode != null) {
- mSelectionActionMode.invalidate();
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidate();
}
}
@@ -4024,8 +4067,8 @@ public class Editor {
Selection.setSelection((Spannable) mTextView.getText(), offset,
mTextView.getSelectionEnd());
updateDrawable();
- if (mSelectionActionMode != null) {
- mSelectionActionMode.invalidate();
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidate();
}
}
@@ -4150,8 +4193,8 @@ public class Editor {
public void updateSelection(int offset) {
Selection.setSelection((Spannable) mTextView.getText(),
mTextView.getSelectionStart(), offset);
- if (mSelectionActionMode != null) {
- mSelectionActionMode.invalidate();
+ if (mTextActionMode != null) {
+ mTextActionMode.invalidate();
}
updateDrawable();
}
@@ -4515,7 +4558,7 @@ public class Editor {
mEndHandle.showAtLocation(endOffset);
// No longer the first dragging motion, reset.
- startSelectionActionModeWithSelection();
+ startSelectionActionMode();
mDragAcceleratorActive = false;
mStartOffset = -1;
}
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 73a873a..6b28f89 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -1088,8 +1088,8 @@ public class ImageView extends View {
} else if (ScaleType.CENTER == mScaleType) {
// Center bitmap in view, no scaling.
mDrawMatrix = mMatrix;
- mDrawMatrix.setTranslate((int) ((vwidth - dwidth) * 0.5f + 0.5f),
- (int) ((vheight - dheight) * 0.5f + 0.5f));
+ mDrawMatrix.setTranslate(Math.round((vwidth - dwidth) * 0.5f),
+ Math.round((vheight - dheight) * 0.5f));
} else if (ScaleType.CENTER_CROP == mScaleType) {
mDrawMatrix = mMatrix;
@@ -1105,7 +1105,7 @@ public class ImageView extends View {
}
mDrawMatrix.setScale(scale, scale);
- mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f));
+ mDrawMatrix.postTranslate(Math.round(dx), Math.round(dy));
} else if (ScaleType.CENTER_INSIDE == mScaleType) {
mDrawMatrix = mMatrix;
float scale;
@@ -1119,8 +1119,8 @@ public class ImageView extends View {
(float) vheight / (float) dheight);
}
- dx = (int) ((vwidth - dwidth * scale) * 0.5f + 0.5f);
- dy = (int) ((vheight - dheight * scale) * 0.5f + 0.5f);
+ dx = Math.round((vwidth - dwidth * scale) * 0.5f);
+ dy = Math.round((vheight - dheight * scale) * 0.5f);
mDrawMatrix.setScale(scale, scale);
mDrawMatrix.postTranslate(dx, dy);
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index f153ce5..9d14254 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -185,6 +185,8 @@ public class LinearLayout extends ViewGroup {
private int mShowDividers;
private int mDividerPadding;
+ private int mLayoutDirection = View.LAYOUT_DIRECTION_UNDEFINED;
+
public LinearLayout(Context context) {
this(context, null);
}
@@ -1567,6 +1569,17 @@ public class LinearLayout extends ViewGroup {
}
}
+ @Override
+ public void onRtlPropertiesChanged(@ResolvedLayoutDir int layoutDirection) {
+ super.onRtlPropertiesChanged(layoutDirection);
+ if (layoutDirection != mLayoutDirection) {
+ mLayoutDirection = layoutDirection;
+ if (mOrientation == HORIZONTAL) {
+ requestLayout();
+ }
+ }
+ }
+
/**
* Position the children during a layout pass if the orientation of this
* LinearLayout is set to {@link #HORIZONTAL}.
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 97348e30..ff2f22b 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -28,13 +28,15 @@ import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import com.android.internal.policy.PhoneWindow;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
+import android.view.accessibility.AccessibilityManager;
import android.widget.SeekBar.OnSeekBarChangeListener;
+import com.android.internal.policy.PhoneWindow;
+
import java.util.Formatter;
import java.util.Locale;
@@ -44,7 +46,7 @@ import java.util.Locale;
* slider. It takes care of synchronizing the controls with the state
* of the MediaPlayer.
* <p>
- * The way to use this class is to instantiate it programatically.
+ * The way to use this class is to instantiate it programmatically.
* The MediaController will create a default set of controls
* and put them in a window floating above your application. Specifically,
* the controls will float above the view specified with setAnchorView().
@@ -69,7 +71,7 @@ import java.util.Locale;
public class MediaController extends FrameLayout {
private MediaPlayerControl mPlayer;
- private Context mContext;
+ private final Context mContext;
private View mAnchor;
private View mRoot;
private WindowManager mWindowManager;
@@ -83,7 +85,7 @@ public class MediaController extends FrameLayout {
private static final int sDefaultTimeout = 3000;
private static final int FADE_OUT = 1;
private static final int SHOW_PROGRESS = 2;
- private boolean mUseFastForward;
+ private final boolean mUseFastForward;
private boolean mFromXml;
private boolean mListenersSet;
private View.OnClickListener mNextListener, mPrevListener;
@@ -96,6 +98,7 @@ public class MediaController extends FrameLayout {
private ImageButton mPrevButton;
private CharSequence mPlayDescription;
private CharSequence mPauseDescription;
+ private final AccessibilityManager mAccessibilityManager;
public MediaController(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -103,6 +106,7 @@ public class MediaController extends FrameLayout {
mContext = context;
mUseFastForward = true;
mFromXml = true;
+ mAccessibilityManager = AccessibilityManager.getInstance(context);
}
@Override
@@ -117,6 +121,7 @@ public class MediaController extends FrameLayout {
mUseFastForward = useFastForward;
initFloatingWindowLayout();
initFloatingWindow();
+ mAccessibilityManager = AccessibilityManager.getInstance(context);
}
public MediaController(Context context) {
@@ -179,8 +184,9 @@ public class MediaController extends FrameLayout {
}
// This is called whenever mAnchor's layout bound changes
- private OnLayoutChangeListener mLayoutChangeListener =
+ private final OnLayoutChangeListener mLayoutChangeListener =
new OnLayoutChangeListener() {
+ @Override
public void onLayoutChange(View v, int left, int top, int right,
int bottom, int oldLeft, int oldTop, int oldRight,
int oldBottom) {
@@ -191,7 +197,8 @@ public class MediaController extends FrameLayout {
}
};
- private OnTouchListener mTouchListener = new OnTouchListener() {
+ private final OnTouchListener mTouchListener = new OnTouchListener() {
+ @Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mShowing) {
@@ -368,9 +375,9 @@ public class MediaController extends FrameLayout {
// paused with the progress bar showing the user hits play.
mHandler.sendEmptyMessage(SHOW_PROGRESS);
- Message msg = mHandler.obtainMessage(FADE_OUT);
- if (timeout != 0) {
+ if (timeout != 0 && !mAccessibilityManager.isTouchExplorationEnabled()) {
mHandler.removeMessages(FADE_OUT);
+ Message msg = mHandler.obtainMessage(FADE_OUT);
mHandler.sendMessageDelayed(msg, timeout);
}
}
@@ -397,7 +404,7 @@ public class MediaController extends FrameLayout {
}
}
- private Handler mHandler = new Handler() {
+ private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
int pos;
@@ -527,7 +534,8 @@ public class MediaController extends FrameLayout {
return super.dispatchKeyEvent(event);
}
- private View.OnClickListener mPauseListener = new View.OnClickListener() {
+ private final View.OnClickListener mPauseListener = new View.OnClickListener() {
+ @Override
public void onClick(View v) {
doPauseResume();
show(sDefaultTimeout);
@@ -567,7 +575,8 @@ public class MediaController extends FrameLayout {
// The second scenario involves the user operating the scroll ball, in this
// case there WON'T BE onStartTrackingTouch/onStopTrackingTouch notifications,
// we will simply apply the updated position without suspending regular updates.
- private OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
+ private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
+ @Override
public void onStartTrackingTouch(SeekBar bar) {
show(3600000);
@@ -581,6 +590,7 @@ public class MediaController extends FrameLayout {
mHandler.removeMessages(SHOW_PROGRESS);
}
+ @Override
public void onProgressChanged(SeekBar bar, int progress, boolean fromuser) {
if (!fromuser) {
// We're not interested in programmatically generated changes to
@@ -595,6 +605,7 @@ public class MediaController extends FrameLayout {
mCurrentTime.setText(stringForTime( (int) newposition));
}
+ @Override
public void onStopTrackingTouch(SeekBar bar) {
mDragging = false;
setProgress();
@@ -637,7 +648,8 @@ public class MediaController extends FrameLayout {
return MediaController.class.getName();
}
- private View.OnClickListener mRewListener = new View.OnClickListener() {
+ private final View.OnClickListener mRewListener = new View.OnClickListener() {
+ @Override
public void onClick(View v) {
int pos = mPlayer.getCurrentPosition();
pos -= 5000; // milliseconds
@@ -648,7 +660,8 @@ public class MediaController extends FrameLayout {
}
};
- private View.OnClickListener mFfwdListener = new View.OnClickListener() {
+ private final View.OnClickListener mFfwdListener = new View.OnClickListener() {
+ @Override
public void onClick(View v) {
int pos = mPlayer.getCurrentPosition();
pos += 15000; // milliseconds
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index ca57d1a..11904e1 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -18,6 +18,7 @@ package android.widget;
import android.annotation.NonNull;
import android.os.Build;
+import android.os.Build.VERSION_CODES;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.R;
@@ -349,17 +350,24 @@ public class ScrollView extends FrameLayout {
if (getChildCount() > 0) {
final View child = getChildAt(0);
- int height = getMeasuredHeight();
+ final int height = getMeasuredHeight();
if (child.getMeasuredHeight() < height) {
+ final int widthPadding;
+ final int heightPadding;
final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
+ if (targetSdkVersion >= VERSION_CODES.MNC) {
+ widthPadding = mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin;
+ heightPadding = mPaddingTop + mPaddingBottom + lp.topMargin + lp.bottomMargin;
+ } else {
+ widthPadding = mPaddingLeft + mPaddingRight;
+ heightPadding = mPaddingTop + mPaddingBottom;
+ }
- int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
- mPaddingLeft + mPaddingRight, lp.width);
- height -= mPaddingTop;
- height -= mPaddingBottom;
- int childHeightMeasureSpec =
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
-
+ final int childWidthMeasureSpec = getChildMeasureSpec(
+ widthMeasureSpec, widthPadding, lp.width);
+ final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ height - heightPadding, MeasureSpec.EXACTLY);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 3a85476..b68934b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1481,7 +1481,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
if (mEditor.hasSelectionController()) {
- mEditor.startSelectionActionModeWithSelection();
+ mEditor.startSelectionActionMode();
}
}
}
@@ -5282,7 +5282,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// - onFocusChanged cannot start it when focus is given to a view with selected text (after
// a screen rotation) since layout is not yet initialized at that point.
if (mEditor != null && mEditor.mCreatedWithASelection) {
- mEditor.startSelectionActionModeWithSelection();
+ mEditor.startSelectionActionMode();
mEditor.mCreatedWithASelection = false;
}
@@ -5290,7 +5290,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// ExtractEditText does not call onFocus when it is displayed, and mHasSelectionOnFocus can
// not be set. Do the test here instead.
if (this instanceof ExtractEditText && hasSelection() && mEditor != null) {
- mEditor.startSelectionActionModeWithSelection();
+ mEditor.startSelectionActionMode();
}
unregisterForPreDraw();
@@ -5908,7 +5908,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
- boolean isInSelectionMode = mEditor != null && mEditor.mSelectionActionMode != null;
+ boolean isInSelectionMode = mEditor != null && mEditor.mTextActionMode != null;
if (isInSelectionMode) {
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
@@ -5923,7 +5923,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
state.handleUpEvent(event);
}
if (event.isTracking() && !event.isCanceled()) {
- stopSelectionActionMode();
+ stopTextActionMode();
return true;
}
}
@@ -6092,8 +6092,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// Has to be done on key down (and not on key up) to correctly be intercepted.
case KeyEvent.KEYCODE_BACK:
- if (mEditor != null && mEditor.mSelectionActionMode != null) {
- stopSelectionActionMode();
+ if (mEditor != null && mEditor.mTextActionMode != null) {
+ stopTextActionMode();
return -1;
}
break;
@@ -6423,7 +6423,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// extracted mode will start. Some text is selected though, and will trigger an action mode
// in the extracted view.
mEditor.hideControllers();
- stopSelectionActionMode();
+ stopTextActionMode();
}
/**
@@ -8258,7 +8258,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
super.onVisibilityChanged(changedView, visibility);
if (mEditor != null && visibility != VISIBLE) {
mEditor.hideControllers();
- stopSelectionActionMode();
+ stopTextActionMode();
}
}
@@ -8976,7 +8976,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
Selection.setSelection((Spannable) text, start, end);
// Make sure selection mode is engaged.
if (mEditor != null) {
- mEditor.startSelectionActionModeWithSelection();
+ mEditor.startSelectionActionMode();
}
return true;
}
@@ -9072,9 +9072,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
switch (id) {
case ID_SELECT_ALL:
- // This does not enter text selection mode. Text is highlighted, so that it can be
- // bulk edited, like selectAllOnFocus does. Returns true even if text is empty.
+ // This starts an action mode if triggered from another action mode. Text is
+ // highlighted, so that it can be bulk edited, like selectAllOnFocus does. Returns
+ // true even if text is empty.
+ boolean shouldRestartActionMode =
+ mEditor != null && mEditor.mTextActionMode != null;
+ stopTextActionMode();
selectAllText();
+ if (shouldRestartActionMode) {
+ mEditor.startSelectionActionMode();
+ }
return true;
case ID_UNDO:
@@ -9100,12 +9107,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
case ID_CUT:
setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
deleteText_internal(min, max);
- stopSelectionActionMode();
+ stopTextActionMode();
return true;
case ID_COPY:
setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
- stopSelectionActionMode();
+ stopTextActionMode();
return true;
case ID_REPLACE:
@@ -9195,14 +9202,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* selection is initiated in this View.
*
* The standard implementation populates the menu with a subset of Select All, Cut, Copy,
- * Paste and Share actions, depending on what this View supports.
+ * Paste, Replace and Share actions, depending on what this View supports.
*
* A custom implementation can add new entries in the default menu in its
* {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
* default actions can also be removed from the menu using
* {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
- * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste} or
- * {@link android.R.id#shareText} ids as parameters.
+ * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste},
+ * {@link android.R.id#replaceText} or {@link android.R.id#shareText} ids as parameters.
*
* Returning false from
* {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
@@ -9230,11 +9237,48 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
/**
+ * If provided, this ActionMode.Callback will be used to create the ActionMode when text
+ * insertion is initiated in this View.
+ *
+ * The standard implementation populates the menu with a subset of Select All,
+ * Paste and Replace actions, depending on what this View supports.
+ *
+ * A custom implementation can add new entries in the default menu in its
+ * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
+ * default actions can also be removed from the menu using
+ * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
+ * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters.
+ *
+ * Returning false from
+ * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
+ * the action mode from being started.
+ *
+ * Action click events should be handled by the custom implementation of
+ * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
+ *
+ * Note that text insertion mode is not started when a TextView receives focus and the
+ * {@link android.R.attr#selectAllOnFocus} flag has been set.
+ */
+ public void setCustomInsertionActionModeCallback(ActionMode.Callback actionModeCallback) {
+ createEditorIfNeeded();
+ mEditor.mCustomInsertionActionModeCallback = actionModeCallback;
+ }
+
+ /**
+ * Retrieves the value set in {@link #setCustomInsertionActionModeCallback}. Default is null.
+ *
+ * @return The current custom insertion callback.
+ */
+ public ActionMode.Callback getCustomInsertionActionModeCallback() {
+ return mEditor == null ? null : mEditor.mCustomInsertionActionModeCallback;
+ }
+
+ /**
* @hide
*/
- protected void stopSelectionActionMode() {
+ protected void stopTextActionMode() {
if (mEditor != null) {
- mEditor.stopSelectionActionMode();
+ mEditor.stopTextActionMode();
}
}
@@ -9298,7 +9342,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
boolean canSelectAllText() {
- return canSelectText() && !hasPasswordTransformationMethod();
+ return canSelectText() && !hasPasswordTransformationMethod()
+ && !(getSelectionStart() == 0 && getSelectionEnd() == mText.length());
}
boolean selectAllText() {
@@ -9346,7 +9391,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
}
- stopSelectionActionMode();
+ stopTextActionMode();
sLastCutCopyOrTextChangedTime = 0;
}
}
@@ -9359,7 +9404,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
sharingIntent.removeExtra(android.content.Intent.EXTRA_TEXT);
sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, selectedText);
getContext().startActivity(Intent.createChooser(sharingIntent, null));
- stopSelectionActionMode();
+ stopTextActionMode();
}
}
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 644adb6..a2bd700 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -97,6 +97,11 @@ interface IVoiceInteractionManagerService {
void showSessionForActiveService(IVoiceInteractionSessionShowCallback showCallback);
/**
+ * Hides the session from the active service, if it is showing.
+ */
+ void hideCurrentSession();
+
+ /**
* Notifies the active service that a launch was requested from the Keyguard. This will only
* be called if {@link #activeServiceSupportsLaunchFromKeyguard()} returns true.
*/
diff --git a/core/java/com/android/internal/app/IVoiceInteractor.aidl b/core/java/com/android/internal/app/IVoiceInteractor.aidl
index 84e9cf0..44feafb 100644
--- a/core/java/com/android/internal/app/IVoiceInteractor.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractor.aidl
@@ -27,14 +27,14 @@ import com.android.internal.app.IVoiceInteractorRequest;
*/
interface IVoiceInteractor {
IVoiceInteractorRequest startConfirmation(String callingPackage,
- IVoiceInteractorCallback callback, CharSequence prompt, in Bundle extras);
+ IVoiceInteractorCallback callback, in VoiceInteractor.Prompt prompt, in Bundle extras);
IVoiceInteractorRequest startPickOption(String callingPackage,
- IVoiceInteractorCallback callback, CharSequence prompt,
+ IVoiceInteractorCallback callback, in VoiceInteractor.Prompt prompt,
in VoiceInteractor.PickOptionRequest.Option[] options, in Bundle extras);
IVoiceInteractorRequest startCompleteVoice(String callingPackage,
- IVoiceInteractorCallback callback, CharSequence message, in Bundle extras);
+ IVoiceInteractorCallback callback, in VoiceInteractor.Prompt prompt, in Bundle extras);
IVoiceInteractorRequest startAbortVoice(String callingPackage,
- IVoiceInteractorCallback callback, CharSequence message, in Bundle extras);
+ IVoiceInteractorCallback callback, in VoiceInteractor.Prompt prompt, in Bundle extras);
IVoiceInteractorRequest startCommand(String callingPackage,
IVoiceInteractorCallback callback, String command, in Bundle extras);
boolean[] supportsCommands(String callingPackage, in String[] commands);
diff --git a/core/java/com/android/internal/logging/MetricsLogger.java b/core/java/com/android/internal/logging/MetricsLogger.java
index 230d96d..2f21efd 100644
--- a/core/java/com/android/internal/logging/MetricsLogger.java
+++ b/core/java/com/android/internal/logging/MetricsLogger.java
@@ -27,6 +27,7 @@ import android.view.View;
*/
public class MetricsLogger implements MetricsConstants {
// Temporary constants go here, to await migration to MetricsConstants.
+ public static final int ACTION_EMERGENCY_CALL = 200;
public static void visible(Context context, int category) throws IllegalArgumentException {
if (Build.IS_DEBUGGABLE && category == VIEW_UNKNOWN) {
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
index 056b0aa..049d3eb 100644
--- a/core/java/com/android/internal/os/BatterySipper.java
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -42,6 +42,8 @@ public class BatterySipper implements Comparable<BatterySipper> {
public long wifiRunningTimeMs;
public long cpuFgTimeMs;
public long wakeLockTimeMs;
+ public long cameraTimeMs;
+ public long flashlightTimeMs;
public long mobileRxPackets;
public long mobileTxPackets;
@@ -67,6 +69,8 @@ public class BatterySipper implements Comparable<BatterySipper> {
public double mobileRadioPowerMah;
public double gpsPowerMah;
public double sensorPowerMah;
+ public double cameraPowerMah;
+ public double flashlightPowerMah;
public enum DrainType {
IDLE,
@@ -79,7 +83,8 @@ public class BatterySipper implements Comparable<BatterySipper> {
APP,
USER,
UNACCOUNTED,
- OVERCOUNTED
+ OVERCOUNTED,
+ CAMERA
}
public BatterySipper(DrainType drainType, Uid uid, double value) {
@@ -135,6 +140,8 @@ public class BatterySipper implements Comparable<BatterySipper> {
wifiRunningTimeMs += other.wifiRunningTimeMs;
cpuFgTimeMs += other.cpuFgTimeMs;
wakeLockTimeMs += other.wakeLockTimeMs;
+ cameraTimeMs += other.cameraTimeMs;
+ flashlightTimeMs += other.flashlightTimeMs;
mobileRxPackets += other.mobileRxPackets;
mobileTxPackets += other.mobileTxPackets;
mobileActive += other.mobileActive;
@@ -151,6 +158,8 @@ public class BatterySipper implements Comparable<BatterySipper> {
sensorPowerMah += other.sensorPowerMah;
mobileRadioPowerMah += other.mobileRadioPowerMah;
wakeLockPowerMah += other.wakeLockPowerMah;
+ cameraPowerMah += other.cameraPowerMah;
+ flashlightPowerMah += other.flashlightPowerMah;
}
/**
@@ -158,7 +167,8 @@ public class BatterySipper implements Comparable<BatterySipper> {
* @return the sum of all the power in this BatterySipper.
*/
public double sumPower() {
- return totalPowerMah = usagePowerMah + wifiPowerMah + gpsPowerMah + cpuPowerMah + sensorPowerMah
- + mobileRadioPowerMah + wakeLockPowerMah;
+ return totalPowerMah = usagePowerMah + wifiPowerMah + gpsPowerMah + cpuPowerMah +
+ sensorPowerMah + mobileRadioPowerMah + wakeLockPowerMah + cameraPowerMah +
+ flashlightPowerMah;
}
}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index fbe87c5..4290e22 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -122,6 +122,8 @@ public final class BatteryStatsHelper {
PowerCalculator mWifiPowerCalculator;
PowerCalculator mBluetoothPowerCalculator;
PowerCalculator mSensorPowerCalculator;
+ PowerCalculator mCameraPowerCalculator;
+ PowerCalculator mFlashlightPowerCalculator;
public static boolean checkWifiOnly(Context context) {
ConnectivityManager cm = (ConnectivityManager)context.getSystemService(
@@ -352,9 +354,9 @@ public final class BatteryStatsHelper {
if (mBluetoothPowerCalculator == null) {
if (checkHasBluetoothPowerReporting(mStats, mPowerProfile)) {
- mBluetoothPowerCalculator = new BluetoothPowerCalculator();
+ mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
} else {
- mBluetoothPowerCalculator = new BluetoothPowerCalculator();
+ mBluetoothPowerCalculator = new BluetoothPowerCalculator(mPowerProfile);
}
}
mBluetoothPowerCalculator.reset();
@@ -365,6 +367,16 @@ public final class BatteryStatsHelper {
}
mSensorPowerCalculator.reset();
+ if (mCameraPowerCalculator == null) {
+ mCameraPowerCalculator = new CameraPowerCalculator(mPowerProfile);
+ }
+ mCameraPowerCalculator.reset();
+
+ if (mFlashlightPowerCalculator == null) {
+ mFlashlightPowerCalculator = new FlashlightPowerCalculator(mPowerProfile);
+ }
+ mFlashlightPowerCalculator.reset();
+
mStatsType = statsType;
mRawUptime = rawUptimeUs;
mRawRealtime = rawRealtimeUs;
@@ -480,6 +492,8 @@ public final class BatteryStatsHelper {
mWifiPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
mBluetoothPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
mSensorPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
+ mCameraPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
+ mFlashlightPowerCalculator.calculateApp(app, u, mRawRealtime, mRawUptime, mStatsType);
final double totalPower = app.sumPower();
if (DEBUG && totalPower != 0) {
@@ -619,15 +633,6 @@ public final class BatteryStatsHelper {
}
}
- private void addFlashlightUsage() {
- long flashlightOnTimeMs = mStats.getFlashlightOnTime(mRawRealtime, mStatsType) / 1000;
- double flashlightPower = flashlightOnTimeMs
- * mPowerProfile.getAveragePower(PowerProfile.POWER_FLASHLIGHT) / (60*60*1000);
- if (flashlightPower != 0) {
- addEntry(BatterySipper.DrainType.FLASHLIGHT, flashlightOnTimeMs, flashlightPower);
- }
- }
-
private void addUserUsage() {
for (int i = 0; i < mUserSippers.size(); i++) {
final int userId = mUserSippers.keyAt(i);
@@ -643,7 +648,6 @@ public final class BatteryStatsHelper {
addUserUsage();
addPhoneUsage();
addScreenUsage();
- addFlashlightUsage();
addWiFiUsage();
addBluetoothUsage();
addIdleUsage(); // Not including cellular idle power
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 62745d4..087db78 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -105,7 +105,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
- private static final int VERSION = 126 + (USE_OLD_HISTORY ? 1000 : 0);
+ private static final int VERSION = 127 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -272,18 +272,19 @@ public final class BatteryStatsImpl extends BatteryStats {
final HistoryStepDetails mCurHistoryStepDetails = new HistoryStepDetails();
final HistoryStepDetails mReadHistoryStepDetails = new HistoryStepDetails();
final HistoryStepDetails mTmpHistoryStepDetails = new HistoryStepDetails();
+
/**
- * Total time (in 1/100 sec) spent executing in user code.
+ * Total time (in milliseconds) spent executing in user code.
*/
long mLastStepCpuUserTime;
long mCurStepCpuUserTime;
/**
- * Total time (in 1/100 sec) spent executing in kernel code.
+ * Total time (in milliseconds) spent executing in kernel code.
*/
long mLastStepCpuSystemTime;
long mCurStepCpuSystemTime;
/**
- * Times from /proc/stat
+ * Times from /proc/stat (but measured in milliseconds).
*/
long mLastStepStatUserTime;
long mLastStepStatSystemTime;
@@ -4337,15 +4338,22 @@ public final class BatteryStatsImpl extends BatteryStats {
return 0;
}
- @Override public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
+ @Override
+ public long getFlashlightOnTime(long elapsedRealtimeUs, int which) {
return mFlashlightOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
}
- @Override public long getFlashlightOnCount(int which) {
+ @Override
+ public long getFlashlightOnCount(int which) {
return mFlashlightOnTimer.getCountLocked(which);
}
@Override
+ public long getCameraOnTime(long elapsedRealtimeUs, int which) {
+ return mCameraOnTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
+ }
+
+ @Override
public long getNetworkActivityBytes(int type, int which) {
if (type >= 0 && type < mNetworkByteActivityCounters.length) {
return mNetworkByteActivityCounters[type].getCountLocked(which);
@@ -7806,11 +7814,13 @@ public final class BatteryStatsImpl extends BatteryStats {
mWifiActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
info.getControllerIdleTimeMillis());
- final double opVoltage = mPowerProfile.getAveragePower(
- PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE);
- if (opVoltage != 0) {
+ // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
+ final double opVolt = mPowerProfile.getAveragePower(
+ PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+ if (opVolt != 0) {
+ // We store the power drain as mAms.
mWifiActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
- (long)(info.getControllerEnergyUsed() / opVoltage));
+ (long)(info.getControllerEnergyUsed() / opVolt));
}
}
}
@@ -7900,11 +7910,13 @@ public final class BatteryStatsImpl extends BatteryStats {
mBluetoothActivityCounters[CONTROLLER_IDLE_TIME].addCountLocked(
info.getControllerIdleTimeMillis());
- final double opVoltage = mPowerProfile.getAveragePower(
- PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE);
- if (opVoltage != 0) {
+ // POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
+ final double opVolt = mPowerProfile.getAveragePower(
+ PowerProfile.POWER_BLUETOOTH_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+ if (opVolt != 0) {
+ // We store the power drain as mAms.
mBluetoothActivityCounters[CONTROLLER_POWER_DRAIN].addCountLocked(
- (long) (info.getControllerEnergyUsed() / opVoltage));
+ (long) (info.getControllerEnergyUsed() / opVolt));
}
}
}
diff --git a/core/java/com/android/internal/os/BluetoothPowerCalculator.java b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
index 3557209..1f59672 100644
--- a/core/java/com/android/internal/os/BluetoothPowerCalculator.java
+++ b/core/java/com/android/internal/os/BluetoothPowerCalculator.java
@@ -21,6 +21,15 @@ import android.util.Log;
public class BluetoothPowerCalculator extends PowerCalculator {
private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
private static final String TAG = "BluetoothPowerCalculator";
+ private final double mIdleMa;
+ private final double mRxMa;
+ private final double mTxMa;
+
+ public BluetoothPowerCalculator(PowerProfile profile) {
+ mIdleMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_IDLE);
+ mRxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_RX);
+ mTxMa = profile.getAveragePower(PowerProfile.POWER_BLUETOOTH_CONTROLLER_TX);
+ }
@Override
public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
@@ -37,10 +46,15 @@ public class BluetoothPowerCalculator extends PowerCalculator {
BatteryStats.CONTROLLER_TX_TIME, statsType);
final long rxTimeMs = stats.getBluetoothControllerActivity(
BatteryStats.CONTROLLER_RX_TIME, statsType);
- final long powerMaMs = stats.getBluetoothControllerActivity(
- BatteryStats.CONTROLLER_POWER_DRAIN, statsType);
- final double powerMah = powerMaMs / (double)(1000*60*60);
final long totalTimeMs = idleTimeMs + txTimeMs + rxTimeMs;
+ double powerMah = stats.getBluetoothControllerActivity(
+ BatteryStats.CONTROLLER_POWER_DRAIN, statsType) / (double)(1000*60*60);
+
+ if (powerMah == 0) {
+ // Some devices do not report the power, so calculate it.
+ powerMah = ((idleTimeMs * mIdleMa) + (rxTimeMs * mRxMa) + (txTimeMs * mTxMa))
+ / (1000*60*60);
+ }
if (DEBUG && powerMah != 0) {
Log.d(TAG, "Bluetooth active: time=" + (totalTimeMs)
diff --git a/core/java/com/android/internal/os/CameraPowerCalculator.java b/core/java/com/android/internal/os/CameraPowerCalculator.java
new file mode 100644
index 0000000..3273080
--- /dev/null
+++ b/core/java/com/android/internal/os/CameraPowerCalculator.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os;
+
+import android.os.BatteryStats;
+
+/**
+ * Power calculator for the camera subsystem, excluding the flashlight.
+ *
+ * Note: Power draw for the flash unit should be included in the FlashlightPowerCalculator.
+ */
+public class CameraPowerCalculator extends PowerCalculator {
+ private final double mCameraPowerOnAvg;
+
+ public CameraPowerCalculator(PowerProfile profile) {
+ mCameraPowerOnAvg = profile.getAveragePower(PowerProfile.POWER_CAMERA);
+ }
+
+ @Override
+ public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
+ long rawUptimeUs, int statsType) {
+
+ // Calculate camera power usage. Right now, this is a (very) rough estimate based on the
+ // average power usage for a typical camera application.
+ final BatteryStats.Timer timer = u.getCameraTurnedOnTimer();
+ if (timer != null) {
+ final long totalTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;
+ app.cameraTimeMs = totalTime;
+ app.cameraPowerMah = (totalTime * mCameraPowerOnAvg) / (1000*60*60);
+ } else {
+ app.cameraTimeMs = 0;
+ app.cameraPowerMah = 0;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/os/FlashlightPowerCalculator.java b/core/java/com/android/internal/os/FlashlightPowerCalculator.java
new file mode 100644
index 0000000..fef66ff
--- /dev/null
+++ b/core/java/com/android/internal/os/FlashlightPowerCalculator.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os;
+
+import android.os.BatteryStats;
+
+/**
+ * Power calculator for the flashlight.
+ */
+public class FlashlightPowerCalculator extends PowerCalculator {
+ private final double mFlashlightPowerOnAvg;
+
+ public FlashlightPowerCalculator(PowerProfile profile) {
+ mFlashlightPowerOnAvg = profile.getAveragePower(PowerProfile.POWER_FLASHLIGHT);
+ }
+
+ @Override
+ public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
+ long rawUptimeUs, int statsType) {
+
+ // Calculate flashlight power usage. Right now, this is based on the average power draw
+ // of the flash unit when kept on over a short period of time.
+ final BatteryStats.Timer timer = u.getFlashlightTurnedOnTimer();
+ if (timer != null) {
+ final long totalTime = timer.getTotalTimeLocked(rawRealtimeUs, statsType) / 1000;
+ app.flashlightTimeMs = totalTime;
+ app.flashlightPowerMah = (totalTime * mFlashlightPowerOnAvg) / (1000*60*60);
+ } else {
+ app.flashlightTimeMs = 0;
+ app.flashlightPowerMah = 0;
+ }
+ }
+}
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 1efa565..4ede8dd 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -152,10 +152,17 @@ public class PowerProfile {
public static final String POWER_VIDEO = "dsp.video";
/**
- * Power consumption when camera flashlight is on.
+ * Average power consumption when camera flashlight is on.
*/
public static final String POWER_FLASHLIGHT = "camera.flashlight";
+ /**
+ * Average power consumption when the camera is on over all standard use cases.
+ *
+ * TODO: Add more fine-grained camera power metrics.
+ */
+ public static final String POWER_CAMERA = "camera.avg";
+
public static final String POWER_CPU_SPEEDS = "cpu.speeds";
/**
diff --git a/core/java/com/android/internal/os/ProcessCpuTracker.java b/core/java/com/android/internal/os/ProcessCpuTracker.java
index 8393e2a..bf97f1f 100644
--- a/core/java/com/android/internal/os/ProcessCpuTracker.java
+++ b/core/java/com/android/internal/os/ProcessCpuTracker.java
@@ -139,6 +139,8 @@ public class ProcessCpuTracker {
private float mLoad5 = 0;
private float mLoad15 = 0;
+ // All times are in milliseconds. They are converted from jiffies to milliseconds
+ // when extracted from the kernel.
private long mCurrentSampleTime;
private long mLastSampleTime;
@@ -191,12 +193,34 @@ public class ProcessCpuTracker {
// filter out kernel processes.
public long vsize;
+ /**
+ * Time in milliseconds.
+ */
public long base_uptime;
+
+ /**
+ * Time in milliseconds.
+ */
public long rel_uptime;
+ /**
+ * Time in milliseconds.
+ */
public long base_utime;
+
+ /**
+ * Time in milliseconds.
+ */
public long base_stime;
+
+ /**
+ * Time in milliseconds.
+ */
public int rel_utime;
+
+ /**
+ * Time in milliseconds.
+ */
public int rel_stime;
public long base_minfaults;
@@ -558,7 +582,7 @@ public class ProcessCpuTracker {
}
/**
- * Returns the total time (in clock ticks, or 1/100 sec) spent executing in
+ * Returns the total time (in milliseconds) spent executing in
* both user and system code. Safe to call without lock held.
*/
public long getCpuTimeForPid(int pid) {
@@ -575,26 +599,44 @@ public class ProcessCpuTracker {
}
}
+ /**
+ * @return time in milliseconds.
+ */
final public int getLastUserTime() {
return mRelUserTime;
}
+ /**
+ * @return time in milliseconds.
+ */
final public int getLastSystemTime() {
return mRelSystemTime;
}
+ /**
+ * @return time in milliseconds.
+ */
final public int getLastIoWaitTime() {
return mRelIoWaitTime;
}
+ /**
+ * @return time in milliseconds.
+ */
final public int getLastIrqTime() {
return mRelIrqTime;
}
+ /**
+ * @return time in milliseconds.
+ */
final public int getLastSoftIrqTime() {
return mRelSoftIrqTime;
}
+ /**
+ * @return time in milliseconds.
+ */
final public int getLastIdleTime() {
return mRelIdleTime;
}
diff --git a/core/java/com/android/internal/os/WifiPowerCalculator.java b/core/java/com/android/internal/os/WifiPowerCalculator.java
index 961b0df..da98a67 100644
--- a/core/java/com/android/internal/os/WifiPowerCalculator.java
+++ b/core/java/com/android/internal/os/WifiPowerCalculator.java
@@ -70,14 +70,14 @@ public class WifiPowerCalculator extends PowerCalculator {
statsType);
app.wifiRunningTimeMs = idleTimeMs + rxTimeMs + txTimeMs;
- double powerDrain = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_POWER_DRAIN,
+ double powerDrainMah = stats.getWifiControllerActivity(BatteryStats.CONTROLLER_POWER_DRAIN,
statsType) / (double)(1000*60*60);
- if (powerDrain == 0) {
+ if (powerDrainMah == 0) {
// Some controllers do not report power drain, so we can calculate it here.
- powerDrain = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa)
+ powerDrainMah = ((idleTimeMs * mIdleCurrentMa) + (txTimeMs * mTxCurrentMa)
+ (rxTimeMs * mRxCurrentMa)) / (1000*60*60);
}
- app.wifiPowerMah = Math.max(0, powerDrain - mTotalAppPowerDrain);
+ app.wifiPowerMah = Math.max(0, powerDrainMah - mTotalAppPowerDrain);
if (DEBUG) {
Log.d(TAG, "left over WiFi power: " + BatteryStatsHelper.makemAh(app.wifiPowerMah));
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 5ed4f70..971da77 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -508,7 +508,7 @@ public class ZygoteInit {
String args[] = {
"--setuid=1000",
"--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
+ "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1032,3001,3002,3003,3006,3007",
"--capabilities=" + capabilities + "," + capabilities,
"--nice-name=system_server",
"--runtime-args",
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 14065b1..294e4ba 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -75,6 +75,7 @@ import com.android.internal.widget.SwipeDismissLayout;
import android.app.ActivityManager;
import android.app.KeyguardManager;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
@@ -2740,7 +2741,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
try {
mode = getCallback().onWindowStartingActionMode(wrappedCallback, type);
} catch (AbstractMethodError ame) {
- // Older apps might not implement this callback method.
+ // Older apps might not implement the typed version of this method.
+ if (type == ActionMode.TYPE_PRIMARY) {
+ try {
+ mode = getCallback().onWindowStartingActionMode(wrappedCallback);
+ } catch (AbstractMethodError ame2) {
+ // Older apps might not implement this callback method at all.
+ }
+ }
}
}
if (mode != null) {
@@ -4319,8 +4327,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (!result && (getContext().getResources().getConfiguration().uiMode
& Configuration.UI_MODE_TYPE_MASK) == Configuration.UI_MODE_TYPE_TELEVISION) {
// On TVs, if the app doesn't implement search, we want to launch assist.
+ Bundle args = new Bundle();
+ args.putInt(Intent.EXTRA_ASSIST_INPUT_DEVICE_ID, event.getDeviceId());
return ((SearchManager)getContext().getSystemService(Context.SEARCH_SERVICE))
- .launchAssistAction(null, UserHandle.myUserId());
+ .launchAssistAction(null, UserHandle.myUserId(), args);
}
return result;
}
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 93d2a1d..661dce1 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -23,6 +23,7 @@ import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
+import android.view.ViewConfiguration;
import com.android.internal.util.Preconditions;
import com.android.internal.view.menu.MenuBuilder;
@@ -30,7 +31,7 @@ import com.android.internal.widget.FloatingToolbar;
public class FloatingActionMode extends ActionMode {
- private static final int MAX_SNOOZE_TIME = 3000;
+ private static final int MAX_HIDE_DURATION = 3000;
private static final int MOVING_HIDE_DELAY = 300;
private final Context mContext;
@@ -50,9 +51,9 @@ public class FloatingActionMode extends ActionMode {
}
};
- private final Runnable mSnoozeOff = new Runnable() {
+ private final Runnable mHideOff = new Runnable() {
public void run() {
- mFloatingToolbarVisibilityHelper.setSnoozed(false);
+ mFloatingToolbarVisibilityHelper.setHideRequested(false);
}
};
@@ -127,11 +128,16 @@ public class FloatingActionMode extends ActionMode {
private void repositionToolbar() {
checkToolbarInitialized();
+
+ mContentRectOnWindow.set(mContentRect);
+ mContentRectOnWindow.offset(mViewPosition[0], mViewPosition[1]);
+ // Make sure that content rect is not out of the view's visible bounds.
mContentRectOnWindow.set(
- mContentRect.left + mViewPosition[0],
- mContentRect.top + mViewPosition[1],
- mContentRect.right + mViewPosition[0],
- mContentRect.bottom + mViewPosition[1]);
+ Math.max(mContentRectOnWindow.left, mViewRect.left),
+ Math.max(mContentRectOnWindow.top, mViewRect.top),
+ Math.min(mContentRectOnWindow.right, mViewRect.right),
+ Math.min(mContentRectOnWindow.bottom, mViewRect.bottom));
+
if (!mContentRectOnWindow.equals(mPreviousContentRectOnWindow)) {
if (!mPreviousContentRectOnWindow.isEmpty()) {
notifyContentRectMoving();
@@ -166,15 +172,19 @@ public class FloatingActionMode extends ActionMode {
}
@Override
- public void snooze(int snoozeTime) {
+ public void hide(long duration) {
checkToolbarInitialized();
- snoozeTime = Math.min(MAX_SNOOZE_TIME, snoozeTime);
- mOriginatingView.removeCallbacks(mSnoozeOff);
- if (snoozeTime <= 0) {
- mSnoozeOff.run();
+
+ if (duration == ActionMode.DEFAULT_HIDE_DURATION) {
+ duration = ViewConfiguration.getDefaultActionModeHideDuration();
+ }
+ duration = Math.min(MAX_HIDE_DURATION, duration);
+ mOriginatingView.removeCallbacks(mHideOff);
+ if (duration <= 0) {
+ mHideOff.run();
} else {
- mFloatingToolbarVisibilityHelper.setSnoozed(true);
- mOriginatingView.postDelayed(mSnoozeOff, snoozeTime);
+ mFloatingToolbarVisibilityHelper.setHideRequested(true);
+ mOriginatingView.postDelayed(mHideOff, duration);
}
}
@@ -220,7 +230,7 @@ public class FloatingActionMode extends ActionMode {
private void reset() {
mOriginatingView.removeCallbacks(mMovingOff);
- mOriginatingView.removeCallbacks(mSnoozeOff);
+ mOriginatingView.removeCallbacks(mHideOff);
}
@@ -231,7 +241,7 @@ public class FloatingActionMode extends ActionMode {
private final FloatingToolbar mToolbar;
- private boolean mSnoozed;
+ private boolean mHideRequested;
private boolean mMoving;
private boolean mOutOfBounds;
@@ -239,8 +249,8 @@ public class FloatingActionMode extends ActionMode {
mToolbar = Preconditions.checkNotNull(toolbar);
}
- public void setSnoozed(boolean snoozed) {
- mSnoozed = snoozed;
+ public void setHideRequested(boolean hide) {
+ mHideRequested = hide;
updateToolbarVisibility();
}
@@ -255,7 +265,7 @@ public class FloatingActionMode extends ActionMode {
}
private void updateToolbarVisibility() {
- if (mSnoozed || mMoving || mOutOfBounds) {
+ if (mHideRequested || mMoving || mOutOfBounds) {
mToolbar.hide();
} else if (mToolbar.isHidden()) {
mToolbar.show();