summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/animation/ValueAnimator.java5
-rw-r--r--core/java/android/app/Activity.java12
-rw-r--r--core/java/android/app/ActivityManagerNative.java21
-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/IActivityManager.java3
-rw-r--r--core/java/android/app/IAlarmManager.aidl1
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java10
-rw-r--r--core/java/android/content/pm/PackageCleanItem.java2
-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/IFingerprintService.aidl2
-rw-r--r--core/java/android/net/ConnectivityManager.java23
-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.java90
-rw-r--r--core/java/android/os/Parcelable.java5
-rw-r--r--core/java/android/provider/ContactsContract.java144
-rw-r--r--core/java/android/security/NetworkSecurityPolicy.java8
-rw-r--r--core/java/android/view/ScaleGestureDetector.java46
-rw-r--r--core/java/android/view/ViewDebug.java8
-rw-r--r--core/java/android/widget/Editor.java72
24 files changed, 473 insertions, 126 deletions
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/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/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index add7af2..7f062d9 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();
@@ -5552,6 +5560,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();
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/IActivityManager.java b/core/java/android/app/IActivityManager.java
index 59de281..7e03faa 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;
@@ -834,4 +836,5 @@ 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;
}
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/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/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/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/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 3e9b3d6..a48b324 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2441,17 +2441,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;
}
@@ -2563,7 +2567,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 af23f11..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;
@@ -1375,8 +1376,7 @@ public final class Parcel {
writeString(null);
return;
}
- String name = p.getClass().getName();
- writeString(name);
+ writeParcelableCreator(p);
p.writeToParcel(this, parcelableFlags);
}
@@ -2277,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);
@@ -2371,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;
}
@@ -2426,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) {
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/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/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/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/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/widget/Editor.java b/core/java/android/widget/Editor.java
index 955ad06..7d3a41e 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,17 @@ 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);
}
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 +3124,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).