summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/animation/AnimatorInflater.java28
-rw-r--r--core/java/android/animation/AnimatorSet.java3
-rw-r--r--core/java/android/animation/ValueAnimator.java5
-rw-r--r--core/java/android/annotation/BinderThread.java42
-rw-r--r--core/java/android/annotation/MainThread.java42
-rw-r--r--core/java/android/annotation/UiThread.java42
-rw-r--r--core/java/android/annotation/WorkerThread.java42
-rw-r--r--core/java/android/app/Activity.java12
-rw-r--r--core/java/android/app/ActivityManagerInternal.java21
-rw-r--r--core/java/android/app/ActivityManagerNative.java41
-rw-r--r--core/java/android/app/ActivityThread.java15
-rw-r--r--core/java/android/app/AlarmManager.java9
-rw-r--r--core/java/android/app/AssistStructure.java11
-rw-r--r--core/java/android/app/IActivityManager.java5
-rw-r--r--core/java/android/app/IAlarmManager.aidl1
-rw-r--r--core/java/android/app/INotificationManager.aidl5
-rw-r--r--core/java/android/app/NotificationManager.java29
-rw-r--r--core/java/android/app/admin/DeviceAdminReceiver.java33
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java91
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl7
-rw-r--r--core/java/android/app/admin/SystemUpdatePolicy.java (renamed from core/java/android/app/admin/OtaPolicy.java)64
-rw-r--r--core/java/android/app/backup/BlobBackupHelper.java296
-rw-r--r--core/java/android/content/ContentProvider.java35
-rw-r--r--core/java/android/content/Context.java1
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java10
-rw-r--r--core/java/android/content/pm/LauncherApps.java1
-rw-r--r--core/java/android/content/pm/PackageCleanItem.java2
-rw-r--r--core/java/android/content/pm/PackageManager.java15
-rw-r--r--core/java/android/content/pm/ParceledListSlice.java3
-rw-r--r--core/java/android/database/sqlite/SQLiteConnection.java17
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java22
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintUtils.java18
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl2
-rw-r--r--core/java/android/net/ConnectivityManager.java66
-rw-r--r--core/java/android/net/IConnectivityManager.aidl2
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java48
-rw-r--r--core/java/android/nfc/cardemulation/CardEmulation.java31
-rw-r--r--core/java/android/os/Parcel.java99
-rw-r--r--core/java/android/os/Parcelable.java5
-rw-r--r--core/java/android/os/storage/DiskInfo.java3
-rw-r--r--core/java/android/os/storage/StorageManager.java2
-rw-r--r--core/java/android/provider/ContactsContract.java144
-rw-r--r--core/java/android/provider/Settings.java36
-rw-r--r--core/java/android/security/NetworkSecurityPolicy.java8
-rw-r--r--core/java/android/view/DisplayListCanvas.java4
-rw-r--r--core/java/android/view/KeyEvent.java18
-rw-r--r--core/java/android/view/ScaleGestureDetector.java46
-rw-r--r--core/java/android/view/View.java137
-rw-r--r--core/java/android/view/ViewAssistStructure.java2
-rw-r--r--core/java/android/view/ViewDebug.java8
-rw-r--r--core/java/android/view/ViewGroup.java32
-rw-r--r--core/java/android/webkit/WebSettings.java8
-rw-r--r--core/java/android/widget/Editor.java82
-rw-r--r--core/java/android/widget/PopupWindow.java82
-rw-r--r--core/java/android/widget/TextView.java31
55 files changed, 1534 insertions, 330 deletions
diff --git a/core/java/android/animation/AnimatorInflater.java b/core/java/android/animation/AnimatorInflater.java
index 224e8e9..e47d017 100644
--- a/core/java/android/animation/AnimatorInflater.java
+++ b/core/java/android/animation/AnimatorInflater.java
@@ -790,6 +790,31 @@ public class AnimatorInflater {
return valuesArray;
}
+ // When no value type is provided in keyframe, we need to infer the type from the value. i.e.
+ // if value is defined in the style of a color value, then the color type is returned.
+ // Otherwise, default float type is returned.
+ private static int inferValueTypeOfKeyframe(Resources res, Theme theme, AttributeSet attrs) {
+ int valueType;
+ TypedArray a;
+ if (theme != null) {
+ a = theme.obtainStyledAttributes(attrs, R.styleable.Keyframe, 0, 0);
+ } else {
+ a = res.obtainAttributes(attrs, R.styleable.Keyframe);
+ }
+
+ TypedValue keyframeValue = a.peekValue(R.styleable.Keyframe_value);
+ boolean hasValue = (keyframeValue != null);
+ // When no value type is provided, check whether it's a color type first.
+ // If not, fall back to default value type (i.e. float type).
+ if (hasValue && isColorType(keyframeValue.type)) {
+ valueType = VALUE_TYPE_COLOR;
+ } else {
+ valueType = VALUE_TYPE_FLOAT;
+ }
+ a.recycle();
+ return valueType;
+ }
+
private static void dumpKeyframes(Object[] keyframes, String header) {
if (keyframes == null || keyframes.length == 0) {
return;
@@ -817,6 +842,9 @@ public class AnimatorInflater {
type != XmlPullParser.END_DOCUMENT) {
String name = parser.getName();
if (name.equals("keyframe")) {
+ if (valueType == VALUE_TYPE_UNDEFINED) {
+ valueType = inferValueTypeOfKeyframe(res, theme, Xml.asAttributeSet(parser));
+ }
Keyframe keyframe = loadKeyframe(res, theme, Xml.asAttributeSet(parser), valueType);
if (keyframe != null) {
if (keyframes == null) {
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index dd5f18e..f6ad847 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -1095,7 +1095,8 @@ public final class AnimatorSet extends Animator {
public Node clone() {
try {
Node node = (Node) super.clone();
- node.animation = (Animator) animation.clone();
+ node.animation = animation.clone();
+ node.done = false;
return node;
} catch (CloneNotSupportedException e) {
throw new AssertionError();
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 275e78e..292507b 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1486,6 +1486,11 @@ public class ValueAnimator extends Animator {
anim.mPaused = false;
anim.mResumed = false;
anim.mStartListenersCalled = false;
+ anim.mStartTime = 0;
+ anim.mStartTimeCommitted = false;
+ anim.mPauseTime = 0;
+ anim.mCurrentFraction = 0;
+ anim.mDelayStartTime = 0;
PropertyValuesHolder[] oldValues = mValues;
if (oldValues != null) {
diff --git a/core/java/android/annotation/BinderThread.java b/core/java/android/annotation/BinderThread.java
new file mode 100644
index 0000000..c69ba10
--- /dev/null
+++ b/core/java/android/annotation/BinderThread.java
@@ -0,0 +1,42 @@
+/*
+ * 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.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Denotes that the annotated method should only be called on the binder thread.
+ * If the annotated element is a class, then all methods in the class should be called
+ * on the binder thread.
+ * <p>
+ * Example:
+ * <pre>{@code
+ * (&#64;BinderThread
+ * public BeamShareData createBeamShareData() { ... }
+ * }</pre>
+ *
+ * {@hide}
+ */
+@Retention(SOURCE)
+@Target({METHOD,CONSTRUCTOR,TYPE})
+public @interface BinderThread {
+} \ No newline at end of file
diff --git a/core/java/android/annotation/MainThread.java b/core/java/android/annotation/MainThread.java
new file mode 100644
index 0000000..18a4283
--- /dev/null
+++ b/core/java/android/annotation/MainThread.java
@@ -0,0 +1,42 @@
+/*
+ * 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.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Denotes that the annotated method should only be called on the main thread.
+ * If the annotated element is a class, then all methods in the class should be called
+ * on the main thread.
+ * <p>
+ * Example:
+ * <pre>{@code
+ * &#64;MainThread
+ * public void deliverResult(D data) { ... }
+ * }</pre>
+ *
+ * {@hide}
+ */
+@Retention(SOURCE)
+@Target({METHOD,CONSTRUCTOR,TYPE})
+public @interface MainThread {
+} \ No newline at end of file
diff --git a/core/java/android/annotation/UiThread.java b/core/java/android/annotation/UiThread.java
new file mode 100644
index 0000000..b814600
--- /dev/null
+++ b/core/java/android/annotation/UiThread.java
@@ -0,0 +1,42 @@
+/*
+ * 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.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Denotes that the annotated method or constructor should only be called on the UI thread.
+ * If the annotated element is a class, then all methods in the class should be called
+ * on the UI thread.
+ * <p>
+ * Example:
+ * <pre>{@code
+ * &#64;UiThread
+ * public abstract void setText(&#64;NonNull String text) { ... }
+ * }</pre>
+ *
+ * {@hide}
+ */
+@Retention(SOURCE)
+@Target({METHOD,CONSTRUCTOR,TYPE})
+public @interface UiThread {
+} \ No newline at end of file
diff --git a/core/java/android/annotation/WorkerThread.java b/core/java/android/annotation/WorkerThread.java
new file mode 100644
index 0000000..dd12e05
--- /dev/null
+++ b/core/java/android/annotation/WorkerThread.java
@@ -0,0 +1,42 @@
+/*
+ * 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.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.CONSTRUCTOR;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Denotes that the annotated method should only be called on a worker thread.
+ * If the annotated element is a class, then all methods in the class should be called
+ * on a worker thread.
+ * <p>
+ * Example:
+ * <pre>{@code
+ * (&#64;WorkerThread
+ * protected abstract FilterResults performFiltering(CharSequence constraint);
+ * }</pre>
+ *
+ * {@hide}
+ */
+@Retention(SOURCE)
+@Target({METHOD,CONSTRUCTOR,TYPE})
+public @interface WorkerThread {
+} \ No newline at end of file
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 4ccde1c..69cba78 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -6483,6 +6483,18 @@ public class Activity extends ContextThemeWrapper
}
/**
+ * Shows the user the system defined message for telling the user how to exit
+ * lock task mode. The task containing this activity must be in lock task mode at the time
+ * of this call for the message to be displayed.
+ */
+ public void showLockTaskEscapeMessage() {
+ try {
+ ActivityManagerNative.getDefault().showLockTaskEscapeMessage(mToken);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
* Interface for informing a translucent {@link Activity} once all visible activities below it
* have completed drawing. This is necessary only after an {@link Activity} has been made
* opaque using {@link Activity#convertFromTranslucent()} and before it has been drawn
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index d56dc1e..bde8f39 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -16,6 +16,8 @@
package android.app;
+import android.annotation.NonNull;
+
/**
* Activity manager local system service interface.
*
@@ -27,4 +29,23 @@ public abstract class ActivityManagerInternal {
public abstract int startIsolatedProcess(String entryPoint, String[] mainArgs,
String processName, String abiOverride, int uid, Runnable crashHandler);
+
+ /**
+ * Acquires a sleep token with the specified tag.
+ *
+ * @param tag A string identifying the purpose of the token (eg. "Dream").
+ */
+ public abstract SleepToken acquireSleepToken(@NonNull String tag);
+
+ /**
+ * Sleep tokens cause the activity manager to put the top activity to sleep.
+ * They are used by components such as dreams that may hide and block interaction
+ * with underlying activities.
+ */
+ public static abstract class SleepToken {
+ /**
+ * Releases the sleep token.
+ */
+ public abstract void release();
+ }
}
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index add7af2..b11c509 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -2345,6 +2345,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ final IBinder token = data.readStrongBinder();
+ showLockTaskEscapeMessage(token);
+ reply.writeNoException();
+ return true;
+ }
+
case SET_TASK_DESCRIPTION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
@@ -2505,6 +2513,14 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
return true;
}
+ case UPDATE_DEVICE_OWNER_TRANSACTION: {
+ data.enforceInterface(IActivityManager.descriptor);
+ String packageName = data.readString();
+ updateDeviceOwner(packageName);
+ reply.writeNoException();
+ return true;
+ }
+
case GET_PACKAGE_PROCESS_STATE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
String pkg = data.readString();
@@ -5552,6 +5568,19 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
+ public void showLockTaskEscapeMessage(IBinder token) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeStrongBinder(token);
+ mRemote.transact(SHOW_LOCK_TASK_ESCAPE_MESSAGE_TRANSACTION, data, reply,
+ IBinder.FLAG_ONEWAY);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
throws RemoteException {
Parcel data = Parcel.obtain();
@@ -5780,6 +5809,18 @@ class ActivityManagerProxy implements IActivityManager
}
@Override
+ public void updateDeviceOwner(String packageName) throws RemoteException {
+ Parcel data = Parcel.obtain();
+ Parcel reply = Parcel.obtain();
+ data.writeInterfaceToken(IActivityManager.descriptor);
+ data.writeString(packageName);
+ mRemote.transact(UPDATE_DEVICE_OWNER_TRANSACTION, data, reply, 0);
+ reply.readException();
+ data.recycle();
+ reply.recycle();
+ }
+
+ @Override
public int getPackageProcessState(String packageName) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 10d6d01..ab5f811 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -2541,11 +2541,16 @@ public final class ActivityThread {
if (cmd.requestType == ActivityManager.ASSIST_CONTEXT_FULL) {
data.putParcelable(AssistStructure.ASSIST_KEY, new AssistStructure(r.activity));
AssistContent content = new AssistContent();
- Intent intent = new Intent(r.activity.getIntent());
- intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
- intent.removeUnsafeExtras();
- content.setIntent(intent);
+ Intent activityIntent = r.activity.getIntent();
+ if (activityIntent != null) {
+ Intent intent = new Intent(activityIntent);
+ intent.setFlags(intent.getFlags() & ~(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
+ intent.removeUnsafeExtras();
+ content.setIntent(intent);
+ } else {
+ content.setIntent(new Intent());
+ }
r.activity.onProvideAssistContent(content);
data.putParcelable(AssistContent.ASSIST_KEY, content);
}
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 179957d..9d1d312 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -597,6 +597,15 @@ public class AlarmManager
}
}
+ /** @hide */
+ public long getNextWakeFromIdleTime() {
+ try {
+ return mService.getNextWakeFromIdleTime();
+ } catch (RemoteException ex) {
+ return Long.MAX_VALUE;
+ }
+ }
+
/**
* Gets information about the next alarm clock currently scheduled.
*
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index 1e159a3..9946d79 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -218,6 +218,7 @@ final public class AssistStructure implements Parcelable {
static final int FLAGS_FOCUSED = 0x00000020;
static final int FLAGS_ACCESSIBILITY_FOCUSED = 0x04000000;
static final int FLAGS_SELECTED = 0x00000040;
+ static final int FLAGS_ASSIST_BLOCKED = 0x00000080;
static final int FLAGS_ACTIVATED = 0x40000000;
static final int FLAGS_CHECKABLE = 0x00000100;
static final int FLAGS_CHECKED = 0x00000200;
@@ -356,6 +357,10 @@ final public class AssistStructure implements Parcelable {
return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
}
+ public boolean isAssistBlocked() {
+ return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0;
+ }
+
public boolean isEnabled() {
return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
}
@@ -484,6 +489,12 @@ final public class AssistStructure implements Parcelable {
}
@Override
+ public void setAssistBlocked(boolean state) {
+ mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_ASSIST_BLOCKED)
+ | (state ? 0 : ViewNode.FLAGS_ASSIST_BLOCKED);
+ }
+
+ @Override
public void setEnabled(boolean state) {
mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_DISABLED)
| (state ? 0 : ViewNode.FLAGS_DISABLED);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 59de281..00558fe 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -467,6 +467,8 @@ public interface IActivityManager extends IInterface {
public int getLockTaskModeState() throws RemoteException;
+ public void showLockTaskEscapeMessage(IBinder token) throws RemoteException;
+
public void setTaskDescription(IBinder token, ActivityManager.TaskDescription values)
throws RemoteException;
public void setTaskResizeable(int taskId, boolean resizeable) throws RemoteException;
@@ -493,6 +495,7 @@ public interface IActivityManager extends IInterface {
public void setVoiceKeepAwake(IVoiceInteractionSession session, boolean keepAwake)
throws RemoteException;
public void updateLockTaskPackages(int userId, String[] packages) throws RemoteException;
+ public void updateDeviceOwner(String packageName) throws RemoteException;
public int getPackageProcessState(String packageName) throws RemoteException;
@@ -834,4 +837,6 @@ public interface IActivityManager extends IInterface {
int NOTE_ALARM_START_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+291;
int NOTE_ALARM_FINISH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+292;
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;
}
diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl
index d5719f5..327c00b 100644
--- a/core/java/android/app/IAlarmManager.aidl
+++ b/core/java/android/app/IAlarmManager.aidl
@@ -33,6 +33,7 @@ interface IAlarmManager {
boolean setTime(long millis);
void setTimeZone(String zone);
void remove(in PendingIntent operation);
+ long getNextWakeFromIdleTime();
AlarmManager.AlarmClockInfo getNextAlarmClock(int userId);
}
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 913159a..e275df0 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -89,4 +89,9 @@ interface INotificationManager
boolean isNotificationPolicyTokenValid(String pkg, in NotificationManager.Policy.Token token);
NotificationManager.Policy getNotificationPolicy(in NotificationManager.Policy.Token token);
void setNotificationPolicy(in NotificationManager.Policy.Token token, in NotificationManager.Policy policy);
+
+ byte[] getBackupPayload(int user);
+ void applyRestore(in byte[] payload, int user);
+
+ ParceledListSlice getAppActiveNotifications(String callingPkg, int userId);
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 7133dce..0a59026 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -23,6 +23,7 @@ import android.app.Notification.Builder;
import android.app.NotificationManager.Policy.Token;
import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ParceledListSlice;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -35,10 +36,12 @@ import android.os.StrictMode;
import android.os.UserHandle;
import android.provider.Settings.Global;
import android.service.notification.IConditionListener;
+import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.util.Log;
import java.util.Objects;
+import java.util.List;
/**
* Class to notify the user of events that happen. This is how you tell
@@ -642,4 +645,30 @@ public class NotificationManager
}
}
+ /**
+ * Recover a list of active notifications: ones that have been posted by the calling app that
+ * have not yet been dismissed by the user or {@link #cancel(String, int)}ed by the app.
+ *
+ * Each notification is embedded in a {@link StatusBarNotification} object, including the
+ * original <code>tag</code> and <code>id</code> supplied to
+ * {@link #notify(String, int, Notification) notify()}
+ * (via {@link StatusBarNotification#getTag() getTag()} and
+ * {@link StatusBarNotification#getId() getId()}) as well as a copy of the original
+ * {@link Notification} object (via {@link StatusBarNotification#getNotification()}).
+ *
+ * @return An array of {@link StatusBarNotification}.
+ */
+ public StatusBarNotification[] getActiveNotifications() {
+ final INotificationManager service = getService();
+ final String pkg = mContext.getPackageName();
+ try {
+ final ParceledListSlice<StatusBarNotification> parceledList
+ = service.getAppActiveNotifications(pkg, UserHandle.myUserId());
+ final List<StatusBarNotification> list = parceledList.getList();
+ return list.toArray(new StatusBarNotification[list.size()]);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Unable to talk to notification manager. Woe!", e);
+ }
+ return new StatusBarNotification[0];
+ }
}
diff --git a/core/java/android/app/admin/DeviceAdminReceiver.java b/core/java/android/app/admin/DeviceAdminReceiver.java
index fe284ce..aea413d 100644
--- a/core/java/android/app/admin/DeviceAdminReceiver.java
+++ b/core/java/android/app/admin/DeviceAdminReceiver.java
@@ -264,6 +264,20 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
public static final String EXTRA_CHOOSE_PRIVATE_KEY_RESPONSE = "android.app.extra.CHOOSE_PRIVATE_KEY_RESPONSE";
/**
+ * Broadcast action: notify device owner that there is a pending system update.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_NOTIFY_PENDING_SYSTEM_UPDATE = "android.app.action.NOTIFY_PENDING_SYSTEM_UPDATE";
+
+ /**
+ * A long type extra for {@link #onSystemUpdatePending} recording the system time as given by
+ * {@link System#currentTimeMillis()} when the current pending system update is first available.
+ * @hide
+ */
+ public static final String EXTRA_SYSTEM_UPDATE_RECEIVED_TIME = "android.app.extra.SYSTEM_UPDATE_RECEIVED_TIME";
+
+ /**
* Name under which a DevicePolicy component publishes information
* about itself. This meta-data must reference an XML resource containing
* a device-admin tag.
@@ -486,6 +500,22 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
}
/**
+ * Allows the receiver to be notified when information about a pending system update is
+ * available from the system update service. The same pending system update can trigger multiple
+ * calls to this method, so it is necessary to examine the incoming parameters for details about
+ * the update.
+ * <p>
+ * This callback is only applicable to device owners.
+ *
+ * @param context The running context as per {@link #onReceive}.
+ * @param intent The received intent as per {@link #onReceive}.
+ * @param receivedTime The time as given by {@link System#currentTimeMillis()} indicating when
+ * the current pending update was first available. -1 if no pending update is available.
+ */
+ public void onSystemUpdatePending(Context context, Intent intent, long receivedTime) {
+ }
+
+ /**
* Intercept standard device administrator broadcasts. Implementations
* should not override this method; it is better to implement the
* convenience callbacks for each action.
@@ -530,6 +560,9 @@ public class DeviceAdminReceiver extends BroadcastReceiver {
onLockTaskModeExiting(context, intent);
} else if (ACTION_READY_FOR_USER_INITIALIZATION.equals(action)) {
onReadyForUserInitialization(context, intent);
+ } else if (ACTION_NOTIFY_PENDING_SYSTEM_UPDATE.equals(action)) {
+ long receivedTime = intent.getLongExtra(EXTRA_SYSTEM_UPDATE_RECEIVED_TIME, -1);
+ onSystemUpdatePending(context, intent, receivedTime);
}
}
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 0ea237a..a20aa66 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -800,11 +800,12 @@ public class DevicePolicyManager {
public static final int FLAG_MANAGED_CAN_ACCESS_PARENT = 0x0002;
/**
- * Broadcast action: notify that a new local OTA policy has been set by the device owner.
- * The new policy can be retrieved by {@link #getOtaPolicy()}.
+ * Broadcast action: notify that a new local system update policy has been set by the device
+ * owner. The new policy can be retrieved by {@link #getSystemUpdatePolicy()}.
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_OTA_POLICY_CHANGED = "android.app.action.OTA_POLICY_CHANGED";
+ public static final String ACTION_SYSTEM_UPDATE_POLICY_CHANGED
+ = "android.app.action.SYSTEM_UPDATE_POLICY_CHANGED";
/**
@@ -1634,6 +1635,23 @@ public class DevicePolicyManager {
}
/**
+ * Queries whether {@link #DO_NOT_ASK_CREDENTIALS_ON_BOOT} flag is set.
+ *
+ * @return true if DO_NOT_ASK_CREDENTIALS_ON_BOOT flag is set.
+ * @hide
+ */
+ public boolean getDoNotAskCredentialsOnBoot() {
+ if (mService != null) {
+ try {
+ return mService.getDoNotAskCredentialsOnBoot();
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed to call getDoNotAskCredentialsOnBoot()", e);
+ }
+ }
+ return false;
+ }
+
+ /**
* Setting this to a value greater than zero enables a built-in policy
* that will perform a device wipe after too many incorrect
* device-unlock passwords have been entered. This built-in policy combines
@@ -1710,6 +1728,16 @@ public class DevicePolicyManager {
public static final int RESET_PASSWORD_REQUIRE_ENTRY = 0x0001;
/**
+ * Flag for {@link #resetPassword}: don't ask for user credentials on device boot.
+ * If the flag is set, the device can be booted without asking for user password.
+ * The absence of this flag does not change the current boot requirements. This flag
+ * can be set by the device owner only. If the app is not the device owner, the flag
+ * is ignored. Once the flag is set, it cannot be reverted back without resetting the
+ * device to factory defaults.
+ */
+ public static final int DO_NOT_ASK_CREDENTIALS_ON_BOOT = 0x0002;
+
+ /**
* Force a new device unlock password (the password needed to access the
* entire device, not for individual accounts) on the user. This takes
* effect immediately.
@@ -1732,7 +1760,8 @@ public class DevicePolicyManager {
* <p>Calling this from a managed profile will throw a security exception.
*
* @param password The new password for the user. Null or empty clears the password.
- * @param flags May be 0 or {@link #RESET_PASSWORD_REQUIRE_ENTRY}.
+ * @param flags May be 0 or combination of {@link #RESET_PASSWORD_REQUIRE_ENTRY} and
+ * {@link #DO_NOT_ASK_CREDENTIALS_ON_BOOT}.
* @return Returns true if the password was applied, or false if it is
* not acceptable for the current constraints.
*/
@@ -4189,46 +4218,46 @@ public class DevicePolicyManager {
}
}
- /*
- * Called by device owners to set a local OTA update policy. When a new OTA policy is set,
- * {@link #ACTION_OTA_POLICY_CHANGED} is broadcasted.
+ /**
+ * Called by device owners to set a local system update policy. When a new policy is set,
+ * {@link #ACTION_SYSTEM_UPDATE_POLICY_CHANGED} is broadcasted.
*
* @param who Which {@link DeviceAdminReceiver} this request is associated with. All components
- * in the device owner package can set OTA policies and the most recent policy takes effect.
- * @param policy the new OTA policy, or null to clear the current policy.
- * @see OtaPolicy
+ * in the device owner package can set system update policies and the most recent policy takes
+ * effect.
+ * @param policy the new policy, or null to clear the current policy.
+ * @see SystemUpdatePolicy
*/
- public void setOtaPolicy(ComponentName who, OtaPolicy policy) {
+ public void setSystemUpdatePolicy(ComponentName who, SystemUpdatePolicy policy) {
if (mService != null) {
try {
if (policy != null) {
- mService.setOtaPolicy(who, policy.getPolicyBundle());
+ mService.setSystemUpdatePolicy(who, policy.getPolicyBundle());
} else {
- mService.setOtaPolicy(who, null);
+ mService.setSystemUpdatePolicy(who, null);
}
} catch (RemoteException re) {
- Log.w(TAG, "Error calling setOtaPolicy", re);
+ Log.w(TAG, "Error calling setSystemUpdatePolicy", re);
}
}
}
/**
- * Retrieve a local OTA update policy set previously by {@link #setOtaPolicy}.
+ * Retrieve a local system update policy set previously by {@link #setSystemUpdatePolicy}.
*
- * @return The current OTA policy object, or null if no policy is set or the system does not
- * support managed OTA.
+ * @return The current policy object, or null if no policy is set.
*/
- public OtaPolicy getOtaPolicy() {
+ public SystemUpdatePolicy getSystemUpdatePolicy() {
if (mService != null) {
try {
- PersistableBundle bundle = mService.getOtaPolicy();
+ PersistableBundle bundle = mService.getSystemUpdatePolicy();
if (bundle != null) {
- return new OtaPolicy(bundle);
+ return new SystemUpdatePolicy(bundle);
} else {
return null;
}
} catch (RemoteException re) {
- Log.w(TAG, "Error calling getOtaPolicy", re);
+ Log.w(TAG, "Error calling getSystemUpdatePolicy", re);
}
}
return null;
@@ -4272,4 +4301,24 @@ public class DevicePolicyManager {
Log.w(TAG, "Failed talking with device policy service", re);
}
}
+
+ /**
+ * Callable by the system update service to notify device owners about pending updates.
+ * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE}
+ * permission.
+ *
+ * @param updateReceivedTime The time as given by {@link System#currentTimeMillis()} indicating
+ * when the current pending update was first available. -1 if no update is available.
+ * @hide
+ */
+ @SystemApi
+ public void notifyPendingSystemUpdate(long updateReceivedTime) {
+ if (mService != null) {
+ try {
+ mService.notifyPendingSystemUpdate(updateReceivedTime);
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not notify device owner about pending system update", re);
+ }
+ }
+ }
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7502e1d..087fc88 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -219,9 +219,12 @@ interface IDevicePolicyManager {
void setUserIcon(in ComponentName admin, in Bitmap icon);
void sendDeviceInitializerStatus(int statusCode, String description);
- void setOtaPolicy(in ComponentName who, in PersistableBundle policy);
- PersistableBundle getOtaPolicy();
+ void setSystemUpdatePolicy(in ComponentName who, in PersistableBundle policy);
+ PersistableBundle getSystemUpdatePolicy();
boolean setKeyguardEnabledState(in ComponentName admin, boolean enabled);
void setStatusBarEnabledState(in ComponentName who, boolean enabled);
+ boolean getDoNotAskCredentialsOnBoot();
+
+ void notifyPendingSystemUpdate(in long updateReceivedTime);
}
diff --git a/core/java/android/app/admin/OtaPolicy.java b/core/java/android/app/admin/SystemUpdatePolicy.java
index 98581a7..de56cd0 100644
--- a/core/java/android/app/admin/OtaPolicy.java
+++ b/core/java/android/app/admin/SystemUpdatePolicy.java
@@ -23,12 +23,12 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
- * A class that represents a local OTA policy set by the device owner.
+ * A class that represents a local system update policy set by the device owner.
*
- * @see DevicePolicyManager#setOtaPolicy
- * @see DevicePolicyManager#getOtaPolicy
+ * @see DevicePolicyManager#setSystemUpdatePolicy
+ * @see DevicePolicyManager#getSystemUpdatePolicy
*/
-public class OtaPolicy {
+public class SystemUpdatePolicy {
/** @hide */
@IntDef({
@@ -36,22 +36,27 @@ public class OtaPolicy {
TYPE_INSTALL_WINDOWED,
TYPE_POSTPONE})
@Retention(RetentionPolicy.SOURCE)
- @interface OtaPolicyType {}
+ @interface SystemUpdatePolicyType {}
/**
- * Install OTA update automatically as soon as one is available.
+ * Install system update automatically as soon as one is available.
*/
public static final int TYPE_INSTALL_AUTOMATIC = 1;
/**
- * Install OTA update automatically within a daily maintenance window, for a maximum of two-week
- * period. After that period the OTA will be installed automatically.
+ * Install system update automatically within a daily maintenance window, for a maximum of 30
+ * days. After the expiration the policy will no longer be effective and the system should
+ * revert back to its normal behavior as if no policy were set. The only exception is
+ * {@link #TYPE_INSTALL_AUTOMATIC} which should still take effect to install system update
+ * immediately.
*/
public static final int TYPE_INSTALL_WINDOWED = 2;
/**
- * Incoming OTA will be blocked for a maximum of two weeks, after which it will be installed
- * automatically.
+ * Incoming system update will be blocked for a maximum of 30 days, after which the system
+ * should revert back to its normal behavior as if no policy were set. The only exception is
+ * {@link #TYPE_INSTALL_AUTOMATIC} which should still take effect to install system update
+ * immediately.
*/
public static final int TYPE_POSTPONE = 3;
@@ -61,15 +66,15 @@ public class OtaPolicy {
private PersistableBundle mPolicy;
- public OtaPolicy() {
+ public SystemUpdatePolicy() {
mPolicy = new PersistableBundle();
}
/**
- * Construct an OtaPolicy object from a bundle.
+ * Construct an SystemUpdatePolicy object from a bundle.
* @hide
*/
- public OtaPolicy(PersistableBundle in) {
+ public SystemUpdatePolicy(PersistableBundle in) {
mPolicy = new PersistableBundle(in);
}
@@ -82,7 +87,9 @@ public class OtaPolicy {
}
/**
- * Set the OTA policy to: install OTA update automatically as soon as one is available.
+ * Set the policy to: install update automatically as soon as one is available.
+ *
+ * @see #TYPE_INSTALL_AUTOMATIC
*/
public void setAutomaticInstallPolicy() {
mPolicy.clear();
@@ -90,18 +97,19 @@ public class OtaPolicy {
}
/**
- * Set the OTA policy to: new OTA update will only be installed automatically when the system
+ * Set the policy to: new system update will only be installed automatically when the system
* clock is inside a daily maintenance window. If the start and end times are the same, the
- * window is considered to include the WHOLE 24 hours, that is, OTAs can install at any time. If
- * the given window in invalid, a {@link OtaPolicy.InvalidWindowException} will be thrown. If
- * start time is later than end time, the window is considered spanning midnight, i.e. end time
- * donates a time on the next day. The maintenance window will last for two weeks, after which
- * the OTA will be installed automatically.
+ * window is considered to include the WHOLE 24 hours, that is, updates can install at any time.
+ * If the given window in invalid, a {@link SystemUpdatePolicy.InvalidWindowException} will be
+ * thrown. If start time is later than end time, the window is considered spanning midnight,
+ * i.e. end time donates a time on the next day. The maintenance window will last for 30 days,
+ * after which the system should revert back to its normal behavior as if no policy were set.
*
* @param startTime the start of the maintenance window, measured as the number of minutes from
- * midnight in the device's local time. Must be in the range of [0, 1440).
+ * midnight in the device's local time. Must be in the range of [0, 1440).
* @param endTime the end of the maintenance window, measured as the number of minutes from
- * midnight in the device's local time. Must be in the range of [0, 1440).
+ * midnight in the device's local time. Must be in the range of [0, 1440).
+ * @see #TYPE_INSTALL_WINDOWED
*/
public void setWindowedInstallPolicy(int startTime, int endTime) throws InvalidWindowException{
if (startTime < 0 || startTime >= 1440 || endTime < 0 || endTime >= 1440) {
@@ -114,8 +122,10 @@ public class OtaPolicy {
}
/**
- * Set the OTA policy to: block installation for a maximum period of two weeks. After the
- * block expires the OTA will be installed automatically.
+ * Set the policy to: block installation for a maximum period of 30 days. After expiration the
+ * system should revert back to its normal behavior as if no policy were set.
+ *
+ * @see #TYPE_POSTPONE
*/
public void setPostponeInstallPolicy() {
mPolicy.clear();
@@ -123,12 +133,12 @@ public class OtaPolicy {
}
/**
- * Returns the type of OTA policy.
+ * Returns the type of system update policy.
*
* @return an integer, either one of {@link #TYPE_INSTALL_AUTOMATIC},
* {@link #TYPE_INSTALL_WINDOWED} and {@link #TYPE_POSTPONE}, or -1 if no policy has been set.
*/
- @OtaPolicyType
+ @SystemUpdatePolicyType
public int getPolicyType() {
return mPolicy.getInt(KEY_POLICY_TYPE, -1);
}
@@ -167,7 +177,7 @@ public class OtaPolicy {
}
/**
- * Exception thrown by {@link OtaPolicy#setWindowedInstallPolicy(int, int)} in case the
+ * Exception thrown by {@link SystemUpdatePolicy#setWindowedInstallPolicy(int, int)} in case the
* specified window is invalid.
*/
public static class InvalidWindowException extends Exception {
diff --git a/core/java/android/app/backup/BlobBackupHelper.java b/core/java/android/app/backup/BlobBackupHelper.java
new file mode 100644
index 0000000..cdc62dc
--- /dev/null
+++ b/core/java/android/app/backup/BlobBackupHelper.java
@@ -0,0 +1,296 @@
+/*
+ * 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.backup;
+
+import android.os.ParcelFileDescriptor;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.EOFException;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.zip.CRC32;
+import java.util.zip.DeflaterOutputStream;
+import java.util.zip.InflaterInputStream;
+
+/**
+ * Utility class for writing BackupHelpers whose underlying data is a
+ * fixed set of byte-array blobs. The helper manages diff detection
+ * and compression on the wire.
+ *
+ * @hide
+ */
+public abstract class BlobBackupHelper implements BackupHelper {
+ private static final String TAG = "BlobBackupHelper";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ private final int mCurrentBlobVersion;
+ private final String[] mKeys;
+
+ public BlobBackupHelper(int currentBlobVersion, String... keys) {
+ mCurrentBlobVersion = currentBlobVersion;
+ mKeys = keys;
+ }
+
+ // Client interface
+
+ /**
+ * Generate and return the byte array containing the backup payload describing
+ * the current data state. During a backup operation this method is called once
+ * per key that was supplied to the helper's constructor.
+ *
+ * @return A byte array containing the data blob that the caller wishes to store,
+ * or {@code null} if the current state is empty or undefined.
+ */
+ abstract protected byte[] getBackupPayload(String key);
+
+ /**
+ * Given a byte array that was restored from backup, do whatever is appropriate
+ * to apply that described state in the live system. This method is called once
+ * per key/value payload that was delivered for restore. Typically data is delivered
+ * for restore in lexical order by key, <i>not</i> in the order in which the keys
+ * were supplied in the constructor.
+ *
+ * @param payload The byte array that was passed to {@link #getBackupPayload()}
+ * on the ancestral device.
+ */
+ abstract protected void applyRestoredPayload(String key, byte[] payload);
+
+
+ // Internal implementation
+
+ /*
+ * State on-disk format:
+ * [Int] : overall blob version number
+ * [Int=N] : number of keys represented in the state blob
+ * N* :
+ * [String] key
+ * [Long] blob checksum, calculated after compression
+ */
+ @SuppressWarnings("resource")
+ private ArrayMap<String, Long> readOldState(ParcelFileDescriptor oldStateFd) {
+ final ArrayMap<String, Long> state = new ArrayMap<String, Long>();
+
+ FileInputStream fis = new FileInputStream(oldStateFd.getFileDescriptor());
+ BufferedInputStream bis = new BufferedInputStream(fis);
+ DataInputStream in = new DataInputStream(bis);
+
+ try {
+ int version = in.readInt();
+ if (version <= mCurrentBlobVersion) {
+ final int numKeys = in.readInt();
+ for (int i = 0; i < numKeys; i++) {
+ String key = in.readUTF();
+ long checksum = in.readLong();
+ state.put(key, checksum);
+ }
+ } else {
+ Log.w(TAG, "Prior state from unrecognized version " + version);
+ }
+ } catch (EOFException e) {
+ // Empty file is expected on first backup, so carry on. If the state
+ // is truncated we just treat it the same way.
+ state.clear();
+ } catch (Exception e) {
+ Log.e(TAG, "Error examining prior backup state " + e.getMessage());
+ state.clear();
+ }
+
+ return state;
+ }
+
+ /**
+ * New overall state record
+ */
+ private void writeBackupState(ArrayMap<String, Long> state, ParcelFileDescriptor stateFile) {
+ try {
+ FileOutputStream fos = new FileOutputStream(stateFile.getFileDescriptor());
+
+ // We explicitly don't close 'out' because we must not close the backing fd.
+ // The FileOutputStream will not close it implicitly.
+ @SuppressWarnings("resource")
+ DataOutputStream out = new DataOutputStream(fos);
+
+ out.writeInt(mCurrentBlobVersion);
+
+ final int N = (state != null) ? state.size() : 0;
+ out.writeInt(N);
+ for (int i = 0; i < N; i++) {
+ out.writeUTF(state.keyAt(i));
+ out.writeLong(state.valueAt(i).longValue());
+ }
+ } catch (IOException e) {
+ Log.e(TAG, "Unable to write updated state", e);
+ }
+ }
+
+ // Also versions the deflated blob internally in case we need to revise it
+ private byte[] deflate(byte[] data) {
+ byte[] result = null;
+ if (data != null) {
+ try {
+ ByteArrayOutputStream sink = new ByteArrayOutputStream();
+ DataOutputStream headerOut = new DataOutputStream(sink);
+
+ // write the header directly to the sink ahead of the deflated payload
+ headerOut.writeInt(mCurrentBlobVersion);
+
+ DeflaterOutputStream out = new DeflaterOutputStream(sink);
+ out.write(data);
+ out.close(); // finishes and commits the compression run
+ result = sink.toByteArray();
+ if (DEBUG) {
+ Log.v(TAG, "Deflated " + data.length + " bytes to " + result.length);
+ }
+ } catch (IOException e) {
+ Log.w(TAG, "Unable to process payload: " + e.getMessage());
+ }
+ }
+ return result;
+ }
+
+ // Returns null if inflation failed
+ private byte[] inflate(byte[] compressedData) {
+ byte[] result = null;
+ if (compressedData != null) {
+ try {
+ ByteArrayInputStream source = new ByteArrayInputStream(compressedData);
+ DataInputStream headerIn = new DataInputStream(source);
+ int version = headerIn.readInt();
+ if (version > mCurrentBlobVersion) {
+ Log.w(TAG, "Saved payload from unrecognized version " + version);
+ return null;
+ }
+
+ InflaterInputStream in = new InflaterInputStream(source);
+ ByteArrayOutputStream inflated = new ByteArrayOutputStream();
+ byte[] buffer = new byte[4096];
+ int nRead;
+ while ((nRead = in.read(buffer)) > 0) {
+ inflated.write(buffer, 0, nRead);
+ }
+ in.close();
+ inflated.flush();
+ result = inflated.toByteArray();
+ if (DEBUG) {
+ Log.v(TAG, "Inflated " + compressedData.length + " bytes to " + result.length);
+ }
+ } catch (IOException e) {
+ // result is still null here
+ Log.w(TAG, "Unable to process restored payload: " + e.getMessage());
+ }
+ }
+ return result;
+ }
+
+ private long checksum(byte[] buffer) {
+ if (buffer != null) {
+ try {
+ CRC32 crc = new CRC32();
+ ByteArrayInputStream bis = new ByteArrayInputStream(buffer);
+ byte[] buf = new byte[4096];
+ int nRead = 0;
+ while ((nRead = bis.read(buf)) >= 0) {
+ crc.update(buf, 0, nRead);
+ }
+ return crc.getValue();
+ } catch (Exception e) {
+ // whoops; fall through with an explicitly bogus checksum
+ }
+ }
+ return -1;
+ }
+
+ // BackupHelper interface
+
+ @Override
+ public void performBackup(ParcelFileDescriptor oldStateFd, BackupDataOutput data,
+ ParcelFileDescriptor newStateFd) {
+
+ final ArrayMap<String, Long> oldState = readOldState(oldStateFd);
+ final ArrayMap<String, Long> newState = new ArrayMap<String, Long>();
+
+ try {
+ for (String key : mKeys) {
+ final byte[] payload = deflate(getBackupPayload(key));
+ final long checksum = checksum(payload);
+ newState.put(key, checksum);
+
+ Long oldChecksum = oldState.get(key);
+ if (oldChecksum == null || checksum != oldChecksum) {
+ if (DEBUG) {
+ Log.i(TAG, "State has changed for key " + key + ", writing");
+ }
+ if (payload != null) {
+ data.writeEntityHeader(key, payload.length);
+ data.writeEntityData(payload, payload.length);
+ } else {
+ // state's changed but there's no current payload => delete
+ data.writeEntityHeader(key, -1);
+ }
+ } else {
+ if (DEBUG) {
+ Log.i(TAG, "No change under key " + key + " => not writing");
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.w(TAG, "Unable to record notification state: " + e.getMessage());
+ newState.clear();
+ } finally {
+ // Always recommit the state even if nothing changed
+ writeBackupState(newState, newStateFd);
+ }
+ }
+
+ @Override
+ public void restoreEntity(BackupDataInputStream data) {
+ final String key = data.getKey();
+ try {
+ // known key?
+ int which;
+ for (which = 0; which < mKeys.length; which++) {
+ if (key.equals(mKeys[which])) {
+ break;
+ }
+ }
+ if (which >= mKeys.length) {
+ Log.e(TAG, "Unrecognized key " + key + ", ignoring");
+ return;
+ }
+
+ byte[] compressed = new byte[data.size()];
+ data.read(compressed);
+ byte[] payload = inflate(compressed);
+ applyRestoredPayload(key, payload);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception restoring entity " + key + " : " + e.getMessage());
+ }
+ }
+
+ @Override
+ public void writeNewStateDescription(ParcelFileDescriptor newState) {
+ // Just ensure that we do a full backup the first time after a restore
+ writeBackupState(null, newState);
+ }
+}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 393cf8e..fd65d56 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -26,6 +26,7 @@ import android.content.pm.ProviderInfo;
import android.content.res.AssetFileDescriptor;
import android.content.res.Configuration;
import android.database.Cursor;
+import android.database.MatrixCursor;
import android.database.SQLException;
import android.net.Uri;
import android.os.AsyncTask;
@@ -204,8 +205,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
validateIncomingUri(uri);
uri = getUriWithoutUserId(uri);
if (enforceReadPermission(callingPkg, uri, null) != AppOpsManager.MODE_ALLOWED) {
- return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
- CancellationSignal.fromTransport(cancellationSignal));
+ // The caller has no access to the data, so return an empty cursor with
+ // the columns in the requested order. The caller may ask for an invalid
+ // column and we would not catch that but this is not a problem in practice.
+ // We do not call ContentProvider#query with a modified where clause since
+ // the implementation is not guaranteed to be backed by a SQL database, hence
+ // it may not handle properly the tautology where clause we would have created.
+ return new MatrixCursor(projection, 0);
}
final String original = setCallingPackage(callingPkg);
try {
@@ -817,31 +823,6 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
/**
- * @hide
- * Implementation when a caller has performed a query on the content
- * provider, but that call has been rejected for the operation given
- * to {@link #setAppOps(int, int)}. The default implementation
- * rewrites the <var>selection</var> argument to include a condition
- * that is never true (so will always result in an empty cursor)
- * and calls through to {@link #query(android.net.Uri, String[], String, String[],
- * String, android.os.CancellationSignal)} with that.
- */
- public Cursor rejectQuery(Uri uri, String[] projection,
- String selection, String[] selectionArgs, String sortOrder,
- CancellationSignal cancellationSignal) {
- // The read is not allowed... to fake it out, we replace the given
- // selection statement with a dummy one that will always be false.
- // This way we will get a cursor back that has the correct structure
- // but contains no rows.
- if (selection == null || selection.isEmpty()) {
- selection = "'A' = 'B'";
- } else {
- selection = "'A' = 'B' AND (" + selection + ")";
- }
- return query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);
- }
-
- /**
* Implement this to handle query requests from clients.
* This method can be called from multiple threads, as described in
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3bf3f85..5eacce3 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3098,7 +3098,6 @@ public abstract class Context {
* {@link android.media.midi.MidiManager} for accessing the MIDI service.
*
* @see #getSystemService
- * @hide
*/
public static final String MIDI_SERVICE = "midi";
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index e2701ee..6c32873 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -339,8 +339,14 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* (e.g., HTTP rather than HTTPS; WebSockets rather than WebSockets Secure; XMPP, IMAP, STMP
* without STARTTLS or TLS). If {@code false}, the app declares that it does not intend to use
* cleartext network traffic, in which case platform components (e.g., HTTP stacks,
- * {@code WebView}, {@code DownloadManager}, {@code MediaPlayer}) will refuse app's requests to
- * use cleartext traffic. Third-party libraries are encouraged to honor this flag as well.
+ * {@code DownloadManager}, {@code MediaPlayer}) will refuse app's requests to use cleartext
+ * traffic. Third-party libraries are encouraged to honor this flag as well.
+ *
+ * <p>NOTE: {@code WebView} does not honor this flag.
+ *
+ * <p>This flag comes from
+ * {@link android.R.styleable#AndroidManifestApplication_usesCleartextTraffic
+ * android:usesCleartextTraffic} of the &lt;application&gt; tag.
*/
public static final int FLAG_USES_CLEARTEXT_TRAFFIC = 1<<27;
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index c81517a..5c21c8e 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -146,6 +146,7 @@ public class LauncherApps {
try {
activities = mService.getLauncherActivities(packageName, user);
} catch (RemoteException re) {
+ throw new RuntimeException("Failed to call LauncherAppsService");
}
if (activities == null) {
return Collections.EMPTY_LIST;
diff --git a/core/java/android/content/pm/PackageCleanItem.java b/core/java/android/content/pm/PackageCleanItem.java
index b1896aa..e1656d6 100644
--- a/core/java/android/content/pm/PackageCleanItem.java
+++ b/core/java/android/content/pm/PackageCleanItem.java
@@ -20,7 +20,7 @@ import android.os.Parcel;
import android.os.Parcelable;
/** @hide */
-public class PackageCleanItem {
+public class PackageCleanItem implements Parcelable {
public final int userId;
public final String packageName;
public final boolean andCode;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index a0cec50..e4108b1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1574,6 +1574,21 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and
* {@link #hasSystemFeature}: This is a device dedicated to showing UI
+ * on a vehicle headunit. A headunit here is defined to be inside a
+ * vehicle that may or may not be moving. A headunit uses either a
+ * primary display in the center console and/or additional displays in
+ * the instrument cluster or elsewhere in the vehicle. Headunit display(s)
+ * have limited size and resolution. The user will likely be focused on
+ * driving so limiting driver distraction is a primary concern. User input
+ * can be a variety of hard buttons, touch, rotary controllers and even mouse-
+ * like interfaces.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_AUTOMOTIVE = "android.hardware.type.automotive";
+
+ /**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: This is a device dedicated to showing UI
* on a television. Television here is defined to be a typical living
* room television experience: displayed on a big screen, where the user
* is sitting far away from it, and the dominant form of input will be
diff --git a/core/java/android/content/pm/ParceledListSlice.java b/core/java/android/content/pm/ParceledListSlice.java
index 335a45e..e5c2203 100644
--- a/core/java/android/content/pm/ParceledListSlice.java
+++ b/core/java/android/content/pm/ParceledListSlice.java
@@ -55,6 +55,7 @@ public class ParceledListSlice<T extends Parcelable> implements Parcelable {
mList = list;
}
+ @SuppressWarnings("unchecked")
private ParceledListSlice(Parcel p, ClassLoader loader) {
final int N = p.readInt();
mList = new ArrayList<T>(N);
@@ -63,7 +64,7 @@ public class ParceledListSlice<T extends Parcelable> implements Parcelable {
return;
}
- Parcelable.Creator<T> creator = p.readParcelableCreator(loader);
+ Parcelable.Creator<?> creator = p.readParcelableCreator(loader);
Class<?> listElementClass = null;
int i = 0;
diff --git a/core/java/android/database/sqlite/SQLiteConnection.java b/core/java/android/database/sqlite/SQLiteConnection.java
index 24a7d33..3cda39a 100644
--- a/core/java/android/database/sqlite/SQLiteConnection.java
+++ b/core/java/android/database/sqlite/SQLiteConnection.java
@@ -91,8 +91,6 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
- private static final Pattern TRIM_SQL_PATTERN = Pattern.compile("[\\s]*\\n+[\\s]*");
-
private final CloseGuard mCloseGuard = CloseGuard.get();
private final SQLiteConnectionPool mPool;
@@ -1203,7 +1201,11 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
}
private static String trimSqlForDisplay(String sql) {
- return TRIM_SQL_PATTERN.matcher(sql).replaceAll(" ");
+ // Note: Creating and caching a regular expression is expensive at preload-time
+ // and stops compile-time initialization. This pattern is only used when
+ // dumping the connection, which is a rare (mainly error) case. So:
+ // DO NOT CACHE.
+ return sql.replaceAll("[\\s]*\\n+[\\s]*", " ");
}
/**
@@ -1437,9 +1439,6 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
}
private static final class Operation {
- private static final SimpleDateFormat sDateFormat =
- new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
-
public long mStartTime;
public long mEndTime;
public String mKind;
@@ -1494,7 +1493,11 @@ public final class SQLiteConnection implements CancellationSignal.OnCancelListen
}
private String getFormattedStartTime() {
- return sDateFormat.format(new Date(mStartTime));
+ // Note: SimpleDateFormat is not thread-safe, cannot be compile-time created, and is
+ // relatively expensive to create during preloading. This method is only used
+ // when dumping a connection, which is a rare (mainly error) case. So:
+ // DO NOT CACHE.
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date(mStartTime));
}
}
}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index 0d7b261..2257b0a 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -587,6 +587,25 @@ public class FingerprintManager {
return false;
}
+ /**
+ * Retrieves the authenticator token for binding keys to the lifecycle
+ * of the current set of fingerprints. Used only by internal clients.
+ *
+ * @hide
+ */
+ public long getAuthenticatorId() {
+ if (mService != null) {
+ try {
+ return mService.getAuthenticatorId();
+ } catch (RemoteException e) {
+ Log.v(TAG, "Remote exception in getAuthenticatorId(): ", e);
+ }
+ } else {
+ Log.w(TAG, "getAuthenticatorId(): Service not connected!");
+ }
+ return 0;
+ }
+
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch(msg.what) {
@@ -792,4 +811,5 @@ public class FingerprintManager {
}
};
-} \ No newline at end of file
+}
+
diff --git a/core/java/android/hardware/fingerprint/FingerprintUtils.java b/core/java/android/hardware/fingerprint/FingerprintUtils.java
index ae3d4a4..525f254 100644
--- a/core/java/android/hardware/fingerprint/FingerprintUtils.java
+++ b/core/java/android/hardware/fingerprint/FingerprintUtils.java
@@ -17,6 +17,8 @@
package android.hardware.fingerprint;
import android.content.ContentResolver;
+import android.content.Context;
+import android.os.Vibrator;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
@@ -35,6 +37,8 @@ public
class FingerprintUtils {
private static final boolean DEBUG = true;
private static final String TAG = "FingerprintUtils";
+ private static final long[] FP_ERROR_VIBRATE_PATTERN = new long[] {0, 30, 100, 30};
+ private static final long[] FP_SUCCESS_VIBRATE_PATTERN = new long[] {0, 30};
private static int[] toIntArray(List<Integer> list) {
if (list == null) {
@@ -104,5 +108,19 @@ class FingerprintUtils {
return false;
}
+ public static void vibrateFingerprintError(Context context) {
+ Vibrator vibrator = context.getSystemService(Vibrator.class);
+ if (vibrator != null) {
+ vibrator.vibrate(FP_ERROR_VIBRATE_PATTERN, -1);
+ }
+ }
+
+ public static void vibrateFingerprintSuccess(Context context) {
+ Vibrator vibrator = context.getSystemService(Vibrator.class);
+ if (vibrator != null) {
+ vibrator.vibrate(FP_SUCCESS_VIBRATE_PATTERN, -1);
+ }
+ }
+
};
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 51a0e4c..c5ec08c 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -63,4 +63,6 @@ interface IFingerprintService {
// Gets the unique device id for hardware enumerated at i
// long getHardwareDevice(int i);
+ // Gets the authenticator ID for fingerprint
+ long getAuthenticatorId();
}
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index e75f337..63f48cf 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -98,16 +98,6 @@ public class ConnectivityManager {
public static final String CONNECTIVITY_ACTION = "android.net.conn.CONNECTIVITY_CHANGE";
/**
- * Identical to {@link #CONNECTIVITY_ACTION} broadcast, but sent without any
- * historic {@link Settings.Global#CONNECTIVITY_CHANGE_DELAY}.
- *
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String CONNECTIVITY_ACTION_IMMEDIATE =
- "android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE";
-
- /**
* The lookup key for a {@link NetworkInfo} object. Retrieve with
* {@link android.content.Intent#getParcelableExtra(String)}.
*
@@ -315,6 +305,9 @@ public class ConnectivityManager {
* same network interface as {@link #TYPE_MOBILE} or it may use a different
* one. This is used by applications needing to talk to the carrier's
* Multimedia Messaging Service servers.
+ *
+ * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+ * provides the {@link NetworkCapabilities#NET_CAPABILITY_MMS} capability.
*/
public static final int TYPE_MOBILE_MMS = 2;
/**
@@ -322,6 +315,9 @@ public class ConnectivityManager {
* same network interface as {@link #TYPE_MOBILE} or it may use a different
* one. This is used by applications needing to talk to the carrier's
* Secure User Plane Location servers for help locating the device.
+ *
+ * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+ * provides the {@link NetworkCapabilities#NET_CAPABILITY_SUPL} capability.
*/
public static final int TYPE_MOBILE_SUPL = 3;
/**
@@ -334,9 +330,10 @@ public class ConnectivityManager {
/**
* A High Priority Mobile data connection. This network type uses the
* same network interface as {@link #TYPE_MOBILE} but the routing setup
- * is different. Only requesting processes will have access to the
- * Mobile DNS servers and only IP's explicitly requested via {@link #requestRouteToHost}
- * will route over this interface if no default route exists.
+ * is different.
+ *
+ * @deprecated Applications should instead use {@link #requestNetwork} to request a network that
+ * uses the {@link NetworkCapabilities#TRANSPORT_CELLULAR} transport.
*/
public static final int TYPE_MOBILE_HIPRI = 5;
/**
@@ -396,7 +393,7 @@ public class ConnectivityManager {
*/
public static final int TYPE_MOBILE_IA = 14;
-/**
+ /**
* Emergency PDN connection for emergency calls
* {@hide}
*/
@@ -746,7 +743,7 @@ public class ConnectivityManager {
}
/**
- * Returns an array of of {@link NetworkCapabilities} objects, representing
+ * Returns an array of {@link android.net.NetworkCapabilities} objects, representing
* the Networks that applications run by the given user will use by default.
* @hide
*/
@@ -836,11 +833,11 @@ public class ConnectivityManager {
}
/**
- * Get the {@link NetworkCapabilities} for the given {@link Network}. This
+ * Get the {@link android.net.NetworkCapabilities} for the given {@link Network}. This
* will return {@code null} if the network is unknown.
*
* @param network The {@link Network} object identifying the network in question.
- * @return The {@link NetworkCapabilities} for the network, or {@code null}.
+ * @return The {@link android.net.NetworkCapabilities} for the network, or {@code null}.
*/
public NetworkCapabilities getNetworkCapabilities(Network network) {
try {
@@ -864,6 +861,7 @@ public class ConnectivityManager {
* always indicates failure.
*
* @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
+ * @removed
*/
public int startUsingNetworkFeature(int networkType, String feature) {
NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature);
@@ -911,6 +909,7 @@ public class ConnectivityManager {
* always indicates failure.
*
* @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
+ * @removed
*/
public int stopUsingNetworkFeature(int networkType, String feature) {
NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature);
@@ -1189,6 +1188,7 @@ public class ConnectivityManager {
*
* @deprecated Deprecated in favor of the {@link #requestNetwork},
* {@link #bindProcessToNetwork} and {@link Network#getSocketFactory} api.
+ * @removed
*/
public boolean requestRouteToHost(int networkType, int hostAddress) {
return requestRouteToHostAddress(networkType, NetworkUtils.intToInetAddress(hostAddress));
@@ -1207,6 +1207,7 @@ public class ConnectivityManager {
* @hide
* @deprecated Deprecated in favor of the {@link #requestNetwork} and
* {@link #bindProcessToNetwork} api.
+ * @removed
*/
public boolean requestRouteToHostAddress(int networkType, InetAddress hostAddress) {
try {
@@ -2067,7 +2068,7 @@ public class ConnectivityManager {
* changes capabilities but still satisfies the stated need.
*
* @param network The {@link Network} whose capabilities have changed.
- * @param networkCapabilities The new {@link NetworkCapabilities} for this network.
+ * @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this network.
*/
public void onCapabilitiesChanged(Network network,
NetworkCapabilities networkCapabilities) {}
@@ -2309,7 +2310,7 @@ public class ConnectivityManager {
}
/**
- * Request a network to satisfy a set of {@link NetworkCapabilities}.
+ * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}.
*
* This {@link NetworkRequest} will live until released via
* {@link #unregisterNetworkCallback} or the calling application exits.
@@ -2328,7 +2329,7 @@ public class ConnectivityManager {
}
/**
- * Request a network to satisfy a set of {@link NetworkCapabilities}, limited
+ * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}, limited
* by a timeout.
*
* This function behaves identically to the non-timedout version, but if a suitable
@@ -2375,7 +2376,7 @@ public class ConnectivityManager {
/**
- * Request a network to satisfy a set of {@link NetworkCapabilities}.
+ * Request a network to satisfy a set of {@link android.net.NetworkCapabilities}.
*
* This function behaves identically to the version that takes a NetworkCallback, but instead
* of {@link NetworkCallback} a {@link PendingIntent} is used. This means
@@ -2451,17 +2452,21 @@ public class ConnectivityManager {
}
/**
- * Request connectivityservice to refresh network capabilities for the given
- * {@link network}. This method returns true if the network is still active, false
- * otherwise. Notice the method call assumes the caller has registered for
- * listening NetworkCapabilities updates.
+ * Requests bandwidth update for a given {@link Network} and returns whether the update request
+ * is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying
+ * network connection for updated bandwidth information. The caller will be notified via
+ * {@link ConnectivityManager.NetworkCallback} if there is an update. Notice that this
+ * method assumes that the caller has previously called {@link #registerNetworkCallback} to
+ * listen for network changes.
*
* @param network{@link Network} specifying which network you're interested.
+ * @return {@code true} on success, {@code false} if the {@link Network} is no longer valid.
+ *
* @hide
*/
- public boolean requestBwUpdate(Network network) {
+ public boolean requestBandwidthUpdate(Network network) {
try {
- return mService.requestBwUpdate(network);
+ return mService.requestBandwidthUpdate(network);
} catch (RemoteException e) {
return false;
}
@@ -2573,7 +2578,12 @@ public class ConnectivityManager {
if (NetworkUtils.bindProcessToNetwork(netId)) {
// Set HTTP proxy system properties to match network.
// TODO: Deprecate this static method and replace it with a non-static version.
- Proxy.setHttpProxySystemProperty(getInstance().getDefaultProxy());
+ try {
+ Proxy.setHttpProxySystemProperty(getInstance().getDefaultProxy());
+ } catch (SecurityException e) {
+ // The process doesn't have ACCESS_NETWORK_STATE, so we can't fetch the proxy.
+ Log.e(TAG, "Can't set proxy properties", e);
+ }
// Must flush DNS cache as new network may have different DNS resolutions.
InetAddress.clearDnsCache();
// Must flush socket pool as idle sockets will be bound to previous network and may
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index d6c0693..efc76b3 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -134,7 +134,7 @@ interface IConnectivityManager
void registerNetworkFactory(in Messenger messenger, in String name);
- boolean requestBwUpdate(in Network network);
+ boolean requestBandwidthUpdate(in Network network);
void unregisterNetworkFactory(in Messenger messenger);
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index f10e530..3d065e3 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -17,6 +17,7 @@
package android.nfc.cardemulation;
import android.content.ComponentName;
+import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
@@ -28,6 +29,7 @@ import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.ResultReceiver;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -88,12 +90,24 @@ public final class ApduServiceInfo implements Parcelable {
* The uid of the package the service belongs to
*/
final int mUid;
+
+ /**
+ * Whether this service has dynamic resources
+ */
+ final boolean mHasDynamicResources;
+
+ /**
+ * Settings Activity for this service
+ */
+ final String mSettingsActivityName;
+
/**
* @hide
*/
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
- boolean requiresUnlock, int bannerResource, int uid) {
+ boolean requiresUnlock, int bannerResource, int uid, boolean hasDynamicResources,
+ String settingsActivityName) {
this.mService = info;
this.mDescription = description;
this.mStaticAidGroups = new HashMap<String, AidGroup>();
@@ -108,6 +122,8 @@ public final class ApduServiceInfo implements Parcelable {
}
this.mBannerResourceId = bannerResource;
this.mUid = uid;
+ this.mHasDynamicResources = hasDynamicResources;
+ this.mSettingsActivityName = settingsActivityName;
}
public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost) throws
@@ -156,6 +172,10 @@ 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();
} else {
TypedArray sa = res.obtainAttributes(attrs,
@@ -166,6 +186,10 @@ 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();
}
@@ -359,6 +383,15 @@ public final class ApduServiceInfo implements Parcelable {
return mService.loadLabel(pm);
}
+ public CharSequence loadAppLabel(PackageManager pm) {
+ try {
+ return pm.getApplicationLabel(pm.getApplicationInfo(
+ mService.resolvePackageName, PackageManager.GET_META_DATA));
+ } catch (PackageManager.NameNotFoundException e) {
+ return null;
+ }
+ }
+
public Drawable loadIcon(PackageManager pm) {
return mService.loadIcon(pm);
}
@@ -377,6 +410,11 @@ public final class ApduServiceInfo implements Parcelable {
return null;
}
}
+ public boolean hasDynamicResources() {
+ return mHasDynamicResources;
+ }
+
+ public String getSettingsActivityName() { return mSettingsActivityName; }
@Override
public String toString() {
@@ -430,6 +468,8 @@ 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);
};
public static final Parcelable.Creator<ApduServiceInfo> CREATOR =
@@ -452,8 +492,11 @@ 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);
+ dynamicAidGroups, requiresUnlock, bannerResource, uid, dynamicResources,
+ settingsActivityName);
}
@Override
@@ -479,5 +522,6 @@ public final class ApduServiceInfo implements Parcelable {
pw.println(" AID: " + aid);
}
}
+ pw.println(" Settings Activity: " + mSettingsActivityName);
}
}
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 64c2bc2..b94d4a6 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -90,6 +90,37 @@ 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/Parcel.java b/core/java/android/os/Parcel.java
index 9d8a1ba..43309c0 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -34,6 +34,7 @@ import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.Serializable;
import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -283,6 +284,8 @@ public final class Parcel {
private static native void nativeWriteInterfaceToken(long nativePtr, String interfaceName);
private static native void nativeEnforceInterface(long nativePtr, String interfaceName);
+ private static native long nativeGetBlobAshmemSize(long nativePtr);
+
public final static Parcelable.Creator<String> STRING_CREATOR
= new Parcelable.Creator<String>() {
public String createFromParcel(Parcel source) {
@@ -1373,8 +1376,7 @@ public final class Parcel {
writeString(null);
return;
}
- String name = p.getClass().getName();
- writeString(name);
+ writeParcelableCreator(p);
p.writeToParcel(this, parcelableFlags);
}
@@ -2275,78 +2277,94 @@ public final class Parcel {
* @throws BadParcelableException Throws BadParcelableException if there
* was an error trying to instantiate the Parcelable.
*/
+ @SuppressWarnings("unchecked")
public final <T extends Parcelable> T readParcelable(ClassLoader loader) {
- Parcelable.Creator<T> creator = readParcelableCreator(loader);
+ Parcelable.Creator<?> creator = readParcelableCreator(loader);
if (creator == null) {
return null;
}
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
- return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
+ Parcelable.ClassLoaderCreator<?> classLoaderCreator =
+ (Parcelable.ClassLoaderCreator<?>) creator;
+ return (T) classLoaderCreator.createFromParcel(this, loader);
}
- return creator.createFromParcel(this);
+ return (T) creator.createFromParcel(this);
}
/** @hide */
- public final <T extends Parcelable> T readCreator(Parcelable.Creator<T> creator,
+ @SuppressWarnings("unchecked")
+ public final <T extends Parcelable> T readCreator(Parcelable.Creator<?> creator,
ClassLoader loader) {
if (creator instanceof Parcelable.ClassLoaderCreator<?>) {
- return ((Parcelable.ClassLoaderCreator<T>)creator).createFromParcel(this, loader);
+ Parcelable.ClassLoaderCreator<?> classLoaderCreator =
+ (Parcelable.ClassLoaderCreator<?>) creator;
+ return (T) classLoaderCreator.createFromParcel(this, loader);
}
- return creator.createFromParcel(this);
+ return (T) creator.createFromParcel(this);
}
/** @hide */
- public final <T extends Parcelable> Parcelable.Creator<T> readParcelableCreator(
- ClassLoader loader) {
+ public final Parcelable.Creator<?> readParcelableCreator(ClassLoader loader) {
String name = readString();
if (name == null) {
return null;
}
- Parcelable.Creator<T> creator;
+ Parcelable.Creator<?> creator;
synchronized (mCreators) {
- HashMap<String,Parcelable.Creator> map = mCreators.get(loader);
+ HashMap<String,Parcelable.Creator<?>> map = mCreators.get(loader);
if (map == null) {
- map = new HashMap<String,Parcelable.Creator>();
+ map = new HashMap<>();
mCreators.put(loader, map);
}
creator = map.get(name);
if (creator == null) {
try {
- Class c = loader == null ?
- Class.forName(name) : Class.forName(name, true, loader);
- Field f = c.getField("CREATOR");
- creator = (Parcelable.Creator)f.get(null);
+ // If loader == null, explicitly emulate Class.forName(String) "caller
+ // classloader" behavior.
+ ClassLoader parcelableClassLoader =
+ (loader == null ? getClass().getClassLoader() : loader);
+ // Avoid initializing the Parcelable class until we know it implements
+ // Parcelable and has the necessary CREATOR field. http://b/1171613.
+ Class<?> parcelableClass = Class.forName(name, false /* initialize */,
+ parcelableClassLoader);
+ if (!Parcelable.class.isAssignableFrom(parcelableClass)) {
+ throw new BadParcelableException("Parcelable protocol requires that the "
+ + "class implements Parcelable");
+ }
+ Field f = parcelableClass.getField("CREATOR");
+ if ((f.getModifiers() & Modifier.STATIC) == 0) {
+ throw new BadParcelableException("Parcelable protocol requires "
+ + "the CREATOR object to be static on class " + name);
+ }
+ Class<?> creatorType = f.getType();
+ if (!Parcelable.Creator.class.isAssignableFrom(creatorType)) {
+ // Fail before calling Field.get(), not after, to avoid initializing
+ // parcelableClass unnecessarily.
+ throw new BadParcelableException("Parcelable protocol requires a "
+ + "Parcelable.Creator object called "
+ + "CREATOR on class " + name);
+ }
+ creator = (Parcelable.Creator<?>) f.get(null);
}
catch (IllegalAccessException e) {
- Log.e(TAG, "Illegal access when unmarshalling: "
- + name, e);
+ Log.e(TAG, "Illegal access when unmarshalling: " + name, e);
throw new BadParcelableException(
"IllegalAccessException when unmarshalling: " + name);
}
catch (ClassNotFoundException e) {
- Log.e(TAG, "Class not found when unmarshalling: "
- + name, e);
+ Log.e(TAG, "Class not found when unmarshalling: " + name, e);
throw new BadParcelableException(
"ClassNotFoundException when unmarshalling: " + name);
}
- catch (ClassCastException e) {
- throw new BadParcelableException("Parcelable protocol requires a "
- + "Parcelable.Creator object called "
- + " CREATOR on class " + name);
- }
catch (NoSuchFieldException e) {
throw new BadParcelableException("Parcelable protocol requires a "
- + "Parcelable.Creator object called "
- + " CREATOR on class " + name);
- }
- catch (NullPointerException e) {
- throw new BadParcelableException("Parcelable protocol requires "
- + "the CREATOR object to be static on class " + name);
+ + "Parcelable.Creator object called "
+ + "CREATOR on class " + name);
}
if (creator == null) {
throw new BadParcelableException("Parcelable protocol requires a "
- + "Parcelable.Creator object called "
- + " CREATOR on class " + name);
+ + "non-null Parcelable.Creator object called "
+ + "CREATOR on class " + name);
}
map.put(name, creator);
@@ -2369,7 +2387,7 @@ public final class Parcel {
}
Parcelable[] p = new Parcelable[N];
for (int i = 0; i < N; i++) {
- p[i] = (Parcelable) readParcelable(loader);
+ p[i] = readParcelable(loader);
}
return p;
}
@@ -2424,8 +2442,8 @@ public final class Parcel {
// Cache of previously looked up CREATOR.createFromParcel() methods for
// particular classes. Keys are the names of the classes, values are
// Method objects.
- private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator>>
- mCreators = new HashMap<ClassLoader,HashMap<String,Parcelable.Creator>>();
+ private static final HashMap<ClassLoader,HashMap<String,Parcelable.Creator<?>>>
+ mCreators = new HashMap<>();
/** @hide for internal use only. */
static protected final Parcel obtain(int obj) {
@@ -2594,4 +2612,11 @@ public final class Parcel {
N--;
}
}
+
+ /**
+ * @hide For testing
+ */
+ public long getBlobAshmemSize() {
+ return nativeGetBlobAshmemSize(mNativePtr);
+ }
}
diff --git a/core/java/android/os/Parcelable.java b/core/java/android/os/Parcelable.java
index 594fbb2..448b591 100644
--- a/core/java/android/os/Parcelable.java
+++ b/core/java/android/os/Parcelable.java
@@ -19,9 +19,8 @@ package android.os;
/**
* Interface for classes whose instances can be written to
* and restored from a {@link Parcel}. Classes implementing the Parcelable
- * interface must also have a static field called <code>CREATOR</code>, which
- * is an object implementing the {@link Parcelable.Creator Parcelable.Creator}
- * interface.
+ * interface must also have a non-null static field called <code>CREATOR</code>
+ * of a type that implements the {@link Parcelable.Creator} interface.
*
* <p>A typical implementation of Parcelable is:</p>
*
diff --git a/core/java/android/os/storage/DiskInfo.java b/core/java/android/os/storage/DiskInfo.java
index 9f38de8..64f2a05 100644
--- a/core/java/android/os/storage/DiskInfo.java
+++ b/core/java/android/os/storage/DiskInfo.java
@@ -68,6 +68,9 @@ public class DiskInfo implements Parcelable {
if (TextUtils.isEmpty(label)) {
return false;
}
+ if (label.equalsIgnoreCase("ata")) {
+ return false;
+ }
if (label.toLowerCase().contains("generic")) {
return false;
}
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index efa3ef2..f101352 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -69,6 +69,8 @@ public class StorageManager {
/** {@hide} */
public static final String PROP_PRIMARY_PHYSICAL = "ro.vold.primary_physical";
+ /** {@hide} */
+ public static final String PROP_FORCE_ADOPTABLE = "persist.fw.force_adoptable";
/** {@hide} */
public static final int FLAG_ALL_METADATA = 1 << 0;
diff --git a/core/java/android/provider/ContactsContract.java b/core/java/android/provider/ContactsContract.java
index bf7f3cb..396cf19 100644
--- a/core/java/android/provider/ContactsContract.java
+++ b/core/java/android/provider/ContactsContract.java
@@ -2201,7 +2201,6 @@ public final class ContactsContract {
public static final long DAYS_KEPT_MILLISECONDS = 1000L * 60L * 60L * 24L * (long)DAYS_KEPT;
}
-
protected interface RawContactsColumns {
/**
* A reference to the {@link ContactsContract.Contacts#_ID} that this
@@ -8921,4 +8920,147 @@ public final class ContactsContract {
public static final String EXTRA_DATA_SET = "android.provider.extra.DATA_SET";
}
}
+
+ /**
+ * @hide
+ */
+ protected interface MetadataSyncColumns {
+
+ /**
+ * The raw contact backup id.
+ * A reference to the {@link ContactsContract.RawContacts#BACKUP_ID} that save the
+ * persistent unique id for each raw contact within its source system.
+ *
+ * @hide
+ */
+ public static final String RAW_CONTACT_BACKUP_ID = "raw_contact_backup_id";
+
+ /**
+ * The account type to which the raw_contact of this item is associated. See
+ * {@link RawContacts#ACCOUNT_TYPE}
+ *
+ * @hide
+ */
+ public static final String ACCOUNT_TYPE = "account_type";
+
+ /**
+ * The account name to which the raw_contact of this item is associated. See
+ * {@link RawContacts#ACCOUNT_NAME}
+ *
+ * @hide
+ */
+ public static final String ACCOUNT_NAME = "account_name";
+
+ /**
+ * The data set within the account that the raw_contact of this row belongs to. This allows
+ * multiple sync adapters for the same account type to distinguish between
+ * each others' data.
+ * {@link RawContacts#DATA_SET}
+ *
+ * @hide
+ */
+ public static final String DATA_SET = "data_set";
+
+ /**
+ * A text column contains the Json string got from People API. The Json string contains
+ * all the metadata related to the raw contact, i.e., all the data fields and
+ * aggregation exceptions.
+ *
+ * Here is an example of the Json string got from the actual schema.
+ * <pre>
+ * {
+ * "unique_contact_id": {
+ * "account_type": "CUSTOM_ACCOUNT",
+ * "custom_account_type": "facebook",
+ * "account_name": "android-test",
+ * "contact_id": "1111111",
+ * "data_set": "FOCUS"
+ * },
+ * "contact_prefs": {
+ * "send_to_voicemail": true,
+ * "starred": false,
+ * "pinned": 2
+ * },
+ * "aggregation_data": [
+ * {
+ * "type": "TOGETHER",
+ * "contact_ids": [
+ * {
+ * "account_type": "GOOGLE_ACCOUNT",
+ * "account_name": "android-test2",
+ * "contact_id": "2222222",
+ * "data_set": "GOOGLE_PLUS"
+ * },
+ * {
+ * "account_type": "GOOGLE_ACCOUNT",
+ * "account_name": "android-test3",
+ * "contact_id": "3333333",
+ * "data_set": "CUSTOM",
+ * "custom_data_set": "custom type"
+ * }
+ * ]
+ * }
+ * ],
+ * "field_data": [
+ * {
+ * "field_data_id": "1001",
+ * "field_data_prefs": {
+ * "is_primary": true,
+ * "is_super_primary": true
+ * },
+ * "usage_stats": [
+ * {
+ * "usage_type": "CALL",
+ * "last_time_used": 10000001,
+ * "usage_count": 10
+ * }
+ * ]
+ * }
+ * ]
+ * }
+ * </pre>
+ *
+ * @hide
+ */
+ public static final String DATA = "data";
+
+ /**
+ * The "deleted" flag: "0" by default, "1" if the row has been marked
+ * for deletion. When {@link android.content.ContentResolver#delete} is
+ * called on a raw contact, updating MetadataSync table to set the flag of the raw contact
+ * as "1", then metadata sync adapter deletes the raw contact metadata on the server.
+ * <P>Type: INTEGER</P>
+ *
+ * @hide
+ */
+ public static final String DELETED = "deleted";
+ }
+
+ /**
+ * Constants for the metadata sync table. This table is used to cache the metadata_sync data
+ * from server before it is merged into other CP2 tables.
+ *
+ * @hide
+ */
+ public static final class MetadataSync implements BaseColumns, MetadataSyncColumns {
+
+ /** The authority for the contacts metadata */
+ public static final String METADATA_AUTHORITY = "com.android.contacts.metadata";
+
+ /** A content:// style uri to the authority for the contacts metadata */
+ public static final Uri METADATA_AUTHORITY_URI = Uri.parse(
+ "content://" + METADATA_AUTHORITY);
+
+ /**
+ * This utility class cannot be instantiated
+ */
+ private MetadataSync() {
+ }
+
+ /**
+ * The content:// style URI for this table.
+ */
+ public static final Uri CONTENT_URI = Uri.withAppendedPath(METADATA_AUTHORITY_URI,
+ "metadata_sync");
+ }
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a622a21..00c851b 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -189,6 +189,36 @@ public final class Settings {
"android.settings.USAGE_ACCESS_SETTINGS";
/**
+ * Activity Category: Show application settings related to usage access.
+ * <p>
+ * An activity that provides a user interface for adjusting usage access related
+ * preferences for its containing application. Optional but recommended for apps that
+ * use {@link android.Manifest.permission#PACKAGE_USAGE_STATS}.
+ * <p>
+ * The activity may define meta-data to describe what usage access is
+ * used for within their app with {@link #METADATA_USAGE_ACCESS_REASON}, which
+ * will be displayed in Settings.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String INTENT_CATEGORY_USAGE_ACCESS_CONFIG =
+ "android.intent.category.USAGE_ACCESS_CONFIG";
+
+ /**
+ * Metadata key: Reason for needing usage access.
+ * <p>
+ * A key for metadata attached to an activity that receives action
+ * {@link #INTENT_CATEGORY_USAGE_ACCESS_CONFIG}, shown to the
+ * user as description of how the app uses usage access.
+ * <p>
+ */
+ public static final String METADATA_USAGE_ACCESS_REASON =
+ "android.settings.metadata.USAGE_ACCESS_REASON";
+
+ /**
* Activity Action: Show settings to allow configuration of security and
* location privacy.
* <p>
@@ -5361,6 +5391,12 @@ public final class Settings {
public static final String SMS_DEFAULT_APPLICATION = "sms_default_application";
/**
+ * Specifies the package name currently configured to be the default dialer application
+ * @hide
+ */
+ public static final String DIALER_DEFAULT_APPLICATION = "dialer_default_application";
+
+ /**
* Specifies the package name currently configured to be the emergency assistance application
*
* @see android.telephony.TelephonyManager#ACTION_EMERGENCY_ASSISTANCE
diff --git a/core/java/android/security/NetworkSecurityPolicy.java b/core/java/android/security/NetworkSecurityPolicy.java
index 70cd388..7e87717 100644
--- a/core/java/android/security/NetworkSecurityPolicy.java
+++ b/core/java/android/security/NetworkSecurityPolicy.java
@@ -46,9 +46,9 @@ public class NetworkSecurityPolicy {
* without TLS or STARTTLS) is permitted for this process.
*
* <p>When cleartext network traffic is not permitted, the platform's components (e.g. HTTP and
- * FTP stacks, {@link android.webkit.WebView}, {@link android.app.DownloadManager},
- * {@link android.media.MediaPlayer}) will refuse this process's requests to use cleartext
- * traffic. Third-party libraries are strongly encouraged to honor this setting as well.
+ * FTP stacks, {@link android.app.DownloadManager}, {@link android.media.MediaPlayer}) will
+ * refuse this process's requests to use cleartext traffic. Third-party libraries are strongly
+ * encouraged to honor this setting as well.
*
* <p>This flag is honored on a best effort basis because it's impossible to prevent all
* cleartext traffic from Android applications given the level of access provided to them. For
@@ -56,6 +56,8 @@ public class NetworkSecurityPolicy {
* because it cannot determine whether its traffic is in cleartext. However, most network
* traffic from applications is handled by higher-level network stacks/components which can
* honor this aspect of the policy.
+ *
+ * <p>NOTE: {@link android.webkit.WebView} does not honor this flag.
*/
public boolean isCleartextTrafficPermitted() {
return libcore.net.NetworkSecurityPolicy.isCleartextTrafficPermitted();
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index ec8f802..eedbc70 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -88,10 +88,10 @@ public class DisplayListCanvas extends Canvas {
///////////////////////////////////////////////////////////////////////////
private DisplayListCanvas() {
- super(nCreateDisplayListRenderer());
+ super(nCreateDisplayListCanvas());
}
- private static native long nCreateDisplayListRenderer();
+ private static native long nCreateDisplayListCanvas();
public static void setProperty(String name, String value) {
nSetProperty(name, value);
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 779560c..1ac3f45 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -747,8 +747,22 @@ public class KeyEvent extends InputEvent implements Parcelable {
public static final int KEYCODE_TV_TIMER_PROGRAMMING = 258;
/** Key code constant: Help key. */
public static final int KEYCODE_HELP = 259;
-
- private static final int LAST_KEYCODE = KEYCODE_HELP;
+ /** Key code constant: Navigate to previous key.
+ * Goes backward by one item in an ordered collection of items. */
+ public static final int KEYCODE_NAVIGATE_PREVIOUS = 260;
+ /** Key code constant: Navigate to next key.
+ * Advances to the next item in an ordered collection of items. */
+ public static final int KEYCODE_NAVIGATE_NEXT = 261;
+ /** Key code constant: Navigate in key.
+ * Activates the item that currently has focus or expands to the next level of a navigation
+ * hierarchy. */
+ public static final int KEYCODE_NAVIGATE_IN = 262;
+ /** Key code constant: Navigate out key.
+ * Backs out one level of a navigation hierarchy or collapses the item that currently has
+ * focus. */
+ public static final int KEYCODE_NAVIGATE_OUT = 263;
+
+ private static final int LAST_KEYCODE = KEYCODE_NAVIGATE_OUT;
// NOTE: If you add a new keycode here you must also add it to:
// isSystem()
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 5cf2c5c..b055efe 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -130,7 +130,7 @@ public class ScaleGestureDetector {
private float mFocusY;
private boolean mQuickScaleEnabled;
- private boolean mButtonScaleEnabled;
+ private boolean mStylusScaleEnabled;
private float mCurrSpan;
private float mPrevSpan;
@@ -162,7 +162,7 @@ public class ScaleGestureDetector {
private static final float SCALE_FACTOR = .5f;
private static final int ANCHORED_SCALE_MODE_NONE = 0;
private static final int ANCHORED_SCALE_MODE_DOUBLE_TAP = 1;
- private static final int ANCHORED_SCALE_MODE_BUTTON = 2;
+ private static final int ANCHORED_SCALE_MODE_STYLUS = 2;
/**
@@ -212,9 +212,14 @@ public class ScaleGestureDetector {
mMinSpan = res.getDimensionPixelSize(com.android.internal.R.dimen.config_minScalingSpan);
mHandler = handler;
// Quick scale is enabled by default after JB_MR2
- if (context.getApplicationInfo().targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN_MR2) {
+ final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
+ if (targetSdkVersion > Build.VERSION_CODES.JELLY_BEAN_MR2) {
setQuickScaleEnabled(true);
}
+ // Stylus scale is enabled by default after LOLLIPOP_MR1
+ if (targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) {
+ setStylusScaleEnabled(true);
+ }
}
/**
@@ -315,14 +320,11 @@ public class ScaleGestureDetector {
}
final int count = event.getPointerCount();
- final int toolType = event.getToolType(0);
- final boolean isButtonTool = toolType == MotionEvent.TOOL_TYPE_STYLUS
- || toolType == MotionEvent.TOOL_TYPE_MOUSE;
- final boolean isAnchoredScaleButtonDown = isButtonTool && (count == 1)
+ final boolean isStylusButtonDown = (event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS)
&& (event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0;
final boolean anchoredScaleCancelled =
- mAnchoredScaleMode == ANCHORED_SCALE_MODE_BUTTON && !isAnchoredScaleButtonDown;
+ mAnchoredScaleMode == ANCHORED_SCALE_MODE_STYLUS && !isStylusButtonDown;
final boolean streamComplete = action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_CANCEL || anchoredScaleCancelled;
@@ -347,12 +349,12 @@ public class ScaleGestureDetector {
}
}
- if (!mInProgress && mButtonScaleEnabled && !inAnchoredScaleMode()
- && !streamComplete && isAnchoredScaleButtonDown) {
+ if (!mInProgress && mStylusScaleEnabled && !inAnchoredScaleMode()
+ && !streamComplete && isStylusButtonDown) {
// Start of a button scale gesture
mAnchoredScaleStartX = event.getX();
mAnchoredScaleStartY = event.getY();
- mAnchoredScaleMode = ANCHORED_SCALE_MODE_BUTTON;
+ mAnchoredScaleMode = ANCHORED_SCALE_MODE_STYLUS;
mInitialSpan = 0;
}
@@ -503,24 +505,22 @@ public class ScaleGestureDetector {
}
/**
- * Sets whether the associates {@link OnScaleGestureListener} should receive onScale callbacks
- * when the user presses a {@value MotionEvent#BUTTON_SECONDARY} (right mouse button, stylus
- * first button) and drags the pointer on the screen. Note that this is enabled by default if
- * the app targets API 23 and newer.
+ * Sets whether the associates {@link OnScaleGestureListener} should receive
+ * onScale callbacks when the user uses a stylus and presses the button.
+ * Note that this is enabled by default if the app targets API 23 and newer.
*
- * @param scales true to enable stylus or mouse scaling, false to disable.
+ * @param scales true to enable stylus scaling, false to disable.
*/
- public void setSecondaryButtonScaleEnabled(boolean scales) {
- mButtonScaleEnabled = scales;
+ public void setStylusScaleEnabled(boolean scales) {
+ mStylusScaleEnabled = scales;
}
/**
- * Return whether the button scale gesture, in which the user presses a
- * {@value MotionEvent#BUTTON_SECONDARY} (right mouse button, stylus first button) and drags the
- * pointer on the screen, should perform scaling. {@see #setButtonScaleEnabled(boolean)}.
+ * Return whether the stylus scale gesture, in which the user uses a stylus
+ * and presses the button, should preform scaling. {@see #setButtonScaleEnabled(boolean)}.
*/
- public boolean isSecondaryButtonScaleEnabled() {
- return mButtonScaleEnabled;
+ public boolean isStylusScaleEnabled() {
+ return mStylusScaleEnabled;
}
/**
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6176b9a..5c6ce76 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -631,6 +631,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* </p>
*
* @attr ref android.R.styleable#View_alpha
+ * @attr ref android.R.styleable#View_assistBlocked
* @attr ref android.R.styleable#View_background
* @attr ref android.R.styleable#View_clickable
* @attr ref android.R.styleable#View_contentDescription
@@ -2324,6 +2325,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* 1 PFLAG3_IS_LAID_OUT
* 1 PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
* 1 PFLAG3_CALLED_SUPER
+ * 1 PFLAG3_APPLYING_INSETS
+ * 1 PFLAG3_FITTING_SYSTEM_WINDOWS
+ * 1 PFLAG3_NESTED_SCROLLING_ENABLED
+ * 1 PFLAG3_ASSIST_BLOCKED
* |-------|-------|-------|-------|
*/
@@ -2381,6 +2386,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
/**
+ * <p>Indicates that we are allowing {@link android.view.ViewAssistStructure} to traverse
+ * into this view.<p>
+ */
+ static final int PFLAG3_ASSIST_BLOCKED = 0x100;
+
+ /**
* Always allow a user to over-scroll this view, provided it is a
* view that can scroll.
*
@@ -3869,6 +3880,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
viewFlagMasks |= SAVE_DISABLED_MASK;
}
break;
+ case com.android.internal.R.styleable.View_assistBlocked:
+ if (a.getBoolean(attr, false)) {
+ mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
+ }
+ break;
case com.android.internal.R.styleable.View_duplicateParentState:
if (a.getBoolean(attr, false)) {
viewFlagValues |= DUPLICATE_PARENT_STATE;
@@ -5775,7 +5791,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} else {
structure.setId(id, null, null, null);
}
- structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight-mLeft, mBottom-mTop);
+ structure.setDimens(mLeft, mTop, mScrollX, mScrollY, mRight - mLeft, mBottom - mTop);
structure.setVisibility(getVisibility());
structure.setEnabled(isEnabled());
if (isClickable()) {
@@ -5890,8 +5906,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@link #onProvideVirtualAssistStructure}.
*/
public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
- onProvideAssistStructure(structure);
- onProvideVirtualAssistStructure(structure);
+ if (!isAssistBlocked()) {
+ onProvideAssistStructure(structure);
+ onProvideVirtualAssistStructure(structure);
+ } else {
+ structure.setClassName(getAccessibilityClassName().toString());
+ structure.setAssistBlocked(true);
+ }
}
/**
@@ -7458,6 +7479,42 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Indicates whether this view will participate in data collection through
+ * {@link android.view.ViewAssistStructure}. If true, it will not provide any data
+ * for itself or its children. If false, the normal data collection will be allowed.
+ *
+ * @return Returns false if assist data collection is not blocked, else true.
+ *
+ * @see #setAssistBlocked(boolean)
+ * @attr ref android.R.styleable#View_assistBlocked
+ */
+ public boolean isAssistBlocked() {
+ return (mPrivateFlags3 & PFLAG3_ASSIST_BLOCKED) != 0;
+ }
+
+ /**
+ * Controls whether assist data collection from this view and its children is enabled
+ * (that is, whether {@link #onProvideAssistStructure} and
+ * {@link #onProvideVirtualAssistStructure} will be called). The default value is false,
+ * allowing normal assist collection. Setting this to false will disable assist collection.
+ *
+ * @param enabled Set to true to <em>disable</em> assist data collection, or false
+ * (the default) to allow it.
+ *
+ * @see #isAssistBlocked()
+ * @see #onProvideAssistStructure
+ * @see #onProvideVirtualAssistStructure
+ * @attr ref android.R.styleable#View_assistBlocked
+ */
+ public void setAssistBlocked(boolean enabled) {
+ if (enabled) {
+ mPrivateFlags3 |= PFLAG3_ASSIST_BLOCKED;
+ } else {
+ mPrivateFlags3 &= ~PFLAG3_ASSIST_BLOCKED;
+ }
+ }
+
+ /**
* Indicates whether this view will save its state (that is,
* whether its {@link #onSaveInstanceState} method will be called).
*
@@ -15101,6 +15158,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return (mClipBounds != null) ? new Rect(mClipBounds) : null;
}
+
+ /**
+ * Populates an output rectangle with the clip bounds of the view,
+ * returning {@code true} if successful or {@code false} if the view's
+ * clip bounds are {@code null}.
+ *
+ * @param outRect rectangle in which to place the clip bounds of the view
+ * @return {@code true} if successful or {@code false} if the view's
+ * clip bounds are {@code null}
+ */
+ public boolean getClipBounds(Rect outRect) {
+ if (mClipBounds != null) {
+ outRect.set(mClipBounds);
+ return true;
+ }
+ return false;
+ }
+
/**
* Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
* case of an active Animation being run on the view.
@@ -15283,9 +15358,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
RenderNode renderNode = null;
Bitmap cache = null;
- int layerType = getLayerType();
+ int layerType = getLayerType(); // TODO: signify cache state with just 'cache' local
if (layerType == LAYER_TYPE_SOFTWARE
|| (!drawingWithRenderNode && layerType != LAYER_TYPE_NONE)) {
+ // If not drawing with RenderNode, treat HW layers as SW
layerType = LAYER_TYPE_SOFTWARE;
buildDrawingCache(true);
cache = getDrawingCache(true);
@@ -15312,10 +15388,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
sy = mScrollY;
}
- final boolean hasNoCache = cache == null || drawingWithRenderNode;
- final boolean offsetForScroll = cache == null
- && !drawingWithRenderNode
- && layerType != LAYER_TYPE_HARDWARE;
+ final boolean drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
+ final boolean offsetForScroll = cache == null && !drawingWithRenderNode;
int restoreTo = -1;
if (!drawingWithRenderNode || transformToApply != null) {
@@ -15388,17 +15462,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
}
parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
- if (hasNoCache) {
+ if (!drawingWithDrawingCache) {
final int multipliedAlpha = (int) (255 * alpha);
if (!onSetAlpha(multipliedAlpha)) {
- int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
- if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0
- || layerType != LAYER_TYPE_NONE) {
- layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
- }
if (drawingWithRenderNode) {
renderNode.setAlpha(alpha * getAlpha() * getTransitionAlpha());
} else if (layerType == LAYER_TYPE_NONE) {
+ int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
+ if ((parentFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0) {
+ layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
+ }
canvas.saveLayerAlpha(sx, sy, sx + getWidth(), sy + getHeight(),
multipliedAlpha, layerFlags);
}
@@ -15433,33 +15506,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- if (hasNoCache) {
- boolean layerRendered = false;
- if (layerType == LAYER_TYPE_HARDWARE && !drawingWithRenderNode) {
- final HardwareLayer layer = getHardwareLayer();
- if (layer != null && layer.isValid()) {
- int restoreAlpha = mLayerPaint.getAlpha();
- mLayerPaint.setAlpha((int) (alpha * 255));
- ((DisplayListCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
- mLayerPaint.setAlpha(restoreAlpha);
- layerRendered = true;
- } else {
- canvas.saveLayer(sx, sy, sx + getWidth(), sy + getHeight(), mLayerPaint);
- }
- }
-
- if (!layerRendered) {
- if (!drawingWithRenderNode) {
- // Fast path for layouts with no backgrounds
- if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
- mPrivateFlags &= ~PFLAG_DIRTY_MASK;
- dispatchDraw(canvas);
- } else {
- draw(canvas);
- }
- } else {
+ if (!drawingWithDrawingCache) {
+ if (drawingWithRenderNode) {
+ mPrivateFlags &= ~PFLAG_DIRTY_MASK;
+ ((DisplayListCanvas) canvas).drawRenderNode(renderNode, parentFlags);
+ } else {
+ // Fast path for layouts with no backgrounds
+ if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
- ((DisplayListCanvas) canvas).drawRenderNode(renderNode, parentFlags);
+ dispatchDraw(canvas);
+ } else {
+ draw(canvas);
}
}
} else if (cache != null) {
diff --git a/core/java/android/view/ViewAssistStructure.java b/core/java/android/view/ViewAssistStructure.java
index 7d263c5..346b8ec 100644
--- a/core/java/android/view/ViewAssistStructure.java
+++ b/core/java/android/view/ViewAssistStructure.java
@@ -32,6 +32,8 @@ public abstract class ViewAssistStructure {
public abstract void setVisibility(int visibility);
+ public abstract void setAssistBlocked(boolean state);
+
public abstract void setEnabled(boolean state);
public abstract void setClickable(boolean state);
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index a237afd..27304f5 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -1040,14 +1040,10 @@ public class ViewDebug {
return methods;
}
- final ArrayList<Method> declaredMethods = new ArrayList();
- klass.getDeclaredMethodsUnchecked(false, declaredMethods);
+ methods = klass.getDeclaredMethodsUnchecked(false);
final ArrayList<Method> foundMethods = new ArrayList<Method>();
- final int count = declaredMethods.size();
- for (int i = 0; i < count; i++) {
- final Method method = declaredMethods.get(i);
-
+ for (final Method method : methods) {
// Ensure the method return and parameter types can be resolved.
try {
method.getReturnType();
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 8f2be99..4324e75 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2881,21 +2881,23 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
*/
public void dispatchProvideAssistStructure(ViewAssistStructure structure) {
super.dispatchProvideAssistStructure(structure);
- if (structure.getChildCount() == 0) {
- final int childrenCount = getChildCount();
- if (childrenCount > 0) {
- structure.setChildCount(childrenCount);
- final ArrayList<View> preorderedList = buildOrderedChildList();
- final boolean customOrder = preorderedList == null
- && isChildrenDrawingOrderEnabled();
- final View[] children = mChildren;
- for (int i=0; i<childrenCount; i++) {
- final int childIndex = customOrder
- ? getChildDrawingOrder(childrenCount, i) : i;
- final View child = (preorderedList == null)
- ? children[childIndex] : preorderedList.get(childIndex);
- ViewAssistStructure cstructure = structure.newChild(i);
- child.dispatchProvideAssistStructure(cstructure);
+ if (!isAssistBlocked()) {
+ if (structure.getChildCount() == 0) {
+ final int childrenCount = getChildCount();
+ if (childrenCount > 0) {
+ structure.setChildCount(childrenCount);
+ final ArrayList<View> preorderedList = buildOrderedChildList();
+ final boolean customOrder = preorderedList == null
+ && isChildrenDrawingOrderEnabled();
+ final View[] children = mChildren;
+ for (int i=0; i<childrenCount; i++) {
+ final int childIndex = customOrder
+ ? getChildDrawingOrder(childrenCount, i) : i;
+ final View child = (preorderedList == null)
+ ? children[childIndex] : preorderedList.get(childIndex);
+ ViewAssistStructure cstructure = structure.newChild(i);
+ child.dispatchProvideAssistStructure(cstructure);
+ }
}
}
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 943beb0..453e4f5 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -900,7 +900,9 @@ public abstract class WebSettings {
* and therefore secure policy, this setting should be disabled.
* Note that this setting affects only JavaScript access to file scheme
* resources. Other access to such resources, for example, from image HTML
- * elements, is unaffected.
+ * elements, is unaffected. To prevent possible violation of same domain policy
+ * on {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} and earlier
+ * devices, you should explicitly set this value to {@code false}.
* <p>
* The default value is true for API level
* {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
@@ -920,7 +922,9 @@ public abstract class WebSettings {
* the value of {@link #getAllowUniversalAccessFromFileURLs} is true.
* Note too, that this setting affects only JavaScript access to file scheme
* resources. Other access to such resources, for example, from image HTML
- * elements, is unaffected.
+ * elements, is unaffected. To prevent possible violation of same domain policy
+ * on {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH} and earlier
+ * devices, you should explicitly set this value to {@code false}.
* <p>
* The default value is true for API level
* {@link android.os.Build.VERSION_CODES#ICE_CREAM_SANDWICH_MR1} and below,
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 955ad06..b049e49 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -39,7 +39,6 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.inputmethodservice.ExtractEditText;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcel;
@@ -104,7 +103,6 @@ import android.widget.TextView.OnEditorActionListener;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
-import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.widget.EditableInputConnection;
import java.text.BreakIterator;
@@ -1764,15 +1762,55 @@ public class Editor {
}
/**
- * @return <code>true</code> if the cursor/current selection overlaps a {@link SuggestionSpan}.
+ * @return <code>true</code> if it's reasonable to offer to show suggestions depending on
+ * the current cursor position or selection range. This method is consistent with the
+ * method to show suggestions {@link SuggestionsPopupWindow#updateSuggestions}.
*/
- private boolean isCursorInsideSuggestionSpan() {
+ private boolean shouldOfferToShowSuggestions() {
CharSequence text = mTextView.getText();
if (!(text instanceof Spannable)) return false;
- SuggestionSpan[] suggestionSpans = ((Spannable) text).getSpans(
- mTextView.getSelectionStart(), mTextView.getSelectionEnd(), SuggestionSpan.class);
- return (suggestionSpans.length > 0);
+ final Spannable spannable = (Spannable) text;
+ final int selectionStart = mTextView.getSelectionStart();
+ final int selectionEnd = mTextView.getSelectionEnd();
+ final SuggestionSpan[] suggestionSpans = spannable.getSpans(selectionStart, selectionEnd,
+ SuggestionSpan.class);
+ if (suggestionSpans.length == 0) {
+ return false;
+ }
+ if (selectionStart == selectionEnd) {
+ // Spans overlap the cursor.
+ return true;
+ }
+ int minSpanStart = mTextView.getText().length();
+ int maxSpanEnd = 0;
+ int unionOfSpansCoveringSelectionStartStart = mTextView.getText().length();
+ int unionOfSpansCoveringSelectionStartEnd = 0;
+ for (int i = 0; i < suggestionSpans.length; i++) {
+ final int spanStart = spannable.getSpanStart(suggestionSpans[i]);
+ final int spanEnd = spannable.getSpanEnd(suggestionSpans[i]);
+ minSpanStart = Math.min(minSpanStart, spanStart);
+ maxSpanEnd = Math.max(maxSpanEnd, spanEnd);
+ if (selectionStart < spanStart || selectionStart > spanEnd) {
+ // The span doesn't cover the current selection start point.
+ continue;
+ }
+ unionOfSpansCoveringSelectionStartStart =
+ Math.min(unionOfSpansCoveringSelectionStartStart, spanStart);
+ unionOfSpansCoveringSelectionStartEnd =
+ Math.max(unionOfSpansCoveringSelectionStartEnd, spanEnd);
+ }
+ if (unionOfSpansCoveringSelectionStartStart >= unionOfSpansCoveringSelectionStartEnd) {
+ // No spans cover the selection start point.
+ return false;
+ }
+ if (minSpanStart < unionOfSpansCoveringSelectionStartStart
+ || maxSpanEnd > unionOfSpansCoveringSelectionStartEnd) {
+ // There is a span that is not covered by the union. In this case, we soouldn't offer
+ // to show suggestions as it's confusing.
+ return false;
+ }
+ return true;
}
/**
@@ -3020,18 +3058,8 @@ public class Editor {
}
private void populateMenuWithItems(Menu menu) {
- final boolean legacy = mTextView.getContext().getApplicationInfo().targetSdkVersion <
- Build.VERSION_CODES.LOLLIPOP;
- final Context context = !legacy && menu instanceof MenuBuilder ?
- ((MenuBuilder) menu).getContext() :
- mTextView.getContext();
- final TypedArray styledAttributes = context.obtainStyledAttributes(
- com.android.internal.R.styleable.SelectionModeDrawables);
-
if (mTextView.canCut()) {
menu.add(0, TextView.ID_CUT, 0, com.android.internal.R.string.cut).
- setIcon(styledAttributes.getResourceId(
- R.styleable.SelectionModeDrawables_actionModeCutDrawable, 0)).
setAlphabeticShortcut('x').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
@@ -3039,8 +3067,6 @@ public class Editor {
if (mTextView.canCopy()) {
menu.add(0, TextView.ID_COPY, 0, com.android.internal.R.string.copy).
- setIcon(styledAttributes.getResourceId(
- R.styleable.SelectionModeDrawables_actionModeCopyDrawable, 0)).
setAlphabeticShortcut('c').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
@@ -3048,23 +3074,23 @@ public class Editor {
if (mTextView.canPaste()) {
menu.add(0, TextView.ID_PASTE, 0, com.android.internal.R.string.paste).
- setIcon(styledAttributes.getResourceId(
- R.styleable.SelectionModeDrawables_actionModePasteDrawable, 0)).
setAlphabeticShortcut('v').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
}
+ if (mTextView.canShare()) {
+ menu.add(0, TextView.ID_SHARE, 0, com.android.internal.R.string.share).
+ setShowAsAction(
+ MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
+ }
+
menu.add(0, TextView.ID_SELECT_ALL, 0, com.android.internal.R.string.selectAll).
- setIcon(styledAttributes.getResourceId(
- R.styleable.SelectionModeDrawables_actionModeSelectAllDrawable, 0)).
setAlphabeticShortcut('a').
setShowAsAction(
MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
updateReplaceItem(menu);
-
- styledAttributes.recycle();
}
private void addIntentMenuItemsForTextProcessing(Menu menu) {
@@ -3104,7 +3130,7 @@ public class Editor {
}
private void updateReplaceItem(Menu menu) {
- boolean canReplace = mTextView.isSuggestionsEnabled() && isCursorInsideSuggestionSpan();
+ 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).
@@ -4025,9 +4051,9 @@ public class Editor {
positionCursor = true;
} else if (offset + mTouchWordOffset < mPreviousOffset) {
// User is shrinking the selection.
- if (currLine > mPrevLine) {
+ if (currLine < mPrevLine) {
// We're on a different line, so we'll snap to word boundaries.
- offset = getWordStart(offset);
+ offset = start;
}
offset += mTouchWordOffset;
positionCursor = true;
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index c5b5c84..c3ac278 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -94,7 +94,6 @@ public class PopupWindow {
private final int[] mDrawingLocation = new int[2];
private final int[] mScreenLocation = new int[2];
private final Rect mTempRect = new Rect();
- private final Rect mAnchorBounds = new Rect();
private Context mContext;
private WindowManager mWindowManager;
@@ -159,28 +158,6 @@ public class PopupWindow {
private WeakReference<View> mAnchor;
- private final EpicenterCallback mEpicenterCallback = new EpicenterCallback() {
- @Override
- public Rect onGetEpicenter(Transition transition) {
- final View anchor = mAnchor != null ? mAnchor.get() : null;
- final View decor = mDecorView;
- if (anchor == null || decor == null) {
- return null;
- }
-
- final Rect anchorBounds = mAnchorBounds;
- final int[] anchorLocation = anchor.getLocationOnScreen();
- final int[] popupLocation = mDecorView.getLocationOnScreen();
-
- // Compute the position of the anchor relative to the popup.
- anchorBounds.set(0, 0, anchor.getWidth(), anchor.getHeight());
- anchorBounds.offset(anchorLocation[0] - popupLocation[0],
- anchorLocation[1] - popupLocation[1]);
-
- return anchorBounds;
- }
- };
-
private final OnScrollChangedListener mOnScrollChangedListener = new OnScrollChangedListener() {
@Override
public void onScrollChanged() {
@@ -355,18 +332,10 @@ public class PopupWindow {
public void setEnterTransition(Transition enterTransition) {
mEnterTransition = enterTransition;
-
- if (mEnterTransition != null) {
- mEnterTransition.setEpicenterCallback(mEpicenterCallback);
- }
}
public void setExitTransition(Transition exitTransition) {
mExitTransition = exitTransition;
-
- if (mExitTransition != null) {
- mExitTransition.setEpicenterCallback(mEpicenterCallback);
- }
}
private Transition getTransition(int resId) {
@@ -1281,11 +1250,14 @@ public class PopupWindow {
final PopupDecorView decorView = mDecorView;
decorView.setFitsSystemWindows(mLayoutInsetDecor);
- decorView.requestEnterTransition(mEnterTransition);
setLayoutDirectionFromAnchor();
mWindowManager.addView(decorView, p);
+
+ if (mEnterTransition != null) {
+ decorView.requestEnterTransition(mEnterTransition);
+ }
}
private void setLayoutDirectionFromAnchor() {
@@ -1607,13 +1579,25 @@ public class PopupWindow {
// Ensure any ongoing or pending transitions are canceled.
decorView.cancelTransitions();
- unregisterForScrollChanged();
-
mIsShowing = false;
mIsTransitioningToDismiss = true;
- if (mExitTransition != null && decorView.isLaidOut()) {
- decorView.startExitTransition(mExitTransition, new TransitionListenerAdapter() {
+ final Transition exitTransition = mExitTransition;
+ if (exitTransition != null && decorView.isLaidOut()) {
+ // The decor view is non-interactive during exit transitions.
+ final LayoutParams p = (LayoutParams) decorView.getLayoutParams();
+ p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
+ p.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
+ mWindowManager.updateViewLayout(decorView, p);
+
+ final Rect epicenter = getRelativeAnchorBounds();
+ exitTransition.setEpicenterCallback(new EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return epicenter;
+ }
+ });
+ decorView.startExitTransition(exitTransition, new TransitionListenerAdapter() {
@Override
public void onTransitionEnd(Transition transition) {
dismissImmediate(decorView, contentHolder, contentView);
@@ -1623,11 +1607,30 @@ public class PopupWindow {
dismissImmediate(decorView, contentHolder, contentView);
}
+ // Clears the anchor view.
+ unregisterForScrollChanged();
+
if (mOnDismissListener != null) {
mOnDismissListener.onDismiss();
}
}
+ private Rect getRelativeAnchorBounds() {
+ final View anchor = mAnchor != null ? mAnchor.get() : null;
+ final View decor = mDecorView;
+ if (anchor == null || decor == null) {
+ return null;
+ }
+
+ final int[] anchorLocation = anchor.getLocationOnScreen();
+ final int[] popupLocation = mDecorView.getLocationOnScreen();
+
+ // Compute the position of the anchor relative to the popup.
+ final Rect bounds = new Rect(0, 0, anchor.getWidth(), anchor.getHeight());
+ bounds.offset(anchorLocation[0] - popupLocation[0], anchorLocation[1] - popupLocation[1]);
+ return bounds;
+ }
+
/**
* Removes the popup from the window manager and tears down the supporting
* view hierarchy, if necessary.
@@ -1996,6 +1999,13 @@ public class PopupWindow {
observer.removeOnGlobalLayoutListener(this);
}
+ final Rect epicenter = getRelativeAnchorBounds();
+ enterTransition.setEpicenterCallback(new EpicenterCallback() {
+ @Override
+ public Rect onGetEpicenter(Transition transition) {
+ return epicenter;
+ }
+ });
startEnterTransition(enterTransition);
}
});
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 726b89a..3e8df08 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8955,13 +8955,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
static final int ID_CUT = android.R.id.cut;
static final int ID_COPY = android.R.id.copy;
static final int ID_PASTE = android.R.id.paste;
+ static final int ID_SHARE = android.R.id.shareText;
static final int ID_PASTE_AS_PLAIN_TEXT = android.R.id.pasteAsPlainText;
static final int ID_REPLACE = android.R.id.replaceText;
/**
* Called when a context menu option for the text view is selected. Currently
* this will be one of {@link android.R.id#selectAll}, {@link android.R.id#cut},
- * {@link android.R.id#copy} or {@link android.R.id#paste}.
+ * {@link android.R.id#copy}, {@link android.R.id#paste} or {@link android.R.id#shareText}.
*
* @return true if the context menu item action was performed.
*/
@@ -9014,6 +9015,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
setPrimaryClip(ClipData.newPlainText(null, getTransformedText(min, max)));
stopSelectionActionMode();
return true;
+
+ case ID_SHARE:
+ shareSelectedText();
+ return true;
}
return false;
}
@@ -9091,15 +9096,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* If provided, this ActionMode.Callback will be used to create the ActionMode when text
* selection is initiated in this View.
*
- * The standard implementation populates the menu with a subset of Select All, Cut, Copy and
- * Paste actions, depending on what this View supports.
+ * The standard implementation populates the menu with a subset of Select All, Cut, Copy,
+ * Paste 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} or {@link android.R.id#paste} ids as
- * parameters.
+ * {@link android.R.id#cut}, {@link android.R.id#copy}, {@link android.R.id#paste} or
+ * {@link android.R.id#shareText} ids as parameters.
*
* Returning false from
* {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
@@ -9168,6 +9173,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return false;
}
+ boolean canShare() {
+ return canCopy();
+ }
+
boolean canPaste() {
return (mText instanceof Editable &&
mEditor != null && mEditor.mKeyListener != null &&
@@ -9241,6 +9250,18 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
}
}
+ private void shareSelectedText() {
+ String selectedText = getSelectedText();
+ if (selectedText != null && !selectedText.isEmpty()) {
+ Intent sharingIntent = new Intent(android.content.Intent.ACTION_SEND);
+ sharingIntent.setType("text/plain");
+ sharingIntent.removeExtra(android.content.Intent.EXTRA_TEXT);
+ sharingIntent.putExtra(android.content.Intent.EXTRA_TEXT, selectedText);
+ getContext().startActivity(Intent.createChooser(sharingIntent, null));
+ stopSelectionActionMode();
+ }
+ }
+
private void setPrimaryClip(ClipData clip) {
ClipboardManager clipboard = (ClipboardManager) getContext().
getSystemService(Context.CLIPBOARD_SERVICE);