diff options
Diffstat (limited to 'services/java/com/android')
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 54cc885..811221e 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(); @@ -7776,6 +7855,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) { @@ -9238,7 +9321,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 { @@ -10342,7 +10426,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 } @@ -10414,7 +10499,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(); @@ -11261,6 +11347,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); |