diff options
Diffstat (limited to 'core')
46 files changed, 1001 insertions, 150 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 5262a5f..2a17fa6 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -25,4 +25,6 @@ public abstract class ActivityManagerInternal { // Called by the power manager. public abstract void goingToSleep(); public abstract void wakingUp(); + public abstract int startIsolatedProcess(String entryPoint, String[] mainArgs, + String processName, String abiOverride, int uid, Runnable crashHandler); } diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java index 1326064..b5d362d 100644 --- a/core/java/android/app/EnterTransitionCoordinator.java +++ b/core/java/android/app/EnterTransitionCoordinator.java @@ -256,7 +256,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { @Override protected Transition getViewsTransition() { if (mIsReturning) { - return getWindow().getExitTransition(); + return getWindow().getReenterTransition(); } else { return getWindow().getEnterTransition(); } @@ -264,7 +264,7 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator { protected Transition getSharedElementTransition() { if (mIsReturning) { - return getWindow().getSharedElementExitTransition(); + return getWindow().getSharedElementReenterTransition(); } else { return getWindow().getSharedElementEnterTransition(); } diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java index 2ce6018..b3fdcc7 100644 --- a/core/java/android/app/ExitTransitionCoordinator.java +++ b/core/java/android/app/ExitTransitionCoordinator.java @@ -395,7 +395,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { @Override protected Transition getViewsTransition() { if (mIsReturning) { - return getWindow().getEnterTransition(); + return getWindow().getReturnTransition(); } else { return getWindow().getExitTransition(); } @@ -403,7 +403,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator { protected Transition getSharedElementTransition() { if (mIsReturning) { - return getWindow().getSharedElementEnterTransition(); + return getWindow().getSharedElementReturnTransition(); } else { return getWindow().getSharedElementExitTransition(); } diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java index 5347f03..772e132 100644 --- a/core/java/android/app/IActivityManager.java +++ b/core/java/android/app/IActivityManager.java @@ -454,7 +454,7 @@ public interface IActivityManager extends IInterface { * Private non-Binder interfaces */ /* package */ boolean testIsSystemReady(); - + /** Information you can retrieve about a particular application. */ public static class ContentProviderHolder implements Parcelable { public final ProviderInfo info; diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index c7fdbed..acf7ade 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -247,7 +247,6 @@ public class Notification implements Parcelable /** - * @hide * A medium-format version of {@link #contentView}, providing the Notification an * opportunity to add action buttons to contentView. At its discretion, the system UI may * choose to show this as a heads-up notification, which will pop up so the user can see diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 8be52a2..e28f00c 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -449,9 +449,17 @@ public class DevicePolicyManager { * active (enabled) in the system. */ public boolean isAdminActive(ComponentName who) { + return isAdminActiveAsUser(who, UserHandle.myUserId()); + } + + /** + * @see #isAdminActive(ComponentName) + * @hide + */ + public boolean isAdminActiveAsUser(ComponentName who, int userId) { if (mService != null) { try { - return mService.isAdminActive(who, UserHandle.myUserId()); + return mService.isAdminActive(who, userId); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -465,9 +473,17 @@ public class DevicePolicyManager { * returned. */ public List<ComponentName> getActiveAdmins() { + return getActiveAdminsAsUser(UserHandle.myUserId()); + } + + /** + * @see #getActiveAdmins() + * @hide + */ + public List<ComponentName> getActiveAdminsAsUser(int userId) { if (mService != null) { try { - return mService.getActiveAdmins(UserHandle.myUserId()); + return mService.getActiveAdmins(userId); } catch (RemoteException e) { Log.w(TAG, "Failed talking with device policy service", e); } @@ -2314,9 +2330,17 @@ public class DevicePolicyManager { * @throws IllegalArgumentException if the userId is invalid. */ public ComponentName getProfileOwner() throws IllegalArgumentException { + return getProfileOwnerAsUser(Process.myUserHandle().getIdentifier()); + } + + /** + * @see #getProfileOwner() + * @hide + */ + public ComponentName getProfileOwnerAsUser(final int userId) throws IllegalArgumentException { if (mService != null) { try { - return mService.getProfileOwner(Process.myUserHandle().getIdentifier()); + return mService.getProfileOwner(userId); } catch (RemoteException re) { Log.w(TAG, "Failed to get profile owner"); throw new IllegalArgumentException( @@ -2856,7 +2880,7 @@ public class DevicePolicyManager { * @see #setAccountManagementDisabled */ public String[] getAccountTypesWithManagementDisabled() { - return getAccountTypesWithManagementDisabledAsUser(UserHandle.getCallingUserId()); + return getAccountTypesWithManagementDisabledAsUser(UserHandle.myUserId()); } /** diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl index a31ae54..39ae1a0 100644 --- a/core/java/android/content/pm/IPackageInstallerCallback.aidl +++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl @@ -19,6 +19,8 @@ package android.content.pm; /** {@hide} */ oneway interface IPackageInstallerCallback { void onSessionCreated(int sessionId); + void onSessionOpened(int sessionId); void onSessionProgressChanged(int sessionId, float progress); + void onSessionClosed(int sessionId); void onSessionFinished(int sessionId, boolean success); } diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl index 2fd7ddb..af0323f 100644 --- a/core/java/android/content/pm/IPackageInstallerSession.aidl +++ b/core/java/android/content/pm/IPackageInstallerSession.aidl @@ -24,7 +24,9 @@ interface IPackageInstallerSession { void setClientProgress(float progress); void addClientProgress(float progress); + String[] list(); ParcelFileDescriptor openWrite(String name, long offsetBytes, long lengthBytes); + ParcelFileDescriptor openRead(String name); void close(); void commit(in IPackageInstallObserver2 observer); diff --git a/core/java/android/content/pm/InstallSessionInfo.java b/core/java/android/content/pm/InstallSessionInfo.java index a9c574a..f263885 100644 --- a/core/java/android/content/pm/InstallSessionInfo.java +++ b/core/java/android/content/pm/InstallSessionInfo.java @@ -16,7 +16,9 @@ package android.content.pm; +import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Intent; import android.graphics.Bitmap; import android.os.Parcel; import android.os.Parcelable; @@ -32,6 +34,8 @@ public class InstallSessionInfo implements Parcelable { public String installerPackageName; /** {@hide} */ public float progress; + /** {@hide} */ + public boolean open; /** {@hide} */ public int mode; @@ -53,6 +57,7 @@ public class InstallSessionInfo implements Parcelable { sessionId = source.readInt(); installerPackageName = source.readString(); progress = source.readFloat(); + open = source.readInt() != 0; mode = source.readInt(); sizeBytes = source.readLong(); @@ -88,6 +93,13 @@ public class InstallSessionInfo implements Parcelable { } /** + * Return if this session is currently open. + */ + public boolean isOpen() { + return open; + } + + /** * Return the package name this session is working with. May be {@code null} * if unknown. */ @@ -111,6 +123,23 @@ public class InstallSessionInfo implements Parcelable { return appLabel; } + /** + * Return an Intent that can be started to view details about this install + * session. This may surface actions such as pause, resume, or cancel. + * <p> + * In some cases, a matching Activity may not exist, so ensure you safeguard + * against this. + * + * @see PackageInstaller#ACTION_SESSION_DETAILS + */ + public @Nullable Intent getDetailsIntent() { + final Intent intent = new Intent(PackageInstaller.ACTION_SESSION_DETAILS); + intent.putExtra(PackageInstaller.EXTRA_SESSION_ID, sessionId); + intent.setPackage(installerPackageName); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + return intent; + } + @Override public int describeContents() { return 0; @@ -121,6 +150,7 @@ public class InstallSessionInfo implements Parcelable { dest.writeInt(sessionId); dest.writeString(installerPackageName); dest.writeFloat(progress); + dest.writeInt(open ? 1 : 0); dest.writeInt(mode); dest.writeLong(sizeBytes); diff --git a/core/java/android/content/pm/InstallSessionParams.java b/core/java/android/content/pm/InstallSessionParams.java index 3de9863..1716e39 100644 --- a/core/java/android/content/pm/InstallSessionParams.java +++ b/core/java/android/content/pm/InstallSessionParams.java @@ -17,6 +17,7 @@ package android.content.pm; import android.annotation.Nullable; +import android.app.ActivityManager; import android.content.Intent; import android.graphics.Bitmap; import android.net.Uri; @@ -30,6 +31,9 @@ import com.android.internal.util.IndentingPrintWriter; */ public class InstallSessionParams implements Parcelable { + /** {@hide} */ + public static final int MODE_INVALID = -1; + /** * Mode for an install session whose staged APKs should fully replace any * existing APKs for the target app. @@ -48,21 +52,19 @@ public class InstallSessionParams implements Parcelable { public static final int MODE_INHERIT_EXISTING = 2; /** {@hide} */ - public int mode; + public int mode = MODE_INVALID; /** {@hide} */ public int installFlags; /** {@hide} */ public int installLocation = PackageInfo.INSTALL_LOCATION_INTERNAL_ONLY; /** {@hide} */ - public Signature[] signatures; - /** {@hide} */ public long sizeBytes = -1; /** {@hide} */ public String appPackageName; /** {@hide} */ public Bitmap appIcon; /** {@hide} */ - public CharSequence appLabel; + public String appLabel; /** {@hide} */ public Uri originatingUri; /** {@hide} */ @@ -86,7 +88,6 @@ public class InstallSessionParams implements Parcelable { mode = source.readInt(); installFlags = source.readInt(); installLocation = source.readInt(); - signatures = (Signature[]) source.readParcelableArray(null); sizeBytes = source.readLong(); appPackageName = source.readString(); appIcon = source.readParcelable(null); @@ -106,16 +107,13 @@ public class InstallSessionParams implements Parcelable { } /** - * Optionally provide a set of certificates for the app being installed. - * <p> - * If the APKs staged in the session aren't consistent with these - * signatures, the install will fail. Regardless of this value, all APKs in - * the app must have the same signing certificates. - * - * @see PackageInfo#signatures + * @deprecated use {@link PackageInstaller.Session#openRead(String)} to + * calculate message digest instead. + * @hide */ + @Deprecated public void setSignatures(@Nullable Signature[] signatures) { - this.signatures = signatures; + throw new UnsupportedOperationException(); } /** @@ -146,7 +144,8 @@ public class InstallSessionParams implements Parcelable { /** * Optionally set an icon representing the app being installed. This should - * be at least {@link android.R.dimen#app_icon_size} in both dimensions. + * be roughly {@link ActivityManager#getLauncherLargeIconSize()} in both + * dimensions. */ public void setAppIcon(@Nullable Bitmap appIcon) { this.appIcon = appIcon; @@ -156,7 +155,7 @@ public class InstallSessionParams implements Parcelable { * Optionally set a label representing the app being installed. */ public void setAppLabel(@Nullable CharSequence appLabel) { - this.appLabel = appLabel; + this.appLabel = (appLabel != null) ? appLabel.toString() : null; } /** @@ -184,7 +183,6 @@ public class InstallSessionParams implements Parcelable { pw.printPair("mode", mode); pw.printHexPair("installFlags", installFlags); pw.printPair("installLocation", installLocation); - pw.printPair("signatures", (signatures != null)); pw.printPair("sizeBytes", sizeBytes); pw.printPair("appPackageName", appPackageName); pw.printPair("appIcon", (appIcon != null)); @@ -205,11 +203,10 @@ public class InstallSessionParams implements Parcelable { dest.writeInt(mode); dest.writeInt(installFlags); dest.writeInt(installLocation); - dest.writeParcelableArray(signatures, flags); dest.writeLong(sizeBytes); dest.writeString(appPackageName); dest.writeParcelable(appIcon, flags); - dest.writeString(appLabel != null ? appLabel.toString() : null); + dest.writeString(appLabel); dest.writeParcelable(originatingUri, flags); dest.writeParcelable(referrerUri, flags); dest.writeString(abiOverride); diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java index a114bb8..8af827e 100644 --- a/core/java/android/content/pm/PackageInstaller.java +++ b/core/java/android/content/pm/PackageInstaller.java @@ -18,9 +18,10 @@ package android.content.pm; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SdkConstant; +import android.annotation.SdkConstant.SdkConstantType; import android.app.PackageInstallObserver; import android.app.PackageUninstallObserver; -import android.content.pm.PackageManager.NameNotFoundException; import android.os.Bundle; import android.os.FileBridge; import android.os.Handler; @@ -32,7 +33,9 @@ import android.util.ExceptionUtils; import java.io.Closeable; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; +import java.security.MessageDigest; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -63,6 +66,27 @@ import java.util.List; * </ul> */ public class PackageInstaller { + /** + * Activity Action: Show details about a particular install session. This + * may surface actions such as pause, resume, or cancel. + * <p> + * This should always be scoped to the installer package that owns the + * session. Clients should use {@link InstallSessionInfo#getDetailsIntent()} + * to build this intent correctly. + * <p> + * In some cases, a matching Activity may not exist, so ensure you safeguard + * against this. + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS"; + + /** + * An integer session ID. + * + * @see #ACTION_SESSION_DETAILS + */ + public static final String EXTRA_SESSION_ID = "android.content.pm.extra.SESSION_ID"; + private final PackageManager mPm; private final IPackageInstaller mInstaller; private final int mUserId; @@ -180,14 +204,32 @@ public class PackageInstaller { /** * Events for observing session lifecycle. + * <p> + * A typical session lifecycle looks like this: + * <ul> + * <li>An installer creates a session to indicate pending app delivery. All + * install details are available at this point. + * <li>The installer opens the session to deliver APK data. Note that a + * session may be opened and closed multiple times as network connectivity + * changes. The installer may deliver periodic progress updates. + * <li>The installer commits or abandons the session, resulting in the + * session being finished. + * </ul> */ public static abstract class SessionCallback { /** - * New session has been created. + * New session has been created. Details about the session can be + * obtained from {@link PackageInstaller#getSessionInfo(int)}. */ public abstract void onCreated(int sessionId); /** + * Session has been opened. A session is usually opened when the + * installer is actively writing data. + */ + public abstract void onOpened(int sessionId); + + /** * Progress for given session has been updated. * <p> * Note that this progress may not directly correspond to the value @@ -198,6 +240,11 @@ public class PackageInstaller { public abstract void onProgressChanged(int sessionId, float progress); /** + * Session has been closed. + */ + public abstract void onClosed(int sessionId); + + /** * Session has completely finished, either with success or failure. */ public abstract void onFinished(int sessionId, boolean success); @@ -207,8 +254,10 @@ public class PackageInstaller { private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements Handler.Callback { private static final int MSG_SESSION_CREATED = 1; - private static final int MSG_SESSION_PROGRESS_CHANGED = 2; - private static final int MSG_SESSION_FINISHED = 3; + private static final int MSG_SESSION_OPENED = 2; + private static final int MSG_SESSION_PROGRESS_CHANGED = 3; + private static final int MSG_SESSION_CLOSED = 4; + private static final int MSG_SESSION_FINISHED = 5; final SessionCallback mCallback; final Handler mHandler; @@ -224,9 +273,15 @@ public class PackageInstaller { case MSG_SESSION_CREATED: mCallback.onCreated(msg.arg1); return true; + case MSG_SESSION_OPENED: + mCallback.onOpened(msg.arg1); + return true; case MSG_SESSION_PROGRESS_CHANGED: mCallback.onProgressChanged(msg.arg1, (float) msg.obj); return true; + case MSG_SESSION_CLOSED: + mCallback.onClosed(msg.arg1); + return true; case MSG_SESSION_FINISHED: mCallback.onFinished(msg.arg1, msg.arg2 != 0); return true; @@ -240,12 +295,22 @@ public class PackageInstaller { } @Override + public void onSessionOpened(int sessionId) { + mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget(); + } + + @Override public void onSessionProgressChanged(int sessionId, float progress) { mHandler.obtainMessage(MSG_SESSION_PROGRESS_CHANGED, sessionId, 0, progress) .sendToTarget(); } @Override + public void onSessionClosed(int sessionId) { + mHandler.obtainMessage(MSG_SESSION_CLOSED, sessionId, 0).sendToTarget(); + } + + @Override public void onSessionFinished(int sessionId, boolean success) { mHandler.obtainMessage(MSG_SESSION_FINISHED, sessionId, success ? 1 : 0) .sendToTarget(); @@ -373,7 +438,7 @@ public class PackageInstaller { ExceptionUtils.maybeUnwrapIOException(e); throw e; } catch (RemoteException e) { - throw new IOException(e); + throw e.rethrowAsRuntimeException(); } } @@ -391,6 +456,40 @@ public class PackageInstaller { } /** + * List all APK names contained in this session. + * <p> + * This returns all names which have been previously written through + * {@link #openWrite(String, long, long)} as part of this session. + */ + public @NonNull String[] list() { + try { + return mSession.list(); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** + * Open a stream to read an APK file from the session. + * <p> + * This is only valid for names which have been previously written + * through {@link #openWrite(String, long, long)} as part of this + * session. For example, this stream may be used to calculate a + * {@link MessageDigest} of a written APK before committing. + */ + public @NonNull InputStream openRead(@NonNull String name) throws IOException { + try { + final ParcelFileDescriptor pfd = mSession.openRead(name); + return new ParcelFileDescriptor.AutoCloseInputStream(pfd); + } catch (RuntimeException e) { + ExceptionUtils.maybeUnwrapIOException(e); + throw e; + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + } + + /** * Attempt to commit everything staged in this session. This may require * user intervention, and so it may not happen immediately. The final * result of the commit will be reported through the given callback. diff --git a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java index 27829a7..6e1844a 100644 --- a/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java +++ b/core/java/android/hardware/hdmi/HdmiCecDeviceInfo.java @@ -65,6 +65,18 @@ public final class HdmiCecDeviceInfo implements Parcelable { */ public static final int ADDR_INTERNAL = 0; + /** + * Physical address used to indicate the source comes from internal device. + * The physical address of TV(0) is used. + */ + public static final int PATH_INTERNAL = 0x0000; + + /** Invalid physical address (routing path) */ + public static final int PATH_INVALID = 0xFFFF; + + /** Invalid port ID */ + public static final int PORT_INVALID = -1; + // Logical address, physical address, device type, vendor id and display name // are immutable value. private final int mLogicalAddress; diff --git a/core/java/android/hardware/hdmi/IHdmiControlService.aidl b/core/java/android/hardware/hdmi/IHdmiControlService.aidl index 808e0c9..920a1f4 100644 --- a/core/java/android/hardware/hdmi/IHdmiControlService.aidl +++ b/core/java/android/hardware/hdmi/IHdmiControlService.aidl @@ -37,6 +37,7 @@ import java.util.List; */ interface IHdmiControlService { int[] getSupportedTypes(); + HdmiCecDeviceInfo getActiveSource(); void oneTouchPlay(IHdmiControlCallback callback); void queryDisplayStatus(IHdmiControlCallback callback); void addHotplugEventListener(IHdmiHotplugEventListener listener); diff --git a/core/java/android/hardware/location/GeofenceHardwareImpl.java b/core/java/android/hardware/location/GeofenceHardwareImpl.java index 6734878..5c7a8da 100644 --- a/core/java/android/hardware/location/GeofenceHardwareImpl.java +++ b/core/java/android/hardware/location/GeofenceHardwareImpl.java @@ -139,8 +139,8 @@ public final class GeofenceHardwareImpl { private void updateFusedHardwareAvailability() { boolean fusedSupported; try { - fusedSupported = mFusedService.isSupported(); - } catch(RemoteException e) { + fusedSupported = (mFusedService != null ? mFusedService.isSupported() : false); + } catch (RemoteException e) { Log.e(TAG, "RemoteException calling LocationManagerService"); fusedSupported = false; } diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java index afac239..c3ac012 100644 --- a/core/java/android/os/Process.java +++ b/core/java/android/os/Process.java @@ -61,6 +61,12 @@ public class Process { public static final String SECONDARY_ZYGOTE_SOCKET = "zygote_secondary"; /** + * Defines the root UID. + * @hide + */ + public static final int ROOT_UID = 0; + + /** * Defines the UID/GID under which system code runs. */ public static final int SYSTEM_UID = 1000; diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index d385131..13f93a7 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -625,8 +625,9 @@ public class UserManager { Settings.Secure.putStringForUser(context.getContentResolver(), Settings.Secure.SKIP_FIRST_USE_HINTS, "1", guest.id); try { - mService.setUserRestrictions( - mService.getDefaultGuestRestrictions(), guest.id); + Bundle guestRestrictions = mService.getDefaultGuestRestrictions(); + guestRestrictions.putBoolean(DISALLOW_SMS, true); + mService.setUserRestrictions(guestRestrictions, guest.id); } catch (RemoteException re) { Log.w(TAG, "Could not update guest restrictions"); } diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index 3f53ad4..5248131 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -45,18 +45,22 @@ public class AlwaysOnHotwordDetector { * Indicates that this hotword detector is no longer valid for any recognition * and should not be used anymore. */ - public static final int STATE_INVALID = -3; + private static final int STATE_INVALID = -3; + /** * Indicates that recognition for the given keyphrase is not available on the system * because of the hardware configuration. + * No further interaction should be performed with the detector that returns this availability. */ public static final int STATE_HARDWARE_UNAVAILABLE = -2; /** * Indicates that recognition for the given keyphrase is not supported. + * No further interaction should be performed with the detector that returns this availability. */ public static final int STATE_KEYPHRASE_UNSUPPORTED = -1; /** * Indicates that the given keyphrase is not enrolled. + * The caller may choose to begin an enrollment flow for the keyphrase. */ public static final int STATE_KEYPHRASE_UNENROLLED = 1; /** @@ -91,12 +95,14 @@ public class AlwaysOnHotwordDetector { // Must be kept in sync with the related attribute defined as searchKeyphraseRecognitionFlags. /** - * Simple recognition of the key phrase. Returned by {@link #getSupportedRecognitionModes()} + * Simple recognition of the key phrase. + * Returned by {@link #getSupportedRecognitionModes()} */ public static final int RECOGNITION_MODE_VOICE_TRIGGER = SoundTrigger.RECOGNITION_MODE_VOICE_TRIGGER; /** - * Trigger only if one user is identified. Returned by {@link #getSupportedRecognitionModes()} + * User identification performed with the keyphrase recognition. + * Returned by {@link #getSupportedRecognitionModes()} */ public static final int RECOGNITION_MODE_USER_IDENTIFICATION = SoundTrigger.RECOGNITION_MODE_USER_IDENTIFICATION; @@ -149,16 +155,11 @@ public class AlwaysOnHotwordDetector { * * Availability implies whether the hardware on this system is capable of listening for * the given keyphrase or not. <p/> - * If the return code is one of {@link #STATE_HARDWARE_UNAVAILABLE} or - * {@link #STATE_KEYPHRASE_UNSUPPORTED}, - * detection is not possible and no further interaction should be - * performed with this detector. <br/> - * If it is {@link #STATE_KEYPHRASE_UNENROLLED} the caller may choose to begin - * an enrollment flow for the keyphrase. <br/> - * and for {@link #STATE_KEYPHRASE_ENROLLED} a recognition can be started as desired. <p/> * - * If the return code is {@link #STATE_INVALID}, this detector is stale. - * A new detector should be obtained for use in the future. + * @see AlwaysOnHotwordDetector#STATE_HARDWARE_UNAVAILABLE + * @see AlwaysOnHotwordDetector#STATE_KEYPHRASE_UNSUPPORTED + * @see AlwaysOnHotwordDetector#STATE_KEYPHRASE_UNENROLLED + * @see AlwaysOnHotwordDetector#STATE_KEYPHRASE_ENROLLED */ void onAvailabilityChanged(int status); /** @@ -217,9 +218,15 @@ public class AlwaysOnHotwordDetector { /** * Gets the recognition modes supported by the associated keyphrase. * + * @see #RECOGNITION_MODE_USER_IDENTIFICATION + * @see #RECOGNITION_MODE_VOICE_TRIGGER + * * @throws UnsupportedOperationException if the keyphrase itself isn't supported. * Callers should only call this method after a supported state callback on * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * @throws IllegalStateException if the detector is in an invalid state. + * This may happen if another detector has been instantiated or the + * {@link VoiceInteractionService} hosting this detector has been shut down. */ public int getSupportedRecognitionModes() { synchronized (mLock) { @@ -228,6 +235,11 @@ public class AlwaysOnHotwordDetector { } private int getSupportedRecognitionModesLocked() { + if (mAvailability == STATE_INVALID) { + throw new IllegalStateException( + "getSupportedRecognitionModes called on an invalid detector"); + } + // This method only makes sense if we can actually support a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED && mAvailability != STATE_KEYPHRASE_UNENROLLED) { @@ -247,9 +259,16 @@ public class AlwaysOnHotwordDetector { * @throws UnsupportedOperationException if the recognition isn't supported. * Callers should only call this method after a supported state callback on * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * @throws IllegalStateException if the detector is in an invalid state. + * This may happen if another detector has been instantiated or the + * {@link VoiceInteractionService} hosting this detector has been shut down. */ public void startRecognition(int recognitionFlags) { synchronized (mLock) { + if (mAvailability == STATE_INVALID) { + throw new IllegalStateException("startRecognition called on an invalid detector"); + } + // Check if we can start/stop a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { throw new UnsupportedOperationException( @@ -268,9 +287,16 @@ public class AlwaysOnHotwordDetector { * @throws UnsupportedOperationException if the recognition isn't supported. * Callers should only call this method after a supported state callback on * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * @throws IllegalStateException if the detector is in an invalid state. + * This may happen if another detector has been instantiated or the + * {@link VoiceInteractionService} hosting this detector has been shut down. */ public void stopRecognition() { synchronized (mLock) { + if (mAvailability == STATE_INVALID) { + throw new IllegalStateException("stopRecognition called on an invalid detector"); + } + // Check if we can start/stop a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED) { throw new UnsupportedOperationException( @@ -293,14 +319,28 @@ public class AlwaysOnHotwordDetector { * @throws UnsupportedOperationException if managing they keyphrase isn't supported. * Callers should only call this method after a supported state callback on * {@link Callback#onAvailabilityChanged(int)} to avoid this exception. + * @throws IllegalStateException if the detector is in an invalid state. + * This may happen if another detector has been instantiated or the + * {@link VoiceInteractionService} hosting this detector has been shut down. */ public Intent getManageIntent(int action) { + synchronized (mLock) { + return getManageIntentLocked(action); + } + } + + private Intent getManageIntentLocked(int action) { + if (mAvailability == STATE_INVALID) { + throw new IllegalStateException("getManageIntent called on an invalid detector"); + } + // This method only makes sense if we can actually support a recognition. if (mAvailability != STATE_KEYPHRASE_ENROLLED && mAvailability != STATE_KEYPHRASE_UNENROLLED) { throw new UnsupportedOperationException( "Managing the given keyphrase is not supported"); } + if (action != MANAGE_ACTION_ENROLL && action != MANAGE_ACTION_RE_ENROLL && action != MANAGE_ACTION_UN_ENROLL) { @@ -387,7 +427,6 @@ public class AlwaysOnHotwordDetector { if (DBG) Slog.d(TAG, "starting recognition..."); int status = startRecognitionLocked(); if (status == STATUS_OK) { - mInternalState |= FLAG_STARTED; mHandler.sendEmptyMessage(MSG_DETECTION_STARTED); } else { if (DBG) Slog.d(TAG, "failed to start recognition: " + status); @@ -404,7 +443,6 @@ public class AlwaysOnHotwordDetector { if (DBG) Slog.d(TAG, "stopping recognition..."); int status = stopRecognitionLocked(); if (status == STATUS_OK) { - mInternalState &= ~FLAG_STARTED; if (!requested) mHandler.sendEmptyMessage(MSG_DETECTION_STOPPED); } else { if (!requested) mHandler.sendEmptyMessage(MSG_DETECTION_ERROR); @@ -483,20 +521,42 @@ public class AlwaysOnHotwordDetector { class MyHandler extends Handler { @Override public void handleMessage(Message msg) { + synchronized (mLock) { + if (mAvailability == STATE_INVALID) { + Slog.w(TAG, "Received message: " + msg.what + " for an invalid detector"); + return; + } + } + switch (msg.what) { case MSG_STATE_CHANGED: mExternalCallback.onAvailabilityChanged(msg.arg1); break; case MSG_HOTWORD_DETECTED: + synchronized (mLock) { + mInternalState &= ~FLAG_REQUESTED; + mInternalState &= ~FLAG_STARTED; + } mExternalCallback.onDetected((byte[]) msg.obj); break; case MSG_DETECTION_STARTED: + synchronized (mLock) { + mInternalState |= FLAG_STARTED; + } mExternalCallback.onDetectionStarted(); break; case MSG_DETECTION_STOPPED: + synchronized (mLock) { + mInternalState &= ~FLAG_REQUESTED; + mInternalState &= ~FLAG_STARTED; + } mExternalCallback.onDetectionStopped(); break; case MSG_DETECTION_ERROR: + synchronized (mLock) { + mInternalState &= ~FLAG_REQUESTED; + mInternalState &= ~FLAG_STARTED; + } mExternalCallback.onError(); break; default: diff --git a/core/java/android/text/style/TtsSpan.java b/core/java/android/text/style/TtsSpan.java index f3a48a6..cb447fd 100644 --- a/core/java/android/text/style/TtsSpan.java +++ b/core/java/android/text/style/TtsSpan.java @@ -518,7 +518,7 @@ public class TtsSpan implements ParcelableSpan { * This class uses generics so methods from this class can return instances * of its child classes, resulting in a fluent API (CRTP pattern). */ - public static abstract class Builder<C extends Builder<C>> { + public static class Builder<C extends Builder<?>> { // Holds the type of this class. private final String mType; @@ -580,7 +580,7 @@ public class TtsSpan implements ParcelableSpan { * this builder like {@link TtsSpan.TextBuilder} and * {@link TtsSpan.CardinalBuilder} are likely more useful. */ - public static class SemioticClassBuilder<C extends SemioticClassBuilder<C>> + public static class SemioticClassBuilder<C extends SemioticClassBuilder<?>> extends Builder<C> { public SemioticClassBuilder(String type) { diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java index e9ec565..eee4973 100644 --- a/core/java/android/view/RenderNode.java +++ b/core/java/android/view/RenderNode.java @@ -355,9 +355,10 @@ public class RenderNode { return nSetOutlineEmpty(mNativeRenderNode); } else if (outline.mRect != null) { return nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top, - outline.mRect.right, outline.mRect.bottom, outline.mRadius); + outline.mRect.right, outline.mRect.bottom, outline.mRadius, outline.mAlpha); } else if (outline.mPath != null) { - return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath); + return nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath, + outline.mAlpha); } throw new IllegalArgumentException("Unrecognized outline?"); } @@ -849,8 +850,9 @@ public class RenderNode { private static native boolean nSetProjectBackwards(long renderNode, boolean shouldProject); private static native boolean nSetProjectionReceiver(long renderNode, boolean shouldRecieve); private static native boolean nSetOutlineRoundRect(long renderNode, int left, int top, - int right, int bottom, float radius); - private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath); + int right, int bottom, float radius, float alpha); + private static native boolean nSetOutlineConvexPath(long renderNode, long nativePath, + float alpha); private static native boolean nSetOutlineEmpty(long renderNode); private static native boolean nSetOutlineNone(long renderNode); private static native boolean nSetClipToOutline(long renderNode, boolean clipToOutline); diff --git a/core/java/android/view/ViewOutlineProvider.java b/core/java/android/view/ViewOutlineProvider.java index 64624ae..4054031 100644 --- a/core/java/android/view/ViewOutlineProvider.java +++ b/core/java/android/view/ViewOutlineProvider.java @@ -25,7 +25,8 @@ import android.graphics.drawable.Drawable; public abstract class ViewOutlineProvider { /** * Default outline provider for Views, which queries the Outline from the View's background, - * or returns <code>false</code> if the View does not have a background. + * or generates a 0 alpha, rectangular Outline the size of the View if a background + * isn't present. * * @see Drawable#getOutline(Outline) */ @@ -35,6 +36,10 @@ public abstract class ViewOutlineProvider { Drawable background = view.getBackground(); if (background != null) { background.getOutline(outline); + } else { + + outline.setRect(0, 0, view.getWidth(), view.getHeight()); + outline.setAlpha(0.0f); } } }; diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index c169d35..e7b3152 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -1425,6 +1425,21 @@ public abstract class Window { public void setEnterTransition(Transition transition) {} /** + * Sets the Transition that will be used to move Views out of the scene when the Window is + * preparing to close, for example after a call to + * {@link android.app.Activity#finishAfterTransition()}. The exiting + * Views will be those that are regular Views or ViewGroups that have + * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend + * {@link android.transition.Visibility} as entering is governed by changing visibility from + * {@link View#VISIBLE} to {@link View#INVISIBLE}. If <code>transition</code> is null, + * entering Views will remain unaffected. If nothing is set, the default will be to + * use the same value as set in {@link #setEnterTransition(android.transition.Transition)}. + * @param transition The Transition to use to move Views out of the Scene when the Window + * is preparing to close. + */ + public void setReturnTransition(Transition transition) {} + + /** * Sets the Transition that will be used to move Views out of the scene when starting a * new Activity. The exiting Views will be those that are regular Views or ViewGroups that * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend @@ -1437,6 +1452,20 @@ public abstract class Window { public void setExitTransition(Transition transition) {} /** + * Sets the Transition that will be used to move Views in to the scene when returning from + * a previously-started Activity. The entering Views will be those that are regular Views + * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions + * will extend {@link android.transition.Visibility} as exiting is governed by changing + * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, + * the views will remain unaffected. If nothing is set, the default will be to use the same + * transition as {@link #setExitTransition(android.transition.Transition)}. + * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * @param transition The Transition to use to move Views into the scene when reentering from a + * previously-started Activity. + */ + public void setReenterTransition(Transition transition) {} + + /** * Returns the transition used to move Views into the initial scene. The entering * Views will be those that are regular Views or ViewGroups that have * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend @@ -1449,6 +1478,19 @@ public abstract class Window { public Transition getEnterTransition() { return null; } /** + * Returns he Transition that will be used to move Views out of the scene when the Window is + * preparing to close, for example after a call to + * {@link android.app.Activity#finishAfterTransition()}. The exiting + * Views will be those that are regular Views or ViewGroups that have + * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend + * {@link android.transition.Visibility} as entering is governed by changing visibility from + * {@link View#VISIBLE} to {@link View#INVISIBLE}. + * @return The Transition to use to move Views out of the Scene when the Window + * is preparing to close. + */ + public Transition getReturnTransition() { return null; } + + /** * Returns the Transition that will be used to move Views out of the scene when starting a * new Activity. The exiting Views will be those that are regular Views or ViewGroups that * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend @@ -1461,6 +1503,18 @@ public abstract class Window { public Transition getExitTransition() { return null; } /** + * Returns the Transition that will be used to move Views in to the scene when returning from + * a previously-started Activity. The entering Views will be those that are regular Views + * or ViewGroups that have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions + * will extend {@link android.transition.Visibility} as exiting is governed by changing + * visibility from {@link View#VISIBLE} to {@link View#INVISIBLE}. + * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * @return The Transition to use to move Views into the scene when reentering from a + * previously-started Activity. + */ + public Transition getReenterTransition() { return null; } + + /** * Sets the Transition that will be used for shared elements transferred into the content * Scene. Typical Transitions will affect size and location, such as * {@link android.transition.ChangeBounds}. A null @@ -1472,6 +1526,19 @@ public abstract class Window { public void setSharedElementEnterTransition(Transition transition) {} /** + * Sets the Transition that will be used for shared elements transferred back to a + * calling Activity. Typical Transitions will affect size and location, such as + * {@link android.transition.ChangeBounds}. A null + * value will cause transferred shared elements to blink to the final position. + * If no value is set, the default will be to use the same value as + * {@link #setSharedElementEnterTransition(android.transition.Transition)}. + * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * @param transition The Transition to use for shared elements transferred out of the content + * Scene. + */ + public void setSharedElementReturnTransition(Transition transition) {} + + /** * Returns the Transition that will be used for shared elements transferred into the content * Scene. Requires {@link #FEATURE_CONTENT_TRANSITIONS}. * @return Transition to use for sharend elements transferred into the content Scene. @@ -1479,6 +1546,13 @@ public abstract class Window { public Transition getSharedElementEnterTransition() { return null; } /** + * Returns the Transition that will be used for shared elements transferred back to a + * calling Activity. Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * @return Transition to use for sharend elements transferred into the content Scene. + */ + public Transition getSharedElementReturnTransition() { return null; } + + /** * Sets the Transition that will be used for shared elements after starting a new Activity * before the shared elements are transferred to the called Activity. If the shared elements * must animate during the exit transition, this Transition should be used. Upon completion, @@ -1490,6 +1564,17 @@ public abstract class Window { public void setSharedElementExitTransition(Transition transition) {} /** + * Sets the Transition that will be used for shared elements reentering from a started + * Activity after it has returned the shared element to it start location. If no value + * is set, this will default to + * {@link #setSharedElementExitTransition(android.transition.Transition)}. + * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * @param transition The Transition to use for shared elements in the launching Window + * after the shared element has returned to the Window. + */ + public void setSharedElementReenterTransition(Transition transition) {} + + /** * Returns the Transition to use for shared elements in the launching Window prior * to transferring to the launched Activity's Window. * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. @@ -1500,6 +1585,16 @@ public abstract class Window { public Transition getSharedElementExitTransition() { return null; } /** + * Returns the Transition that will be used for shared elements reentering from a started + * Activity after it has returned the shared element to it start location. + * Requires {@link #FEATURE_CONTENT_TRANSITIONS}. + * + * @return the Transition that will be used for shared elements reentering from a started + * Activity after it has returned the shared element to it start location. + */ + public Transition getSharedElementReenterTransition() { return null; } + + /** * Controls how the transition set in * {@link #setEnterTransition(android.transition.Transition)} overlaps with the exit * transition of the calling Activity. When true, the transition will start as soon as possible. diff --git a/core/java/android/webkit/WebViewFactory.java b/core/java/android/webkit/WebViewFactory.java index 2c7b3eb..2e836fb 100644 --- a/core/java/android/webkit/WebViewFactory.java +++ b/core/java/android/webkit/WebViewFactory.java @@ -16,16 +16,26 @@ package android.webkit; +import android.app.ActivityManagerInternal; +import android.app.Application; +import android.app.AppGlobals; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; import android.os.Build; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.StrictMode; +import android.os.SystemProperties; +import android.text.TextUtils; import android.util.AndroidRuntimeException; import android.util.Log; +import com.android.server.LocalServices; import dalvik.system.VMRuntime; import java.io.File; +import java.util.Arrays; import com.android.internal.os.Zygote; @@ -42,17 +52,15 @@ public final class WebViewFactory { private static final String NULL_WEBVIEW_FACTORY = "com.android.webview.nullwebview.NullWebViewFactoryProvider"; - // TODO(torne): we need to use a system property instead of hardcoding the library paths to - // enable it to be changed when a webview update apk is installed. - private static final String CHROMIUM_WEBVIEW_NATIVE_LIB_32 = - "/system/lib/libwebviewchromium.so"; - private static final String CHROMIUM_WEBVIEW_NATIVE_LIB_64 = - "/system/lib64/libwebviewchromium.so"; private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_32 = "/data/misc/shared_relro/libwebviewchromium32.relro"; private static final String CHROMIUM_WEBVIEW_NATIVE_RELRO_64 = "/data/misc/shared_relro/libwebviewchromium64.relro"; + public static final String CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY = + "persist.sys.webview.vmsize"; + private static final long CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES = 100 * 1024 * 1024; + private static final String LOGTAG = "WebViewFactory"; private static final boolean DEBUG = false; @@ -64,8 +72,8 @@ public final class WebViewFactory { private static boolean sAddressSpaceReserved = false; public static String getWebViewPackageName() { - // TODO: Make this dynamic based on resource configuration. - return "com.android.webview"; + return AppGlobals.getInitialApplication().getString( + com.android.internal.R.string.config_webViewPackageName); } static WebViewFactoryProvider getProvider() { @@ -99,10 +107,18 @@ public final class WebViewFactory { } private static Class<WebViewFactoryProvider> getFactoryClass() throws ClassNotFoundException { + Application initialApplication = AppGlobals.getInitialApplication(); try { - return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY); - } catch (ClassNotFoundException e) { - Log.e(LOGTAG, "Chromium WebView does not exist"); + Context webViewContext = initialApplication.createPackageContext( + getWebViewPackageName(), + Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY); + initialApplication.getAssets().addAssetPath( + webViewContext.getApplicationInfo().sourceDir); + ClassLoader clazzLoader = webViewContext.getClassLoader(); + return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY, true, + clazzLoader); + } catch (PackageManager.NameNotFoundException e) { + Log.e(LOGTAG, "Chromium WebView package does not exist"); return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY); } } @@ -114,79 +130,197 @@ public final class WebViewFactory { public static void prepareWebViewInZygote() { try { System.loadLibrary("webviewchromium_loader"); - sAddressSpaceReserved = nativeReserveAddressSpace(CHROMIUM_WEBVIEW_NATIVE_LIB_32, - CHROMIUM_WEBVIEW_NATIVE_LIB_64); + long addressSpaceToReserve = + SystemProperties.getLong(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY, + CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES); + sAddressSpaceReserved = nativeReserveAddressSpace(addressSpaceToReserve); + if (sAddressSpaceReserved) { - if (DEBUG) Log.v(LOGTAG, "address space reserved"); + if (DEBUG) { + Log.v(LOGTAG, "address space reserved: " + addressSpaceToReserve + " bytes"); + } } else { - Log.e(LOGTAG, "reserving address space failed"); + Log.e(LOGTAG, "reserving " + addressSpaceToReserve + + " bytes of address space failed"); } - } catch (Throwable e) { + } catch (Throwable t) { // Log and discard errors at this stage as we must not crash the zygote. - Log.e(LOGTAG, "error preparing native loader", e); + Log.e(LOGTAG, "error preparing native loader", t); } } /** * Perform any WebView loading preparations that must happen at boot from the system server, - * after the package manager has started. + * after the package manager has started or after an update to the webview is installed. * This must be called in the system server. * Currently, this means spawning the child processes which will create the relro files. */ public static void prepareWebViewInSystemServer() { + String[] nativePaths = null; + try { + nativePaths = getWebViewNativeLibraryPaths(); + } catch (PackageManager.NameNotFoundException e) { + } + prepareWebViewInSystemServer(nativePaths); + } + + private static void prepareWebViewInSystemServer(String[] nativeLibraryPaths) { if (DEBUG) Log.v(LOGTAG, "creating relro files"); - if (new File(CHROMIUM_WEBVIEW_NATIVE_LIB_64).exists()) { - createRelroFile(Build.SUPPORTED_64_BIT_ABIS[0]); + + // We must always trigger createRelRo regardless of the value of nativeLibraryPaths. Any + // unexpected values will be handled there to ensure that we trigger notifying any process + // waiting on relreo creation. + if (Build.SUPPORTED_32_BIT_ABIS.length > 0) { + if (DEBUG) Log.v(LOGTAG, "Create 32 bit relro"); + createRelroFile(false /* is64Bit */, nativeLibraryPaths); + } + + if (Build.SUPPORTED_64_BIT_ABIS.length > 0) { + if (DEBUG) Log.v(LOGTAG, "Create 64 bit relro"); + createRelroFile(true /* is64Bit */, nativeLibraryPaths); } - if (new File(CHROMIUM_WEBVIEW_NATIVE_LIB_32).exists()) { - createRelroFile(Build.SUPPORTED_32_BIT_ABIS[0]); + } + + public static void onWebViewUpdateInstalled() { + String[] nativeLibs = null; + try { + nativeLibs = WebViewFactory.getWebViewNativeLibraryPaths(); + } catch (PackageManager.NameNotFoundException e) { + } + + if (nativeLibs != null) { + long newVmSize = 0L; + + for (String path : nativeLibs) { + if (DEBUG) Log.d(LOGTAG, "Checking file size of " + path); + if (path == null) continue; + File f = new File(path); + if (f.exists()) { + long length = f.length(); + if (length > newVmSize) { + newVmSize = length; + } + } + } + + if (DEBUG) { + Log.v(LOGTAG, "Based on library size, need " + newVmSize + + " bytes of address space."); + } + // The required memory can be larger than the file on disk (due to .bss), and an + // upgraded version of the library will likely be larger, so always attempt to reserve + // twice as much as we think to allow for the library to grow during this boot cycle. + newVmSize = Math.max(2 * newVmSize, CHROMIUM_WEBVIEW_DEFAULT_VMSIZE_BYTES); + Log.d(LOGTAG, "Setting new address space to " + newVmSize); + SystemProperties.set(CHROMIUM_WEBVIEW_VMSIZE_SIZE_PROPERTY, + Long.toString(newVmSize)); + } + prepareWebViewInSystemServer(nativeLibs); + } + + private static String[] getWebViewNativeLibraryPaths() + throws PackageManager.NameNotFoundException { + final String NATIVE_LIB_FILE_NAME = "libwebviewchromium.so"; + + PackageManager pm = AppGlobals.getInitialApplication().getPackageManager(); + ApplicationInfo ai = pm.getApplicationInfo(getWebViewPackageName(), 0); + + String path32; + String path64; + boolean primaryArchIs64bit = VMRuntime.is64BitAbi(ai.primaryCpuAbi); + if (!TextUtils.isEmpty(ai.secondaryCpuAbi)) { + // Multi-arch case. + if (primaryArchIs64bit) { + // Primary arch: 64-bit, secondary: 32-bit. + path64 = ai.nativeLibraryDir; + path32 = ai.secondaryNativeLibraryDir; + } else { + // Primary arch: 32-bit, secondary: 64-bit. + path64 = ai.secondaryNativeLibraryDir; + path32 = ai.nativeLibraryDir; + } + } else if (primaryArchIs64bit) { + // Single-arch 64-bit. + path64 = ai.nativeLibraryDir; + path32 = ""; + } else { + // Single-arch 32-bit. + path32 = ai.nativeLibraryDir; + path64 = ""; } + if (!TextUtils.isEmpty(path32)) path32 += "/" + NATIVE_LIB_FILE_NAME; + if (!TextUtils.isEmpty(path64)) path64 += "/" + NATIVE_LIB_FILE_NAME; + return new String[] { path32, path64 }; } - private static void createRelroFile(String abi) { + private static void createRelroFile(final boolean is64Bit, String[] nativeLibraryPaths) { + final String abi = + is64Bit ? Build.SUPPORTED_64_BIT_ABIS[0] : Build.SUPPORTED_32_BIT_ABIS[0]; + + // crashHandler is invoked by the ActivityManagerService when the isolated process crashes. + Runnable crashHandler = new Runnable() { + @Override + public void run() { + try { + Log.e(LOGTAG, "relro file creator for " + abi + " crashed. Proceeding without"); + getUpdateService().notifyRelroCreationCompleted(is64Bit, false); + } catch (RemoteException e) { + Log.e(LOGTAG, "Cannot reach WebViewUpdateService. " + e.getMessage()); + } + } + }; + try { - Process.start("android.webkit.WebViewFactory$RelroFileCreator", - "WebViewLoader-" + abi, - Process.SHARED_RELRO_UID, - Process.SHARED_RELRO_UID, - null, - 0, // TODO(torne): do we need to set debug flags? - Zygote.MOUNT_EXTERNAL_NONE, - Build.VERSION.SDK_INT, - null, - abi, - null); - } catch (Throwable e) { + if (nativeLibraryPaths == null + || nativeLibraryPaths[0] == null || nativeLibraryPaths[1] == null) { + throw new IllegalArgumentException( + "Native library paths to the WebView RelRo process must not be null!"); + } + int pid = LocalServices.getService(ActivityManagerInternal.class).startIsolatedProcess( + RelroFileCreator.class.getName(), nativeLibraryPaths, "WebViewLoader-" + abi, abi, + Process.SHARED_RELRO_UID, crashHandler); + if (pid <= 0) throw new Exception("Failed to start the relro file creator process"); + } catch (Throwable t) { // Log and discard errors as we must not crash the system server. - Log.e(LOGTAG, "error starting relro file creator for abi " + abi, e); + Log.e(LOGTAG, "error starting relro file creator for abi " + abi, t); + crashHandler.run(); } } private static class RelroFileCreator { // Called in an unprivileged child process to create the relro file. public static void main(String[] args) { - if (!sAddressSpaceReserved) { - Log.e(LOGTAG, "can't create relro file; address space not reserved"); - return; - } - boolean result = nativeCreateRelroFile(CHROMIUM_WEBVIEW_NATIVE_LIB_32, - CHROMIUM_WEBVIEW_NATIVE_LIB_64, - CHROMIUM_WEBVIEW_NATIVE_RELRO_32, - CHROMIUM_WEBVIEW_NATIVE_RELRO_64); - if (!result) { - Log.e(LOGTAG, "failed to create relro file"); - } else if (DEBUG) { - Log.v(LOGTAG, "created relro file"); - } - try { - getUpdateService().notifyRelroCreationCompleted(VMRuntime.getRuntime().is64Bit(), - result); - } catch (RemoteException e) { - Log.e(LOGTAG, "error notifying update service", e); - } + boolean result = false; + boolean is64Bit = VMRuntime.getRuntime().is64Bit(); + try{ + if (args.length != 2 || args[0] == null || args[1] == null) { + Log.e(LOGTAG, "Invalid RelroFileCreator args: " + Arrays.toString(args)); + return; + } + Log.v(LOGTAG, "RelroFileCreator (64bit = " + is64Bit + "), " + + " 32-bit lib: " + args[0] + ", 64-bit lib: " + args[1]); + if (!sAddressSpaceReserved) { + Log.e(LOGTAG, "can't create relro file; address space not reserved"); + return; + } + result = nativeCreateRelroFile(args[0] /* path32 */, + args[1] /* path64 */, + CHROMIUM_WEBVIEW_NATIVE_RELRO_32, + CHROMIUM_WEBVIEW_NATIVE_RELRO_64); + if (result && DEBUG) Log.v(LOGTAG, "created relro file"); + } finally { + // We must do our best to always notify the update service, even if something fails. + try { + getUpdateService().notifyRelroCreationCompleted(is64Bit, result); + } catch (RemoteException e) { + Log.e(LOGTAG, "error notifying update service", e); + } + + if (!result) Log.e(LOGTAG, "failed to create relro file"); - // Must explicitly exit or else this process will just sit around after we return. - System.exit(0); + // Must explicitly exit or else this process will just sit around after we return. + System.exit(0); + } } } @@ -203,14 +337,19 @@ public final class WebViewFactory { return; } - boolean result = nativeLoadWithRelroFile(CHROMIUM_WEBVIEW_NATIVE_LIB_32, - CHROMIUM_WEBVIEW_NATIVE_LIB_64, - CHROMIUM_WEBVIEW_NATIVE_RELRO_32, - CHROMIUM_WEBVIEW_NATIVE_RELRO_64); - if (!result) { - Log.w(LOGTAG, "failed to load with relro file, proceeding without"); - } else if (DEBUG) { - Log.v(LOGTAG, "loaded with relro file"); + try { + String[] args = getWebViewNativeLibraryPaths(); + boolean result = nativeLoadWithRelroFile(args[0] /* path32 */, + args[1] /* path64 */, + CHROMIUM_WEBVIEW_NATIVE_RELRO_32, + CHROMIUM_WEBVIEW_NATIVE_RELRO_64); + if (!result) { + Log.w(LOGTAG, "failed to load with relro file, proceeding without"); + } else if (DEBUG) { + Log.v(LOGTAG, "loaded with relro file"); + } + } catch (PackageManager.NameNotFoundException e) { + Log.e(LOGTAG, "Failed to list WebView package libraries for loadNativeLibrary", e); } } @@ -218,7 +357,7 @@ public final class WebViewFactory { return IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate")); } - private static native boolean nativeReserveAddressSpace(String lib32, String lib64); + private static native boolean nativeReserveAddressSpace(long addressSpaceToReserve); private static native boolean nativeCreateRelroFile(String lib32, String lib64, String relro32, String relro64); private static native boolean nativeLoadWithRelroFile(String lib32, String lib64, diff --git a/core/java/com/android/internal/util/XmlUtils.java b/core/java/com/android/internal/util/XmlUtils.java index dca9921..7db70ba 100644 --- a/core/java/com/android/internal/util/XmlUtils.java +++ b/core/java/com/android/internal/util/XmlUtils.java @@ -16,12 +16,18 @@ package com.android.internal.util; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Bitmap.CompressFormat; +import android.net.Uri; +import android.util.Base64; import android.util.Xml; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -1415,6 +1421,20 @@ public class XmlUtils { out.attribute(null, name, Long.toString(value)); } + public static float readFloatAttribute(XmlPullParser in, String name) throws IOException { + final String value = in.getAttributeValue(null, name); + try { + return Float.parseFloat(value); + } catch (NumberFormatException e) { + throw new ProtocolException("problem parsing " + name + "=" + value + " as long"); + } + } + + public static void writeFloatAttribute(XmlSerializer out, String name, float value) + throws IOException { + out.attribute(null, name, Float.toString(value)); + } + public static boolean readBooleanAttribute(XmlPullParser in, String name) { final String value = in.getAttributeValue(null, name); return Boolean.parseBoolean(value); @@ -1425,6 +1445,63 @@ public class XmlUtils { out.attribute(null, name, Boolean.toString(value)); } + public static Uri readUriAttribute(XmlPullParser in, String name) { + final String value = in.getAttributeValue(null, name); + return (value != null) ? Uri.parse(value) : null; + } + + public static void writeUriAttribute(XmlSerializer out, String name, Uri value) + throws IOException { + if (value != null) { + out.attribute(null, name, value.toString()); + } + } + + public static String readStringAttribute(XmlPullParser in, String name) { + return in.getAttributeValue(null, name); + } + + public static void writeStringAttribute(XmlSerializer out, String name, String value) + throws IOException { + if (value != null) { + out.attribute(null, name, value); + } + } + + public static byte[] readByteArrayAttribute(XmlPullParser in, String name) { + final String value = in.getAttributeValue(null, name); + if (value != null) { + return Base64.decode(value, Base64.DEFAULT); + } else { + return null; + } + } + + public static void writeByteArrayAttribute(XmlSerializer out, String name, byte[] value) + throws IOException { + if (value != null) { + out.attribute(null, name, Base64.encodeToString(value, Base64.DEFAULT)); + } + } + + public static Bitmap readBitmapAttribute(XmlPullParser in, String name) { + final byte[] value = readByteArrayAttribute(in, name); + if (value != null) { + return BitmapFactory.decodeByteArray(value, 0, value.length); + } else { + return null; + } + } + + public static void writeBitmapAttribute(XmlSerializer out, String name, Bitmap value) + throws IOException { + if (value != null) { + final ByteArrayOutputStream os = new ByteArrayOutputStream(); + value.compress(CompressFormat.PNG, 90, os); + writeByteArrayAttribute(out, name, os.toByteArray()); + } + } + /** @hide */ public interface WriteMapCallback { /** diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java index 790b611..9e24844 100644 --- a/core/java/com/android/internal/widget/ActionBarContainer.java +++ b/core/java/com/android/internal/widget/ActionBarContainer.java @@ -16,10 +16,12 @@ package com.android.internal.widget; +import android.annotation.NonNull; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.ColorFilter; +import android.graphics.Outline; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.ActionMode; @@ -324,18 +326,36 @@ public class ActionBarContainer extends FrameLayout { * projection surfaces. */ private class ActionBarBackgroundDrawable extends Drawable { - @Override - public void draw(Canvas canvas) { + private Drawable getDrawable() { if (mIsSplit) { - if (mSplitBackground != null) mSplitBackground.draw(canvas); + if (mSplitBackground != null) { + return mSplitBackground; + } } else { if (mBackground != null) { - mBackground.draw(canvas); + return mBackground; } if (mStackedBackground != null && mIsStacked) { - mStackedBackground.draw(canvas); + return mStackedBackground; } } + return null; + } + + @Override + public void draw(Canvas canvas) { + final Drawable drawable = getDrawable(); + if (drawable != null) { + drawable.draw(canvas); + } + } + + @Override + public void getOutline(@NonNull Outline outline) { + final Drawable drawable = getDrawable(); + if (drawable != null) { + drawable.getOutline(outline); + } } @Override diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index a890eb4..2ce1b15 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -353,7 +353,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding ninePatchInsets = env->NewObject(gInsetStruct_class, gInsetStruct_constructorMethodID, peeker.mOpticalInsets[0], peeker.mOpticalInsets[1], peeker.mOpticalInsets[2], peeker.mOpticalInsets[3], peeker.mOutlineInsets[0], peeker.mOutlineInsets[1], peeker.mOutlineInsets[2], peeker.mOutlineInsets[3], - peeker.mOutlineRadius, peeker.mOutlineFilled, scale); + peeker.mOutlineRadius, peeker.mOutlineAlpha, scale); if (javaBitmap != NULL) { env->SetObjectField(javaBitmap, gBitmap_ninePatchInsetsFieldID, ninePatchInsets); } @@ -589,7 +589,7 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) { "Landroid/graphics/NinePatch$InsetStruct;"); gInsetStruct_class = (jclass) env->NewGlobalRef(env->FindClass("android/graphics/NinePatch$InsetStruct")); - gInsetStruct_constructorMethodID = env->GetMethodID(gInsetStruct_class, "<init>", "(IIIIIIIIFZF)V"); + gInsetStruct_constructorMethodID = env->GetMethodID(gInsetStruct_class, "<init>", "(IIIIIIIIFIF)V"); int ret = AndroidRuntime::registerNativeMethods(env, "android/graphics/BitmapFactory$Options", diff --git a/core/jni/android/graphics/NinePatchPeeker.cpp b/core/jni/android/graphics/NinePatchPeeker.cpp index ea5193b..1dafa1b 100644 --- a/core/jni/android/graphics/NinePatchPeeker.cpp +++ b/core/jni/android/graphics/NinePatchPeeker.cpp @@ -48,11 +48,11 @@ bool NinePatchPeeker::peek(const char tag[], const void* data, size_t length) { } else if (!strcmp("npLb", tag) && length == sizeof(int32_t) * 4) { mHasInsets = true; memcpy(&mOpticalInsets, data, sizeof(int32_t) * 4); - } else if (!strcmp("npOl", tag) && length == 24) { // 4 int32_ts, 1 float, 1 int32_t sized bool + } else if (!strcmp("npOl", tag) && length == 24) { // 4 int32_ts, 1 float, 1 int32_t sized byte mHasInsets = true; memcpy(&mOutlineInsets, data, sizeof(int32_t) * 4); mOutlineRadius = ((const float*)data)[4]; - mOutlineFilled = ((const int32_t*)data)[5] & 0x01; + mOutlineAlpha = ((const int32_t*)data)[5] & 0xff; } return true; // keep on decoding } diff --git a/core/jni/android/graphics/NinePatchPeeker.h b/core/jni/android/graphics/NinePatchPeeker.h index 8d3e6cf..7c18b2d 100644 --- a/core/jni/android/graphics/NinePatchPeeker.h +++ b/core/jni/android/graphics/NinePatchPeeker.h @@ -33,7 +33,7 @@ public: , mPatchSize(0) , mHasInsets(false) , mOutlineRadius(0) - , mOutlineFilled(false) { + , mOutlineAlpha(0) { memset(mOpticalInsets, 0, 4 * sizeof(int32_t)); memset(mOutlineInsets, 0, 4 * sizeof(int32_t)); } @@ -50,7 +50,7 @@ public: int32_t mOpticalInsets[4]; int32_t mOutlineInsets[4]; float mOutlineRadius; - bool mOutlineFilled; + uint8_t mOutlineAlpha; }; #endif // NinePatchPeeker_h diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp index ff54fb9..1e9d722 100644 --- a/core/jni/android_view_RenderNode.cpp +++ b/core/jni/android_view_RenderNode.cpp @@ -140,18 +140,19 @@ static jboolean android_view_RenderNode_setProjectionReceiver(JNIEnv* env, static jboolean android_view_RenderNode_setOutlineRoundRect(JNIEnv* env, jobject clazz, jlong renderNodePtr, jint left, jint top, - jint right, jint bottom, jfloat radius) { + jint right, jint bottom, jfloat radius, jfloat alpha) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); - renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius); + renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, + radius, alpha); renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); return true; } static jboolean android_view_RenderNode_setOutlineConvexPath(JNIEnv* env, - jobject clazz, jlong renderNodePtr, jlong outlinePathPtr) { + jobject clazz, jlong renderNodePtr, jlong outlinePathPtr, jfloat alpha) { RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr); - renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath); + renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath, alpha); renderNode->setPropertyFieldsDirty(RenderNode::GENERIC); return true; } @@ -480,8 +481,8 @@ static JNINativeMethod gMethods[] = { { "nSetProjectBackwards", "(JZ)Z", (void*) android_view_RenderNode_setProjectBackwards }, { "nSetProjectionReceiver","(JZ)Z", (void*) android_view_RenderNode_setProjectionReceiver }, - { "nSetOutlineRoundRect", "(JIIIIF)Z", (void*) android_view_RenderNode_setOutlineRoundRect }, - { "nSetOutlineConvexPath", "(JJ)Z", (void*) android_view_RenderNode_setOutlineConvexPath }, + { "nSetOutlineRoundRect", "(JIIIIFF)Z", (void*) android_view_RenderNode_setOutlineRoundRect }, + { "nSetOutlineConvexPath", "(JJF)Z", (void*) android_view_RenderNode_setOutlineConvexPath }, { "nSetOutlineEmpty", "(J)Z", (void*) android_view_RenderNode_setOutlineEmpty }, { "nSetOutlineNone", "(J)Z", (void*) android_view_RenderNode_setOutlineNone }, { "nSetClipToOutline", "(JZ)Z", (void*) android_view_RenderNode_setClipToOutline }, diff --git a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png Binary files differdeleted file mode 100644 index 8148ab8..0000000 --- a/core/res/res/drawable-hdpi/stat_notify_wifi_in_range.png +++ /dev/null diff --git a/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png b/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png Binary files differdeleted file mode 100644 index 7d4df50..0000000 --- a/core/res/res/drawable-hdpi/stat_sys_tether_wifi.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-ldpi/stat_notify_wifi_in_range.png Binary files differdeleted file mode 100644 index 1ff50ea..0000000 --- a/core/res/res/drawable-ldpi/stat_notify_wifi_in_range.png +++ /dev/null diff --git a/core/res/res/drawable-ldpi/stat_sys_tether_wifi.png b/core/res/res/drawable-ldpi/stat_sys_tether_wifi.png Binary files differdeleted file mode 100644 index b4b3cfd..0000000 --- a/core/res/res/drawable-ldpi/stat_sys_tether_wifi.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png Binary files differdeleted file mode 100644 index b7e2a6a..0000000 --- a/core/res/res/drawable-mdpi/stat_notify_wifi_in_range.png +++ /dev/null diff --git a/core/res/res/drawable-mdpi/stat_sys_tether_wifi.png b/core/res/res/drawable-mdpi/stat_sys_tether_wifi.png Binary files differdeleted file mode 100644 index 869ad35..0000000 --- a/core/res/res/drawable-mdpi/stat_sys_tether_wifi.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png Binary files differdeleted file mode 100644 index 0dbae57..0000000 --- a/core/res/res/drawable-xhdpi/stat_notify_wifi_in_range.png +++ /dev/null diff --git a/core/res/res/drawable-xhdpi/stat_sys_tether_wifi.png b/core/res/res/drawable-xhdpi/stat_sys_tether_wifi.png Binary files differdeleted file mode 100644 index dc48646..0000000 --- a/core/res/res/drawable-xhdpi/stat_sys_tether_wifi.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/stat_notify_wifi_in_range.png b/core/res/res/drawable-xxhdpi/stat_notify_wifi_in_range.png Binary files differdeleted file mode 100644 index 47e74fb..0000000 --- a/core/res/res/drawable-xxhdpi/stat_notify_wifi_in_range.png +++ /dev/null diff --git a/core/res/res/drawable-xxhdpi/stat_sys_tether_wifi.png b/core/res/res/drawable-xxhdpi/stat_sys_tether_wifi.png Binary files differdeleted file mode 100644 index da44e6a..0000000 --- a/core/res/res/drawable-xxhdpi/stat_sys_tether_wifi.png +++ /dev/null diff --git a/core/res/res/drawable/stat_notify_wifi_in_range.xml b/core/res/res/drawable/stat_notify_wifi_in_range.xml new file mode 100644 index 0000000..9a5407d --- /dev/null +++ b/core/res/res/drawable/stat_notify_wifi_in_range.xml @@ -0,0 +1,27 @@ +<!-- +Copyright (C) 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26.0dp" + android:height="24.0dp" + android:viewportWidth="26.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#4DFFFFFF" + android:pathData="M19.100000,14.000000l-3.400000,0.000000l0.000000,-1.500000c0.000000,-1.800000 0.800000,-2.800000 1.500000,-3.400000C18.100000,8.300000 19.200001,8.000000 20.600000,8.000000c1.200000,0.000000 2.300000,0.300000 3.100000,0.800000l1.900000,-2.300000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l0.000000,0.000000l6.500000,-8.100000L19.100000,14.000000z"/> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M19.500000,17.799999c0.000000,-0.800000 0.100000,-1.300000 0.200000,-1.600000c0.200000,-0.300000 0.500000,-0.700000 1.100000,-1.200000c0.400000,-0.400000 0.700000,-0.800000 1.000000,-1.100000s0.400000,-0.800000 0.400000,-1.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.400000,-1.200000c-0.300000,-0.300000 -0.700000,-0.400000 -1.200000,-0.400000c-0.400000,0.000000 -0.800000,0.100000 -1.100000,0.300000c-0.300000,0.200000 -0.400000,0.600000 -0.400000,1.100000l-1.900000,0.000000c0.000000,-1.000000 0.300000,-1.700000 1.000000,-2.200000c0.600000,-0.500000 1.500000,-0.800000 2.500000,-0.800000c1.100000,0.000000 2.000000,0.300000 2.600000,0.800000c0.600000,0.500000 0.900000,1.300000 0.900000,2.300000c0.000000,0.700000 -0.200000,1.300000 -0.600000,1.800000c-0.400000,0.600000 -0.900000,1.100000 -1.500000,1.600000c-0.300000,0.300000 -0.500000,0.500000 -0.600000,0.700000c-0.100000,0.200000 -0.100000,0.600000 -0.100000,1.000000L19.500000,17.700001zM21.400000,21.000000l-1.900000,0.000000l0.000000,-1.800000l1.900000,0.000000L21.400000,21.000000z"/> +</vector> diff --git a/core/res/res/drawable/stat_sys_tether_wifi.xml b/core/res/res/drawable/stat_sys_tether_wifi.xml new file mode 100644 index 0000000..a816db8 --- /dev/null +++ b/core/res/res/drawable/stat_sys_tether_wifi.xml @@ -0,0 +1,24 @@ +<!-- +Copyright (C) 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="26.0dp" + android:height="24.0dp" + android:viewportWidth="26.0" + android:viewportHeight="24.0"> + <path + android:fillColor="#FFFFFFFF" + android:pathData="M13.000000,22.000000L25.600000,6.500000C25.100000,6.100000 20.299999,2.100000 13.000000,2.100000S0.900000,6.100000 0.400000,6.500000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000L13.000000,22.000000z"/> +</vector> diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index 5cb3068..a31f18f 100644 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -464,24 +464,48 @@ <attr name="windowEnterTransition" format="reference"/> <!-- Reference to a Transition XML resource defining the desired Transition + used to move Views out of the scene when the Window is + preparing to close. Corresponds to + {@link android.view.Window#setReturnTransition(android.transition.Transition)}. --> + <attr name="windowReturnTransition" format="reference"/> + + <!-- Reference to a Transition XML resource defining the desired Transition used to move Views out of the Window's content Scene when launching a new Activity. Corresponds to {@link android.view.Window#setExitTransition(android.transition.Transition)}. --> <attr name="windowExitTransition" format="reference"/> <!-- Reference to a Transition XML resource defining the desired Transition + used to move Views in to the scene when returning from a previously-started Activity. + Corresponds to + {@link android.view.Window#setReenterTransition(android.transition.Transition)}. --> + <attr name="windowReenterTransition" format="reference"/> + + <!-- Reference to a Transition XML resource defining the desired Transition used to move shared elements transferred into the Window's initial content Scene. Corresponds to {@link android.view.Window#setSharedElementEnterTransition( android.transition.Transition)}. --> <attr name="windowSharedElementEnterTransition" format="reference"/> <!-- Reference to a Transition XML resource defining the desired Transition + used to move shared elements transferred back to a calling Activity. + Corresponds to {@link android.view.Window#setSharedElementReturnTransition( + android.transition.Transition)}. --> + <attr name="windowSharedElementReturnTransition" format="reference"/> + + <!-- Reference to a Transition XML resource defining the desired Transition used when starting a new Activity to move shared elements prior to transferring to the called Activity. Corresponds to {@link android.view.Window#setSharedElementExitTransition( android.transition.Transition)}. --> <attr name="windowSharedElementExitTransition" format="reference"/> + <!-- Reference to a Transition XML resource defining the desired Transition + used for shared elements transferred back to a calling Activity. + Corresponds to {@link android.view.Window#setSharedElementReenterTransition( + android.transition.Transition)}. --> + <attr name="windowSharedElementReenterTransition" format="reference"/> + <!-- Flag indicating whether this Window's transition should overlap with the exiting transition of the calling Activity. Corresponds to {@link android.view.Window#setAllowEnterTransitionOverlap(boolean)}. --> @@ -1751,30 +1775,54 @@ or a fraction of the screen size in that dimension. --> <attr name="windowFixedHeightMajor" format="dimension|fraction" /> <attr name="windowOutsetBottom" format="dimension" /> - <!-- Reference to a TransitionManager XML resource defining the desired Transition + <!-- Reference to a Transition XML resource defining the desired Transition used to move Views into the initial Window's content Scene. Corresponds to {@link android.view.Window#setEnterTransition(android.transition.Transition)}. --> <attr name="windowEnterTransition"/> - <!-- Reference to a TransitionManager XML resource defining the desired Transition + <!-- Reference to a Transition XML resource defining the desired Transition + used to move Views out of the scene when the Window is + preparing to close. Corresponds to + {@link android.view.Window#setReturnTransition(android.transition.Transition)}. --> + <attr name="windowReturnTransition"/> + + <!-- Reference to a Transition XML resource defining the desired Transition used to move Views out of the Window's content Scene when launching a new Activity. Corresponds to {@link android.view.Window#setExitTransition(android.transition.Transition)}. --> <attr name="windowExitTransition"/> - <!-- Reference to a TransitionManager XML resource defining the desired Transition + <!-- Reference to a Transition XML resource defining the desired Transition + used to move Views in to the scene when returning from a previously-started Activity. + Corresponds to + {@link android.view.Window#setReenterTransition(android.transition.Transition)}. --> + <attr name="windowReenterTransition"/> + + <!-- Reference to a Transition XML resource defining the desired Transition used to move shared elements transferred into the Window's initial content Scene. Corresponds to {@link android.view.Window#setSharedElementEnterTransition( android.transition.Transition)}. --> <attr name="windowSharedElementEnterTransition"/> - <!-- Reference to a TransitionManager XML resource defining the desired Transition + <!-- Reference to a Transition XML resource defining the desired Transition + used to move shared elements transferred back to a calling Activity. + Corresponds to {@link android.view.Window#setSharedElementReturnTransition( + android.transition.Transition)}. --> + <attr name="windowSharedElementReturnTransition"/> + + <!-- Reference to a Transition XML resource defining the desired Transition used when starting a new Activity to move shared elements prior to transferring to the called Activity. Corresponds to {@link android.view.Window#setSharedElementExitTransition( android.transition.Transition)}. --> <attr name="windowSharedElementExitTransition"/> + <!-- Reference to a Transition XML resource defining the desired Transition + used for shared elements transferred back to a calling Activity. + Corresponds to {@link android.view.Window#setSharedElementReenterTransition( + android.transition.Transition)}. --> + <attr name="windowSharedElementReenterTransition"/> + <!-- Flag indicating whether this Window's transition should overlap with the exiting transition of the calling Activity. Corresponds to @@ -7211,7 +7259,9 @@ <!-- Component name of an activity that allows the user to modify the settings for this service. --> <attr name="settingsActivity" /> - <!-- Type of this service. --> + <!-- Component name of an xml file that describes the structure of TV content ratings that + this service uses. --> + <attr name="contentRatingSystemXml" format="reference" /> </declare-styleable> <declare-styleable name="ResolverDrawerLayout"> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 217658c..b9e5c66 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1661,4 +1661,8 @@ <!--Support decoding the user data payload as pack GSM 8-bit (a GSM alphabet string that's stored in 8-bit unpacked format) characters.--> <bool translatable="false" name="config_sms_decode_gsm_8bit_data">false</bool> + + <!-- Package name providing WebView implementation. --> + <string name="config_webViewPackageName" translatable="false">com.android.webview</string> + </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 0cb14e3..08398f0 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2265,6 +2265,10 @@ <public type="attr" name="windowClipToOutline" /> <public type="attr" name="datePickerDialogTheme" /> <public type="attr" name="showText" /> + <public type="attr" name="windowReturnTransition" /> + <public type="attr" name="windowReenterTransition" /> + <public type="attr" name="windowSharedElementReturnTransition" /> + <public type="attr" name="windowSharedElementReenterTransition" /> <public-padding type="dimen" name="l_resource_pad" end="0x01050010" /> @@ -2556,4 +2560,6 @@ <public type="raw" name="loaderror" id="0x01100000"/> <!-- WebView error page for when domain lookup fails. @hide @SystemApi --> <public type="raw" name="nodomain"/> + + <public type="attr" name="contentRatingSystemXml"/> </resources> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 11c41e3..195851f 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -3754,10 +3754,10 @@ <!-- DO NOT TRANSLATE --> <string name="locale_replacement">""</string> - <!-- Title of the pop-up dialog in which the user switches input method components. --> - <string name="select_input_method">Choose input method</string> - <!-- Title of a button to open the settings for input methods [CHAR LIMIT=30] --> - <string name="configure_input_methods">Set up input methods</string> + <!-- Title of the pop-up dialog in which the user switches keyboard, also known as input method. --> + <string name="select_input_method">Change keyboard</string> + <!-- Title of a button to open the settings to enable or disable keyboards, also known as input methods [CHAR LIMIT=30] --> + <string name="configure_input_methods">Choose keyboards</string> <!-- Summary text of a toggle switch to enable/disable use of the physical keyboard in the input method selector [CHAR LIMIT=25] --> <string name="use_physical_keyboard">Physical keyboard</string> <!-- Title of the physical keyboard category in the input method selector [CHAR LIMIT=10] --> @@ -4841,4 +4841,41 @@ <!-- Lock-to-app unlock password string --> <string name="lock_to_app_unlock_password">password</string> + <string name="display_name_ustvpg" translatable="false">US-TV</string> + <string name="description_ustvpg">The TV Parental Guidelines</string> + <string name="display_name_krtv" translatable="false">KR-TV</string> + + <string name="display_name_ustvpg_d" translatable="false">D</string> + <string name="display_name_ustvpg_l" translatable="false">L</string> + <string name="display_name_ustvpg_s" translatable="false">S</string> + <string name="display_name_ustvpg_v" translatable="false">V</string> + <string name="display_name_ustvpg_fv" translatable="false">FV</string> + <string name="display_name_ustvpg_y" translatable="false">TV-Y</string> + <string name="display_name_ustvpg_y7" translatable="false">TV-Y7</string> + <string name="display_name_ustvpg_g" translatable="false">TV-G</string> + <string name="display_name_ustvpg_pg" translatable="false">TV-PG</string> + <string name="display_name_ustvpg_14" translatable="false">TV-14</string> + <string name="display_name_ustvpg_ma" translatable="false">TV-MA</string> + <string name="display_name_krtv_all" translatable="false">모든연령시청가</string> + <string name="display_name_krtv_7" translatable="false">7세이상시청가</string> + <string name="display_name_krtv_12" translatable="false">12세이상시청가</string> + <string name="display_name_krtv_15" translatable="false">15세이상시청가</string> + <string name="display_name_krtv_19" translatable="false">19세이상시청가</string> + + <string name="description_ustvpg_d">Suggestive dialogue (Usually means talks about sex)</string> + <string name="description_ustvpg_l">Coarse language</string> + <string name="description_ustvpg_s">Sexual content</string> + <string name="description_ustvpg_v">Violence</string> + <string name="description_ustvpg_fv">Fantasy violence (Children\'s programming only)</string> + <string name="description_ustvpg_y">This program is designed to be appropriate for all children.</string> + <string name="description_ustvpg_y7">This program is designed for children age 7 and above.</string> + <string name="description_ustvpg_g">Most parents would find this program suitable for all ages.</string> + <string name="description_ustvpg_pg">This program contains material that parents may find unsuitable for younger children.</string> + <string name="description_ustvpg_14">This program contains some material that many parents would find unsuitable for children under 14 years of age.</string> + <string name="description_ustvpg_ma">This program is specifically designed to be viewed by adults and therefore may be unsuitable for children under 17.</string> + <string name="description_krtv_all">모든 연령의 시청자가 시청하기에 부적절한 내용이 없는 등급을 말한다.</string> + <string name="description_krtv_7">7세미만의 어린이가 시청하기에 부적절한 내용이 포함되어 있어 보호자의 시청지도가 필요한 등급을 말한다.</string> + <string name="description_krtv_12">12세미만의 청소년이 시청하기에 부적절한 내용이 포함되어 있어 보호자의 시청지도가 필요한 등급을 말한다.</string> + <string name="description_krtv_15">15세미만의 청소년이 시청하기에 부적절한 내용이 포함되어 있어 보호자의 시청지도가 필요한 등급을 말한다.</string> + <string name="description_krtv_19">19세미만의 청소년이 시청하기에 부적절한 내용이 포함되어 있어 청소년이 시청할 수 없는 등급을 말한다.</string> </resources> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 6e23557..ccd7005 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1259,6 +1259,7 @@ <java-symbol type="xml" name="audio_assets" /> <java-symbol type="xml" name="global_keys" /> <java-symbol type="xml" name="default_zen_mode_config" /> + <java-symbol type="xml" name="tv_content_rating_systems" /> <java-symbol type="raw" name="accessibility_gestures" /> <java-symbol type="raw" name="incognito_mode_start_page" /> @@ -1838,6 +1839,7 @@ <java-symbol type="attr" name="actionModeWebSearchDrawable" /> <java-symbol type="string" name="websearch" /> <java-symbol type="drawable" name="ic_media_video_poster" /> + <java-symbol type="string" name="config_webViewPackageName" /> <!-- From SubtitleView --> <java-symbol type="dimen" name="subtitle_corner_radius" /> diff --git a/core/res/res/xml/tv_content_rating_systems.xml b/core/res/res/xml/tv_content_rating_systems.xml new file mode 100644 index 0000000..238ce13 --- /dev/null +++ b/core/res/res/xml/tv_content_rating_systems.xml @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** 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. +*/ +--> +<rating-system-definitions> + <rating-system-definition id="US_TVPG" + displayName="@string/display_name_ustvpg" + description="@string/description_ustvpg" + country="US"> + <sub-rating-definition id="US_TVPG_D" + displayName="@string/display_name_ustvpg_d" + description="@string/description_ustvpg_d" /> + <sub-rating-definition id="US_TVPG_L" + displayName="@string/display_name_ustvpg_l" + description="@string/description_ustvpg_l" /> + <sub-rating-definition id="US_TVPG_S" + displayName="@string/display_name_ustvpg_s" + description="@string/description_ustvpg_s" /> + <sub-rating-definition id="US_TVPG_V" + displayName="@string/display_name_ustvpg_v" + description="@string/description_ustvpg_v" /> + <sub-rating-definition id="US_TVPG_FV" + displayName="@string/display_name_ustvpg_fv" + description="@string/description_ustvpg_fv" /> + + <rating-definition id="US_TVPG_TV_Y" + displayName="@string/display_name_ustvpg_y" + description="@string/description_ustvpg_y" + ageHint="0" /> + <rating-definition id="US_TVPG_TV_Y7" + displayName="@string/display_name_ustvpg_y7" + description="@string/description_ustvpg_y7" + ageHint="7"> + <sub-rating id="US_TVPG_FV" /> + </rating-definition> + <rating-definition id="US_TVPG_TV_G" + displayName="@string/display_name_ustvpg_g" + description="@string/description_ustvpg_g" + ageHint="0" /> + <rating-definition id="US_TVPG_TV_PG" + displayName="@string/display_name_ustvpg_pg" + description="@string/description_ustvpg_pg" + ageHint="14"> + <sub-rating id="US_TVPG_D" /> + <sub-rating id="US_TVPG_L" /> + <sub-rating id="US_TVPG_S" /> + <sub-rating id="US_TVPG_V" /> + </rating-definition> + <rating-definition id="US_TVPG_TV_14" + displayName="@string/display_name_ustvpg_14" + description="@string/description_ustvpg_14" + ageHint="14"> + <sub-rating id="US_TVPG_D" /> + <sub-rating id="US_TVPG_L" /> + <sub-rating id="US_TVPG_S" /> + <sub-rating id="US_TVPG_V" /> + </rating-definition> + <rating-definition id="US_TVPG_TV_MA" + displayName="@string/display_name_ustvpg_ma" + description="@string/description_ustvpg_ma" + ageHint="17"> + <sub-rating id="US_TVPG_L" /> + <sub-rating id="US_TVPG_S" /> + <sub-rating id="US_TVPG_V" /> + </rating-definition> + <order> + <rating id="US_TVPG_Y" /> + <rating id="US_TVPG_Y7" /> + </order> + <order> + <rating id="US_TVPG_TV_G" /> + <rating id="US_TVPG_TV_PG" /> + <rating id="US_TVPG_TV_14" /> + <rating id="US_TVPG_TV_MA" /> + </order> + </rating-system-definition> + + <rating-system-definition id="KR_TV" + displayName="@string/display_name_krtv" + country="KR"> + <rating-definition id="KR_TV_ALL" + displayName="@string/display_name_krtv_all" + description="@string/description_krtv_all" + ageHint="0" /> + <rating-definition id="KR_TV_7" + displayName="@string/display_name_krtv_7" + description="@string/description_krtv_7" + ageHint="7"> + </rating-definition> + <rating-definition id="KR_TV_12" + displayName="@string/display_name_krtv_12" + description="@string/description_krtv_12" + ageHint="12"> + </rating-definition> + <rating-definition id="KR_TV_15" + displayName="@string/display_name_krtv_15" + description="@string/description_krtv_15" + ageHint="15"> + </rating-definition> + <rating-definition id="KR_TV_19" + displayName="@string/display_name_krtv_19" + description="@string/description_krtv_19" + ageHint="19"> + </rating-definition> + <order> + <rating id="KR_TV_ALL" /> + <rating id="KR_TV_7" /> + <rating id="KR_TV_12" /> + <rating id="KR_TV_15" /> + <rating id="KR_TV_19" /> + </order> + </rating-system-definition> +</rating-system-definitions> |