diff options
Diffstat (limited to 'core/java/android')
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 <application> 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). |
