Merge "AOD: Only play wakeup animation when actually waking up" into oc-mr1-dev
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index b2fd169..3fa8927 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -761,6 +761,7 @@
boolean mStartedActivity;
private boolean mDestroyed;
private boolean mDoReportFullyDrawn = true;
+ private boolean mRestoredFromBundle;
/** true if the activity is going through a transient pause */
/*package*/ boolean mTemporaryPause = false;
/** true if the activity is being destroyed in order to recreate it with a new configuration */
@@ -1012,6 +1013,7 @@
if (mVoiceInteractor != null) {
mVoiceInteractor.attachActivity(this);
}
+ mRestoredFromBundle = savedInstanceState != null;
mCalled = true;
}
@@ -1948,7 +1950,7 @@
if (mDoReportFullyDrawn) {
mDoReportFullyDrawn = false;
try {
- ActivityManager.getService().reportActivityFullyDrawn(mToken);
+ ActivityManager.getService().reportActivityFullyDrawn(mToken, mRestoredFromBundle);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index fa9d7ca..897e42b 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -376,7 +376,7 @@
boolean convertFromTranslucent(in IBinder token);
boolean convertToTranslucent(in IBinder token, in Bundle options);
void notifyActivityDrawn(in IBinder token);
- void reportActivityFullyDrawn(in IBinder token);
+ void reportActivityFullyDrawn(in IBinder token, boolean restoredFromBundle);
void restart();
void performIdleMaintenance();
void takePersistableUriPermission(in Uri uri, int modeFlags, int userId);
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index df2b35b..4e59baa 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -208,7 +208,6 @@
// TODO: Currently assume full FBO damage, due to FrameInfoVisualizer::unionDirty.
// Should should scissor/set mHasDrawn safely.
mRenderState.scissor().setEnabled(false);
- mHasDrawn = true;
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setRoundRectClipState(nullptr)
@@ -217,7 +216,11 @@
.setTransform(Matrix4::identity(), TransformFlags::None)
.setModelViewIdentityEmptyBounds()
.build();
- mRenderState.render(glop, mRenderTarget.orthoMatrix);
+ // Disable blending if this is the first draw to the main framebuffer, in case app has defined
+ // transparency where it doesn't make sense - as first draw in opaque window.
+ bool overrideDisableBlending = !mHasDrawn && mOpaque && !mRenderTarget.frameBufferId;
+ mRenderState.render(glop, mRenderTarget.orthoMatrix, overrideDisableBlending);
+ mHasDrawn = true;
}
// clears and re-fills stencil with provided rendertarget space quads,
@@ -234,7 +237,7 @@
.setTransform(Matrix4::identity(), TransformFlags::None)
.setModelViewIdentityEmptyBounds()
.build();
- mRenderState.render(glop, mRenderTarget.orthoMatrix);
+ mRenderState.render(glop, mRenderTarget.orthoMatrix, false);
mRenderState.stencil().enableTest(incrementThreshold);
}
@@ -346,7 +349,10 @@
void BakedOpRenderer::renderGlopImpl(const Rect* dirtyBounds, const ClipBase* clip,
const Glop& glop) {
prepareRender(dirtyBounds, clip);
- mRenderState.render(glop, mRenderTarget.orthoMatrix);
+ // Disable blending if this is the first draw to the main framebuffer, in case app has defined
+ // transparency where it doesn't make sense - as first draw in opaque window.
+ bool overrideDisableBlending = !mHasDrawn && mOpaque && !mRenderTarget.frameBufferId;
+ mRenderState.render(glop, mRenderTarget.orthoMatrix, overrideDisableBlending);
if (!mRenderTarget.frameBufferId) mHasDrawn = true;
}
diff --git a/libs/hwui/OpenGLReadback.cpp b/libs/hwui/OpenGLReadback.cpp
index 025503b..f9a1cc5 100644
--- a/libs/hwui/OpenGLReadback.cpp
+++ b/libs/hwui/OpenGLReadback.cpp
@@ -228,7 +228,7 @@
.build();
Matrix4 ortho;
ortho.loadOrtho(destWidth, destHeight);
- renderState.render(glop, ortho);
+ renderState.render(glop, ortho, false);
// TODO: We should convert to linear space when the target is RGBA16F
glReadPixels(0, 0, bitmap->width(), bitmap->height(), format,
diff --git a/libs/hwui/renderstate/Blend.cpp b/libs/hwui/renderstate/Blend.cpp
index 8865c6e..b1ca4a2 100644
--- a/libs/hwui/renderstate/Blend.cpp
+++ b/libs/hwui/renderstate/Blend.cpp
@@ -118,7 +118,7 @@
}
void Blend::setFactors(GLenum srcMode, GLenum dstMode) {
- if (srcMode == GL_ZERO && dstMode == GL_ZERO) {
+ if ((srcMode == GL_ZERO || srcMode == GL_ONE) && dstMode == GL_ZERO) {
// disable blending
if (mEnabled) {
glDisable(GL_BLEND);
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index ededffb..5fc5cb2 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -262,7 +262,8 @@
// Render
///////////////////////////////////////////////////////////////////////////////
-void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix) {
+void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix,
+ bool overrideDisableBlending) {
const Glop::Mesh& mesh = glop.mesh;
const Glop::Mesh::Vertices& vertices = mesh.vertices;
const Glop::Mesh::Indices& indices = mesh.indices;
@@ -417,7 +418,11 @@
// ------------------------------------
// ---------- GL state setup ----------
// ------------------------------------
- blend().setFactors(glop.blend.src, glop.blend.dst);
+ if (CC_UNLIKELY(overrideDisableBlending)) {
+ blend().setFactors(GL_ZERO, GL_ZERO);
+ } else {
+ blend().setFactors(glop.blend.src, glop.blend.dst);
+ }
GL_CHECKPOINT(MODERATE);
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index df81e86..315fa2d 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -106,7 +106,7 @@
// more thinking...
void postDecStrong(VirtualLightRefBase* object);
- void render(const Glop& glop, const Matrix4& orthoMatrix);
+ void render(const Glop& glop, const Matrix4& orthoMatrix, bool overrideDisableBlending);
Blend& blend() { return *mBlend; }
MeshState& meshState() { return *mMeshState; }
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 8d7afc2..0c787db 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -62,6 +62,14 @@
// The action failed
TYPE_FAILURE = 11;
+
+ // Type for APP_TRANSITION_REPORTED_DRAWN event: The activity was started without restoring from
+ // a bundle.
+ TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE = 12;
+
+ // Type for APP_TRANSITION_REPORTED_DRAWN event: The activity was started with restoring from
+ // a bundle.
+ TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE = 13;
}
// Types of alerts, as bit field values
@@ -4265,6 +4273,14 @@
// FIELD: The numeric preference value (of type int) when it is changed in Settings
FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE = 1089;
+ // ACTION: Logged when the app has notified that it has fully drawn. See
+ // Activity.reportFullyDrawn().
+ APP_TRANSITION_REPORTED_DRAWN = 1090;
+
+ // FIELD: The delay of the activity reporting to be fully drawn measured from the beginning of
+ // the app transition.
+ APP_TRANSITION_REPORTED_DRAWN_MS = 1091;
+
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index bfa10f2..d1cf025 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -2964,7 +2964,7 @@
private InFlight removeLocked(PendingIntent pi, Intent intent) {
for (int i = 0; i < mInFlight.size(); i++) {
- if (mInFlight.get(i).mPendingIntent.equals(pi)) {
+ if (mInFlight.get(i).mPendingIntent == pi) {
return mInFlight.remove(i);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 30e5a2c..45387bd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4902,13 +4902,13 @@
}
@Override
- public void reportActivityFullyDrawn(IBinder token) {
+ public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) {
synchronized (this) {
ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r == null) {
return;
}
- r.reportFullyDrawnLocked();
+ r.reportFullyDrawnLocked(restoredFromBundle);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
index 98815d7..f396e9e 100644
--- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java
+++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java
@@ -15,12 +15,17 @@
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_PROCESS_RUNNING;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE;
+import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -67,12 +72,14 @@
private final MetricsLogger mMetricsLogger = new MetricsLogger();
private long mCurrentTransitionStartTime = INVALID_START_TIME;
+ private long mLastTransitionStartTime = INVALID_START_TIME;
private int mCurrentTransitionDeviceUptime;
private int mCurrentTransitionDelayMs;
private boolean mLoggedTransitionStarting;
private final SparseArray<StackTransitionInfo> mStackTransitionInfo = new SparseArray<>();
+ private final SparseArray<StackTransitionInfo> mLastStackTransitionInfo = new SparseArray<>();
private final class StackTransitionInfo {
private ActivityRecord launchedActivity;
@@ -136,6 +143,7 @@
void notifyActivityLaunching() {
if (!isAnyTransitionActive()) {
mCurrentTransitionStartTime = SystemClock.uptimeMillis();
+ mLastTransitionStartTime = mCurrentTransitionStartTime;
}
}
@@ -223,7 +231,8 @@
newInfo.launchedActivity = launchedActivity;
newInfo.currentTransitionProcessRunning = processRunning;
newInfo.startResult = resultCode;
- mStackTransitionInfo.append(stackId, newInfo);
+ mStackTransitionInfo.put(stackId, newInfo);
+ mLastStackTransitionInfo.put(stackId, newInfo);
mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000);
}
@@ -361,7 +370,7 @@
builder.setType(type);
builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name);
final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp();
- if (isInstantApp && info.launchedActivity.launchedFromPackage != null) {
+ if (info.launchedActivity.launchedFromPackage != null) {
builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME,
info.launchedActivity.launchedFromPackage);
}
@@ -388,6 +397,24 @@
}
}
+ void logAppTransitionReportedDrawn(ActivityRecord r, boolean restoredFromBundle) {
+ final StackTransitionInfo info = mLastStackTransitionInfo.get(r.getStackId());
+ if (info == null) {
+ return;
+ }
+ final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN);
+ builder.setPackageName(r.packageName);
+ builder.addTaggedData(FIELD_CLASS_NAME, r.info.name);
+ builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS,
+ SystemClock.uptimeMillis() - mLastTransitionStartTime);
+ builder.setType(restoredFromBundle
+ ? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE
+ : TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE);
+ builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING,
+ info.currentTransitionProcessRunning ? 1 : 0);
+ mMetricsLogger.write(builder);
+ }
+
private int getTransitionType(StackTransitionInfo info) {
if (info.currentTransitionProcessRunning) {
if (info.startResult == START_SUCCESS) {
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index 995ac37..44727c3 100644
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -1836,7 +1836,7 @@
}
}
- public void reportFullyDrawnLocked() {
+ public void reportFullyDrawnLocked(boolean restoredFromBundle) {
final long curTime = SystemClock.uptimeMillis();
if (displayStartTime != 0) {
reportLaunchTimeLocked(curTime);
@@ -1869,6 +1869,8 @@
}
stack.mFullyDrawnStartTime = 0;
}
+ mStackSupervisor.mActivityMetricsLogger.logAppTransitionReportedDrawn(this,
+ restoredFromBundle);
fullyDrawnStartTime = 0;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4ff4885..529fcc4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -85,6 +85,8 @@
import static android.content.pm.PackageParser.PARSE_IS_PRIVILEGED;
import static android.content.pm.PackageParser.isApkFile;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
+import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.system.OsConstants.O_CREAT;
import static android.system.OsConstants.O_RDWR;
@@ -19757,6 +19759,10 @@
// writer
synchronized (mPackages) {
+ // NOTE: The system package always needs to be enabled; even if it's for
+ // a compressed stub. If we don't, installing the system package fails
+ // during scan [scanning checks the disabled packages]. We will reverse
+ // this later, after we've "installed" the stub.
// Reinstate the old system package
enableSystemPackageLPw(disabledPs.pkg);
// Remove any native libraries from the upgraded package.
@@ -19765,23 +19771,38 @@
// Install the system package
if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
- int parseFlags = mDefParseFlags
- | PackageParser.PARSE_MUST_BE_APK
- | PackageParser.PARSE_IS_SYSTEM
- | PackageParser.PARSE_IS_SYSTEM_DIR;
- if (locationIsPrivileged(disabledPs.codePath)) {
- parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
- }
-
- final PackageParser.Package newPkg;
try {
- newPkg = scanPackageTracedLI(disabledPs.codePath, parseFlags, 0 /* scanFlags */,
- 0 /* currentTime */, null);
+ installPackageFromSystemLIF(disabledPs.codePath, false /*isPrivileged*/, allUserHandles,
+ outInfo.origUsers, deletedPs.getPermissionsState(), writeSettings);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": "
+ e.getMessage());
return false;
+ } finally {
+ if (disabledPs.pkg.isStub) {
+ mSettings.disableSystemPackageLPw(disabledPs.name, true /*replaced*/);
+ }
}
+ return true;
+ }
+
+ /**
+ * Installs a package that's already on the system partition.
+ */
+ private PackageParser.Package installPackageFromSystemLIF(@NonNull File codePath,
+ boolean isPrivileged, @Nullable int[] allUserHandles, @Nullable int[] origUserHandles,
+ @Nullable PermissionsState origPermissionState, boolean writeSettings)
+ throws PackageManagerException {
+ int parseFlags = mDefParseFlags
+ | PackageParser.PARSE_MUST_BE_APK
+ | PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR;
+ if (isPrivileged || locationIsPrivileged(codePath)) {
+ parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
+ }
+
+ final PackageParser.Package newPkg =
+ scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/, 0 /*currentTime*/, null);
try {
// update shared libraries for the newly re-installed system package
@@ -19799,17 +19820,21 @@
// Propagate the permissions state as we do not want to drop on the floor
// runtime permissions. The update permissions method below will take
// care of removing obsolete permissions and grant install permissions.
- ps.getPermissionsState().copyFrom(deletedPs.getPermissionsState());
+ if (origPermissionState != null) {
+ ps.getPermissionsState().copyFrom(origPermissionState);
+ }
updatePermissionsLPw(newPkg.packageName, newPkg,
UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
+ final boolean applyUserRestrictions
+ = (allUserHandles != null) && (origUserHandles != null);
if (applyUserRestrictions) {
boolean installedStateChanged = false;
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across reinstall");
}
for (int userId : allUserHandles) {
- final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId);
+ final boolean installed = ArrayUtils.contains(origUserHandles, userId);
if (DEBUG_REMOVE) {
Slog.d(TAG, " user " + userId + " => " + installed);
}
@@ -19832,7 +19857,7 @@
mSettings.writeLPr();
}
}
- return true;
+ return newPkg;
}
private boolean deleteInstalledPackageLIF(PackageSetting ps,
@@ -21765,77 +21790,183 @@
}
}
- synchronized (mPackages) {
- if (callingUid == Process.SHELL_UID
- && (pkgSetting.pkgFlags & ApplicationInfo.FLAG_TEST_ONLY) == 0) {
- // Shell can only change whole packages between ENABLED and DISABLED_USER states
- // unless it is a test package.
- int oldState = pkgSetting.getEnabled(userId);
- if (className == null
- &&
- (oldState == COMPONENT_ENABLED_STATE_DISABLED_USER
- || oldState == COMPONENT_ENABLED_STATE_DEFAULT
- || oldState == COMPONENT_ENABLED_STATE_ENABLED)
- &&
- (newState == COMPONENT_ENABLED_STATE_DISABLED_USER
- || newState == COMPONENT_ENABLED_STATE_DEFAULT
- || newState == COMPONENT_ENABLED_STATE_ENABLED)) {
- // ok
- } else {
- throw new SecurityException(
- "Shell cannot change component state for " + packageName + "/"
- + className + " to " + newState);
- }
- }
- if (className == null) {
- // We're dealing with an application/package level state change
- if (pkgSetting.getEnabled(userId) == newState) {
- // Nothing to do
- return;
- }
- if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
- || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
- // Don't care about who enables an app.
- callingPackage = null;
- }
- pkgSetting.setEnabled(newState, userId, callingPackage);
- // pkgSetting.pkg.mSetEnabled = newState;
+ if (callingUid == Process.SHELL_UID
+ && (pkgSetting.pkgFlags & ApplicationInfo.FLAG_TEST_ONLY) == 0) {
+ // Shell can only change whole packages between ENABLED and DISABLED_USER states
+ // unless it is a test package.
+ int oldState = pkgSetting.getEnabled(userId);
+ if (className == null
+ &&
+ (oldState == COMPONENT_ENABLED_STATE_DISABLED_USER
+ || oldState == COMPONENT_ENABLED_STATE_DEFAULT
+ || oldState == COMPONENT_ENABLED_STATE_ENABLED)
+ &&
+ (newState == COMPONENT_ENABLED_STATE_DISABLED_USER
+ || newState == COMPONENT_ENABLED_STATE_DEFAULT
+ || newState == COMPONENT_ENABLED_STATE_ENABLED)) {
+ // ok
} else {
- // We're dealing with a component level state change
- // First, verify that this is a valid class name.
- PackageParser.Package pkg = pkgSetting.pkg;
- if (pkg == null || !pkg.hasComponentClassName(className)) {
- if (pkg != null &&
- pkg.applicationInfo.targetSdkVersion >=
- Build.VERSION_CODES.JELLY_BEAN) {
- throw new IllegalArgumentException("Component class " + className
- + " does not exist in " + packageName);
- } else {
- Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
- + className + " does not exist in " + packageName);
- }
- }
- switch (newState) {
- case COMPONENT_ENABLED_STATE_ENABLED:
- if (!pkgSetting.enableComponentLPw(className, userId)) {
- return;
- }
- break;
- case COMPONENT_ENABLED_STATE_DISABLED:
- if (!pkgSetting.disableComponentLPw(className, userId)) {
- return;
- }
- break;
- case COMPONENT_ENABLED_STATE_DEFAULT:
- if (!pkgSetting.restoreComponentLPw(className, userId)) {
- return;
- }
- break;
- default:
- Slog.e(TAG, "Invalid new component state: " + newState);
+ throw new SecurityException(
+ "Shell cannot change component state for " + packageName + "/"
+ + className + " to " + newState);
+ }
+ }
+ if (className == null) {
+ // We're dealing with an application/package level state change
+ if (pkgSetting.getEnabled(userId) == newState) {
+ // Nothing to do
+ return;
+ }
+ // If we're enabling a system stub, there's a little more work to do.
+ // Prior to enabling the package, we need to decompress the APK(s) to the
+ // data partition and then replace the version on the system partition.
+ final PackageParser.Package deletedPkg = pkgSetting.pkg;
+ final boolean isSystemStub = deletedPkg.isStub
+ && deletedPkg.isSystemApp();
+ if (isSystemStub
+ && (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
+ final File codePath = decompressPackage(deletedPkg);
+ if (codePath == null) {
+ Slog.e(TAG, "couldn't decompress pkg: " + pkgSetting.name);
return;
}
+ // TODO remove direct parsing of the package object during internal cleanup
+ // of scan package
+ // We need to call parse directly here for no other reason than we need
+ // the new package in order to disable the old one [we use the information
+ // for some internal optimization to optionally create a new package setting
+ // object on replace]. However, we can't get the package from the scan
+ // because the scan modifies live structures and we need to remove the
+ // old [system] package from the system before a scan can be attempted.
+ // Once scan is indempotent we can remove this parse and use the package
+ // object we scanned, prior to adding it to package settings.
+ final PackageParser pp = new PackageParser();
+ pp.setSeparateProcesses(mSeparateProcesses);
+ pp.setDisplayMetrics(mMetrics);
+ pp.setCallback(mPackageParserCallback);
+ final PackageParser.Package tmpPkg;
+ try {
+ final int parseFlags = mDefParseFlags
+ | PackageParser.PARSE_MUST_BE_APK
+ | PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR;
+ tmpPkg = pp.parsePackage(codePath, parseFlags);
+ } catch (PackageParserException e) {
+ Slog.w(TAG, "Failed to parse compressed system package:" + pkgSetting.name, e);
+ return;
+ }
+ synchronized (mInstallLock) {
+ // Disable the stub and remove any package entries
+ removePackageLI(deletedPkg, true);
+ synchronized (mPackages) {
+ disableSystemPackageLPw(deletedPkg, tmpPkg);
+ }
+ final PackageParser.Package newPkg;
+ try (PackageFreezer freezer =
+ freezePackage(deletedPkg.packageName, "setEnabledSetting")) {
+ final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
+ | PackageParser.PARSE_ENFORCE_CODE;
+ newPkg = scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/,
+ 0 /*currentTime*/, null /*user*/);
+ prepareAppDataAfterInstallLIF(newPkg);
+ synchronized (mPackages) {
+ try {
+ updateSharedLibrariesLPr(newPkg, null);
+ } catch (PackageManagerException e) {
+ Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e);
+ }
+ updatePermissionsLPw(newPkg.packageName, newPkg,
+ UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
+ mSettings.writeLPr();
+ }
+ } catch (PackageManagerException e) {
+ // Whoops! Something went wrong; try to roll back to the stub
+ Slog.w(TAG, "Failed to install compressed system package:"
+ + pkgSetting.name, e);
+ // Remove the failed install
+ removeCodePathLI(codePath);
+
+ // Install the system package
+ try (PackageFreezer freezer =
+ freezePackage(deletedPkg.packageName, "setEnabledSetting")) {
+ synchronized (mPackages) {
+ // NOTE: The system package always needs to be enabled; even
+ // if it's for a compressed stub. If we don't, installing the
+ // system package fails during scan [scanning checks the disabled
+ // packages]. We will reverse this later, after we've "installed"
+ // the stub.
+ // This leaves us in a fragile state; the stub should never be
+ // enabled, so, cross your fingers and hope nothing goes wrong
+ // until we can disable the package later.
+ enableSystemPackageLPw(deletedPkg);
+ }
+ installPackageFromSystemLIF(new File(deletedPkg.codePath),
+ false /*isPrivileged*/, null /*allUserHandles*/,
+ null /*origUserHandles*/, null /*origPermissionsState*/,
+ true /*writeSettings*/);
+ } catch (PackageManagerException pme) {
+ Slog.w(TAG, "Failed to restore system package:"
+ + deletedPkg.packageName, pme);
+ } finally {
+ synchronized (mPackages) {
+ mSettings.disableSystemPackageLPw(
+ deletedPkg.packageName, true /*replaced*/);
+ mSettings.writeLPr();
+ }
+ }
+ return;
+ }
+ clearAppDataLIF(newPkg, UserHandle.USER_ALL, FLAG_STORAGE_DE
+ | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+ clearAppProfilesLIF(newPkg, UserHandle.USER_ALL);
+ mDexManager.notifyPackageUpdated(newPkg.packageName,
+ newPkg.baseCodePath, newPkg.splitCodePaths);
+ }
}
+ if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+ // Don't care about who enables an app.
+ callingPackage = null;
+ }
+ pkgSetting.setEnabled(newState, userId, callingPackage);
+ } else {
+ // We're dealing with a component level state change
+ // First, verify that this is a valid class name.
+ PackageParser.Package pkg = pkgSetting.pkg;
+ if (pkg == null || !pkg.hasComponentClassName(className)) {
+ if (pkg != null &&
+ pkg.applicationInfo.targetSdkVersion >=
+ Build.VERSION_CODES.JELLY_BEAN) {
+ throw new IllegalArgumentException("Component class " + className
+ + " does not exist in " + packageName);
+ } else {
+ Slog.w(TAG, "Failed setComponentEnabledSetting: component class "
+ + className + " does not exist in " + packageName);
+ }
+ }
+ switch (newState) {
+ case COMPONENT_ENABLED_STATE_ENABLED:
+ if (!pkgSetting.enableComponentLPw(className, userId)) {
+ return;
+ }
+ break;
+ case COMPONENT_ENABLED_STATE_DISABLED:
+ if (!pkgSetting.disableComponentLPw(className, userId)) {
+ return;
+ }
+ break;
+ case COMPONENT_ENABLED_STATE_DEFAULT:
+ if (!pkgSetting.restoreComponentLPw(className, userId)) {
+ return;
+ }
+ break;
+ default:
+ Slog.e(TAG, "Invalid new component state: " + newState);
+ return;
+ }
+ }
+ synchronized (mPackages) {
scheduleWritePackageRestrictionsLocked(userId);
updateSequenceNumberLP(pkgSetting, new int[] { userId });
final long callingId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 46049f59..f4ac961 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -63,6 +63,7 @@
import android.view.IApplicationToken;
import android.view.SurfaceControl;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.view.WindowManagerPolicy.StartingSurface;
import com.android.internal.util.ToBooleanFunction;
@@ -471,6 +472,20 @@
return delayed;
}
+ /**
+ * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns
+ * true.
+ */
+ WindowState getTopFullscreenWindow() {
+ for (int i = mChildren.size() - 1; i >= 0; i--) {
+ final WindowState win = mChildren.get(i);
+ if (win != null && win.mAttrs.isFullscreen()) {
+ return win;
+ }
+ }
+ return null;
+ }
+
WindowState findMainWindow() {
WindowState candidate = null;
int j = mChildren.size();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 4e4d42d..bc7f330 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -211,7 +211,7 @@
}
final GraphicBuffer buffer = top.mDisplayContent.screenshotApplicationsToBuffer(top.token,
-1, -1, false, 1.0f, false, true);
- if (buffer == null) {
+ if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) {
return null;
}
return new TaskSnapshot(buffer, top.getConfiguration().orientation,
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 1bece69..0610b94 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -162,7 +162,7 @@
+ task);
return null;
}
- final WindowState topFullscreenWindow = topFullscreenToken.findMainWindow();
+ final WindowState topFullscreenWindow = topFullscreenToken.getTopFullscreenWindow();
if (mainWindow == null || topFullscreenWindow == null) {
Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
+ token);
diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
index b09601e..9ad7add 100644
--- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -97,6 +97,24 @@
}
@Test
+ public void testGetTopFullscreenWindow() throws Exception {
+ final WindowTestUtils.TestAppWindowToken token =
+ new WindowTestUtils.TestAppWindowToken(mDisplayContent);
+
+ assertNull(token.getTopFullscreenWindow());
+
+ final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token, "window1");
+ final WindowState window11 = createWindow(null, TYPE_APPLICATION, token, "window11");
+ final WindowState window12 = createWindow(null, TYPE_APPLICATION, token, "window12");
+ assertEquals(window12, token.getTopFullscreenWindow());
+ window12.mAttrs.width = 500;
+ assertEquals(window11, token.getTopFullscreenWindow());
+ window11.mAttrs.width = 500;
+ assertEquals(window1, token.getTopFullscreenWindow());
+ token.removeImmediately();
+ }
+
+ @Test
public void testLandscapeSeascapeRotationByApp() throws Exception {
// Some plumbing to get the service ready for rotation updates.
sWm.mDisplayReady = true;