summaryrefslogtreecommitdiffstats
path: root/services/java/com/android/server
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server')
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java103
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java4
-rw-r--r--services/java/com/android/server/am/ActivityStack.java11
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java1
-rw-r--r--services/java/com/android/server/wm/InputMonitor.java11
-rw-r--r--services/java/com/android/server/wm/InputWindow.java4
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java65
-rw-r--r--services/java/com/android/server/wm/WindowState.java129
8 files changed, 268 insertions, 60 deletions
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 01ae522..07d050af 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -74,6 +74,7 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Proxy;
@@ -146,7 +147,7 @@ public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
static final String TAG = "ActivityManager";
static final boolean DEBUG = false;
- static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
+ static final boolean localLOGV = DEBUG;
static final boolean DEBUG_SWITCH = localLOGV || false;
static final boolean DEBUG_TASKS = localLOGV || false;
static final boolean DEBUG_PAUSE = localLOGV || false;
@@ -546,6 +547,12 @@ public final class ActivityManagerService extends ActivityManagerNative
ProcessRecord mHomeProcess;
/**
+ * Packages that the user has asked to have run in screen size
+ * compatibility mode instead of filling the screen.
+ */
+ final HashSet<String> mScreenCompatPackages = new HashSet<String>();
+
+ /**
* Set of PendingResultRecord objects that are currently active.
*/
final HashSet mPendingResultRecords = new HashSet();
@@ -2091,6 +2098,74 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
+ return new CompatibilityInfo(ai, mConfiguration.screenLayout,
+ mScreenCompatPackages.contains(ai.packageName));
+ }
+
+ public void setPackageScreenCompatMode(String packageName, boolean compatEnabled) {
+ synchronized (this) {
+ ApplicationInfo ai = null;
+ try {
+ ai = AppGlobals.getPackageManager().
+ getApplicationInfo(packageName, STOCK_PM_FLAGS);
+ } catch (RemoteException e) {
+ }
+ if (ai == null) {
+ Slog.w(TAG, "setPackageScreenCompatMode failed: unknown package " + packageName);
+ return;
+ }
+ boolean changed = false;
+ if (compatEnabled) {
+ if (!mScreenCompatPackages.contains(packageName)) {
+ changed = true;
+ mScreenCompatPackages.add(packageName);
+ }
+ } else {
+ if (mScreenCompatPackages.contains(packageName)) {
+ changed = true;
+ mScreenCompatPackages.remove(packageName);
+ }
+ }
+ if (changed) {
+ CompatibilityInfo ci = compatibilityInfoForPackageLocked(ai);
+
+ // Tell all processes that loaded this package about the change.
+ for (int i=mLruProcesses.size()-1; i>=0; i--) {
+ ProcessRecord app = mLruProcesses.get(i);
+ if (!app.pkgList.contains(packageName)) {
+ continue;
+ }
+ try {
+ if (app.thread != null) {
+ if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending to proc "
+ + app.processName + " new compat " + ci);
+ app.thread.updatePackageCompatibilityInfo(packageName, ci);
+ }
+ } catch (Exception e) {
+ }
+ }
+
+ // All activities that came from the packge must be
+ // restarted as if there was a config change.
+ for (int i=mMainStack.mHistory.size()-1; i>=0; i--) {
+ ActivityRecord a = (ActivityRecord)mMainStack.mHistory.get(i);
+ if (a.info.packageName.equals(packageName)) {
+ a.forceNewConfig = true;
+ }
+ }
+
+ ActivityRecord starting = mMainStack.topRunningActivityLocked(null);
+ if (starting != null) {
+ mMainStack.ensureActivityConfigurationLocked(starting, 0);
+ // And we need to make sure at this point that all other activities
+ // are made visible with the correct configuration.
+ mMainStack.ensureActivitiesVisibleLocked(starting, 0);
+ }
+ }
+ }
+ }
+
void reportResumedActivityLocked(ActivityRecord r) {
//Slog.i(TAG, "**** REPORT RESUME: " + r);
@@ -3589,12 +3664,14 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (DEBUG_CONFIGURATION) Slog.v(TAG, "Binding proc "
+ processName + " with config " + mConfiguration);
- thread.bindApplication(processName, app.instrumentationInfo != null
- ? app.instrumentationInfo : app.info, providers,
+ ApplicationInfo appInfo = app.instrumentationInfo != null
+ ? app.instrumentationInfo : app.info;
+ thread.bindApplication(processName, appInfo, providers,
app.instrumentationClass, app.instrumentationProfileFile,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
isRestrictedBackupMode || !normalMode,
- mConfiguration, getCommonServicesLocked(),
+ mConfiguration, compatibilityInfoForPackageLocked(appInfo),
+ getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, true);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
@@ -3685,7 +3762,9 @@ public final class ActivityManagerService extends ActivityManagerNative
if (DEBUG_BACKUP) Slog.v(TAG, "New app is backup target, launching agent for " + app);
ensurePackageDexOpt(mBackupTarget.appInfo.packageName);
try {
- thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, mBackupTarget.backupMode);
+ thread.scheduleCreateBackupAgent(mBackupTarget.appInfo,
+ compatibilityInfoForPackageLocked(mBackupTarget.appInfo),
+ mBackupTarget.backupMode);
} catch (Exception e) {
Slog.w(TAG, "Exception scheduling backup agent creation: ");
e.printStackTrace();
@@ -7784,6 +7863,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
pw.println(" mConfiguration: " + mConfiguration);
pw.println(" mConfigWillChange: " + mMainStack.mConfigWillChange);
+ if (mScreenCompatPackages.size() > 0) {
+ pw.print(" mScreenCompatPackages=");
+ pw.println(mScreenCompatPackages);
+ }
pw.println(" mSleeping=" + mSleeping + " mShuttingDown=" + mShuttingDown);
if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
|| mOrigWaitForDebugger) {
@@ -9246,7 +9329,8 @@ public final class ActivityManagerService extends ActivityManagerNative
r.stats.startLaunchedLocked();
}
ensurePackageDexOpt(r.serviceInfo.packageName);
- app.thread.scheduleCreateService(r, r.serviceInfo);
+ app.thread.scheduleCreateService(r, r.serviceInfo,
+ compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo));
r.postNotification();
created = true;
} finally {
@@ -10350,7 +10434,8 @@ public final class ActivityManagerService extends ActivityManagerNative
if (proc.thread != null) {
if (DEBUG_BACKUP) Slog.v(TAG, "Agent proc already running: " + proc);
try {
- proc.thread.scheduleCreateBackupAgent(app, backupMode);
+ proc.thread.scheduleCreateBackupAgent(app,
+ compatibilityInfoForPackageLocked(app), backupMode);
} catch (RemoteException e) {
// Will time out on the backup manager side
}
@@ -10422,7 +10507,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// If the app crashed during backup, 'thread' will be null here
if (proc.thread != null) {
try {
- proc.thread.scheduleDestroyBackupAgent(appInfo);
+ proc.thread.scheduleDestroyBackupAgent(appInfo,
+ compatibilityInfoForPackageLocked(appInfo));
} catch (Exception e) {
Slog.e(TAG, "Exception when unbinding backup agent:");
e.printStackTrace();
@@ -11269,6 +11355,7 @@ public final class ActivityManagerService extends ActivityManagerNative
+ ": " + r);
ensurePackageDexOpt(r.intent.getComponent().getPackageName());
app.thread.scheduleReceiver(new Intent(r.intent), r.curReceiver,
+ compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo),
r.resultCode, r.resultData, r.resultExtras, r.ordered);
if (DEBUG_BROADCAST) Slog.v(TAG,
"Process cur broadcast " + r + " DELIVERED for app " + app);
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index 0fb30ff..cb0a0f0 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -111,6 +111,7 @@ class ActivityRecord extends IApplicationToken.Stub {
boolean hasBeenLaunched;// has this activity ever been launched?
boolean frozenBeforeDestroy;// has been frozen but not yet destroyed.
boolean immersive; // immersive mode (don't interrupt if possible)
+ boolean forceNewConfig; // force re-create with new config next time
String stringName; // for caching of toString().
@@ -174,7 +175,8 @@ class ActivityRecord extends IApplicationToken.Stub {
pw.print(" immersive="); pw.print(immersive);
pw.print(" launchMode="); pw.println(launchMode);
pw.print(prefix); pw.print("frozenBeforeDestroy="); pw.print(frozenBeforeDestroy);
- pw.print(" thumbnailNeeded="); pw.println(thumbnailNeeded);
+ pw.print(" thumbnailNeeded="); pw.print(thumbnailNeeded);
+ pw.print(" forceNewConfig="); pw.println(forceNewConfig);
if (launchTime != 0 || startTime != 0) {
pw.print(prefix); pw.print("launchTime=");
TimeUtils.formatDuration(launchTime, pw); pw.print(" startTime=");
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index c087aec..f385042 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -537,9 +537,11 @@ public class ActivityStack {
}
mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
r.sleeping = false;
+ r.forceNewConfig = false;
app.thread.scheduleLaunchActivity(new Intent(r.intent), r,
System.identityHashCode(r),
- r.info, r.icicle, results, newIntents, !andResume,
+ r.info, mService.compatibilityInfoForPackageLocked(r.info.applicationInfo),
+ r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward());
if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
@@ -3750,7 +3752,7 @@ public class ActivityStack {
// Short circuit: if the two configurations are the exact same
// object (the common case), then there is nothing to do.
Configuration newConfig = mService.mConfiguration;
- if (r.configuration == newConfig) {
+ if (r.configuration == newConfig && !r.forceNewConfig) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Configuration unchanged in " + r);
return true;
@@ -3775,6 +3777,7 @@ public class ActivityStack {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Configuration doesn't matter not running " + r);
r.stopFreezingScreenLocked(false);
+ r.forceNewConfig = false;
return true;
}
@@ -3786,10 +3789,11 @@ public class ActivityStack {
+ Integer.toHexString(r.info.configChanges)
+ ", newConfig=" + newConfig);
}
- if ((changes&(~r.info.configChanges)) != 0) {
+ if ((changes&(~r.info.configChanges)) != 0 || r.forceNewConfig) {
// Aha, the activity isn't handling the change, so DIE DIE DIE.
r.configChangeFlags |= changes;
r.startFreezingScreenLocked(r.app, globalChanges);
+ r.forceNewConfig = false;
if (r.app == null || r.app.thread == null) {
if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
"Switch is destroying non-running " + r);
@@ -3860,6 +3864,7 @@ public class ActivityStack {
try {
if (DEBUG_SWITCH) Slog.i(TAG, "Switch is restarting resumed " + r);
+ r.forceNewConfig = false;
r.app.thread.scheduleRelaunchActivity(r, results, newIntents,
changes, !andResume, mService.mConfiguration);
// Note: don't need to call pauseIfSleepingLocked() here, because
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index 353ff6d..a63ffae 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -24,6 +24,7 @@ import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
import android.content.ComponentName;
import android.content.pm.ApplicationInfo;
+import android.content.res.CompatibilityInfo;
import android.os.Bundle;
import android.os.IBinder;
import android.os.SystemClock;
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 45a78af..57f0799 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -205,12 +205,21 @@ final class InputMonitor {
inputWindow.ownerPid = child.mSession.mPid;
inputWindow.ownerUid = child.mSession.mUid;
- final Rect frame = child.mFrame;
+ final Rect frame = child.mScaledFrame;
inputWindow.frameLeft = frame.left;
inputWindow.frameTop = frame.top;
inputWindow.frameRight = frame.right;
inputWindow.frameBottom = frame.bottom;
+ if (child.mGlobalScale != 1) {
+ // If we are scaling the window, input coordinates need
+ // to be inversely scaled to map from what is on screen
+ // to what is actually being touched in the UI.
+ inputWindow.scaleFactor = 1.0f/child.mGlobalScale;
+ } else {
+ inputWindow.scaleFactor = 1;
+ }
+
child.getTouchableRegion(inputWindow.touchableRegion);
}
diff --git a/services/java/com/android/server/wm/InputWindow.java b/services/java/com/android/server/wm/InputWindow.java
index e3eb473..578120e 100644
--- a/services/java/com/android/server/wm/InputWindow.java
+++ b/services/java/com/android/server/wm/InputWindow.java
@@ -46,6 +46,10 @@ public final class InputWindow {
public int frameRight;
public int frameBottom;
+ // Global scaling factor applied to touch events when they are dispatched
+ // to the window
+ public float scaleFactor;
+
// Window touchable region.
public final Region touchableRegion = new Region();
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 33e6a36..769e423 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -19,7 +19,6 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_BLUR_BEHIND;
-import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
@@ -586,6 +585,7 @@ public class WindowManagerService extends IWindowManager.Stub
// The frame use to limit the size of the app running in compatibility mode.
Rect mCompatibleScreenFrame = new Rect();
+ float mCompatibleScreenScale;
// The surface used to fill the outer rim of the app running in compatibility mode.
Surface mBackgroundFillerSurface = null;
WindowState mBackgroundFillerTarget = null;
@@ -1757,7 +1757,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean rawChanged = false;
float wpx = mLastWallpaperX >= 0 ? mLastWallpaperX : 0.5f;
float wpxs = mLastWallpaperXStep >= 0 ? mLastWallpaperXStep : -1.0f;
- int availw = wallpaperWin.mFrame.right-wallpaperWin.mFrame.left-dw;
+ int availw = wallpaperWin.mScaledFrame.right-wallpaperWin.mScaledFrame.left-dw;
int offset = availw > 0 ? -(int)(availw*wpx+.5f) : 0;
changed = wallpaperWin.mXOffset != offset;
if (changed) {
@@ -2887,14 +2887,14 @@ public class WindowManagerService extends IWindowManager.Stub
}
private boolean applyAnimationLocked(AppWindowToken wtoken,
- WindowManager.LayoutParams lp, int transit, boolean enter) {
+ WindowManager.LayoutParams lp, int transit, boolean enter, boolean bgFiller) {
// Only apply an animation if the display isn't frozen. If it is
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
if (!mDisplayFrozen && mPolicy.isScreenOn()) {
Animation a;
- if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+ if (bgFiller) {
a = new FadeInOutAnimation(enter);
if (DEBUG_ANIM) Slog.v(TAG,
"applying FadeInOutAnimation for a window in compatibility mode");
@@ -3680,7 +3680,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
boolean setTokenVisibilityLocked(AppWindowToken wtoken, WindowManager.LayoutParams lp,
- boolean visible, int transit, boolean performLayout) {
+ boolean visible, int transit, boolean performLayout, boolean bgFiller) {
boolean delayed = false;
if (wtoken.clientHidden == visible) {
@@ -3702,7 +3702,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (wtoken.animation == sDummyAnimation) {
wtoken.animation = null;
}
- applyAnimationLocked(wtoken, lp, transit, visible);
+ applyAnimationLocked(wtoken, lp, transit, visible, bgFiller);
changed = true;
if (wtoken.animation != null) {
delayed = runningAppAnimation = true;
@@ -3855,7 +3855,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
final long origId = Binder.clearCallingIdentity();
- setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET, true);
+ setTokenVisibilityLocked(wtoken, null, visible, WindowManagerPolicy.TRANSIT_UNSET,
+ true, false);
wtoken.updateReportedVisibilityLocked();
Binder.restoreCallingIdentity(origId);
}
@@ -3981,7 +3982,8 @@ public class WindowManagerService extends IWindowManager.Stub
WindowToken basewtoken = mTokenMap.remove(token);
if (basewtoken != null && (wtoken=basewtoken.appWindowToken) != null) {
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "Removing app token: " + wtoken);
- delayed = setTokenVisibilityLocked(wtoken, null, false, WindowManagerPolicy.TRANSIT_UNSET, true);
+ delayed = setTokenVisibilityLocked(wtoken, null, false,
+ WindowManagerPolicy.TRANSIT_UNSET, true, false);
wtoken.inPendingTransaction = false;
mOpeningApps.remove(wtoken);
wtoken.waitingToShow = false;
@@ -4753,8 +4755,8 @@ public class WindowManagerService extends IWindowManager.Stub
synchronized(mWindowMap) {
long ident = Binder.clearCallingIdentity();
- dw = mDisplay.getWidth();
- dh = mDisplay.getHeight();
+ dw = mPolicy.getNonDecorDisplayWidth(mDisplay.getWidth());
+ dh = mPolicy.getNonDecorDisplayHeight(mDisplay.getHeight());
int aboveAppLayer = mPolicy.windowTypeToLayerLw(
WindowManager.LayoutParams.TYPE_APPLICATION) * TYPE_LAYER_MULTIPLIER
@@ -4802,7 +4804,7 @@ public class WindowManagerService extends IWindowManager.Stub
// Don't include wallpaper in bounds calculation
if (!ws.mIsWallpaper) {
- final Rect wf = ws.mFrame;
+ final Rect wf = ws.mScaledFrame;
final Rect cr = ws.mContentInsets;
int left = wf.left + cr.left;
int top = wf.top + cr.top;
@@ -5447,7 +5449,10 @@ public class WindowManagerService extends IWindowManager.Stub
DisplayMetrics dm = new DisplayMetrics();
mDisplay.getMetrics(dm);
- CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame);
+ dm.realWidthPixels = mPolicy.getNonDecorDisplayWidth(dm.realWidthPixels);
+ dm.realHeightPixels = mPolicy.getNonDecorDisplayHeight(dm.realHeightPixels);
+ mCompatibleScreenScale = CompatibilityInfo.updateCompatibleScreenFrame(
+ dm, mCompatibleScreenFrame, null);
if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) {
// Note we only do this once because at this point we don't
@@ -6582,6 +6587,9 @@ public class WindowManagerService extends IWindowManager.Stub
final int dw = mDisplay.getWidth();
final int dh = mDisplay.getHeight();
+ final int innerDw = mPolicy.getNonDecorDisplayWidth(dw);
+ final int innerDh = mPolicy.getNonDecorDisplayHeight(dh);
+
final int N = mWindows.size();
int i;
@@ -6634,7 +6642,9 @@ public class WindowManagerService extends IWindowManager.Stub
//Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
win.mContentChanged = false;
}
+ win.prelayout();
mPolicy.layoutWindowLw(win, win.mAttrs, null);
+ win.evalNeedsBackgroundFiller(innerDw, innerDh);
win.mLayoutSeq = seq;
if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
+ win.mFrame + " mContainingFrame="
@@ -6669,7 +6679,9 @@ public class WindowManagerService extends IWindowManager.Stub
//Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
win.mContentChanged = false;
}
+ win.prelayout();
mPolicy.layoutWindowLw(win, win.mAttrs, win.mAttachedWindow);
+ win.evalNeedsBackgroundFiller(innerDw, innerDh);
win.mLayoutSeq = seq;
if (DEBUG_LAYOUT) Slog.v(TAG, "-> mFrame="
+ win.mFrame + " mContainingFrame="
@@ -6700,6 +6712,9 @@ public class WindowManagerService extends IWindowManager.Stub
final int dw = mDisplay.getWidth();
final int dh = mDisplay.getHeight();
+ final int innerDw = mPolicy.getNonDecorDisplayWidth(dw);
+ final int innerDh = mPolicy.getNonDecorDisplayHeight(dh);
+
int i;
if (mFocusMayChange) {
@@ -6799,13 +6814,15 @@ public class WindowManagerService extends IWindowManager.Stub
boolean tokensAnimating = false;
final int NAT = mAppTokens.size();
for (i=0; i<NAT; i++) {
- if (mAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
+ if (mAppTokens.get(i).stepAnimationLocked(currentTime,
+ innerDw, innerDh)) {
tokensAnimating = true;
}
}
final int NEAT = mExitingAppTokens.size();
for (i=0; i<NEAT; i++) {
- if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime, dw, dh)) {
+ if (mExitingAppTokens.get(i).stepAnimationLocked(currentTime,
+ innerDw, innerDh)) {
tokensAnimating = true;
}
}
@@ -6858,8 +6875,8 @@ public class WindowManagerService extends IWindowManager.Stub
final boolean wasAnimating = w.mAnimating;
- int animDw = dw;
- int animDh = dh;
+ int animDw = innerDw;
+ int animDh = innerDh;
// If the window has moved due to its containing
// content frame changing, then we'd like to animate
@@ -7116,6 +7133,7 @@ public class WindowManagerService extends IWindowManager.Stub
LayoutParams animLp = null;
int bestAnimLayer = -1;
boolean fullscreenAnim = false;
+ boolean needBgFiller = false;
if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
"New wallpaper target=" + mWallpaperTarget
@@ -7155,9 +7173,10 @@ public class WindowManagerService extends IWindowManager.Stub
if (ws != null) {
// If this is a compatibility mode
// window, we will always use its anim.
- if ((ws.mAttrs.flags&FLAG_COMPATIBLE_WINDOW) != 0) {
+ if (ws.mNeedsBackgroundFiller) {
animLp = ws.mAttrs;
bestAnimLayer = Integer.MAX_VALUE;
+ needBgFiller = true;
} else if (!fullscreenAnim || ws.mLayer > bestAnimLayer) {
animLp = ws.mAttrs;
bestAnimLayer = ws.mLayer;
@@ -7222,7 +7241,8 @@ public class WindowManagerService extends IWindowManager.Stub
wtoken.reportedVisible = false;
wtoken.inPendingTransaction = false;
wtoken.animation = null;
- setTokenVisibilityLocked(wtoken, animLp, true, transit, false);
+ setTokenVisibilityLocked(wtoken, animLp, true,
+ transit, false, needBgFiller);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToShow = false;
wtoken.showAllWindowsLocked();
@@ -7234,7 +7254,8 @@ public class WindowManagerService extends IWindowManager.Stub
"Now closing app" + wtoken);
wtoken.inPendingTransaction = false;
wtoken.animation = null;
- setTokenVisibilityLocked(wtoken, animLp, false, transit, false);
+ setTokenVisibilityLocked(wtoken, animLp, false,
+ transit, false, needBgFiller);
wtoken.updateReportedVisibilityLocked();
wtoken.waitingToHide = false;
// Force the allDrawn flag, because we want to start
@@ -7737,12 +7758,14 @@ public class WindowManagerService extends IWindowManager.Stub
}
boolean opaqueDrawn = canBeSeen && w.isOpaqueDrawn();
- if (opaqueDrawn && w.isFullscreen(dw, dh)) {
+ if (opaqueDrawn && w.isFullscreen(innerDw, innerDh)) {
// This window completely covers everything behind it,
// so we want to leave all of them as unblurred (for
// performance reasons).
obscured = true;
- } else if (w.needsBackgroundFiller(dw, dh) && (canBeSeen || w.isAnimating())) {
+ } else if (w.mNeedsBackgroundFiller && w.mHasDrawn
+ && w.mViewVisibility == View.VISIBLE
+ && (canBeSeen || w.isAnimating())) {
// This window is in compatibility mode, and needs background filler.
obscured = true;
mBackgroundFillerTarget = w;
diff --git a/services/java/com/android/server/wm/WindowState.java b/services/java/com/android/server/wm/WindowState.java
index f8ff5f8..72049ec 100644
--- a/services/java/com/android/server/wm/WindowState.java
+++ b/services/java/com/android/server/wm/WindowState.java
@@ -72,6 +72,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
final boolean mIsImWindow;
final boolean mIsWallpaper;
final boolean mIsFloatingLayer;
+ final boolean mEnforceSizeCompat;
int mViewVisibility;
boolean mPolicyVisibility = true;
boolean mPolicyVisibilityAfterAnim = true;
@@ -91,6 +92,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
int mLastLayer;
boolean mHaveFrame;
boolean mObscured;
+ boolean mNeedsBackgroundFiller;
boolean mTurnOnScreen;
int mLayoutSeq = -1;
@@ -154,6 +156,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// Current transformation being applied.
boolean mHaveMatrix;
+ float mGlobalScale=1;
float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
float mHScale=1, mVScale=1;
@@ -163,6 +166,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// "Real" frame that the application sees.
final Rect mFrame = new Rect();
final Rect mLastFrame = new Rect();
+ final Rect mScaledFrame = new Rect();
final Rect mContainingFrame = new Rect();
final Rect mDisplayFrame = new Rect();
@@ -273,6 +277,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
mViewVisibility = viewVisibility;
DeathRecipient deathRecipient = new DeathRecipient();
mAlpha = a.alpha;
+ mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
if (WindowManagerService.localLOGV) Slog.v(
WindowManagerService.TAG, "Window " + this + " client=" + c.asBinder()
+ " token=" + token + " (" + mAttrs.token + ")");
@@ -368,7 +373,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
final Rect display = mDisplayFrame;
display.set(df);
- if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) {
+ if (mEnforceSizeCompat) {
container.intersect(mService.mCompatibleScreenFrame);
if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) {
display.intersect(mService.mCompatibleScreenFrame);
@@ -416,6 +421,28 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// Now make sure the window fits in the overall display.
Gravity.applyDisplay(mAttrs.gravity, df, frame);
+ int adjRight=0, adjBottom=0;
+
+ if (mEnforceSizeCompat) {
+ // Adjust window offsets by the scaling factor.
+ int xoff = (int)((frame.left-mService.mCompatibleScreenFrame.left)*mGlobalScale)
+ - (frame.left-mService.mCompatibleScreenFrame.left);
+ int yoff = (int)((frame.top-mService.mCompatibleScreenFrame.top)*mGlobalScale)
+ - (frame.top-mService.mCompatibleScreenFrame.top);
+ frame.offset(xoff, yoff);
+
+ // We are temporarily going to apply the compatibility scale
+ // to the window so that we can correctly associate it with the
+ // content and visible frame.
+ adjRight = frame.right - frame.left;
+ adjRight = (int)((adjRight)*mGlobalScale + .5f) - adjRight;
+ adjBottom = frame.bottom - frame.top;
+ adjBottom = (int)((adjBottom)*mGlobalScale + .5f) - adjBottom;
+ frame.right += adjRight;
+ frame.bottom += adjBottom;
+ }
+ mScaledFrame.set(frame);
+
// Make sure the content and visible frames are inside of the
// final window frame.
if (content.left < frame.left) content.left = frame.left;
@@ -439,6 +466,22 @@ final class WindowState implements WindowManagerPolicy.WindowState {
visibleInsets.right = frame.right-visible.right;
visibleInsets.bottom = frame.bottom-visible.bottom;
+ if (mEnforceSizeCompat) {
+ // Scale the computed insets back to the window's compatibility
+ // coordinate space, and put frame back to correct size.
+ final float invScale = 1.0f/mGlobalScale;
+ contentInsets.left = (int)(contentInsets.left*invScale);
+ contentInsets.top = (int)(contentInsets.top*invScale);
+ contentInsets.right = (int)(contentInsets.right*invScale);
+ contentInsets.bottom = (int)(contentInsets.bottom*invScale);
+ visibleInsets.left = (int)(visibleInsets.left*invScale);
+ visibleInsets.top = (int)(visibleInsets.top*invScale);
+ visibleInsets.right = (int)(visibleInsets.right*invScale);
+ visibleInsets.bottom = (int)(visibleInsets.bottom*invScale);
+ frame.right -= adjRight;
+ frame.bottom -= adjBottom;
+ }
+
if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
mService.updateWallpaperOffsetLocked(this, mService.mDisplay.getWidth(),
mService.mDisplay.getHeight(), false);
@@ -819,9 +862,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
if (!mLocalAnimating) {
if (WindowManagerService.DEBUG_ANIM) Slog.v(
WindowManagerService.TAG, "Starting animation in " + this +
- " @ " + currentTime + ": ww=" + mFrame.width() + " wh=" + mFrame.height() +
+ " @ " + currentTime + ": ww=" + mScaledFrame.width() +
+ " wh=" + mScaledFrame.height() +
" dw=" + dw + " dh=" + dh + " scale=" + mService.mWindowAnimationScale);
- mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
+ mAnimation.initialize(mScaledFrame.width(), mScaledFrame.height(), dw, dh);
mAnimation.setStartTime(currentTime);
mLocalAnimating = true;
mAnimating = true;
@@ -988,6 +1032,14 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return true;
}
+ void prelayout() {
+ if (mEnforceSizeCompat) {
+ mGlobalScale = mService.mCompatibleScreenScale;
+ } else {
+ mGlobalScale = 1;
+ }
+ }
+
void computeShownFrameLocked() {
final boolean selfTransformation = mHasLocalTransformation;
Transformation attachedTransformation =
@@ -1031,6 +1083,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
// Compute the desired transformation.
tmpMatrix.setTranslate(0, 0);
+ tmpMatrix.postScale(mGlobalScale, mGlobalScale);
if (selfTransformation) {
tmpMatrix.postConcat(mTransformation.getMatrix());
}
@@ -1105,10 +1158,10 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
mShownAlpha = mAlpha;
mHaveMatrix = false;
- mDsDx = 1;
+ mDsDx = mGlobalScale;
mDtDx = 0;
mDsDy = 0;
- mDtDy = 1;
+ mDtDy = mGlobalScale;
}
/**
@@ -1281,12 +1334,14 @@ final class WindowState implements WindowManagerPolicy.WindowState {
&& mService.mPolicy.isScreenOn();
}
- boolean needsBackgroundFiller(int screenWidth, int screenHeight) {
- return
+ void evalNeedsBackgroundFiller(int screenWidth, int screenHeight) {
+ mNeedsBackgroundFiller =
// only if the application is requesting compatible window
- (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 &&
+ mEnforceSizeCompat &&
// only if it's visible
mHasDrawn && mViewVisibility == View.VISIBLE &&
+ // not needed if the compat window is actually full screen
+ !isFullscreenIgnoringCompat(screenWidth, screenHeight) &&
// and only if the application fills the compatible screen
mFrame.left <= mService.mCompatibleScreenFrame.left &&
mFrame.top <= mService.mCompatibleScreenFrame.top &&
@@ -1295,8 +1350,19 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
boolean isFullscreen(int screenWidth, int screenHeight) {
- return mFrame.left <= 0 && mFrame.top <= 0 &&
- mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
+ if (mEnforceSizeCompat) {
+ return mFrame.left <= mService.mCompatibleScreenFrame.left &&
+ mFrame.top <= mService.mCompatibleScreenFrame.top &&
+ mFrame.right >= mService.mCompatibleScreenFrame.right &&
+ mFrame.bottom >= mService.mCompatibleScreenFrame.bottom;
+ } else {
+ return isFullscreenIgnoringCompat(screenWidth, screenHeight);
+ }
+ }
+
+ boolean isFullscreenIgnoringCompat(int screenWidth, int screenHeight) {
+ return mScaledFrame.left <= 0 && mScaledFrame.top <= 0 &&
+ mScaledFrame.right >= screenWidth && mScaledFrame.bottom >= screenHeight;
}
void removeLocked() {
@@ -1426,30 +1492,38 @@ final class WindowState implements WindowManagerPolicy.WindowState {
return true;
}
+ private static void applyScaledInsets(Region outRegion, Rect frame, Rect inset, float scale) {
+ if (scale != 1) {
+ outRegion.set(frame.left + (int)(inset.left*scale),
+ frame.top + (int)(inset.top*scale),
+ frame.right - (int)(inset.right*scale),
+ frame.bottom - (int)(inset.bottom*scale));
+ } else {
+ outRegion.set(
+ frame.left + inset.left, frame.top + inset.top,
+ frame.right - inset.right, frame.bottom - inset.bottom);
+ }
+ }
+
public void getTouchableRegion(Region outRegion) {
- final Rect frame = mFrame;
+ final Rect frame = mScaledFrame;
switch (mTouchableInsets) {
default:
case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
outRegion.set(frame);
break;
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT: {
- final Rect inset = mGivenContentInsets;
- outRegion.set(
- frame.left + inset.left, frame.top + inset.top,
- frame.right - inset.right, frame.bottom - inset.bottom);
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT:
+ applyScaledInsets(outRegion, frame, mGivenContentInsets, mGlobalScale);
break;
- }
- case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE: {
- final Rect inset = mGivenVisibleInsets;
- outRegion.set(
- frame.left + inset.left, frame.top + inset.top,
- frame.right - inset.right, frame.bottom - inset.bottom);
+ case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE:
+ applyScaledInsets(outRegion, frame, mGivenVisibleInsets, mGlobalScale);
break;
- }
case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
final Region givenTouchableRegion = mGivenTouchableRegion;
outRegion.set(givenTouchableRegion);
+ if (mGlobalScale != 1) {
+ outRegion.scale(mGlobalScale);
+ }
outRegion.translate(frame.left, frame.top);
break;
}
@@ -1512,7 +1586,8 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
pw.print(" h="); pw.print(mRequestedHeight);
- pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
+ pw.print(" mLayoutSeq="); pw.print(mLayoutSeq);
+ pw.print(" mNeedsBackgroundFiller="); pw.println(mNeedsBackgroundFiller);
if (mXOffset != 0 || mYOffset != 0) {
pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
pw.print(" y="); pw.println(mYOffset);
@@ -1533,6 +1608,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.println();
pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
pw.print(" last="); mLastFrame.printShortString(pw);
+ pw.print(" scaled="); mScaledFrame.printShortString(pw);
pw.println();
pw.print(prefix); pw.print("mContainingFrame=");
mContainingFrame.printShortString(pw);
@@ -1568,8 +1644,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
pw.print(" mAlpha="); pw.print(mAlpha);
pw.print(" mLastAlpha="); pw.println(mLastAlpha);
}
- if (mHaveMatrix) {
- pw.print(prefix); pw.print("mDsDx="); pw.print(mDsDx);
+ if (mHaveMatrix || mGlobalScale != 1) {
+ pw.print(prefix); pw.print("mGlobalScale="); pw.print(mGlobalScale);
+ pw.print(" mDsDx="); pw.print(mDsDx);
pw.print(" mDtDx="); pw.print(mDtDx);
pw.print(" mDsDy="); pw.print(mDsDy);
pw.print(" mDtDy="); pw.println(mDtDy);