Merge "Fix runtime restart" into lmp-dev
diff --git a/api/current.txt b/api/current.txt
index 85475fb..dab4f64 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -968,6 +968,7 @@
field public static final int pathData = 16843807; // 0x101041f
field public static final int pathPattern = 16842796; // 0x101002c
field public static final int pathPrefix = 16842795; // 0x101002b
+ field public static final int patternPathData = 16843979; // 0x10104cb
field public static final int permission = 16842758; // 0x1010006
field public static final int permissionFlags = 16843719; // 0x10103c7
field public static final int permissionGroup = 16842762; // 0x101000a
@@ -8680,15 +8681,17 @@
public class PackageInstaller {
method public void abandonSession(int);
- method public void addSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
- method public void addSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
method public int createSession(android.content.pm.PackageInstaller.SessionParams) throws java.io.IOException;
method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getAllSessions();
method public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions();
method public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int);
method public android.content.pm.PackageInstaller.Session openSession(int);
- method public void removeSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+ method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+ method public void registerSessionCallback(android.content.pm.PackageInstaller.SessionCallback, android.os.Handler);
method public void uninstall(java.lang.String, android.content.IntentSender);
+ method public void unregisterSessionCallback(android.content.pm.PackageInstaller.SessionCallback);
+ method public void updateSessionAppIcon(int, android.graphics.Bitmap);
+ method public void updateSessionAppLabel(int, java.lang.CharSequence);
field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
@@ -8720,6 +8723,7 @@
public static abstract class PackageInstaller.SessionCallback {
ctor public PackageInstaller.SessionCallback();
+ method public abstract void onBadgingChanged(int);
method public abstract void onClosed(int);
method public abstract void onCreated(int);
method public abstract void onFinished(int, boolean);
@@ -11438,8 +11442,6 @@
ctor public PorterDuffColorFilter(int, android.graphics.PorterDuff.Mode);
method public int getColor();
method public android.graphics.PorterDuff.Mode getMode();
- method public void setColor(int);
- method public void setMode(android.graphics.PorterDuff.Mode);
}
public class PorterDuffXfermode extends android.graphics.Xfermode {
@@ -31507,13 +31509,13 @@
method public abstract android.graphics.Path getPath(float, float, float, float);
}
- public class PatternMotion extends android.transition.PathMotion {
- ctor public PatternMotion();
- ctor public PatternMotion(android.content.Context, android.util.AttributeSet);
- ctor public PatternMotion(android.graphics.Path);
+ public class PatternPathMotion extends android.transition.PathMotion {
+ ctor public PatternPathMotion();
+ ctor public PatternPathMotion(android.content.Context, android.util.AttributeSet);
+ ctor public PatternPathMotion(android.graphics.Path);
method public android.graphics.Path getPath(float, float, float, float);
- method public android.graphics.Path getPattern();
- method public void setPattern(android.graphics.Path);
+ method public android.graphics.Path getPatternPath();
+ method public void setPatternPath(android.graphics.Path);
}
public final class Scene {
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index c6c0ff6..6daefc8 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -22,14 +22,21 @@
import android.content.pm.PackageInstaller;
import android.content.IntentSender;
+import android.graphics.Bitmap;
+
/** {@hide} */
interface IPackageInstaller {
int createSession(in PackageInstaller.SessionParams params, String installerPackageName, int userId);
+
+ void updateSessionAppIcon(int sessionId, in Bitmap appIcon);
+ void updateSessionAppLabel(int sessionId, String appLabel);
+
void abandonSession(int sessionId);
IPackageInstallerSession openSession(int sessionId);
PackageInstaller.SessionInfo getSessionInfo(int sessionId);
+
List<PackageInstaller.SessionInfo> getAllSessions(int userId);
List<PackageInstaller.SessionInfo> getMySessions(String installerPackageName, int userId);
diff --git a/core/java/android/content/pm/IPackageInstallerCallback.aidl b/core/java/android/content/pm/IPackageInstallerCallback.aidl
index 39ae1a0..fe98ee7 100644
--- a/core/java/android/content/pm/IPackageInstallerCallback.aidl
+++ b/core/java/android/content/pm/IPackageInstallerCallback.aidl
@@ -19,6 +19,7 @@
/** {@hide} */
oneway interface IPackageInstallerCallback {
void onSessionCreated(int sessionId);
+ void onSessionBadgingChanged(int sessionId);
void onSessionOpened(int sessionId);
void onSessionProgressChanged(int sessionId, float progress);
void onSessionClosed(int sessionId);
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 44e24b1..7c34a65 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -312,6 +312,32 @@
}
}
+ /**
+ * Update the icon representing the app being installed in a specific
+ * session. This should be roughly
+ * {@link ActivityManager#getLauncherLargeIconSize()} in both dimensions.
+ */
+ public void updateSessionAppIcon(int sessionId, @Nullable Bitmap appIcon) {
+ try {
+ mInstaller.updateSessionAppIcon(sessionId, appIcon);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
+ /**
+ * Update the label representing the app being installed in a specific
+ * session.
+ */
+ public void updateSessionAppLabel(int sessionId, @Nullable CharSequence appLabel) {
+ try {
+ final String val = (appLabel != null) ? appLabel.toString() : null;
+ mInstaller.updateSessionAppLabel(sessionId, val);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ }
+
public void abandonSession(int sessionId) {
try {
mInstaller.abandonSession(sessionId);
@@ -321,8 +347,7 @@
}
/**
- * Return details for a specific session. To succeed, the caller must either
- * own this session, or be the current home app.
+ * Return details for a specific session.
*/
public @Nullable SessionInfo getSessionInfo(int sessionId) {
try {
@@ -334,7 +359,6 @@
/**
* Return list of all active install sessions, regardless of the installer.
- * To succeed, the caller must be the current home app.
*/
public @NonNull List<SessionInfo> getAllSessions() {
final ApplicationInfo info = mContext.getApplicationInfo();
@@ -406,6 +430,12 @@
public abstract void onCreated(int sessionId);
/**
+ * Badging details for an existing session has changed. For example, the
+ * app icon or label has been updated.
+ */
+ public abstract void onBadgingChanged(int sessionId);
+
+ /**
* Session has been opened. A session is usually opened when the
* installer is actively writing data.
*/
@@ -436,10 +466,11 @@
private static class SessionCallbackDelegate extends IPackageInstallerCallback.Stub implements
Handler.Callback {
private static final int MSG_SESSION_CREATED = 1;
- 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;
+ private static final int MSG_SESSION_BADGING_CHANGED = 2;
+ private static final int MSG_SESSION_OPENED = 3;
+ private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
+ private static final int MSG_SESSION_CLOSED = 5;
+ private static final int MSG_SESSION_FINISHED = 6;
final SessionCallback mCallback;
final Handler mHandler;
@@ -455,6 +486,9 @@
case MSG_SESSION_CREATED:
mCallback.onCreated(msg.arg1);
return true;
+ case MSG_SESSION_BADGING_CHANGED:
+ mCallback.onBadgingChanged(msg.arg1);
+ return true;
case MSG_SESSION_OPENED:
mCallback.onOpened(msg.arg1);
return true;
@@ -477,6 +511,11 @@
}
@Override
+ public void onSessionBadgingChanged(int sessionId) {
+ mHandler.obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, 0).sendToTarget();
+ }
+
+ @Override
public void onSessionOpened(int sessionId) {
mHandler.obtainMessage(MSG_SESSION_OPENED, sessionId, 0).sendToTarget();
}
@@ -499,22 +538,32 @@
}
}
- /**
- * Register to watch for session lifecycle events. To succeed, the caller
- * must be the current home app.
- */
+ /** {@hide} */
+ @Deprecated
public void addSessionCallback(@NonNull SessionCallback callback) {
- addSessionCallback(callback, new Handler());
+ registerSessionCallback(callback);
}
/**
- * Register to watch for session lifecycle events. To succeed, the caller
- * must be the current home app.
+ * Register to watch for session lifecycle events.
+ */
+ public void registerSessionCallback(@NonNull SessionCallback callback) {
+ registerSessionCallback(callback, new Handler());
+ }
+
+ /** {@hide} */
+ @Deprecated
+ public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
+ registerSessionCallback(callback, handler);
+ }
+
+ /**
+ * Register to watch for session lifecycle events.
*
* @param handler to dispatch callback events through, otherwise uses
* calling thread.
*/
- public void addSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
+ public void registerSessionCallback(@NonNull SessionCallback callback, @NonNull Handler handler) {
// TODO: remove this temporary guard once we have new prebuilts
final ApplicationInfo info = mContext.getApplicationInfo();
if ("com.google.android.googlequicksearchbox".equals(info.packageName)
@@ -535,10 +584,16 @@
}
}
+ /** {@hide} */
+ @Deprecated
+ public void removeSessionCallback(@NonNull SessionCallback callback) {
+ unregisterSessionCallback(callback);
+ }
+
/**
* Unregister an existing callback.
*/
- public void removeSessionCallback(@NonNull SessionCallback callback) {
+ public void unregisterSessionCallback(@NonNull SessionCallback callback) {
synchronized (mDelegates) {
for (Iterator<SessionCallbackDelegate> i = mDelegates.iterator(); i.hasNext();) {
final SessionCallbackDelegate delegate = i.next();
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 6a9d565..097b430 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -216,6 +216,128 @@
* <p>Configuring a session with an empty or null list will close the current session, if
* any. This can be used to release the current session's target surfaces for another use.</p>
*
+ * <p>While any of the sizes from {@link StreamConfigurationMap#getOutputSizes} can be used when
+ * a single output stream is configured, a given camera device may not be able to support all
+ * combination of sizes, formats, and targets when multiple outputs are configured at once. The
+ * tables below list the maximum guaranteed resolutions for combinations of streams and targets,
+ * given the capabilities of the camera device.</p>
+ *
+ * <p>If an application tries to create a session using a set of targets that exceed the limits
+ * described in the below tables, one of three possibilities may occur. First, the session may
+ * be successfully created and work normally. Second, the session may be successfully created,
+ * but the camera device won't meet the frame rate guarantees as described in
+ * {@link StreamConfigurationMap#getOutputMinFrameDuration}. Or third, if the output set
+ * cannot be used at all, session creation will fail entirely, with
+ * {@link CameraCaptureSession.StateListener#onConfigureFailed} being invoked.</p>
+ *
+ * <p>For the type column, {@code PRIV} refers to any target whose available sizes are found
+ * using {@link StreamConfigurationMap#getOutputSizes(Class)} with no direct application-visible
+ * format, {@code YUV} refers to a target Surface using the
+ * {@link android.graphics.ImageFormat#YUV_420_888} format, {@code JPEG} refers to the
+ * {@link android.graphics.ImageFormat#JPEG} format, and {@code RAW} refers to the
+ * {@link android.graphics.ImageFormat#RAW_SENSOR} format.</p>
+ *
+ * <p>For the maximum size column, {@code PREVIEW} refers to the best size match to the
+ * device's screen resolution, or to 1080p ({@code 1920x1080}), whichever is
+ * smaller. {@code RECORD} refers to the camera device's maximum supported recording resolution,
+ * as determined by {@link android.media.CamcorderProfile}. And {@code MAXIMUM} refers to the
+ * camera device's maximum output resolution for that format or target from
+ * {@link StreamConfigurationMap#getOutputSizes}.</p>
+ *
+ * <p>To use these tables, determine the number and the formats/targets of outputs needed, and
+ * find the row(s) of the table with those targets. The sizes indicate the maximum set of sizes
+ * that can be used; it is guaranteed that for those targets, the listed sizes and anything
+ * smaller from the list given by {@link StreamConfigurationMap#getOutputSizes} can be
+ * successfully used to create a session. For example, if a row indicates that a 8 megapixel
+ * (MP) YUV_420_888 output can be used together with a 2 MP {@code PRIV} output, then a session
+ * can be created with targets {@code [8 MP YUV, 2 MP PRIV]} or targets {@code [2 MP YUV, 2 MP
+ * PRIV]}; but a session with targets {@code [8 MP YUV, 4 MP PRIV]}, targets {@code [4 MP YUV, 4
+ * MP PRIV]}, or targets {@code [8 MP PRIV, 2 MP YUV]} would not be guaranteed to work, unless
+ * some other row of the table lists such a combination.</p>
+ *
+ * <style scoped>
+ * #rb { border-right-width: thick; }
+ * </style>
+ * <p>Legacy devices ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+ * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY}) support at
+ * least the following stream combinations:
+ *
+ * <table>
+ * <tr><th colspan="7">LEGACY-level guaranteed configurations</th></tr>
+ * <tr> <th colspan="2" id="rb">Target 1</th> <th colspan="2" id="rb">Target 2</th> <th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th> <th>Type</th><th id="rb">Max size</th></tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>Simple preview, GPU video processing, or no-preview video recording.</td> </tr>
+ * <tr> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-viewfinder still image capture.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>In-application video/image processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Standard still imaging.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app processing plus still capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td colspan="2" id="rb"></td> <td>Standard recording.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td colspan="2" id="rb"></td> <td>Preview plus in-app processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Still capture plus in-app processing.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>Limited-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+ * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED}) devices
+ * support at least the following stream combinations in addition to those for
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY LEGACY} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">LIMITED-level additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th></tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution video recording with preview.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>High-resolution in-app video processing with preview.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td colspan="2" id="rb"></td> <td>Two-input in-app video processing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution recording with video snapshot.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code RECORD }</td> <td>{@code JPEG}</td><td id="rb">{@code RECORD }</td> <td>High-resolution in-app processing with video snapshot.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Two-input in-app processing with still capture.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>FULL-capability ({@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL}
+ * {@code == }{@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL}) devices
+ * support at least the following stream combinations in addition to those for
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">FULL-capability additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution GPU processing with preview.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution in-app processing with preview.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Maximum-resolution two-input in-app processsing.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>Video recording with maximum-size video snapshot</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code 640x480}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Standard video recording plus maximum-resolution in-app processing.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code 640x480}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>Preview plus two-input maximum-resolution in-app processing.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>RAW-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES} includes
+ * {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_RAW RAW}) devices additionally support
+ * at least the following stream combinations on both
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_FULL FULL} and
+ * {@link CameraMetadata#INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED LIMITED} devices:
+ *
+ * <table>
+ * <tr><th colspan="7">RAW-capability additional guaranteed configurations</th></tr>
+ * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th colspan="2" id="rb">Target 3</th> <th rowspan="2">Sample use case(s)</th> </tr>
+ * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
+ * <tr> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td colspan="2" id="rb"></td> <td>No-preview DNG capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>Standard DNG capture.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td colspan="2" id="rb"></td> <td>In-app processing plus DNG capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Video recording with DNG capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Preview with in-app processing and DNG capture.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Two-input in-app processing plus DNG capture.</td> </tr>
+ * <tr> <td>{@code PRIV}</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>Still capture with simultaneous JPEG and DNG.</td> </tr>
+ * <tr> <td>{@code YUV }</td><td id="rb">{@code PREVIEW}</td> <td>{@code JPEG}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code RAW }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app processing with simultaneous JPEG and DNG.</td> </tr>
+ * </table><br>
+ * </p>
+ *
+ * <p>Since the capabilities of camera devices vary greatly, a given camera device may support
+ * target combinations with sizes outside of these guarantees, but this can only be tested for
+ * by attempting to create a session with such targets.</p>
+ *
* @param outputs The new set of Surfaces that should be made available as
* targets for captured image data.
* @param listener The listener to notify about the status of the new capture session.
diff --git a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
index c0b7967..5d226e3 100644
--- a/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
+++ b/core/java/android/hardware/camera2/params/StreamConfigurationMap.java
@@ -142,7 +142,7 @@
* or in {@link PixelFormat} (and there is no possibility of collision).</p>
*
* <p>Formats listed in this array are guaranteed to return true if queried with
- * {@link #isOutputSupportedFor(int).</p>
+ * {@link #isOutputSupportedFor(int)}.</p>
*
* @return an array of integer format
*
diff --git a/core/java/android/transition/ArcMotion.java b/core/java/android/transition/ArcMotion.java
index a27063d..f95fb49 100644
--- a/core/java/android/transition/ArcMotion.java
+++ b/core/java/android/transition/ArcMotion.java
@@ -41,9 +41,9 @@
* {@code
* <changeBounds>
* <arcMotion android:minimumHorizontalAngle="15"
- * android:minimumVerticalAngle="0" android:maximumAngle="90"/>
- * </changeBounds>
- * }
+ * android:minimumVerticalAngle="0"
+ * android:maximumAngle="90"/>
+ * </changeBounds>}
* </pre>
*/
public class ArcMotion extends PathMotion {
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
index cb0a875..1b8d57c 100644
--- a/core/java/android/transition/ChangeTransform.java
+++ b/core/java/android/transition/ChangeTransform.java
@@ -99,6 +99,7 @@
* @return <code>true</code> when a changed parent should execute the transition
* inside the scene root's overlay or <code>false</code> if a parent change only
* affects the transform of the transitioning view.
+ * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
*/
public boolean getReparentWithOverlay() {
return mUseOverlay;
@@ -120,6 +121,7 @@
* @return <code>true</code> when a changed parent should execute the transition
* inside the scene root's overlay or <code>false</code> if a parent change only
* affects the transform of the transitioning view.
+ * @attr ref android.R.styleable#ChangeTransform_reparentWithOverlay
*/
public void setReparentWithOverlay(boolean reparentWithOverlay) {
mUseOverlay = reparentWithOverlay;
@@ -132,6 +134,7 @@
* view will be tracked. Default is true.
*
* @return whether parent changes will be tracked by the ChangeTransform.
+ * @attr ref android.R.styleable#ChangeTransform_reparent
*/
public boolean getReparent() {
return mReparent;
@@ -145,6 +148,7 @@
*
* @param reparent Set to true to track parent changes or false to only track changes
* of the transitioning view without considering the parent change.
+ * @attr ref android.R.styleable#ChangeTransform_reparent
*/
public void setReparent(boolean reparent) {
mReparent = reparent;
diff --git a/core/java/android/transition/PatternMotion.java b/core/java/android/transition/PatternPathMotion.java
similarity index 68%
rename from core/java/android/transition/PatternMotion.java
rename to core/java/android/transition/PatternPathMotion.java
index e4045b4..a609df6 100644
--- a/core/java/android/transition/PatternMotion.java
+++ b/core/java/android/transition/PatternPathMotion.java
@@ -34,36 +34,35 @@
* <pre>
* {@code
* <changeBounds>
- * <patternMotion android:pathData="M0 0 L0 100 L100 100"/>
- * </changeBounds>
- * }
+ * <patternPathMotion android:patternPathData="M0 0 L0 100 L100 100"/>
+ * </changeBounds>}
* </pre>
*/
-public class PatternMotion extends PathMotion {
+public class PatternPathMotion extends PathMotion {
- private Path mOriginalPattern;
+ private Path mOriginalPatternPath;
- private final Path mPattern = new Path();
+ private final Path mPatternPath = new Path();
private final Matrix mTempMatrix = new Matrix();
/**
- * Constructs a PatternMotion with a straight-line pattern.
+ * Constructs a PatternPathMotion with a straight-line pattern.
*/
- public PatternMotion() {
- mPattern.lineTo(1, 0);
- mOriginalPattern = mPattern;
+ public PatternPathMotion() {
+ mPatternPath.lineTo(1, 0);
+ mOriginalPatternPath = mPatternPath;
}
- public PatternMotion(Context context, AttributeSet attrs) {
- TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternMotion);
+ public PatternPathMotion(Context context, AttributeSet attrs) {
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PatternPathMotion);
try {
- String pathData = a.getString(R.styleable.PatternMotion_pathData);
+ String pathData = a.getString(R.styleable.PatternPathMotion_patternPathData);
if (pathData == null) {
- throw new RuntimeException("pathData must be supplied for patternMotion");
+ throw new RuntimeException("pathData must be supplied for patternPathMotion");
}
Path pattern = PathParser.createPathFromPathData(pathData);
- setPattern(pattern);
+ setPatternPath(pattern);
} finally {
a.recycle();
}
@@ -71,14 +70,15 @@
}
/**
- * Creates a PatternMotion with the Path defining a pattern of motion between two coordinates.
- * The pattern will be translated, rotated, and scaled to fit between the start and end points.
- * The pattern must not be empty and must have the end point differ from the start point.
+ * Creates a PatternPathMotion with the Path defining a pattern of motion between two
+ * coordinates. The pattern will be translated, rotated, and scaled to fit between the start
+ * and end points. The pattern must not be empty and must have the end point differ from the
+ * start point.
*
- * @param pattern A Path to be used as a pattern for two-dimensional motion.
+ * @param patternPath A Path to be used as a pattern for two-dimensional motion.
*/
- public PatternMotion(Path pattern) {
- setPattern(pattern);
+ public PatternPathMotion(Path patternPath) {
+ setPatternPath(patternPath);
}
/**
@@ -87,10 +87,10 @@
* The pattern must not be empty and must have the end point differ from the start point.
*
* @return the Path defining a pattern of motion between two coordinates.
- * @attr ref android.R.styleable#PatternMotion_pathData
+ * @attr ref android.R.styleable#PatternPathMotion_patternPathData
*/
- public Path getPattern() {
- return mOriginalPattern;
+ public Path getPatternPath() {
+ return mOriginalPatternPath;
}
/**
@@ -98,11 +98,11 @@
* The pattern will be translated, rotated, and scaled to fit between the start and end points.
* The pattern must not be empty and must have the end point differ from the start point.
*
- * @param pattern A Path to be used as a pattern for two-dimensional motion.
- * @attr ref android.R.styleable#PatternMotion_pathData
+ * @param patternPath A Path to be used as a pattern for two-dimensional motion.
+ * @attr ref android.R.styleable#PatternPathMotion_patternPathData
*/
- public void setPattern(Path pattern) {
- PathMeasure pathMeasure = new PathMeasure(pattern, false);
+ public void setPatternPath(Path patternPath) {
+ PathMeasure pathMeasure = new PathMeasure(patternPath, false);
float length = pathMeasure.getLength();
float[] pos = new float[2];
pathMeasure.getPosTan(length, pos, null);
@@ -124,8 +124,8 @@
mTempMatrix.postScale(scale, scale);
double angle = Math.atan2(dy, dx);
mTempMatrix.postRotate((float) Math.toDegrees(-angle));
- pattern.transform(mTempMatrix, mPattern);
- mOriginalPattern = pattern;
+ patternPath.transform(mTempMatrix, mPatternPath);
+ mOriginalPatternPath = patternPath;
}
@Override
@@ -139,7 +139,7 @@
mTempMatrix.postRotate((float) Math.toDegrees(angle));
mTempMatrix.postTranslate(startX, startY);
Path path = new Path();
- mPattern.transform(mTempMatrix, path);
+ mPatternPath.transform(mTempMatrix, path);
return path;
}
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index bd52e71..0d1b568 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -1989,8 +1989,33 @@
* by extending PathMotion and implementing
* {@link android.transition.PathMotion#getPath(float, float, float, float)}.
* </p>
+ * <p>
+ * When describing in XML, use a nested XML tag for the path motion. It can be one of
+ * the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
+ * be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
+ * attributed with the fully-described class name. For example:</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <pathMotion class="my.app.transition.MyPathMotion"/>
+ * </changeBounds>
+ * }
+ * </pre>
+ * <p>or</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <arcMotion android:minimumHorizontalAngle="15"
+ * android:minimumVerticalAngle="0" android:maximumAngle="90"/>
+ * </changeBounds>
+ * }
+ * </pre>
+ *
* @param pathMotion Algorithm object to use for determining how to interpolate in two
* dimensions. If null, a straight-path algorithm will be used.
+ * @see android.transition.ArcMotion
+ * @see PatternPathMotion
+ * @see android.transition.PathMotion
*/
public void setPathMotion(PathMotion pathMotion) {
if (pathMotion == null) {
@@ -2004,7 +2029,31 @@
* Returns the algorithm object used to interpolate along two dimensions. This is typically
* used to determine the View motion between two points.
*
+ * <p>
+ * When describing in XML, use a nested XML tag for the path motion. It can be one of
+ * the built-in tags <code>arcMotion</code> or <code>patternPathMotion</code> or it can
+ * be a custom PathMotion using <code>pathMotion</code> with the <code>class</code>
+ * attributed with the fully-described class name. For example:</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <pathMotion class="my.app.transition.MyPathMotion"/>
+ * </changeBounds>}
+ * </pre>
+ * <p>or</p>
+ * <pre>
+ * {@code
+ * <changeBounds>
+ * <arcMotion android:minimumHorizontalAngle="15"
+ * android:minimumVerticalAngle="0"
+ * android:maximumAngle="90"/>
+ * </changeBounds>}
+ * </pre>
+ *
* @return The algorithm object used to interpolate along two dimensions.
+ * @see android.transition.ArcMotion
+ * @see PatternPathMotion
+ * @see android.transition.PathMotion
*/
public PathMotion getPathMotion() {
return mPathMotion;
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index 760ffe1..9009d6a 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -171,8 +171,8 @@
parent.setPathMotion(new ArcMotion(mContext, attrs));
} else if ("pathMotion".equals(name)) {
parent.setPathMotion((PathMotion)createCustom(attrs, PathMotion.class, "pathMotion"));
- } else if ("patternMotion".equals(name)) {
- parent.setPathMotion(new PatternMotion(mContext, attrs));
+ } else if ("patternPathMotion".equals(name)) {
+ parent.setPathMotion(new PatternPathMotion(mContext, attrs));
} else {
throw new RuntimeException("Unknown scene name: " + parser.getName());
}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ceea9f8..076f1e2 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -800,28 +800,6 @@
}
@Override
- public void drawPicture(Picture picture, Rect dst) {
- save();
- translate(dst.left, dst.top);
- if (picture.getWidth() > 0 && picture.getHeight() > 0) {
- scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
- }
- drawPicture(picture);
- restore();
- }
-
- @Override
- public void drawPicture(Picture picture, RectF dst) {
- save();
- translate(dst.left, dst.top);
- if (picture.getWidth() > 0 && picture.getHeight() > 0) {
- scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
- }
- drawPicture(picture);
- restore();
- }
-
- @Override
public void drawPoint(float x, float y, Paint paint) {
float[] point = getPointStorage();
point[0] = x;
diff --git a/core/jni/android_ddm_DdmHandleNativeHeap.cpp b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
index f5eaf94..9b96320 100644
--- a/core/jni/android_ddm_DdmHandleNativeHeap.cpp
+++ b/core/jni/android_ddm_DdmHandleNativeHeap.cpp
@@ -35,7 +35,15 @@
extern "C" void free_malloc_leak_info(uint8_t* info);
+#define DDMS_HEADER_SIGNATURE 0x812345dd
+#define DDMS_VERSION 2
+
struct Header {
+#if defined(__LP64__)
+ uint32_t signature;
+ uint16_t version;
+ uint16_t pointerSize;
+#endif
size_t mapSize;
size_t allocSize;
size_t allocInfoSize;
@@ -77,6 +85,12 @@
ALOGD("*** mapSize: %d allocSize: %d allocInfoSize: %d totalMemory: %d",
header.mapSize, header.allocSize, header.allocInfoSize, header.totalMemory);
+#if defined(__LP64__)
+ header.signature = DDMS_HEADER_SIGNATURE;
+ header.version = DDMS_VERSION;
+ header.pointerSize = sizeof(void*);
+#endif
+
jbyteArray array = env->NewByteArray(sizeof(Header) + header.mapSize + header.allocSize);
if (array != NULL) {
env->SetByteArrayRegion(array, 0,
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 3629cbb..d1cc1fd 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -5686,12 +5686,12 @@
<attr name="maximumAngle" format="float" />
</declare-styleable>
- <!-- Use <code>patternMotion</code> as the root tag of the XML resource that
- describes a {@link android.transition.PatternMotion}. This must be used
+ <!-- Use <code>patternPathMotion</code> as the root tag of the XML resource that
+ describes a {@link android.transition.PatternPathMotion}. This must be used
within a transition with which the PathMotion should be associated. -->
- <declare-styleable name="PatternMotion">
- <!-- The path string describing the pattern to use for the PathMotion. -->
- <attr name="pathData" />
+ <declare-styleable name="PatternPathMotion">
+ <!-- The path string describing the pattern to use for the PathPathMotion. -->
+ <attr name="patternPathData" format="string" />
</declare-styleable>
<!-- ========================== -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 4bf4531..a4c3474 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2290,6 +2290,7 @@
<public type="attr" name="fragmentReenterTransition" />
<public type="attr" name="fragmentAllowEnterTransitionOverlap" />
<public type="attr" name="fragmentAllowReturnTransitionOverlap" />
+ <public type="attr" name="patternPathData" />
<public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index f18694b..0927ffd 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -203,7 +203,7 @@
*/
public void setBitmap(@Nullable Bitmap bitmap) {
if (isHardwareAccelerated()) {
- throw new RuntimeException("Can't set a bitmap device on a GL canvas");
+ throw new RuntimeException("Can't set a bitmap device on a HW accelerated canvas");
}
if (bitmap == null) {
diff --git a/graphics/java/android/graphics/Picture.java b/graphics/java/android/graphics/Picture.java
index 5aa7c6a..d28c3d5 100644
--- a/graphics/java/android/graphics/Picture.java
+++ b/graphics/java/android/graphics/Picture.java
@@ -122,6 +122,11 @@
* @param canvas The picture is drawn to this canvas
*/
public void draw(Canvas canvas) {
+ if (canvas.isHardwareAccelerated()) {
+ throw new IllegalArgumentException(
+ "Picture playback is only supported on software canvas.");
+ }
+
if (mRecordingCanvas != null) {
endRecording();
}
diff --git a/graphics/java/android/graphics/PorterDuffColorFilter.java b/graphics/java/android/graphics/PorterDuffColorFilter.java
index c078c1c..705f5e6 100644
--- a/graphics/java/android/graphics/PorterDuffColorFilter.java
+++ b/graphics/java/android/graphics/PorterDuffColorFilter.java
@@ -60,6 +60,8 @@
* @see Color
* @see #getColor()
* @see #getMode()
+ *
+ * @hide
*/
public void setColor(int color) {
mColor = color;
@@ -84,6 +86,8 @@
* @see PorterDuff
* @see #getMode()
* @see #getColor()
+ *
+ * @hide
*/
public void setMode(PorterDuff.Mode mode) {
mMode = mode;
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 329033c..1d16793 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -1777,6 +1777,15 @@
return;
}
+ if ( (mode == AudioSystem.MODE_IN_CALL) &&
+ (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.MODIFY_PHONE_STATE)
+ != PackageManager.PERMISSION_GRANTED)) {
+ Log.w(TAG, "MODIFY_PHONE_STATE Permission Denial: setMode(MODE_IN_CALL) from pid="
+ + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
if (mode < AudioSystem.MODE_CURRENT || mode >= AudioSystem.NUM_MODES) {
return;
}
@@ -1798,7 +1807,7 @@
// must be called synchronized on mSetModeDeathHandlers
// setModeInt() returns a valid PID if the audio mode was successfully set to
// any mode other than NORMAL.
- int setModeInt(int mode, IBinder cb, int pid) {
+ private int setModeInt(int mode, IBinder cb, int pid) {
if (DEBUG_MODE) { Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid + ")"); }
int newModeOwnerPid = 0;
if (cb == null) {
@@ -3058,7 +3067,7 @@
}
boolean checkAudioSettingsPermission(String method) {
- if (mContext.checkCallingOrSelfPermission("android.permission.MODIFY_AUDIO_SETTINGS")
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_SETTINGS)
== PackageManager.PERMISSION_GRANTED) {
return true;
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 3f7a607..9a00923 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -47,12 +47,12 @@
import android.content.pm.IPackageInstallerCallback;
import android.content.pm.IPackageInstallerSession;
import android.content.pm.PackageInstaller;
-import android.content.pm.PackageParser;
import android.content.pm.PackageInstaller.SessionInfo;
import android.content.pm.PackageInstaller.SessionParams;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
import android.content.pm.PackageParser.PackageLite;
import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Binder;
@@ -581,6 +581,30 @@
}
@Override
+ public void updateSessionAppIcon(int sessionId, Bitmap appIcon) {
+ synchronized (mSessions) {
+ final PackageInstallerSession session = mSessions.get(sessionId);
+ if (session == null || !isCallingUidOwner(session)) {
+ throw new SecurityException("Caller has no access to session " + sessionId);
+ }
+ session.params.appIcon = appIcon;
+ mInternalCallback.onSessionBadgingChanged(session);
+ }
+ }
+
+ @Override
+ public void updateSessionAppLabel(int sessionId, String appLabel) {
+ synchronized (mSessions) {
+ final PackageInstallerSession session = mSessions.get(sessionId);
+ if (session == null || !isCallingUidOwner(session)) {
+ throw new SecurityException("Caller has no access to session " + sessionId);
+ }
+ session.params.appLabel = appLabel;
+ mInternalCallback.onSessionBadgingChanged(session);
+ }
+ }
+
+ @Override
public void abandonSession(int sessionId) {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
@@ -681,9 +705,6 @@
public SessionInfo getSessionInfo(int sessionId) {
synchronized (mSessions) {
final PackageInstallerSession session = mSessions.get(sessionId);
- if (!isCallingUidOwner(session)) {
- enforceCallerCanReadSessions();
- }
return session != null ? session.generateInfo() : null;
}
}
@@ -691,7 +712,6 @@
@Override
public List<SessionInfo> getAllSessions(int userId) {
mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions");
- enforceCallerCanReadSessions();
final List<SessionInfo> result = new ArrayList<>();
synchronized (mSessions) {
@@ -755,8 +775,6 @@
@Override
public void registerCallback(IPackageInstallerCallback callback, int userId) {
mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback");
- enforceCallerCanReadSessions();
-
mCallbacks.register(callback, userId);
}
@@ -787,21 +805,6 @@
}
}
- /**
- * We allow those with permission, or the current home app.
- */
- private void enforceCallerCanReadSessions() {
- final boolean hasPermission = (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.READ_INSTALL_SESSIONS)
- == PackageManager.PERMISSION_GRANTED);
- final boolean isHomeApp = mPm.checkCallerIsHomeApp();
- if (hasPermission || isHomeApp) {
- return;
- } else {
- throw new SecurityException("Caller must be current home app to read install sessions");
- }
- }
-
static class PackageDeleteObserverAdapter extends PackageDeleteObserver {
private final Context mContext;
private final IntentSender mTarget;
@@ -893,10 +896,11 @@
private static class Callbacks extends Handler {
private static final int MSG_SESSION_CREATED = 1;
- 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;
+ private static final int MSG_SESSION_BADGING_CHANGED = 2;
+ private static final int MSG_SESSION_OPENED = 3;
+ private static final int MSG_SESSION_PROGRESS_CHANGED = 4;
+ private static final int MSG_SESSION_CLOSED = 5;
+ private static final int MSG_SESSION_FINISHED = 6;
private final RemoteCallbackList<IPackageInstallerCallback>
mCallbacks = new RemoteCallbackList<>();
@@ -938,6 +942,9 @@
case MSG_SESSION_CREATED:
callback.onSessionCreated(sessionId);
break;
+ case MSG_SESSION_BADGING_CHANGED:
+ callback.onSessionBadgingChanged(sessionId);
+ break;
case MSG_SESSION_OPENED:
callback.onSessionOpened(sessionId);
break;
@@ -957,6 +964,10 @@
obtainMessage(MSG_SESSION_CREATED, sessionId, userId).sendToTarget();
}
+ private void notifySessionBadgingChanged(int sessionId, int userId) {
+ obtainMessage(MSG_SESSION_BADGING_CHANGED, sessionId, userId).sendToTarget();
+ }
+
private void notifySessionOpened(int sessionId, int userId) {
obtainMessage(MSG_SESSION_OPENED, sessionId, userId).sendToTarget();
}
@@ -1006,14 +1017,19 @@
}
class InternalCallback {
- public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
- mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress);
+ public void onSessionBadgingChanged(PackageInstallerSession session) {
+ mCallbacks.notifySessionBadgingChanged(session.sessionId, session.userId);
+ writeSessionsAsync();
}
public void onSessionOpened(PackageInstallerSession session) {
mCallbacks.notifySessionOpened(session.sessionId, session.userId);
}
+ public void onSessionProgressChanged(PackageInstallerSession session, float progress) {
+ mCallbacks.notifySessionProgressChanged(session.sessionId, session.userId, progress);
+ }
+
public void onSessionClosed(PackageInstallerSession session) {
mCallbacks.notifySessionClosed(session.sessionId, session.userId);
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5264fc4..85ff54e 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -294,7 +294,9 @@
}
private void computeProgressLocked() {
- mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
+ if (mProgress <= 0.8f) {
+ mProgress = MathUtils.constrain(mClientProgress * 0.8f, 0f, 0.8f);
+ }
}
private void maybePublishProgress() {
@@ -485,7 +487,8 @@
}
// TODO: surface more granular state from dexopt
- mCallback.onSessionProgressChanged(this, 0.9f);
+ mProgress = 0.9f;
+ maybePublishProgress();
// Unpack native libraries
extractNativeLibraries(mResolvedStageDir, params.abiOverride);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index a4d4914..d2a627e 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -11746,47 +11746,6 @@
preferred.activityInfo.name);
}
- /**
- * Check if calling UID is the current home app. This handles both the case
- * where the user has selected a specific home app, and where there is only
- * one home app.
- */
- public boolean checkCallerIsHomeApp() {
- final Intent intent = new Intent(Intent.ACTION_MAIN);
- intent.addCategory(Intent.CATEGORY_HOME);
-
- final int callingUid = Binder.getCallingUid();
- final int callingUserId = UserHandle.getCallingUserId();
- final List<ResolveInfo> allHomes = queryIntentActivities(intent, null, 0, callingUserId);
- final ResolveInfo preferredHome = findPreferredActivity(intent, null, 0, allHomes, 0, true,
- false, false, callingUserId);
-
- if (preferredHome != null) {
- if (callingUid == preferredHome.activityInfo.applicationInfo.uid) {
- return true;
- }
- } else {
- for (ResolveInfo info : allHomes) {
- if (callingUid == info.activityInfo.applicationInfo.uid) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Enforce that calling UID is the current home app. This handles both the
- * case where the user has selected a specific home app, and where there is
- * only one home app.
- */
- public void enforceCallerIsHomeApp() {
- if (!checkCallerIsHomeApp()) {
- throw new SecurityException("Caller is not currently selected home app");
- }
- }
-
@Override
public void setApplicationEnabledSetting(String appPackageName,
int newState, int flags, int userId, String callingPackage) {