diff options
Diffstat (limited to 'core/java/android')
48 files changed, 1011 insertions, 373 deletions
diff --git a/core/java/android/animation/PropertyValuesHolder.java b/core/java/android/animation/PropertyValuesHolder.java index 43014ad..21f6eda 100644 --- a/core/java/android/animation/PropertyValuesHolder.java +++ b/core/java/android/animation/PropertyValuesHolder.java @@ -743,9 +743,9 @@ public class PropertyValuesHolder implements Cloneable { static class IntPropertyValuesHolder extends PropertyValuesHolder { // Cache JNI functions to avoid looking them up twice - private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap = - new HashMap<Class, HashMap<String, Integer>>(); - int mJniSetter; + private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap = + new HashMap<Class, HashMap<String, Long>>(); + long mJniSetter; private IntProperty mIntProperty; IntKeyframeSet mIntKeyframeSet; @@ -845,11 +845,11 @@ public class PropertyValuesHolder implements Cloneable { // Check new static hashmap<propName, int> for setter method try { mPropertyMapLock.writeLock().lock(); - HashMap<String, Integer> propertyMap = sJNISetterPropertyMap.get(targetClass); + HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass); if (propertyMap != null) { - Integer mJniSetterInteger = propertyMap.get(mPropertyName); - if (mJniSetterInteger != null) { - mJniSetter = mJniSetterInteger; + Long jniSetter = propertyMap.get(mPropertyName); + if (jniSetter != null) { + mJniSetter = jniSetter; } } if (mJniSetter == 0) { @@ -857,7 +857,7 @@ public class PropertyValuesHolder implements Cloneable { mJniSetter = nGetIntMethod(targetClass, methodName); if (mJniSetter != 0) { if (propertyMap == null) { - propertyMap = new HashMap<String, Integer>(); + propertyMap = new HashMap<String, Long>(); sJNISetterPropertyMap.put(targetClass, propertyMap); } propertyMap.put(mPropertyName, mJniSetter); @@ -880,9 +880,9 @@ public class PropertyValuesHolder implements Cloneable { static class FloatPropertyValuesHolder extends PropertyValuesHolder { // Cache JNI functions to avoid looking them up twice - private static final HashMap<Class, HashMap<String, Integer>> sJNISetterPropertyMap = - new HashMap<Class, HashMap<String, Integer>>(); - int mJniSetter; + private static final HashMap<Class, HashMap<String, Long>> sJNISetterPropertyMap = + new HashMap<Class, HashMap<String, Long>>(); + long mJniSetter; private FloatProperty mFloatProperty; FloatKeyframeSet mFloatKeyframeSet; @@ -982,11 +982,11 @@ public class PropertyValuesHolder implements Cloneable { // Check new static hashmap<propName, int> for setter method try { mPropertyMapLock.writeLock().lock(); - HashMap<String, Integer> propertyMap = sJNISetterPropertyMap.get(targetClass); + HashMap<String, Long> propertyMap = sJNISetterPropertyMap.get(targetClass); if (propertyMap != null) { - Integer mJniSetterInteger = propertyMap.get(mPropertyName); - if (mJniSetterInteger != null) { - mJniSetter = mJniSetterInteger; + Long jniSetter = propertyMap.get(mPropertyName); + if (jniSetter != null) { + mJniSetter = jniSetter; } } if (mJniSetter == 0) { @@ -994,7 +994,7 @@ public class PropertyValuesHolder implements Cloneable { mJniSetter = nGetFloatMethod(targetClass, methodName); if (mJniSetter != 0) { if (propertyMap == null) { - propertyMap = new HashMap<String, Integer>(); + propertyMap = new HashMap<String, Long>(); sJNISetterPropertyMap.put(targetClass, propertyMap); } propertyMap.put(mPropertyName, mJniSetter); @@ -1015,8 +1015,8 @@ public class PropertyValuesHolder implements Cloneable { } - native static private int nGetIntMethod(Class targetClass, String methodName); - native static private int nGetFloatMethod(Class targetClass, String methodName); - native static private void nCallIntMethod(Object target, int methodID, int arg); - native static private void nCallFloatMethod(Object target, int methodID, float arg); -}
\ No newline at end of file + native static private long nGetIntMethod(Class targetClass, String methodName); + native static private long nGetFloatMethod(Class targetClass, String methodName); + native static private void nCallIntMethod(Object target, long methodID, int arg); + native static private void nCallFloatMethod(Object target, long methodID, float arg); +} diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index ec58fb0..63c9fec 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -816,7 +816,7 @@ public class Activity extends ContextThemeWrapper } /** - * Return the LoaderManager for this fragment, creating it if needed. + * Return the LoaderManager for this activity, creating it if needed. */ public LoaderManager getLoaderManager() { if (mLoaderManager != null) { diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index b038f9e..7f8dbba 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -68,6 +68,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.Trace; import android.os.UserHandle; +import android.provider.Settings; import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.DisplayMetrics; @@ -106,6 +107,7 @@ import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.net.InetAddress; import java.security.Security; +import java.text.DateFormat; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -742,8 +744,42 @@ public final class ActivityThread { setCoreSettings(coreSettings); - // Tell the VMRuntime about the application. - VMRuntime.registerAppInfo(appInfo.dataDir, appInfo.processName); + /* + * Two possible indications that this package could be + * sharing its runtime with other packages: + * + * 1.) the sharedUserId attribute is set in the manifest, + * indicating a request to share a VM with other + * packages with the same sharedUserId. + * + * 2.) the application element of the manifest has an + * attribute specifying a non-default process name, + * indicating the desire to run in another packages VM. + * + * If sharing is enabled we do not have a unique application + * in a process and therefore cannot rely on the package + * name inside the runtime. + */ + IPackageManager pm = getPackageManager(); + android.content.pm.PackageInfo pi = null; + try { + pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId()); + } catch (RemoteException e) { + } + if (pi != null) { + boolean sharedUserIdSet = (pi.sharedUserId != null); + boolean processNameNotDefault = + (pi.applicationInfo != null && + !appInfo.packageName.equals(pi.applicationInfo.processName)); + boolean sharable = (sharedUserIdSet || processNameNotDefault); + + // Tell the VMRuntime about the application, unless it is shared + // inside a process. + if (!sharable) { + VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir, + appInfo.processName); + } + } AppBindData data = new AppBindData(); data.processName = processName; @@ -1095,6 +1131,11 @@ public final class ActivityThread { public void scheduleInstallProvider(ProviderInfo provider) { sendMessage(H.INSTALL_PROVIDER, provider); } + + @Override + public final void updateTimePrefs(boolean is24Hour) { + DateFormat.set24HourTimePref(is24Hour); + } } private class H extends Handler { @@ -1144,6 +1185,7 @@ public final class ActivityThread { public static final int REQUEST_ASSIST_CONTEXT_EXTRAS = 143; public static final int TRANSLUCENT_CONVERSION_COMPLETE = 144; public static final int INSTALL_PROVIDER = 145; + String codeToString(int code) { if (DEBUG_MESSAGES) { switch (code) { @@ -1541,11 +1583,11 @@ public final class ActivityThread { /** * Creates the top level resources for the given package. */ - Resources getTopLevelResources(String resDir, + Resources getTopLevelResources(String resDir, String[] overlayDirs, int displayId, Configuration overrideConfiguration, LoadedApk pkgInfo) { - return mResourcesManager.getTopLevelResources(resDir, displayId, overrideConfiguration, - pkgInfo.getCompatibilityInfo(), null); + return mResourcesManager.getTopLevelResources(resDir, overlayDirs, displayId, + overrideConfiguration, pkgInfo.getCompatibilityInfo(), null); } final Handler getHandler() { @@ -4186,6 +4228,11 @@ public final class ActivityThread { Log.e(TAG, "Unable to setupGraphicsSupport due to missing cache directory"); } } + + + final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24)); + DateFormat.set24HourTimePref(is24Hr); + /** * For system applications on userdebug/eng builds, log stack * traces of disk and network access to dropbox for analysis. diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 010988e..c5e6ac4 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -825,7 +825,7 @@ final class ApplicationPackageManager extends PackageManager { } Resources r = mContext.mMainThread.getTopLevelResources( app.uid == Process.myUid() ? app.sourceDir : app.publicSourceDir, - Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo); + app.resourceDirs, Display.DEFAULT_DISPLAY, null, mContext.mPackageInfo); if (r != null) { return r; } diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java index 347d43f..cb453e2 100644 --- a/core/java/android/app/ApplicationThreadNative.java +++ b/core/java/android/app/ApplicationThreadNative.java @@ -627,6 +627,15 @@ public abstract class ApplicationThreadNative extends Binder reply.writeNoException(); return true; } + + case UPDATE_TIME_PREFS_TRANSACTION: + { + data.enforceInterface(IApplicationThread.descriptor); + byte is24Hour = data.readByte(); + updateTimePrefs(is24Hour == (byte) 1); + reply.writeNoException(); + return true; + } } return super.onTransact(code, data, reply, flags); @@ -1266,4 +1275,13 @@ class ApplicationThreadProxy implements IApplicationThread { mRemote.transact(SCHEDULE_INSTALL_PROVIDER_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } + + @Override + public void updateTimePrefs(boolean is24Hour) throws RemoteException { + Parcel data = Parcel.obtain(); + data.writeInterfaceToken(IApplicationThread.descriptor); + data.writeByte(is24Hour ? (byte) 1 : (byte) 0); + mRemote.transact(UPDATE_TIME_PREFS_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); + data.recycle(); + } } diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index bb46197..924d656 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -2036,7 +2036,7 @@ class ContextImpl extends Context { || (compatInfo != null && compatInfo.applicationScale != resources.getCompatibilityInfo().applicationScale)) { resources = mResourcesManager.getTopLevelResources( - packageInfo.getResDir(), displayId, + packageInfo.getResDir(), packageInfo.getOverlayDirs(), displayId, overrideConfiguration, compatInfo, activityToken); } } diff --git a/core/java/android/app/IAlarmManager.aidl b/core/java/android/app/IAlarmManager.aidl index 8476609..ef9f26e 100644 --- a/core/java/android/app/IAlarmManager.aidl +++ b/core/java/android/app/IAlarmManager.aidl @@ -28,7 +28,7 @@ interface IAlarmManager { /** windowLength == 0 means exact; windowLength < 0 means the let the OS decide */ void set(int type, long triggerAtTime, long windowLength, long interval, in PendingIntent operation, in WorkSource workSource); - void setTime(long millis); + boolean setTime(long millis); void setTimeZone(String zone); void remove(in PendingIntent operation); } diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java index d0cc1bb..3aceff9 100644 --- a/core/java/android/app/IApplicationThread.java +++ b/core/java/android/app/IApplicationThread.java @@ -138,6 +138,7 @@ public interface IApplicationThread extends IInterface { throws RemoteException; void setProcessState(int state) throws RemoteException; void scheduleInstallProvider(ProviderInfo provider) throws RemoteException; + void updateTimePrefs(boolean is24Hour) throws RemoteException; String descriptor = "android.app.IApplicationThread"; @@ -191,4 +192,5 @@ public interface IApplicationThread extends IInterface { int SCHEDULE_TRANSLUCENT_CONVERSION_COMPLETE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+48; int SET_PROCESS_STATE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+49; int SCHEDULE_INSTALL_PROVIDER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+50; + int UPDATE_TIME_PREFS_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+51; } diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index 8b0fd87..d409352 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -76,6 +76,7 @@ public final class LoadedApk { final String mPackageName; private final String mAppDir; private final String mResDir; + private final String[] mOverlayDirs; private final String[] mSharedLibraries; private final String mDataDir; private final String mLibDir; @@ -119,6 +120,7 @@ public final class LoadedApk { final int myUid = Process.myUid(); mResDir = aInfo.uid == myUid ? aInfo.sourceDir : aInfo.publicSourceDir; + mOverlayDirs = aInfo.resourceDirs; if (!UserHandle.isSameUser(aInfo.uid, myUid) && !Process.isIsolated()) { aInfo.dataDir = PackageManager.getDataDirForUser(UserHandle.getUserId(myUid), mPackageName); @@ -144,6 +146,7 @@ public final class LoadedApk { mPackageName = "android"; mAppDir = null; mResDir = null; + mOverlayDirs = null; mSharedLibraries = null; mDataDir = null; mDataDirFile = null; @@ -463,6 +466,10 @@ public final class LoadedApk { return mResDir; } + public String[] getOverlayDirs() { + return mOverlayDirs; + } + public String getDataDir() { return mDataDir; } @@ -477,7 +484,7 @@ public final class LoadedApk { public Resources getResources(ActivityThread mainThread) { if (mResources == null) { - mResources = mainThread.getTopLevelResources(mResDir, + mResources = mainThread.getTopLevelResources(mResDir, mOverlayDirs, Display.DEFAULT_DISPLAY, null, this); } return mResources; diff --git a/core/java/android/app/ResourcesManager.java b/core/java/android/app/ResourcesManager.java index f55dba4..728f372 100644 --- a/core/java/android/app/ResourcesManager.java +++ b/core/java/android/app/ResourcesManager.java @@ -147,7 +147,7 @@ public class ResourcesManager { * @param compatInfo the compability info. Must not be null. * @param token the application token for determining stack bounds. */ - public Resources getTopLevelResources(String resDir, int displayId, + public Resources getTopLevelResources(String resDir, String[] overlayDirs, int displayId, Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) { final float scale = compatInfo.applicationScale; ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale, @@ -180,6 +180,12 @@ public class ResourcesManager { return null; } + if (overlayDirs != null) { + for (String idmapPath : overlayDirs) { + assets.addOverlayPath(idmapPath); + } + } + //Slog.i(TAG, "Resource: key=" + key + ", display metrics=" + metrics); DisplayMetrics dm = getDisplayMetricsLocked(displayId); Configuration config; diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java index 9d0ab3a..02c850b 100644 --- a/core/java/android/content/ContentProvider.java +++ b/core/java/android/content/ContentProvider.java @@ -987,7 +987,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 { * Implement this to handle requests to delete one or more rows. * The implementation should apply the selection clause when performing * deletion, allowing the operation to affect multiple rows in a directory. - * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyDelete()} + * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} * after deleting. * This method can be called from multiple threads, as described in * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 106c1d6..95e27e2 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -3360,6 +3360,15 @@ public class Intent implements Parcelable, Cloneable { public static final String EXTRA_SHUTDOWN_USERSPACE_ONLY = "android.intent.extra.SHUTDOWN_USERSPACE_ONLY"; + /** + * Optional boolean extra for {@link #ACTION_TIME_CHANGED} that indicates the + * user has set their time format preferences to the 24 hour format. + * + * @hide for internal use only. + */ + public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT = + "android.intent.extra.TIME_PREF_24_HOUR_FORMAT"; + // --------------------------------------------------------------------- // --------------------------------------------------------------------- // Intent flags (see mFlags variable). diff --git a/core/java/android/content/Loader.java b/core/java/android/content/Loader.java index 911e49c..a045b3a 100644 --- a/core/java/android/content/Loader.java +++ b/core/java/android/content/Loader.java @@ -24,7 +24,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; /** - * An abstract class that performs asynchronous loading of data. While Loaders are active + * A class that performs asynchronous loading of data. While Loaders are active * they should monitor the source of their data and deliver new results when the contents * change. See {@link android.app.LoaderManager} for more detail. * diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 57acdff..0172509 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -447,6 +447,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { public String nativeLibraryDir; /** + * The ABI that this application requires, This is inferred from the ABIs + * of the native JNI libraries the application bundles. Will be {@code null} + * if this application does not require any particular ABI. + * + * {@hide} + */ + public String requiredCpuAbi; + + /** * The kernel user-ID that has been assigned to this application; * currently this is not a unique ID (multiple applications can have * the same uid). @@ -576,6 +585,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { sourceDir = orig.sourceDir; publicSourceDir = orig.publicSourceDir; nativeLibraryDir = orig.nativeLibraryDir; + requiredCpuAbi = orig.requiredCpuAbi; resourceDirs = orig.resourceDirs; seinfo = orig.seinfo; sharedLibraryFiles = orig.sharedLibraryFiles; @@ -616,6 +626,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { dest.writeString(sourceDir); dest.writeString(publicSourceDir); dest.writeString(nativeLibraryDir); + dest.writeString(requiredCpuAbi); dest.writeStringArray(resourceDirs); dest.writeString(seinfo); dest.writeStringArray(sharedLibraryFiles); @@ -655,6 +666,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { sourceDir = source.readString(); publicSourceDir = source.readString(); nativeLibraryDir = source.readString(); + requiredCpuAbi = source.readString(); resourceDirs = source.readStringArray(); seinfo = source.readString(); sharedLibraryFiles = source.readStringArray(); diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index af1a6d5..785f2b4 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -227,6 +227,14 @@ public class PackageInfo implements Parcelable { /** @hide */ public String requiredAccountType; + /** + * What package, if any, this package will overlay. + * + * Package name of target package, or null. + * @hide + */ + public String overlayTarget; + public PackageInfo() { } @@ -270,6 +278,7 @@ public class PackageInfo implements Parcelable { dest.writeInt(requiredForAllUsers ? 1 : 0); dest.writeString(restrictedAccountType); dest.writeString(requiredAccountType); + dest.writeString(overlayTarget); } public static final Parcelable.Creator<PackageInfo> CREATOR @@ -311,5 +320,6 @@ public class PackageInfo implements Parcelable { requiredForAllUsers = source.readInt() != 0; restrictedAccountType = source.readString(); requiredAccountType = source.readString(); + overlayTarget = source.readString(); } } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index e3a0362..226f5a6 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -675,6 +675,25 @@ public abstract class PackageManager { public static final int INSTALL_FAILED_USER_RESTRICTED = -111; /** + * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by + * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} + * if the system failed to install the package because its packaged native code did not + * match any of the ABIs supported by the system. + * + * @hide + */ + public static final int INSTALL_FAILED_NO_MATCHING_ABIS = -112; + + /** + * Internal return code for NativeLibraryHelper methods to indicate that the package + * being processed did not contain any native code. This is placed here only so that + * it can belong to the same value space as the other install failure codes. + * + * @hide + */ + public static final int NO_NATIVE_LIBRARIES = -113; + + /** * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the * package's data directory. * diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 0ce1e44..b3b6e09 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -309,6 +309,7 @@ public class PackageParser { } pi.restrictedAccountType = p.mRestrictedAccountType; pi.requiredAccountType = p.mRequiredAccountType; + pi.overlayTarget = p.mOverlayTarget; pi.firstInstallTime = firstInstallTime; pi.lastUpdateTime = lastUpdateTime; if ((flags&PackageManager.GET_GIDS) != 0) { @@ -492,6 +493,11 @@ public class PackageParser { public Package parsePackage(File sourceFile, String destCodePath, DisplayMetrics metrics, int flags) { + return parsePackage(sourceFile, destCodePath, metrics, flags, false); + } + + public Package parsePackage(File sourceFile, String destCodePath, + DisplayMetrics metrics, int flags, boolean trustedOverlay) { mParseError = PackageManager.INSTALL_SUCCEEDED; mArchiveSourcePath = sourceFile.getPath(); @@ -544,7 +550,7 @@ public class PackageParser { Exception errorException = null; try { // XXXX todo: need to figure out correct configuration. - pkg = parsePackage(res, parser, flags, errorText); + pkg = parsePackage(res, parser, flags, trustedOverlay, errorText); } catch (Exception e) { errorException = e; mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION; @@ -953,8 +959,8 @@ public class PackageParser { } private Package parsePackage( - Resources res, XmlResourceParser parser, int flags, String[] outError) - throws XmlPullParserException, IOException { + Resources res, XmlResourceParser parser, int flags, boolean trustedOverlay, + String[] outError) throws XmlPullParserException, IOException { AttributeSet attrs = parser; mParseInstrumentationArgs = null; @@ -1053,6 +1059,31 @@ public class PackageParser { if (!parseApplication(pkg, res, parser, attrs, flags, outError)) { return null; } + } else if (tagName.equals("overlay")) { + pkg.mTrustedOverlay = trustedOverlay; + + sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.AndroidManifestResourceOverlay); + pkg.mOverlayTarget = sa.getString( + com.android.internal.R.styleable.AndroidManifestResourceOverlay_targetPackage); + pkg.mOverlayPriority = sa.getInt( + com.android.internal.R.styleable.AndroidManifestResourceOverlay_priority, + -1); + sa.recycle(); + + if (pkg.mOverlayTarget == null) { + outError[0] = "<overlay> does not specify a target package"; + mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + if (pkg.mOverlayPriority < 0 || pkg.mOverlayPriority > 9999) { + outError[0] = "<overlay> priority must be between 0 and 9999"; + mParseError = + PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED; + return null; + } + XmlUtils.skipCurrentTag(parser); + } else if (tagName.equals("keys")) { if (!parseKeys(pkg, res, parser, attrs, outError)) { return null; @@ -3572,6 +3603,10 @@ public class PackageParser { */ public ManifestDigest manifestDigest; + public String mOverlayTarget; + public int mOverlayPriority; + public boolean mTrustedOverlay; + /** * Data used to feed the KeySetManager */ diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java index 93ce633..9ce17e4 100644 --- a/core/java/android/content/res/AssetManager.java +++ b/core/java/android/content/res/AssetManager.java @@ -69,13 +69,13 @@ public final class AssetManager { private final long[] mOffsets = new long[2]; // For communication with native code. - private int mObject; + private long mObject; private StringBlock mStringBlocks[] = null; private int mNumRefs = 1; private boolean mOpen = true; - private HashMap<Integer, RuntimeException> mRefStacks; + private HashMap<Long, RuntimeException> mRefStacks; /** * Create a new AssetManager containing only the basic system assets. @@ -90,7 +90,7 @@ public final class AssetManager { mNumRefs = 0; incRefsLocked(this.hashCode()); } - init(); + init(false); if (localLOGV) Log.v(TAG, "New asset manager: " + this); ensureSystemAssets(); } @@ -113,7 +113,7 @@ public final class AssetManager { incRefsLocked(this.hashCode()); } } - init(); + init(true); if (localLOGV) Log.v(TAG, "New asset manager: " + this); } @@ -224,7 +224,7 @@ public final class AssetManager { return retArray; } - /*package*/ final boolean getThemeValue(int theme, int ident, + /*package*/ final boolean getThemeValue(long theme, int ident, TypedValue outValue, boolean resolveRefs) { int block = loadThemeAttributeValue(theme, ident, outValue, resolveRefs); if (block >= 0) { @@ -312,7 +312,7 @@ public final class AssetManager { if (!mOpen) { throw new RuntimeException("Assetmanager has been closed"); } - int asset = openAsset(fileName, accessMode); + long asset = openAsset(fileName, accessMode); if (asset != 0) { AssetInputStream res = new AssetInputStream(asset); incRefsLocked(res.hashCode()); @@ -404,7 +404,7 @@ public final class AssetManager { if (!mOpen) { throw new RuntimeException("Assetmanager has been closed"); } - int asset = openNonAssetNative(cookie, fileName, accessMode); + long asset = openNonAssetNative(cookie, fileName, accessMode); if (asset != 0) { AssetInputStream res = new AssetInputStream(asset); incRefsLocked(res.hashCode()); @@ -484,7 +484,7 @@ public final class AssetManager { if (!mOpen) { throw new RuntimeException("Assetmanager has been closed"); } - int xmlBlock = openXmlAssetNative(cookie, fileName); + long xmlBlock = openXmlAssetNative(cookie, fileName); if (xmlBlock != 0) { XmlBlock res = new XmlBlock(this, xmlBlock); incRefsLocked(res.hashCode()); @@ -500,18 +500,18 @@ public final class AssetManager { } } - /*package*/ final int createTheme() { + /*package*/ final long createTheme() { synchronized (this) { if (!mOpen) { throw new RuntimeException("Assetmanager has been closed"); } - int res = newTheme(); + long res = newTheme(); incRefsLocked(res); return res; } } - /*package*/ final void releaseTheme(int theme) { + /*package*/ final void releaseTheme(long theme) { synchronized (this) { deleteTheme(theme); decRefsLocked(theme); @@ -537,7 +537,7 @@ public final class AssetManager { public final class AssetInputStream extends InputStream { public final int getAssetInt() { - return mAsset; + throw new UnsupportedOperationException(); } /** * @hide @@ -545,7 +545,7 @@ public final class AssetManager { public final long getNativeAsset() { return mAsset; } - private AssetInputStream(int asset) + private AssetInputStream(long asset) { mAsset = asset; mLength = getAssetLength(asset); @@ -597,7 +597,7 @@ public final class AssetManager { close(); } - private int mAsset; + private long mAsset; private long mLength; private long mMarkPos; } @@ -615,6 +615,16 @@ public final class AssetManager { private native final int addAssetPathNative(String path); + /** + * Add a set of assets to overlay an already added set of assets. + * + * This is only intended for application resources. System wide resources + * are handled before any Java code is executed. + * + * {@hide} + */ + public native final int addOverlayPath(String idmapPath); + /** * Add multiple sets of assets to the asset manager at once. See * {@link #addAssetPath(String)} for more information. Returns array of @@ -678,19 +688,19 @@ public final class AssetManager { /*package*/ native final String getResourceTypeName(int resid); /*package*/ native final String getResourceEntryName(int resid); - private native final int openAsset(String fileName, int accessMode); + private native final long openAsset(String fileName, int accessMode); private final native ParcelFileDescriptor openAssetFd(String fileName, long[] outOffsets) throws IOException; - private native final int openNonAssetNative(int cookie, String fileName, + private native final long openNonAssetNative(int cookie, String fileName, int accessMode); private native ParcelFileDescriptor openNonAssetFdNative(int cookie, String fileName, long[] outOffsets) throws IOException; - private native final void destroyAsset(int asset); - private native final int readAssetChar(int asset); - private native final int readAsset(int asset, byte[] b, int off, int len); - private native final long seekAsset(int asset, long offset, int whence); - private native final long getAssetLength(int asset); - private native final long getAssetRemainingLength(int asset); + private native final void destroyAsset(long asset); + private native final int readAssetChar(long asset); + private native final int readAsset(long asset, byte[] b, int off, int len); + private native final long seekAsset(long asset, long offset, int whence); + private native final long getAssetLength(long asset); + private native final long getAssetRemainingLength(long asset); /** Returns true if the resource was found, filling in mRetStringBlock and * mRetData. */ @@ -707,15 +717,15 @@ public final class AssetManager { /*package*/ static final int STYLE_RESOURCE_ID = 3; /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4; /*package*/ static final int STYLE_DENSITY = 5; - /*package*/ native static final boolean applyStyle(int theme, - int defStyleAttr, int defStyleRes, int xmlParser, + /*package*/ native static final boolean applyStyle(long theme, + int defStyleAttr, int defStyleRes, long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices); /*package*/ native final boolean retrieveAttributes( - int xmlParser, int[] inAttrs, int[] outValues, int[] outIndices); + long xmlParser, int[] inAttrs, int[] outValues, int[] outIndices); /*package*/ native final int getArraySize(int resource); /*package*/ native final int retrieveArray(int resource, int[] outValues); private native final int getStringBlockCount(); - private native final int getNativeStringBlock(int block); + private native final long getNativeStringBlock(int block); /** * {@hide} @@ -737,37 +747,37 @@ public final class AssetManager { */ public native static final int getGlobalAssetManagerCount(); - private native final int newTheme(); - private native final void deleteTheme(int theme); - /*package*/ native static final void applyThemeStyle(int theme, int styleRes, boolean force); - /*package*/ native static final void copyTheme(int dest, int source); - /*package*/ native static final int loadThemeAttributeValue(int theme, int ident, + private native final long newTheme(); + private native final void deleteTheme(long theme); + /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force); + /*package*/ native static final void copyTheme(long dest, long source); + /*package*/ native static final int loadThemeAttributeValue(long theme, int ident, TypedValue outValue, boolean resolve); - /*package*/ native static final void dumpTheme(int theme, int priority, String tag, String prefix); + /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix); - private native final int openXmlAssetNative(int cookie, String fileName); + private native final long openXmlAssetNative(int cookie, String fileName); private native final String[] getArrayStringResource(int arrayRes); private native final int[] getArrayStringInfo(int arrayRes); /*package*/ native final int[] getArrayIntResource(int arrayRes); - private native final void init(); + private native final void init(boolean isSystem); private native final void destroy(); - private final void incRefsLocked(int id) { + private final void incRefsLocked(long id) { if (DEBUG_REFS) { if (mRefStacks == null) { - mRefStacks = new HashMap<Integer, RuntimeException>(); - RuntimeException ex = new RuntimeException(); - ex.fillInStackTrace(); - mRefStacks.put(this.hashCode(), ex); + mRefStacks = new HashMap<Long, RuntimeException>(); } + RuntimeException ex = new RuntimeException(); + ex.fillInStackTrace(); + mRefStacks.put(id, ex); } mNumRefs++; } - private final void decRefsLocked(int id) { + private final void decRefsLocked(long id) { if (DEBUG_REFS && mRefStacks != null) { mRefStacks.remove(id); } diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java index 02e1761..3889ce0 100644 --- a/core/java/android/content/res/Resources.java +++ b/core/java/android/content/res/Resources.java @@ -1460,7 +1460,7 @@ public class Resources { } private final AssetManager mAssets; - private final int mTheme; + private final long mTheme; // Needed by layoutlib. /*package*/ int getNativeTheme() { @@ -1574,10 +1574,7 @@ public class Resources { String locale = null; if (mConfiguration.locale != null) { - locale = mConfiguration.locale.getLanguage(); - if (mConfiguration.locale.getCountry() != null) { - locale += "-" + mConfiguration.locale.getCountry(); - } + locale = mConfiguration.locale.toLanguageTag(); } int width, height; if (mMetrics.widthPixels >= mMetrics.heightPixels) { diff --git a/core/java/android/content/res/StringBlock.java b/core/java/android/content/res/StringBlock.java index 78180b1..77b8a33 100644 --- a/core/java/android/content/res/StringBlock.java +++ b/core/java/android/content/res/StringBlock.java @@ -36,7 +36,7 @@ final class StringBlock { private static final String TAG = "AssetManager"; private static final boolean localLOGV = false; - private final int mNative; + private final long mNative; private final boolean mUseSparse; private final boolean mOwnsNative; private CharSequence[] mStrings; @@ -474,7 +474,7 @@ final class StringBlock { * are doing! The given native object must exist for the entire lifetime * of this newly creating StringBlock. */ - StringBlock(int obj, boolean useSparse) { + StringBlock(long obj, boolean useSparse) { mNative = obj; mUseSparse = useSparse; mOwnsNative = false; @@ -482,11 +482,11 @@ final class StringBlock { + ": " + nativeGetSize(mNative)); } - private static native int nativeCreate(byte[] data, + private static native long nativeCreate(byte[] data, int offset, int size); - private static native int nativeGetSize(int obj); - private static native String nativeGetString(int obj, int idx); - private static native int[] nativeGetStyle(int obj, int idx); - private static native void nativeDestroy(int obj); + private static native int nativeGetSize(long obj); + private static native String nativeGetString(long obj, int idx); + private static native int[] nativeGetStyle(long obj, int idx); + private static native void nativeDestroy(long obj); } diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java index bea6529..3ad357f 100644 --- a/core/java/android/content/res/XmlBlock.java +++ b/core/java/android/content/res/XmlBlock.java @@ -75,7 +75,7 @@ final class XmlBlock { } /*package*/ final class Parser implements XmlResourceParser { - Parser(int parseState, XmlBlock block) { + Parser(long parseState, XmlBlock block) { mParseState = parseState; mBlock = block; block.mOpenCount++; @@ -458,7 +458,7 @@ final class XmlBlock { return mStrings.get(id); } - /*package*/ int mParseState; + /*package*/ long mParseState; private final XmlBlock mBlock; private boolean mStarted = false; private boolean mDecNextDepth = false; @@ -476,41 +476,41 @@ final class XmlBlock { * are doing! The given native object must exist for the entire lifetime * of this newly creating XmlBlock. */ - XmlBlock(AssetManager assets, int xmlBlock) { + XmlBlock(AssetManager assets, long xmlBlock) { mAssets = assets; mNative = xmlBlock; mStrings = new StringBlock(nativeGetStringBlock(xmlBlock), false); } private final AssetManager mAssets; - private final int mNative; + private final long mNative; /*package*/ final StringBlock mStrings; private boolean mOpen = true; private int mOpenCount = 1; - private static final native int nativeCreate(byte[] data, + private static final native long nativeCreate(byte[] data, int offset, int size); - private static final native int nativeGetStringBlock(int obj); + private static final native long nativeGetStringBlock(long obj); - private static final native int nativeCreateParseState(int obj); - /*package*/ static final native int nativeNext(int state); - private static final native int nativeGetNamespace(int state); - /*package*/ static final native int nativeGetName(int state); - private static final native int nativeGetText(int state); - private static final native int nativeGetLineNumber(int state); - private static final native int nativeGetAttributeCount(int state); - private static final native int nativeGetAttributeNamespace(int state, int idx); - private static final native int nativeGetAttributeName(int state, int idx); - private static final native int nativeGetAttributeResource(int state, int idx); - private static final native int nativeGetAttributeDataType(int state, int idx); - private static final native int nativeGetAttributeData(int state, int idx); - private static final native int nativeGetAttributeStringValue(int state, int idx); - private static final native int nativeGetIdAttribute(int state); - private static final native int nativeGetClassAttribute(int state); - private static final native int nativeGetStyleAttribute(int state); - private static final native int nativeGetAttributeIndex(int state, String namespace, String name); - private static final native void nativeDestroyParseState(int state); + private static final native long nativeCreateParseState(long obj); + /*package*/ static final native int nativeNext(long state); + private static final native int nativeGetNamespace(long state); + /*package*/ static final native int nativeGetName(long state); + private static final native int nativeGetText(long state); + private static final native int nativeGetLineNumber(long state); + private static final native int nativeGetAttributeCount(long state); + private static final native int nativeGetAttributeNamespace(long state, int idx); + private static final native int nativeGetAttributeName(long state, int idx); + private static final native int nativeGetAttributeResource(long state, int idx); + private static final native int nativeGetAttributeDataType(long state, int idx); + private static final native int nativeGetAttributeData(long state, int idx); + private static final native int nativeGetAttributeStringValue(long state, int idx); + private static final native int nativeGetIdAttribute(long state); + private static final native int nativeGetClassAttribute(long state); + private static final native int nativeGetStyleAttribute(long state); + private static final native int nativeGetAttributeIndex(long state, String namespace, String name); + private static final native void nativeDestroyParseState(long state); - private static final native void nativeDestroy(int obj); + private static final native void nativeDestroy(long obj); } diff --git a/core/java/android/debug/JNITest.java b/core/java/android/debug/JNITest.java deleted file mode 100644 index 2ce374a..0000000 --- a/core/java/android/debug/JNITest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.debug; - -/** - * Simple JNI verification test. - */ -public class JNITest { - - public JNITest() { - } - - public int test(int intArg, double doubleArg, String stringArg) { - int[] intArray = { 42, 53, 65, 127 }; - - return part1(intArg, doubleArg, stringArg, intArray); - } - - private native int part1(int intArg, double doubleArg, String stringArg, - int[] arrayArg); - - private int part2(double doubleArg, int fromArray, String stringArg) { - int result; - - System.out.println(stringArg + " : " + (float) doubleArg + " : " + - fromArray); - result = part3(stringArg); - - return result + 6; - } - - private static native int part3(String stringArg); -} - diff --git a/core/java/android/emoji/EmojiFactory.java b/core/java/android/emoji/EmojiFactory.java index 8fd8695..aba990d 100644 --- a/core/java/android/emoji/EmojiFactory.java +++ b/core/java/android/emoji/EmojiFactory.java @@ -54,7 +54,7 @@ public final class EmojiFactory { } // A pointer to native EmojiFactory object. - private int mNativeEmojiFactory; + private long mNativeEmojiFactory; private String mName; // Cache. private Map<Integer, WeakReference<Bitmap>> mCache; @@ -68,7 +68,7 @@ public final class EmojiFactory { * * This can be called from JNI code. */ - private EmojiFactory(int nativeEmojiFactory, String name) { + private EmojiFactory(long nativeEmojiFactory, String name) { mNativeEmojiFactory = nativeEmojiFactory; mName = name; mCache = new CustomLinkedHashMap<Integer, WeakReference<Bitmap>>(); @@ -272,18 +272,18 @@ public final class EmojiFactory { // native methods - private native void nativeDestructor(int factory); - private native Bitmap nativeGetBitmapFromAndroidPua(int nativeEmojiFactory, int AndroidPua); - private native int nativeGetAndroidPuaFromVendorSpecificSjis(int nativeEmojiFactory, + private native void nativeDestructor(long nativeEmojiFactory); + private native Bitmap nativeGetBitmapFromAndroidPua(long nativeEmojiFactory, int AndroidPua); + private native int nativeGetAndroidPuaFromVendorSpecificSjis(long nativeEmojiFactory, char sjis); - private native int nativeGetVendorSpecificSjisFromAndroidPua(int nativeEmojiFactory, + private native int nativeGetVendorSpecificSjisFromAndroidPua(long nativeEmojiFactory, int pua); - private native int nativeGetAndroidPuaFromVendorSpecificPua(int nativeEmojiFactory, + private native int nativeGetAndroidPuaFromVendorSpecificPua(long nativeEmojiFactory, int vsp); - private native int nativeGetVendorSpecificPuaFromAndroidPua(int nativeEmojiFactory, + private native int nativeGetVendorSpecificPuaFromAndroidPua(long nativeEmojiFactory, int pua); - private native int nativeGetMaximumVendorSpecificPua(int nativeEmojiFactory); - private native int nativeGetMinimumVendorSpecificPua(int nativeEmojiFactory); - private native int nativeGetMaximumAndroidPua(int nativeEmojiFactory); - private native int nativeGetMinimumAndroidPua(int nativeEmojiFactory); + private native int nativeGetMaximumVendorSpecificPua(long nativeEmojiFactory); + private native int nativeGetMinimumVendorSpecificPua(long nativeEmojiFactory); + private native int nativeGetMaximumAndroidPua(long nativeEmojiFactory); + private native int nativeGetMinimumAndroidPua(long nativeEmojiFactory); } diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java index 8c23129..5f2b5f0 100644 --- a/core/java/android/hardware/SensorManager.java +++ b/core/java/android/hardware/SensorManager.java @@ -1359,7 +1359,7 @@ public abstract class SensorManager { float q2 = rotationVector[1]; float q3 = rotationVector[2]; - if (rotationVector.length == 4) { + if (rotationVector.length >= 4) { q0 = rotationVector[3]; } else { q0 = 1 - q1*q1 - q2*q2 - q3*q3; @@ -1416,7 +1416,7 @@ public abstract class SensorManager { * @param Q an array of floats in which to store the computed quaternion */ public static void getQuaternionFromVector(float[] Q, float[] rv) { - if (rv.length == 4) { + if (rv.length >= 4) { Q[0] = rv[3]; } else { Q[0] = 1 - rv[0]*rv[0] - rv[1]*rv[1] - rv[2]*rv[2]; diff --git a/core/java/android/net/http/CertificateChainValidator.java b/core/java/android/net/http/CertificateChainValidator.java index 3652a4c..d06355d 100644 --- a/core/java/android/net/http/CertificateChainValidator.java +++ b/core/java/android/net/http/CertificateChainValidator.java @@ -16,22 +16,28 @@ package android.net.http; -import com.android.org.conscrypt.SSLParametersImpl; -import com.android.org.conscrypt.TrustManagerImpl; +import android.util.Slog; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.lang.reflect.Method; import java.security.GeneralSecurityException; -import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; -import javax.net.ssl.DefaultHostnameVerifier; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLSession; import javax.net.ssl.SSLSocket; -import javax.net.ssl.X509TrustManager; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509ExtendedTrustManager; /** * Class responsible for all server certificate validation functionality @@ -39,28 +45,54 @@ import javax.net.ssl.X509TrustManager; * {@hide} */ public class CertificateChainValidator { + private static final String TAG = "CertificateChainValidator"; - /** - * The singleton instance of the certificate chain validator - */ - private static final CertificateChainValidator sInstance - = new CertificateChainValidator(); + private static class NoPreloadHolder { + /** + * The singleton instance of the certificate chain validator. + */ + private static final CertificateChainValidator sInstance = new CertificateChainValidator(); + + /** + * The singleton instance of the hostname verifier. + */ + private static final HostnameVerifier sVerifier = HttpsURLConnection + .getDefaultHostnameVerifier(); + } - private static final DefaultHostnameVerifier sVerifier - = new DefaultHostnameVerifier(); + private X509ExtendedTrustManager mTrustManager; /** * @return The singleton instance of the certificates chain validator */ public static CertificateChainValidator getInstance() { - return sInstance; + return NoPreloadHolder.sInstance; } /** * Creates a new certificate chain validator. This is a private constructor. * If you need a Certificate chain validator, call getInstance(). */ - private CertificateChainValidator() {} + private CertificateChainValidator() { + try { + TrustManagerFactory tmf = TrustManagerFactory.getInstance("X.509"); + tmf.init((KeyStore) null); + for (TrustManager tm : tmf.getTrustManagers()) { + if (tm instanceof X509ExtendedTrustManager) { + mTrustManager = (X509ExtendedTrustManager) tm; + } + } + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("X.509 TrustManagerFactory must be available", e); + } catch (KeyStoreException e) { + throw new RuntimeException("X.509 TrustManagerFactory cannot be initialized", e); + } + + if (mTrustManager == null) { + throw new RuntimeException( + "None of the X.509 TrustManagers are X509ExtendedTrustManager"); + } + } /** * Performs the handshake and server certificates validation @@ -136,14 +168,31 @@ public class CertificateChainValidator { * Handles updates to credential storage. */ public static void handleTrustStorageUpdate() { - + TrustManagerFactory tmf; try { - X509TrustManager x509TrustManager = SSLParametersImpl.getDefaultTrustManager(); - if( x509TrustManager instanceof TrustManagerImpl ) { - TrustManagerImpl trustManager = (TrustManagerImpl) x509TrustManager; - trustManager.handleTrustStorageUpdate(); + tmf = TrustManagerFactory.getInstance("X.509"); + tmf.init((KeyStore) null); + } catch (NoSuchAlgorithmException e) { + Slog.w(TAG, "Couldn't find default X.509 TrustManagerFactory"); + return; + } catch (KeyStoreException e) { + Slog.w(TAG, "Couldn't initialize default X.509 TrustManagerFactory", e); + return; + } + + TrustManager[] tms = tmf.getTrustManagers(); + boolean sentUpdate = false; + for (TrustManager tm : tms) { + try { + Method updateMethod = tm.getClass().getDeclaredMethod("handleTrustStorageUpdate"); + updateMethod.setAccessible(true); + updateMethod.invoke(tm); + sentUpdate = true; + } catch (Exception e) { } - } catch (KeyManagementException ignored) { + } + if (!sentUpdate) { + Slog.w(TAG, "Didn't find a TrustManager to handle CA list update"); } } @@ -166,7 +215,8 @@ public class CertificateChainValidator { boolean valid = domain != null && !domain.isEmpty() - && sVerifier.verify(domain, currCertificate); + && NoPreloadHolder.sVerifier.verify(domain, + new DelegatingSSLSession.CertificateWrap(currCertificate)); if (!valid) { if (HttpLog.LOGV) { HttpLog.v("certificate not for this host: " + domain); @@ -175,13 +225,8 @@ public class CertificateChainValidator { } try { - X509TrustManager x509TrustManager = SSLParametersImpl.getDefaultTrustManager(); - if (x509TrustManager instanceof TrustManagerImpl) { - TrustManagerImpl trustManager = (TrustManagerImpl) x509TrustManager; - trustManager.checkServerTrusted(chain, authType, domain); - } else { - x509TrustManager.checkServerTrusted(chain, authType); - } + getInstance().getTrustManager().checkServerTrusted(chain, authType, + new DelegatingSocketWrapper(domain)); return null; // No errors. } catch (GeneralSecurityException e) { if (HttpLog.LOGV) { @@ -192,6 +237,12 @@ public class CertificateChainValidator { } } + /** + * Returns the platform default {@link X509ExtendedTrustManager}. + */ + private X509ExtendedTrustManager getTrustManager() { + return mTrustManager; + } private void closeSocketThrowException( SSLSocket socket, String errorMessage, String defaultErrorMessage) @@ -217,4 +268,4 @@ public class CertificateChainValidator { throw new SSLHandshakeException(errorMessage); } -} +}
\ No newline at end of file diff --git a/core/java/android/net/http/DelegatingSSLSession.java b/core/java/android/net/http/DelegatingSSLSession.java new file mode 100644 index 0000000..ff75b24 --- /dev/null +++ b/core/java/android/net/http/DelegatingSSLSession.java @@ -0,0 +1,172 @@ +/* + * Copyright 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.http; + +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSessionContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.X509ExtendedTrustManager; + +/** + * This is used when only a {@code hostname} is available but usage of the new API + * {@link X509ExtendedTrustManager#checkServerTrusted(X509Certificate[], String, Socket)} + * requires a {@link SSLSocket}. + * + * @hide + */ +public class DelegatingSSLSession implements SSLSession { + protected DelegatingSSLSession() { + } + + public static class HostnameWrap extends DelegatingSSLSession { + private final String mHostname; + + public HostnameWrap(String hostname) { + mHostname = hostname; + } + + @Override + public String getPeerHost() { + return mHostname; + } + } + + public static class CertificateWrap extends DelegatingSSLSession { + private final Certificate mCertificate; + + public CertificateWrap(Certificate certificate) { + mCertificate = certificate; + } + + @Override + public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { + return new Certificate[] { mCertificate }; + } + } + + + @Override + public int getApplicationBufferSize() { + throw new UnsupportedOperationException(); + } + + @Override + public String getCipherSuite() { + throw new UnsupportedOperationException(); + } + + @Override + public long getCreationTime() { + throw new UnsupportedOperationException(); + } + + @Override + public byte[] getId() { + throw new UnsupportedOperationException(); + } + + @Override + public long getLastAccessedTime() { + throw new UnsupportedOperationException(); + } + + @Override + public Certificate[] getLocalCertificates() { + throw new UnsupportedOperationException(); + } + + @Override + public Principal getLocalPrincipal() { + throw new UnsupportedOperationException(); + } + + @Override + public int getPacketBufferSize() { + throw new UnsupportedOperationException(); + } + + @Override + public javax.security.cert.X509Certificate[] getPeerCertificateChain() + throws SSLPeerUnverifiedException { + throw new UnsupportedOperationException(); + } + + @Override + public Certificate[] getPeerCertificates() throws SSLPeerUnverifiedException { + throw new UnsupportedOperationException(); + } + + @Override + public String getPeerHost() { + throw new UnsupportedOperationException(); + } + + @Override + public int getPeerPort() { + throw new UnsupportedOperationException(); + } + + @Override + public Principal getPeerPrincipal() throws SSLPeerUnverifiedException { + throw new UnsupportedOperationException(); + } + + @Override + public String getProtocol() { + throw new UnsupportedOperationException(); + } + + @Override + public SSLSessionContext getSessionContext() { + throw new UnsupportedOperationException(); + } + + @Override + public Object getValue(String name) { + throw new UnsupportedOperationException(); + } + + @Override + public String[] getValueNames() { + throw new UnsupportedOperationException(); + } + + @Override + public void invalidate() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isValid() { + throw new UnsupportedOperationException(); + } + + @Override + public void putValue(String name, Object value) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeValue(String name) { + throw new UnsupportedOperationException(); + } +}
\ No newline at end of file diff --git a/core/java/android/net/http/DelegatingSocketWrapper.java b/core/java/android/net/http/DelegatingSocketWrapper.java new file mode 100644 index 0000000..230d017 --- /dev/null +++ b/core/java/android/net/http/DelegatingSocketWrapper.java @@ -0,0 +1,127 @@ +/* + * Copyright 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.http; + +import java.io.IOException; + +import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.X509ExtendedTrustManager; + +/** + * This is used when only a {@code hostname} is available for + * {@link X509ExtendedTrustManager#checkServerTrusted(java.security.cert.X509Certificate[], String, Socket)} + * but we want to use the new API that requires a {@link SSLSocket}. + */ +class DelegatingSocketWrapper extends SSLSocket { + private String hostname; + + public DelegatingSocketWrapper(String hostname) { + this.hostname = hostname; + } + + @Override + public String[] getSupportedCipherSuites() { + throw new UnsupportedOperationException(); + } + + @Override + public String[] getEnabledCipherSuites() { + throw new UnsupportedOperationException(); + } + + @Override + public void setEnabledCipherSuites(String[] suites) { + throw new UnsupportedOperationException(); + } + + @Override + public String[] getSupportedProtocols() { + throw new UnsupportedOperationException(); + } + + @Override + public String[] getEnabledProtocols() { + throw new UnsupportedOperationException(); + } + + @Override + public void setEnabledProtocols(String[] protocols) { + throw new UnsupportedOperationException(); + } + + @Override + public SSLSession getSession() { + return new DelegatingSSLSession.HostnameWrap(hostname); + } + + @Override + public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { + throw new UnsupportedOperationException(); + } + + @Override + public void startHandshake() throws IOException { + throw new UnsupportedOperationException(); + } + + @Override + public void setUseClientMode(boolean mode) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean getUseClientMode() { + throw new UnsupportedOperationException(); + } + + @Override + public void setNeedClientAuth(boolean need) { + throw new UnsupportedOperationException(); + } + + @Override + public void setWantClientAuth(boolean want) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean getNeedClientAuth() { + throw new UnsupportedOperationException(); + } + + @Override + public boolean getWantClientAuth() { + throw new UnsupportedOperationException(); + } + + @Override + public void setEnableSessionCreation(boolean flag) { + throw new UnsupportedOperationException(); + } + + @Override + public boolean getEnableSessionCreation() { + throw new UnsupportedOperationException(); + } +}
\ No newline at end of file diff --git a/core/java/android/net/http/X509TrustManagerExtensions.java b/core/java/android/net/http/X509TrustManagerExtensions.java index cfe5f27..d730a7b 100644 --- a/core/java/android/net/http/X509TrustManagerExtensions.java +++ b/core/java/android/net/http/X509TrustManagerExtensions.java @@ -22,14 +22,25 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.List; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.X509ExtendedTrustManager; import javax.net.ssl.X509TrustManager; /** * X509TrustManager wrapper exposing Android-added features. - * - * <p> The checkServerTrusted method allows callers to perform additional - * verification of certificate chains after they have been successfully - * verified by the platform.</p> + * <p> + * The checkServerTrusted method allows callers to perform additional + * verification of certificate chains after they have been successfully verified + * by the platform. + * </p> + * <p> + * If the returned certificate list is not needed, see also + * {@code X509ExtendedTrustManager#checkServerTrusted(X509Certificate[], String, java.net.Socket)} + * where an {@link SSLSocket} can be used to verify the given hostname during + * handshake using + * {@code SSLParameters#setEndpointIdentificationAlgorithm(String)}. + * </p> */ public class X509TrustManagerExtensions { @@ -45,7 +56,8 @@ public class X509TrustManagerExtensions { if (tm instanceof TrustManagerImpl) { mDelegate = (TrustManagerImpl) tm; } else { - throw new IllegalArgumentException("tm is not a supported type of X509TrustManager"); + throw new IllegalArgumentException("tm is an instance of " + tm.getClass().getName() + + " which is not a supported type of X509TrustManager"); } } @@ -61,6 +73,7 @@ public class X509TrustManagerExtensions { */ public List<X509Certificate> checkServerTrusted(X509Certificate[] chain, String authType, String host) throws CertificateException { - return mDelegate.checkServerTrusted(chain, authType, host); + return mDelegate.checkServerTrusted(chain, authType, + new DelegatingSSLSession.HostnameWrap(host)); } } diff --git a/core/java/android/nfc/tech/Ndef.java b/core/java/android/nfc/tech/Ndef.java index 64aa299..f16dc3b 100644 --- a/core/java/android/nfc/tech/Ndef.java +++ b/core/java/android/nfc/tech/Ndef.java @@ -278,6 +278,8 @@ public final class Ndef extends BasicTagTechnology { throw new TagLostException(); } return msg; + } else if (!tagService.isPresent(serviceHandle)) { + throw new TagLostException(); } else { return null; } diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java index 22e1476..b2e0b29 100644 --- a/core/java/android/os/Build.java +++ b/core/java/android/os/Build.java @@ -74,7 +74,14 @@ public class Build { /** A hardware serial number, if available. Alphanumeric only, case-insensitive. */ public static final String SERIAL = getString("ro.serialno"); - + + /** + * A list of ABIs (in priority) order supported by this device. + * + * @hide + */ + public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").split(","); + /** Various version strings. */ public static class VERSION { /** diff --git a/core/java/android/os/CountDownTimer.java b/core/java/android/os/CountDownTimer.java index 15e6405..58acbcf 100644 --- a/core/java/android/os/CountDownTimer.java +++ b/core/java/android/os/CountDownTimer.java @@ -16,8 +16,6 @@ package android.os; -import android.util.Log; - /** * Schedule a countdown until a time in the future, with * regular notifications on intervals along the way. @@ -56,6 +54,11 @@ public abstract class CountDownTimer { private final long mCountdownInterval; private long mStopTimeInFuture; + + /** + * boolean representing if the timer was cancelled + */ + private boolean mCancelled = false; /** * @param millisInFuture The number of millis in the future from the call @@ -72,7 +75,8 @@ public abstract class CountDownTimer { /** * Cancel the countdown. */ - public final void cancel() { + public synchronized final void cancel() { + mCancelled = true; mHandler.removeMessages(MSG); } @@ -80,6 +84,7 @@ public abstract class CountDownTimer { * Start the countdown. */ public synchronized final CountDownTimer start() { + mCancelled = false; if (mMillisInFuture <= 0) { onFinish(); return this; @@ -112,6 +117,10 @@ public abstract class CountDownTimer { public void handleMessage(Message msg) { synchronized (CountDownTimer.this) { + if (mCancelled) { + return; + } + final long millisLeft = mStopTimeInFuture - SystemClock.elapsedRealtime(); if (millisLeft <= 0) { diff --git a/core/java/android/os/MemoryFile.java b/core/java/android/os/MemoryFile.java index ee7a4c6..6cec55a 100644 --- a/core/java/android/os/MemoryFile.java +++ b/core/java/android/os/MemoryFile.java @@ -63,12 +63,17 @@ public class MemoryFile * Allocates a new ashmem region. The region is initially not purgable. * * @param name optional name for the file (can be null). - * @param length of the memory file in bytes. + * @param length of the memory file in bytes, must be non-negative. * @throws IOException if the memory file could not be created. */ public MemoryFile(String name, int length) throws IOException { mLength = length; - mFD = native_open(name, length); + if (length >= 0) { + mFD = native_open(name, length); + } else { + throw new IOException("Invalid length: " + length); + } + if (length > 0) { mAddress = native_mmap(mFD, length, PROT_READ | PROT_WRITE); } else { diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 6716098..7425f67 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -1246,9 +1246,6 @@ public final class Parcel { } else if (v instanceof Parcelable[]) { writeInt(VAL_PARCELABLEARRAY); writeParcelableArray((Parcelable[]) v, 0); - } else if (v instanceof Object[]) { - writeInt(VAL_OBJECTARRAY); - writeArray((Object[]) v); } else if (v instanceof int[]) { writeInt(VAL_INTARRAY); writeIntArray((int[]) v); @@ -1258,12 +1255,20 @@ public final class Parcel { } else if (v instanceof Byte) { writeInt(VAL_BYTE); writeInt((Byte) v); - } else if (v instanceof Serializable) { - // Must be last - writeInt(VAL_SERIALIZABLE); - writeSerializable((Serializable) v); } else { - throw new RuntimeException("Parcel: unable to marshal value " + v); + Class<?> clazz = v.getClass(); + if (clazz.isArray() && clazz.getComponentType() == Object.class) { + // Only pure Object[] are written here, Other arrays of non-primitive types are + // handled by serialization as this does not record the component type. + writeInt(VAL_OBJECTARRAY); + writeArray((Object[]) v); + } else if (v instanceof Serializable) { + // Must be last + writeInt(VAL_SERIALIZABLE); + writeSerializable((Serializable) v); + } else { + throw new RuntimeException("Parcel: unable to marshal value " + v); + } } } @@ -1454,10 +1459,11 @@ public final class Parcel { } /** - * Use this function for customized exception handling. - * customized method call this method for all unknown case - * @param code exception code - * @param msg exception message + * Throw an exception with the given message. Not intended for use + * outside the Parcel class. + * + * @param code Used to determine which exception class to throw. + * @param msg The exception message. */ public final void readException(int code, String msg) { switch (code) { diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index 057f516..995e396 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -16,17 +16,18 @@ package android.os; -import android.net.LocalSocketAddress; import android.net.LocalSocket; +import android.net.LocalSocketAddress; import android.util.Log; -import dalvik.system.Zygote; - +import com.android.internal.os.Zygote; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.IOException; import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; - +import java.util.Arrays; +import java.util.List; import libcore.io.Libcore; /*package*/ class ZygoteStartFailedEx extends Exception { @@ -47,17 +48,7 @@ public class Process { private static final String ZYGOTE_SOCKET = "zygote"; - /** - * Name of a process for running the platform's media services. - * {@hide} - */ - public static final String ANDROID_SHARED_MEDIA = "com.android.process.media"; - - /** - * Name of the process that Google content providers can share. - * {@hide} - */ - public static final String GOOGLE_SHARED_APP_CONTENT = "com.google.process.content"; + private static final String SECONDARY_ZYGOTE_SOCKET = "zygote_secondary"; /** * Defines the UID/GID under which system code runs. @@ -344,15 +335,112 @@ public class Process { public static final int SIGNAL_QUIT = 3; public static final int SIGNAL_KILL = 9; public static final int SIGNAL_USR1 = 10; - - // State for communicating with zygote process - static LocalSocket sZygoteSocket; - static DataInputStream sZygoteInputStream; - static BufferedWriter sZygoteWriter; + /** + * State for communicating with the zygote process. + */ + static class ZygoteState { + final LocalSocket socket; + final DataInputStream inputStream; + final BufferedWriter writer; + final List<String> abiList; - /** true if previous zygote open failed */ - static boolean sPreviousZygoteOpenFailed; + boolean mClosed; + + private ZygoteState(LocalSocket socket, DataInputStream inputStream, + BufferedWriter writer, List<String> abiList) { + this.socket = socket; + this.inputStream = inputStream; + this.writer = writer; + this.abiList = abiList; + } + + static ZygoteState connect(String socketAddress, int tries) throws ZygoteStartFailedEx { + LocalSocket zygoteSocket = null; + DataInputStream zygoteInputStream = null; + BufferedWriter zygoteWriter = null; + + /* + * See bug #811181: Sometimes runtime can make it up before zygote. + * Really, we'd like to do something better to avoid this condition, + * but for now just wait a bit... + * + * TODO: This bug was filed in 2007. Get rid of this code. The zygote + * forks the system_server so it shouldn't be possible for the zygote + * socket to be brought up after the system_server is. + */ + for (int i = 0; i < tries; i++) { + if (i > 0) { + try { + Log.i(LOG_TAG, "Zygote not up yet, sleeping..."); + Thread.sleep(ZYGOTE_RETRY_MILLIS); + } catch (InterruptedException ex) { + throw new ZygoteStartFailedEx(ex); + } + } + + try { + zygoteSocket = new LocalSocket(); + zygoteSocket.connect(new LocalSocketAddress(socketAddress, + LocalSocketAddress.Namespace.RESERVED)); + + zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream()); + + zygoteWriter = new BufferedWriter(new OutputStreamWriter( + zygoteSocket.getOutputStream()), 256); + break; + } catch (IOException ex) { + if (zygoteSocket != null) { + try { + zygoteSocket.close(); + } catch (IOException ex2) { + Log.e(LOG_TAG,"I/O exception on close after exception", ex2); + } + } + + zygoteSocket = null; + } + } + + if (zygoteSocket == null) { + throw new ZygoteStartFailedEx("connect failed"); + } + + String abiListString = getAbiList(zygoteWriter, zygoteInputStream); + Log.i("Zygote", "Process: zygote socket opened, supported ABIS: " + abiListString); + + return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter, + Arrays.asList(abiListString.split(","))); + } + + boolean matches(String abi) { + return abiList.contains(abi); + } + + void close() { + try { + socket.close(); + } catch (IOException ex) { + Log.e(LOG_TAG,"I/O exception on routine close", ex); + } + + mClosed = true; + } + + boolean isClosed() { + return mClosed; + } + } + + /** + * The state of the connection to the primary zygote. + */ + static ZygoteState primaryZygoteState; + + /** + * The state of the connection to the secondary zygote. + */ + static ZygoteState secondaryZygoteState; /** * Start a new process. @@ -378,6 +466,7 @@ public class Process { * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param seInfo null-ok SELinux information for the new process. + * @param abi non-null the ABI this app should be started with. * @param zygoteArgs Additional arguments to supply to the zygote process. * * @return An object that describes the result of the attempt to start the process. @@ -391,10 +480,12 @@ public class Process { int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, + String abi, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, - debugFlags, mountExternal, targetSdkVersion, seInfo, zygoteArgs); + debugFlags, mountExternal, targetSdkVersion, seInfo, + abi, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); @@ -407,78 +498,31 @@ public class Process { static final int ZYGOTE_RETRY_MILLIS = 500; /** - * Tries to open socket to Zygote process if not already open. If - * already open, does nothing. May block and retry. + * Queries the zygote for the list of ABIS it supports. + * + * @throws ZygoteStartFailedEx if the query failed. */ - private static void openZygoteSocketIfNeeded() + private static String getAbiList(BufferedWriter writer, DataInputStream inputStream) throws ZygoteStartFailedEx { + try { - int retryCount; - - if (sPreviousZygoteOpenFailed) { - /* - * If we've failed before, expect that we'll fail again and - * don't pause for retries. - */ - retryCount = 0; - } else { - retryCount = 10; - } - - /* - * See bug #811181: Sometimes runtime can make it up before zygote. - * Really, we'd like to do something better to avoid this condition, - * but for now just wait a bit... - */ - for (int retry = 0 - ; (sZygoteSocket == null) && (retry < (retryCount + 1)) - ; retry++ ) { - - if (retry > 0) { - try { - Log.i("Zygote", "Zygote not up yet, sleeping..."); - Thread.sleep(ZYGOTE_RETRY_MILLIS); - } catch (InterruptedException ex) { - // should never happen - } - } - - try { - sZygoteSocket = new LocalSocket(); - - sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, - LocalSocketAddress.Namespace.RESERVED)); - - sZygoteInputStream - = new DataInputStream(sZygoteSocket.getInputStream()); - - sZygoteWriter = - new BufferedWriter( - new OutputStreamWriter( - sZygoteSocket.getOutputStream()), - 256); - - Log.i("Zygote", "Process: zygote socket opened"); - - sPreviousZygoteOpenFailed = false; - break; - } catch (IOException ex) { - if (sZygoteSocket != null) { - try { - sZygoteSocket.close(); - } catch (IOException ex2) { - Log.e(LOG_TAG,"I/O exception on close after exception", - ex2); - } - } - - sZygoteSocket = null; - } - } - - if (sZygoteSocket == null) { - sPreviousZygoteOpenFailed = true; - throw new ZygoteStartFailedEx("connect failed"); + // Each query starts with the argument count (1 in this case) + writer.write("1"); + // ... followed by a new-line. + writer.newLine(); + // ... followed by our only argument. + writer.write("--query-abi-list"); + writer.newLine(); + writer.flush(); + + // The response is a length prefixed stream of ASCII bytes. + int numBytes = inputStream.readInt(); + byte[] bytes = new byte[numBytes]; + inputStream.readFully(bytes); + + return new String(bytes, StandardCharsets.US_ASCII); + } catch (IOException ioe) { + throw new ZygoteStartFailedEx(ioe); } } @@ -486,14 +530,12 @@ public class Process { * Sends an argument list to the zygote process, which starts a new child * and returns the child's pid. Please note: the present implementation * replaces newlines in the argument list with spaces. - * @param args argument list - * @return An object that describes the result of the attempt to start the process. + * * @throws ZygoteStartFailedEx if process start failed for any reason */ - private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args) + private static ProcessStartResult zygoteSendArgsAndGetResult( + ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { - openZygoteSocketIfNeeded(); - try { /** * See com.android.internal.os.ZygoteInit.readArgumentList() @@ -505,9 +547,11 @@ public class Process { * the child or -1 on failure, followed by boolean to * indicate whether a wrapper process was used. */ + final BufferedWriter writer = zygoteState.writer; + final DataInputStream inputStream = zygoteState.inputStream; - sZygoteWriter.write(Integer.toString(args.size())); - sZygoteWriter.newLine(); + writer.write(Integer.toString(args.size())); + writer.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { @@ -516,32 +560,22 @@ public class Process { throw new ZygoteStartFailedEx( "embedded newlines not allowed"); } - sZygoteWriter.write(arg); - sZygoteWriter.newLine(); + writer.write(arg); + writer.newLine(); } - sZygoteWriter.flush(); + writer.flush(); // Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult(); - result.pid = sZygoteInputStream.readInt(); + result.pid = inputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } - result.usingWrapper = sZygoteInputStream.readBoolean(); + result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { - try { - if (sZygoteSocket != null) { - sZygoteSocket.close(); - } - } catch (IOException ex2) { - // we're going to fail anyway - Log.e(LOG_TAG,"I/O exception on routine close", ex2); - } - - sZygoteSocket = null; - + zygoteState.close(); throw new ZygoteStartFailedEx(ex); } } @@ -558,6 +592,7 @@ public class Process { * @param debugFlags Additional flags. * @param targetSdkVersion The target SDK version for the app. * @param seInfo null-ok SELinux information for the new process. + * @param abi the ABI the process should use. * @param extraArgs Additional arguments to supply to the zygote process. * @return An object that describes the result of the attempt to start the process. * @throws ZygoteStartFailedEx if process start failed for any reason @@ -569,6 +604,7 @@ public class Process { int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, + String abi, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { @@ -636,10 +672,64 @@ public class Process { } } - return zygoteSendArgsAndGetResult(argsForZygote); + return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } } - + + /** + * Returns the number of times we attempt a connection to the zygote. We + * sleep for {@link #ZYGOTE_RETRY_MILLIS} milliseconds between each try. + * + * This could probably be removed, see TODO in {@code ZygoteState#connect}. + */ + private static int getNumTries(ZygoteState state) { + // Retry 10 times for the first connection to each zygote. + if (state == null) { + return 11; + } + + // This means the connection has already been established, but subsequently + // closed, possibly due to an IOException. We retry just once if that's the + // case. + return 1; + } + + /** + * Tries to open socket to Zygote process if not already open. If + * already open, does nothing. May block and retry. + */ + private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { + if (primaryZygoteState == null || primaryZygoteState.isClosed()) { + primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET, getNumTries(primaryZygoteState)); + } + + if (primaryZygoteState.matches(abi)) { + return primaryZygoteState; + } + + // TODO: Get rid of this. This is a temporary workaround until all the + // compilation related pieces for the dual zygote stack are ready. + // b/3647418. + if (System.getenv("ANDROID_SOCKET_" + SECONDARY_ZYGOTE_SOCKET) == null) { + Log.e(LOG_TAG, "Forcing app to primary zygote, secondary unavailable (ABI= " + abi + ")"); + // Should be : + // throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); + return primaryZygoteState; + } + + // The primary zygote didn't match. Try the secondary. + if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { + secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET, + getNumTries(secondaryZygoteState)); + } + + if (secondaryZygoteState.matches(abi)) { + return secondaryZygoteState; + } + + throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); + } + /** * Returns elapsed milliseconds of the time this process has run. * @return Returns the number of milliseconds this process has return. diff --git a/core/java/android/os/SystemClock.java b/core/java/android/os/SystemClock.java index 729c64b..672df6d 100644 --- a/core/java/android/os/SystemClock.java +++ b/core/java/android/os/SystemClock.java @@ -16,6 +16,9 @@ package android.os; +import android.app.IAlarmManager; +import android.content.Context; +import android.util.Slog; /** * Core timekeeping facilities. @@ -89,6 +92,8 @@ package android.os; * </ul> */ public final class SystemClock { + private static final String TAG = "SystemClock"; + /** * This class is uninstantiable. */ @@ -134,7 +139,23 @@ public final class SystemClock { * * @return if the clock was successfully set to the specified time. */ - native public static boolean setCurrentTimeMillis(long millis); + public static boolean setCurrentTimeMillis(long millis) { + IBinder b = ServiceManager.getService(Context.ALARM_SERVICE); + IAlarmManager mgr = IAlarmManager.Stub.asInterface(b); + if (mgr == null) { + return false; + } + + try { + return mgr.setTime(millis); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to set RTC", e); + } catch (SecurityException e) { + Slog.e(TAG, "Unable to set RTC", e); + } + + return false; + } /** * Returns milliseconds since boot, not counting time spent in deep sleep. diff --git a/core/java/android/util/JsonReader.java b/core/java/android/util/JsonReader.java index f2a86c9..7d1c6c4 100644 --- a/core/java/android/util/JsonReader.java +++ b/core/java/android/util/JsonReader.java @@ -546,6 +546,9 @@ public final class JsonReader implements Closeable { public void skipValue() throws IOException { skipping = true; try { + if (!hasNext() || peek() == JsonToken.END_DOCUMENT) { + throw new IllegalStateException("No element left to skip"); + } int count = 0; do { JsonToken token = advance(); diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java index 9522112..0f8da44 100644 --- a/core/java/android/util/Patterns.java +++ b/core/java/android/util/Patterns.java @@ -191,8 +191,6 @@ public class Patterns { for (int i = 1; i <= numGroups; i++) { String s = matcher.group(i); - System.err.println("Group(" + i + ") : " + s); - if (s != null) { b.append(s); } diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 6a15fa6..d533060 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -392,11 +392,11 @@ class GLES20Canvas extends HardwareCanvas { // Atlas /////////////////////////////////////////////////////////////////////////// - static void initAtlas(GraphicBuffer buffer, int[] map) { + static void initAtlas(GraphicBuffer buffer, long[] map) { nInitAtlas(buffer, map, map.length); } - private static native void nInitAtlas(GraphicBuffer buffer, int[] map, int count); + private static native void nInitAtlas(GraphicBuffer buffer, long[] map, int count); /////////////////////////////////////////////////////////////////////////// // Display list diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 3781bdb..f09a111 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -1981,7 +1981,7 @@ public abstract class HardwareRenderer { if (atlas.isCompatible(android.os.Process.myPpid())) { GraphicBuffer buffer = atlas.getBuffer(); if (buffer != null) { - int[] map = atlas.getMap(); + long[] map = atlas.getMap(); if (map != null) { GLES20Canvas.initAtlas(buffer, map); } diff --git a/core/java/android/view/IAssetAtlas.aidl b/core/java/android/view/IAssetAtlas.aidl index 5f1e238..edce059 100644 --- a/core/java/android/view/IAssetAtlas.aidl +++ b/core/java/android/view/IAssetAtlas.aidl @@ -45,10 +45,10 @@ interface IAssetAtlas { * if the atlas is not available yet. * * Each bitmap is represented by several entries in the array: - * int0: SkBitmap*, the native bitmap object - * int1: x position - * int2: y position - * int3: rotated, 1 if the bitmap must be rotated, 0 otherwise + * long0: SkBitmap*, the native bitmap object + * long1: x position + * long2: y position + * long3: rotated, 1 if the bitmap must be rotated, 0 otherwise */ - int[] getMap(); + long[] getMap(); } diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java index aa43bad..cd905fa 100644 --- a/core/java/android/view/LayoutInflater.java +++ b/core/java/android/view/LayoutInflater.java @@ -591,6 +591,7 @@ public abstract class LayoutInflater { Object[] args = mConstructorArgs; args[1] = attrs; + constructor.setAccessible(true); final View view = constructor.newInstance(args); if (view instanceof ViewStub) { // always use ourselves when inflating ViewStub later diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java index 0dfd94a..3cf5af4 100644 --- a/core/java/android/view/SurfaceSession.java +++ b/core/java/android/view/SurfaceSession.java @@ -24,11 +24,11 @@ package android.view; */ public final class SurfaceSession { // Note: This field is accessed by native code. - private int mNativeClient; // SurfaceComposerClient* + private long mNativeClient; // SurfaceComposerClient* - private static native int nativeCreate(); - private static native void nativeDestroy(int ptr); - private static native void nativeKill(int ptr); + private static native long nativeCreate(); + private static native void nativeDestroy(long ptr); + private static native void nativeKill(long ptr); /** Create a new connection with the surface flinger. */ public SurfaceSession() { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index e6debc1..eb7f45e 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -10232,7 +10232,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * by the layout system and should not generally be called otherwise, because the property * may be changed at any time by the layout. * - * @param left The bottom of this view, in pixels. + * @param left The left of this view, in pixels. */ public final void setLeft(int left) { if (left != mLeft) { @@ -10299,7 +10299,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, * by the layout system and should not generally be called otherwise, because the property * may be changed at any time by the layout. * - * @param right The bottom of this view, in pixels. + * @param right The right of this view, in pixels. */ public final void setRight(int right) { if (right != mRight) { @@ -11972,7 +11972,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } /** - * <p>Compute the vertical extent of the horizontal scrollbar's thumb + * <p>Compute the vertical extent of the vertical scrollbar's thumb * within the vertical range. This value is used to compute the length * of the thumb within the scrollbar's track.</p> * diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 521cfbf..1c7f31c 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -661,7 +661,7 @@ public final class ViewRootImpl implements ViewParent, mHandler.sendMessageAtFrontOfQueue(mHandler.obtainMessage(MSG_FLUSH_LAYER_UPDATES)); } - public boolean attachFunctor(int functor) { + public boolean attachFunctor(long functor) { //noinspection SimplifiableIfStatement if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { return mAttachInfo.mHardwareRenderer.attachFunctor(mAttachInfo, functor); @@ -669,7 +669,7 @@ public final class ViewRootImpl implements ViewParent, return false; } - public void detachFunctor(int functor) { + public void detachFunctor(long functor) { if (mAttachInfo.mHardwareRenderer != null) { mAttachInfo.mHardwareRenderer.detachFunctor(functor); } diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java index 7674837..fe2fc96 100644 --- a/core/java/android/widget/AbsSeekBar.java +++ b/core/java/android/widget/AbsSeekBar.java @@ -292,7 +292,7 @@ public abstract class AbsSeekBar extends ProgressBar { // The extra space for the thumb to move on the track available += mThumbOffset * 2; - int thumbPos = (int) (scale * available); + int thumbPos = (int) (scale * available + 0.5f); int topBound, bottomBound; if (gap == Integer.MIN_VALUE) { diff --git a/core/java/android/widget/AdapterView.java b/core/java/android/widget/AdapterView.java index a5fad60..a06344f 100644 --- a/core/java/android/widget/AdapterView.java +++ b/core/java/android/widget/AdapterView.java @@ -663,7 +663,7 @@ public abstract class AdapterView<T extends Adapter> extends ViewGroup { /** * When the current adapter is empty, the AdapterView can display a special view - * call the empty view. The empty view is used to provide feedback to the user + * called the empty view. The empty view is used to provide feedback to the user * that no data is available in this AdapterView. * * @return The view to show if the adapter is empty. diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java index 9c6a2e3..2c44703 100644 --- a/core/java/android/widget/NumberPicker.java +++ b/core/java/android/widget/NumberPicker.java @@ -1965,7 +1965,16 @@ public class NumberPicker extends LinearLayout { , '\u0669', // Extended Arabic-Indic '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8' - , '\u06f9' + , '\u06f9', + // Hindi and Marathi (Devanagari script) + '\u0966', '\u0967', '\u0968', '\u0969', '\u096a', '\u096b', '\u096c', '\u096d', '\u096e' + , '\u096f', + // Bengali + '\u09e6', '\u09e7', '\u09e8', '\u09e9', '\u09ea', '\u09eb', '\u09ec', '\u09ed', '\u09ee' + , '\u09ef', + // Kannada + '\u0ce6', '\u0ce7', '\u0ce8', '\u0ce9', '\u0cea', '\u0ceb', '\u0cec', '\u0ced', '\u0cee' + , '\u0cef' }; /** diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 9bfb00c..8460375 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -5147,12 +5147,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener final int width = mRight - mLeft; final int padding = getCompoundPaddingLeft() + getCompoundPaddingRight(); final float dx = mLayout.getLineRight(0) - (width - padding); - canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); } if (mMarquee != null && mMarquee.isRunning()) { final float dx = -mMarquee.getScroll(); - canvas.translate(isLayoutRtl ? -dx : +dx, 0.0f); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); } } @@ -5166,8 +5166,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener } if (mMarquee != null && mMarquee.shouldDrawGhost()) { - final int dx = (int) mMarquee.getGhostOffset(); - canvas.translate(isLayoutRtl ? -dx : dx, 0.0f); + final float dx = mMarquee.getGhostOffset(); + canvas.translate(layout.getParagraphDirection(0) * dx, 0.0f); layout.draw(canvas, highlight, mHighlightPaint, cursorOffsetVertical); } |