diff options
author | Jean-Baptiste Queru <jbq@google.com> | 2009-07-29 14:25:07 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2009-07-29 14:25:07 -0700 |
commit | a8675f67e33bc7337d148358783b0fd138b501ff (patch) | |
tree | 71fb9d10330ef9161b3ead71d01074b3ef9e53ba /services | |
parent | cf4550c3198d6b3d92cdc52707fe70d7cc0caa9f (diff) | |
download | frameworks_base-a8675f67e33bc7337d148358783b0fd138b501ff.zip frameworks_base-a8675f67e33bc7337d148358783b0fd138b501ff.tar.gz frameworks_base-a8675f67e33bc7337d148358783b0fd138b501ff.tar.bz2 |
donut snapshot
Diffstat (limited to 'services')
12 files changed, 698 insertions, 271 deletions
diff --git a/services/java/com/android/server/AppWidgetService.java b/services/java/com/android/server/AppWidgetService.java index 131e156..78db6f9 100644 --- a/services/java/com/android/server/AppWidgetService.java +++ b/services/java/com/android/server/AppWidgetService.java @@ -68,6 +68,7 @@ class AppWidgetService extends IAppWidgetService.Stub private static final String SETTINGS_FILENAME = "appwidgets.xml"; private static final String SETTINGS_TMP_FILENAME = SETTINGS_FILENAME + ".tmp"; + private static final int MIN_UPDATE_PERIOD = 30 * 60 * 1000; // 30 minutes /* * When identifying a Host or Provider based on the calling process, use the uid field. @@ -629,9 +630,12 @@ class AppWidgetService extends IAppWidgetService.Stub Binder.restoreCallingIdentity(token); } if (!alreadyRegistered) { + long period = p.info.updatePeriodMillis; + if (period < MIN_UPDATE_PERIOD) { + period = MIN_UPDATE_PERIOD; + } mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, - SystemClock.elapsedRealtime() + p.info.updatePeriodMillis, - p.info.updatePeriodMillis, p.broadcast); + SystemClock.elapsedRealtime() + period, period, p.broadcast); } } } diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java index 3b82284..6e28515 100644 --- a/services/java/com/android/server/BackupManagerService.java +++ b/services/java/com/android/server/BackupManagerService.java @@ -810,17 +810,25 @@ class BackupManagerService extends IBackupManager.Stub { // Now propagate the newly-backed-up data to the transport if (success) { - if (DEBUG) Log.v(TAG, "doBackup() success; calling transport"); - backupData = - ParcelFileDescriptor.open(backupDataName, ParcelFileDescriptor.MODE_READ_ONLY); - if (!transport.performBackup(packInfo, backupData)) { - // STOPSHIP TODO: handle errors - Log.e(TAG, "Backup failure in performBackup()"); + if (DEBUG) Log.v(TAG, "doBackup() success"); + if (backupDataName.length() > 0) { + backupData = + ParcelFileDescriptor.open(backupDataName, + ParcelFileDescriptor.MODE_READ_ONLY); + if (!transport.performBackup(packInfo, backupData)) { + // STOPSHIP TODO: handle errors + Log.e(TAG, "Backup failure in performBackup()"); + } + } else { + if (DEBUG) { + Log.i(TAG, "no backup data written; not calling transport"); + } } - // !!! TODO: After successful transport, delete the now-stale data - // and juggle the files so that next time the new state is passed - //backupDataName.delete(); + // After successful transport, delete the now-stale data + // and juggle the files so that next time we supply the agent + // with the new state file it just created. + backupDataName.delete(); newStateName.renameTo(savedStateName); } } catch (Exception e) { diff --git a/services/java/com/android/server/MountListener.java b/services/java/com/android/server/MountListener.java index 2e430c8..3e53585 100644 --- a/services/java/com/android/server/MountListener.java +++ b/services/java/com/android/server/MountListener.java @@ -202,6 +202,7 @@ final class MountListener implements Runnable { byte[] buffer = new byte[100]; writeCommand(VOLD_CMD_SEND_UMS_STATUS); + mountMedia(Environment.getExternalStorageDirectory().getAbsolutePath()); while (true) { int count = inputStream.read(buffer); diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 854138c..38fb7c9 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -49,6 +49,7 @@ import android.os.IBinder; import android.os.Message; import android.os.Power; import android.os.RemoteException; +import android.os.SystemProperties; import android.os.Vibrator; import android.provider.Settings; import android.text.TextUtils; @@ -88,7 +89,8 @@ class NotificationManagerService extends INotificationManager.Stub private NotificationRecord mSoundNotification; private AsyncPlayer mSound; - private int mDisabledNotifications; + private boolean mSystemReady; + private int mDisabledNotifications = StatusBarManager.DISABLE_NOTIFICATION_ALERTS; private NotificationRecord mVibrateNotification; private Vibrator mVibrator = new Vibrator(); @@ -377,6 +379,11 @@ class NotificationManagerService extends INotificationManager.Stub mSettingsObserver.observe(); } + void systemReady() { + // no beeping until we're basically done booting + mSystemReady = true; + } + // Toasts // ============================================================================ public void enqueueToast(String pkg, ITransientNotification callback, int duration) @@ -637,7 +644,7 @@ class NotificationManagerService extends INotificationManager.Stub } } - sendAccessibilityEventTypeNotificationChangedDoCheck(notification, pkg); + sendAccessibilityEvent(notification, pkg); } else { if (old != null && old.statusBarKey != null) { @@ -654,7 +661,8 @@ class NotificationManagerService extends INotificationManager.Stub // If we're not supposed to beep, vibrate, etc. then don't. if (((mDisabledNotifications & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) == 0) && (!(old != null - && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))) { + && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 )) + && mSystemReady) { // sound final boolean useDefaultSound = (notification.defaults & Notification.DEFAULT_SOUND) != 0; @@ -721,8 +729,7 @@ class NotificationManagerService extends INotificationManager.Stub idOut[0] = id; } - private void sendAccessibilityEventTypeNotificationChangedDoCheck(Notification notification, - CharSequence packageName) { + private void sendAccessibilityEvent(Notification notification, CharSequence packageName) { AccessibilityManager manager = AccessibilityManager.getInstance(mContext); if (!manager.isEnabled()) { return; @@ -939,6 +946,9 @@ class NotificationManagerService extends INotificationManager.Stub // to accidentally lose. private void updateAdbNotification() { if (mAdbEnabled && mBatteryPlugged == BatteryManager.BATTERY_PLUGGED_USB) { + if ("0".equals(SystemProperties.get("persist.adb.notify"))) { + return; + } if (!mAdbNotificationShown) { NotificationManager notificationManager = (NotificationManager) mContext .getSystemService(Context.NOTIFICATION_SERVICE); diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java index 06435c8..ee53274 100644 --- a/services/java/com/android/server/PackageManagerService.java +++ b/services/java/com/android/server/PackageManagerService.java @@ -56,12 +56,11 @@ import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.Signature; -import android.content.res.CompatibilityInfo; -import android.content.res.Configuration; import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.Bundle; +import android.os.Debug; import android.os.HandlerThread; import android.os.Parcel; import android.os.RemoteException; @@ -251,6 +250,9 @@ class PackageManagerService extends IPackageManager.Stub { final HashMap<String, PackageParser.PermissionGroup> mPermissionGroups = new HashMap<String, PackageParser.PermissionGroup>(); + // Broadcast actions that are only available to the system. + final HashSet<String> mProtectedBroadcasts = new HashSet<String>(); + boolean mSystemReady; boolean mSafeMode; boolean mHasSystemUidErrors; @@ -260,7 +262,6 @@ class PackageManagerService extends IPackageManager.Stub { final ResolveInfo mResolveInfo = new ResolveInfo(); ComponentName mResolveComponentName; PackageParser.Package mPlatformPackage; - private boolean mCompatibilityModeEnabled = true; public static final IPackageManager main(Context context, boolean factoryTest) { PackageManagerService m = new PackageManagerService(context, factoryTest); @@ -763,7 +764,7 @@ class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (Config.LOGV) Log.v( - TAG, "getApplicationInfo " + packageName + TAG, "getPackageInfo " + packageName + ": " + p); if (p != null) { return generatePackageInfo(p, flags); @@ -794,7 +795,7 @@ class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (Config.LOGV) Log.v( - TAG, "getApplicationInfo " + packageName + TAG, "getPackageGids" + packageName + ": " + p); if (p != null) { final PackageSetting ps = (PackageSetting)p.mExtras; @@ -892,11 +893,7 @@ class PackageManagerService extends IPackageManager.Stub { + ": " + p); if (p != null) { // Note: isEnabledLP() does not apply here - always return info - ApplicationInfo appInfo = PackageParser.generateApplicationInfo(p, flags); - if (!mCompatibilityModeEnabled) { - appInfo.disableCompatibilityMode(); - } - return appInfo; + return PackageParser.generateApplicationInfo(p, flags); } if ("android".equals(packageName)||"system".equals(packageName)) { return mAndroidApplication; @@ -1128,6 +1125,12 @@ class PackageManagerService extends IPackageManager.Stub { } } + public boolean isProtectedBroadcast(String actionName) { + synchronized (mPackages) { + return mProtectedBroadcasts.contains(actionName); + } + } + public int checkSignatures(String pkg1, String pkg2) { synchronized (mPackages) { PackageParser.Package p1 = mPackages.get(pkg1); @@ -2039,8 +2042,9 @@ class PackageManagerService extends IPackageManager.Stub { + suid.userId + "): packages=" + suid.packages); } } - - // Just create the setting, don't add it yet + + // Just create the setting, don't add it yet. For already existing packages + // the PkgSetting exists already and doesn't have to be created. pkgSetting = mSettings.getPackageLP(pkg, suid, destCodeFile, destResourceFile, pkg.applicationInfo.flags, true, false); if (pkgSetting == null) { @@ -2265,7 +2269,7 @@ class PackageManagerService extends IPackageManager.Stub { // Add the new setting to mSettings mSettings.insertPackageSettingLP(pkgSetting, pkg.packageName, suid); // Add the new setting to mPackages - mPackages.put(pkg.applicationInfo.packageName, pkg); + mPackages.put(pkg.applicationInfo.packageName, pkg); int N = pkg.providers.size(); StringBuilder r = null; int i; @@ -2500,6 +2504,13 @@ class PackageManagerService extends IPackageManager.Stub { if (Config.LOGD) Log.d(TAG, " Instrumentation: " + r); } + if (pkg.protectedBroadcasts != null) { + N = pkg.protectedBroadcasts.size(); + for (i=0; i<N; i++) { + mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i)); + } + } + pkgSetting.setTimeStamp(scanFileTime); } @@ -4801,11 +4812,12 @@ class PackageManagerService extends IPackageManager.Stub { mSystemReady = true; // Read the compatibilty setting when the system is ready. - mCompatibilityModeEnabled = android.provider.Settings.System.getInt( + boolean compatibilityModeEnabled = android.provider.Settings.System.getInt( mContext.getContentResolver(), android.provider.Settings.System.COMPATIBILITY_MODE, 1) == 1; + PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled); if (DEBUG_SETTINGS) { - Log.d(TAG, "compatibility mode:" + mCompatibilityModeEnabled); + Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled); } } @@ -4889,6 +4901,26 @@ class PackageManagerService extends IPackageManager.Stub { pw.print(" resourcePath="); pw.println(ps.resourcePathString); if (ps.pkg != null) { pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); + pw.print(" targetSdk="); pw.println(ps.pkg.applicationInfo.targetSdkVersion); + pw.print(" densities="); pw.println(ps.pkg.supportsDensityList); + ArrayList<String> screens = new ArrayList<String>(); + if ((ps.pkg.applicationInfo.flags & + ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) { + screens.add("medium"); + } + if ((ps.pkg.applicationInfo.flags & + ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) { + screens.add("large"); + } + if ((ps.pkg.applicationInfo.flags & + ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { + screens.add("small,"); + } + if ((ps.pkg.applicationInfo.flags & + ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) { + screens.add("resizeable,"); + } + pw.print(" supportsScreens="); pw.println(screens); } pw.print(" timeStamp="); pw.println(ps.getTimeStampStr()); pw.print(" signatures="); pw.println(ps.signatures); @@ -5408,10 +5440,10 @@ class PackageManagerService extends IPackageManager.Stub { */ static class PackageSettingBase extends GrantedPermissions { final String name; - final File codePath; - final String codePathString; - final File resourcePath; - final String resourcePathString; + File codePath; + String codePathString; + File resourcePath; + String resourcePathString; private long timeStamp; private String timeStampString = "0"; final int versionCode; @@ -5809,11 +5841,16 @@ class PackageManagerService extends IPackageManager.Stub { // and data partition. Just let the most recent version // take precedence. return p; - } else if ((p.pkg != null) && (p.pkg.applicationInfo != null)) { + } else { // Let the app continue with previous uid if code path changes. reportSettingsProblem(Log.WARN, "Package " + name + " codePath changed from " + p.codePath - + " to " + codePath + "; Retaining data and using new code"); + + " to " + codePath + "; Retaining data and using new code from " + + codePath); + p.codePath = codePath; + p.resourcePath = resourcePath; + p.codePathString = codePath.toString(); + p.resourcePathString = resourcePath.toString(); } } else if (p.sharedUser != sharedUser) { reportSettingsProblem(Log.WARN, @@ -5837,6 +5874,7 @@ class PackageManagerService extends IPackageManager.Stub { if (sharedUser != null) { p.userId = sharedUser.userId; } else if (MULTIPLE_APPLICATION_UIDS) { + // Assign new user id p.userId = newUserIdLP(p); } else { p.userId = FIRST_APPLICATION_UID; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 3e4d5f9..aa1a5cf 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -52,6 +52,7 @@ import java.lang.reflect.InvocationTargetException; class ServerThread extends Thread { private static final String TAG = "SystemServer"; private final static boolean INCLUDE_DEMO = false; + private final static boolean INCLUDE_BACKUP = false; private static final int LOG_BOOT_PROGRESS_SYSTEM_RUN = 3010; @@ -190,6 +191,7 @@ class ServerThread extends Thread { StatusBarService statusBar = null; InputMethodManagerService imm = null; AppWidgetService appWidget = null; + NotificationManagerService notification = null; if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { @@ -240,8 +242,8 @@ class ServerThread extends Thread { try { Log.i(TAG, "Starting Notification Manager."); - ServiceManager.addService(Context.NOTIFICATION_SERVICE, - new NotificationManagerService(context, statusBar, hardware)); + notification = new NotificationManagerService(context, statusBar, hardware); + ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification); } catch (Throwable e) { Log.e(TAG, "Failure starting Notification Manager", e); } @@ -317,8 +319,10 @@ class ServerThread extends Thread { } try { - Log.i(TAG, "Starting Backup Service"); - ServiceManager.addService(Context.BACKUP_SERVICE, new BackupManagerService(context)); + if (INCLUDE_BACKUP) { + Log.i(TAG, "Starting Backup Service"); + ServiceManager.addService(Context.BACKUP_SERVICE, new BackupManagerService(context)); + } } catch (Throwable e) { Log.e(TAG, "Failure starting Backup Service", e); } @@ -348,6 +352,11 @@ class ServerThread extends Thread { // It is now time to start up the app processes... boolean safeMode = wm.detectSafeMode(); + + if (notification != null) { + notification.systemReady(); + } + if (statusBar != null) { statusBar.systemReady(); } diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index a940af3..b4754b6 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -192,6 +192,7 @@ public class WifiService extends IWifiManager.Stub { WifiService(Context context, WifiStateTracker tracker) { mContext = context; mWifiStateTracker = tracker; + mWifiStateTracker.enableRssiPolling(true); mBatteryStats = BatteryStatsService.getService(); /* @@ -436,7 +437,7 @@ public class WifiService extends IWifiManager.Stub { * see {@link android.net.wifi.WifiManager#startScan()} * @return {@code true} if the operation succeeds */ - public boolean startScan() { + public boolean startScan(boolean forceActive) { enforceChangePermission(); synchronized (mWifiStateTracker) { switch (mWifiStateTracker.getSupplicantState()) { @@ -450,7 +451,7 @@ public class WifiService extends IWifiManager.Stub { WifiStateTracker.SUPPL_SCAN_HANDLING_LIST_ONLY); break; } - return WifiNative.scanCommand(); + return WifiNative.scanCommand(forceActive); } } @@ -1560,9 +1561,11 @@ public class WifiService extends IWifiManager.Stub { mAlarmManager.cancel(mIdleIntent); mDeviceIdle = false; mScreenOff = false; + mWifiStateTracker.enableRssiPolling(true); } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { Log.d(TAG, "ACTION_SCREEN_OFF"); mScreenOff = true; + mWifiStateTracker.enableRssiPolling(false); /* * Set a timer to put Wi-Fi to sleep, but only if the screen is off * AND the "stay on while plugged in" setting doesn't match the diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java index 2dd70ef..0be8417 100644 --- a/services/java/com/android/server/WindowManagerService.java +++ b/services/java/com/android/server/WindowManagerService.java @@ -24,8 +24,10 @@ import static android.os.LocalPowerManager.TOUCH_UP_EVENT; 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_LAYOUT_NO_LIMITS; import static android.view.WindowManager.LayoutParams.FLAG_SYSTEM_ERROR; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; @@ -53,6 +55,7 @@ import android.app.IActivityManager; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Matrix; import android.graphics.PixelFormat; @@ -100,6 +103,7 @@ import android.view.WindowManager; import android.view.WindowManagerImpl; import android.view.WindowManagerPolicy; import android.view.WindowManager.LayoutParams; +import android.view.animation.AccelerateInterpolator; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.Transformation; @@ -171,6 +175,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo */ static final int DEFAULT_DIM_DURATION = 200; + /** Amount of time (in milliseconds) to animate the fade-in-out transition for + * compatible windows. + */ + static final int DEFAULT_FADE_IN_OUT_DURATION = 400; + /** Adjustment to time to perform a dim, to make it more dramatic. */ static final int DIM_DURATION_MULTIPLIER = 6; @@ -324,12 +333,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo IInputMethodManager mInputMethodManager; SurfaceSession mFxSession; - Surface mDimSurface; - boolean mDimShown; - float mDimCurrentAlpha; - float mDimTargetAlpha; - float mDimDeltaPerMs; - long mLastDimAnimTime; + private DimAnimator mDimAnimator = null; Surface mBlurSurface; boolean mBlurShown; @@ -416,8 +420,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo final Rect mTempRect = new Rect(); final Configuration mTempConfiguration = new Configuration(); - int screenLayout = Configuration.SCREENLAYOUT_UNDEFINED; - + int mScreenLayout = Configuration.SCREENLAYOUT_SIZE_UNDEFINED; + + // The frame use to limit the size of the app running in compatibility mode. + Rect mCompatibleScreenFrame = new Rect(); + // The surface used to fill the outer rim of the app running in compatibility mode. + Surface mBackgroundFillerSurface = null; + boolean mBackgroundFillerShown = false; + public static WindowManagerService main(Context context, PowerManagerService pm, boolean haveInputMethods) { WMThread thr = new WMThread(context, pm, haveInputMethods); @@ -1847,44 +1857,51 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo // artifacts when we unfreeze the display if some different animation // is running. if (!mDisplayFrozen) { - int animAttr = 0; - switch (transit) { - case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_TASK_OPEN: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_TASK_CLOSE: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; - break; - case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: - animAttr = enter - ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation - : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; - break; + Animation a; + if (lp != null && (lp.flags & FLAG_COMPATIBLE_WINDOW) != 0) { + a = new FadeInOutAnimation(enter); + if (DEBUG_ANIM) Log.v(TAG, + "applying FadeInOutAnimation for a window in compatibility mode"); + } else { + int animAttr = 0; + switch (transit) { + case WindowManagerPolicy.TRANSIT_ACTIVITY_OPEN: + animAttr = enter + ? com.android.internal.R.styleable.WindowAnimation_activityOpenEnterAnimation + : com.android.internal.R.styleable.WindowAnimation_activityOpenExitAnimation; + break; + case WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE: + animAttr = enter + ? com.android.internal.R.styleable.WindowAnimation_activityCloseEnterAnimation + : com.android.internal.R.styleable.WindowAnimation_activityCloseExitAnimation; + break; + case WindowManagerPolicy.TRANSIT_TASK_OPEN: + animAttr = enter + ? com.android.internal.R.styleable.WindowAnimation_taskOpenEnterAnimation + : com.android.internal.R.styleable.WindowAnimation_taskOpenExitAnimation; + break; + case WindowManagerPolicy.TRANSIT_TASK_CLOSE: + animAttr = enter + ? com.android.internal.R.styleable.WindowAnimation_taskCloseEnterAnimation + : com.android.internal.R.styleable.WindowAnimation_taskCloseExitAnimation; + break; + case WindowManagerPolicy.TRANSIT_TASK_TO_FRONT: + animAttr = enter + ? com.android.internal.R.styleable.WindowAnimation_taskToFrontEnterAnimation + : com.android.internal.R.styleable.WindowAnimation_taskToFrontExitAnimation; + break; + case WindowManagerPolicy.TRANSIT_TASK_TO_BACK: + animAttr = enter + ? com.android.internal.R.styleable.WindowAnimation_taskToBackEnterAnimation + : com.android.internal.R.styleable.WindowAnimation_taskToBackExitAnimation; + break; + } + a = loadAnimation(lp, animAttr); + if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: wtoken=" + wtoken + + " anim=" + a + + " animAttr=0x" + Integer.toHexString(animAttr) + + " transit=" + transit); } - Animation a = loadAnimation(lp, animAttr); - if (DEBUG_ANIM) Log.v(TAG, "applyAnimation: wtoken=" + wtoken - + " anim=" + a - + " animAttr=0x" + Integer.toHexString(animAttr) - + " transit=" + transit); if (a != null) { if (DEBUG_ANIM) { RuntimeException e = new RuntimeException(); @@ -3738,12 +3755,14 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } config.orientation = orientation; - if (screenLayout == Configuration.SCREENLAYOUT_UNDEFINED) { + DisplayMetrics dm = new DisplayMetrics(); + mDisplay.getMetrics(dm); + CompatibilityInfo.updateCompatibleScreenFrame(dm, orientation, mCompatibleScreenFrame); + + if (mScreenLayout == Configuration.SCREENLAYOUT_SIZE_UNDEFINED) { // Note we only do this once because at this point we don't // expect the screen to change in this way at runtime, and want // to avoid all of this computation for every config change. - DisplayMetrics dm = new DisplayMetrics(); - mDisplay.getMetrics(dm); int longSize = dw; int shortSize = dh; if (longSize < shortSize) { @@ -3753,23 +3772,42 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } longSize = (int)(longSize/dm.density); shortSize = (int)(shortSize/dm.density); - + // These semi-magic numbers define our compatibility modes for // applications with different screens. Don't change unless you // make sure to test lots and lots of apps! if (longSize < 470) { // This is shorter than an HVGA normal density screen (which // is 480 pixels on its long side). - screenLayout = Configuration.SCREENLAYOUT_SMALL; - } else if (longSize > 490 && shortSize > 330) { - // This is larger than an HVGA normal density screen (which - // is 480x320 pixels). - screenLayout = Configuration.SCREENLAYOUT_LARGE; + mScreenLayout = Configuration.SCREENLAYOUT_SIZE_SMALL + | Configuration.SCREENLAYOUT_LONG_NO; } else { - screenLayout = Configuration.SCREENLAYOUT_NORMAL; + // Is this a large screen? + if (longSize > 640 && shortSize >= 480) { + // VGA or larger screens at medium density are the point + // at which we consider it to be a large screen. + mScreenLayout = Configuration.SCREENLAYOUT_SIZE_LARGE; + } else { + mScreenLayout = Configuration.SCREENLAYOUT_SIZE_NORMAL; + + // If this screen is wider than normal HVGA, or taller + // than FWVGA, then for old apps we want to run in size + // compatibility mode. + if (shortSize > 321 || longSize > 570) { + mScreenLayout |= Configuration.SCREENLAYOUT_COMPAT_NEEDED; + } + } + + // Is this a long screen? + if (((longSize*3)/5) >= (shortSize-1)) { + // Anything wider than WVGA (5:3) is considering to be long. + mScreenLayout |= Configuration.SCREENLAYOUT_LONG_YES; + } else { + mScreenLayout |= Configuration.SCREENLAYOUT_LONG_NO; + } } } - config.screenLayout = screenLayout; + config.screenLayout = mScreenLayout; config.keyboardHidden = Configuration.KEYBOARDHIDDEN_NO; config.hardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_NO; @@ -5845,8 +5883,21 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) { mHaveFrame = true; - final int pw = pf.right-pf.left; - final int ph = pf.bottom-pf.top; + final Rect container = mContainingFrame; + container.set(pf); + + final Rect display = mDisplayFrame; + display.set(df); + + if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) { + container.intersect(mCompatibleScreenFrame); + if ((mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) == 0) { + display.intersect(mCompatibleScreenFrame); + } + } + + final int pw = container.right - container.left; + final int ph = container.bottom - container.top; int w,h; if ((mAttrs.flags & mAttrs.FLAG_SCALED) != 0) { @@ -5857,12 +5908,6 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo h = mAttrs.height== mAttrs.FILL_PARENT ? ph : mRequestedHeight; } - final Rect container = mContainingFrame; - container.set(pf); - - final Rect display = mDisplayFrame; - display.set(df); - final Rect content = mContentFrame; content.set(cf); @@ -5882,7 +5927,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo // Now make sure the window fits in the overall display. Gravity.applyDisplay(mAttrs.gravity, df, frame); - + // Make sure the content and visible frames are inside of the // final window frame. if (content.left < frame.left) content.left = frame.left; @@ -6565,24 +6610,45 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo return false; } final Rect frame = shownFrame ? mShownFrame : mFrame; - if (frame.left <= 0 && frame.top <= 0 - && frame.right >= screenWidth - && frame.bottom >= screenHeight) { - return true; + + if ((mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0) { + return frame.left <= mCompatibleScreenFrame.left && + frame.top <= mCompatibleScreenFrame.top && + frame.right >= mCompatibleScreenFrame.right && + frame.bottom >= mCompatibleScreenFrame.bottom; + } else { + return frame.left <= 0 && frame.top <= 0 + && frame.right >= screenWidth + && frame.bottom >= screenHeight; } - return false; } - boolean isFullscreenOpaque(int screenWidth, int screenHeight) { - if (mAttrs.format != PixelFormat.OPAQUE || mSurface == null - || mAnimation != null || mDrawPending || mCommitDrawPending) { - return false; - } - if (mFrame.left <= 0 && mFrame.top <= 0 && - mFrame.right >= screenWidth && mFrame.bottom >= screenHeight) { - return true; - } - return false; + /** + * Return true if the window is opaque and fully drawn. + */ + boolean isOpaqueDrawn() { + return mAttrs.format == PixelFormat.OPAQUE && mSurface != null + && mAnimation == null && !mDrawPending && !mCommitDrawPending; + } + + boolean needsBackgroundFiller(int screenWidth, int screenHeight) { + return + // only if the application is requesting compatible window + (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0 && + // only if it's visible + mHasDrawn && mViewVisibility == View.VISIBLE && + // and only if the application fills the compatible screen + mFrame.left <= mCompatibleScreenFrame.left && + mFrame.top <= mCompatibleScreenFrame.top && + mFrame.right >= mCompatibleScreenFrame.right && + mFrame.bottom >= mCompatibleScreenFrame.bottom && + // and starting window do not need background filler + mAttrs.type != mAttrs.TYPE_APPLICATION_STARTING; + } + + boolean isFullscreen(int screenWidth, int screenHeight) { + return mFrame.left <= 0 && mFrame.top <= 0 && + mFrame.right >= screenWidth && mFrame.bottom >= screenHeight; } void removeLocked() { @@ -7190,17 +7256,27 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo public static WindowManager.LayoutParams findAnimations( ArrayList<AppWindowToken> order, - ArrayList<AppWindowToken> tokenList1, - ArrayList<AppWindowToken> tokenList2) { + ArrayList<AppWindowToken> openingTokenList1, + ArrayList<AppWindowToken> closingTokenList2) { // We need to figure out which animation to use... + + // First, check if there is a compatible window in opening/closing + // apps, and use it if exists. WindowManager.LayoutParams animParams = null; int animSrc = 0; - + animParams = findCompatibleWindowParams(openingTokenList1); + if (animParams == null) { + animParams = findCompatibleWindowParams(closingTokenList2); + } + if (animParams != null) { + return animParams; + } + //Log.i(TAG, "Looking for animations..."); for (int i=order.size()-1; i>=0; i--) { AppWindowToken wtoken = order.get(i); //Log.i(TAG, "Token " + wtoken + " with " + wtoken.windows.size() + " windows"); - if (tokenList1.contains(wtoken) || tokenList2.contains(wtoken)) { + if (openingTokenList1.contains(wtoken) || closingTokenList2.contains(wtoken)) { int j = wtoken.windows.size(); while (j > 0) { j--; @@ -7228,6 +7304,21 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo return animParams; } + private static LayoutParams findCompatibleWindowParams(ArrayList<AppWindowToken> tokenList) { + for (int appCount = tokenList.size() - 1; appCount >= 0; appCount--) { + AppWindowToken wtoken = tokenList.get(appCount); + // Just checking one window is sufficient as all windows have the compatible flag + // if the application is in compatibility mode. + if (wtoken.windows.size() > 0) { + WindowManager.LayoutParams params = wtoken.windows.get(0).mAttrs; + if ((params.flags & FLAG_COMPATIBLE_WINDOW) != 0) { + return params; + } + } + } + return null; + } + // ------------------------------------------------------------- // DummyAnimation // ------------------------------------------------------------- @@ -8102,6 +8193,7 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo boolean dimming = false; boolean covered = false; boolean syswin = false; + boolean backgroundFillerShown = false; for (i=N-1; i>=0; i--) { WindowState w = (WindowState)mWindows.get(i); @@ -8371,11 +8463,39 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo syswin = true; } } - if (w.isFullscreenOpaque(dw, dh)) { + + boolean opaqueDrawn = w.isOpaqueDrawn(); + if (opaqueDrawn && w.isFullscreen(dw, dh)) { // This window completely covers everything behind it, // so we want to leave all of them as unblurred (for // performance reasons). obscured = true; + } else if (opaqueDrawn && w.needsBackgroundFiller(dw, dh)) { + if (SHOW_TRANSACTIONS) Log.d(TAG, "showing background filler"); + // This window is in compatibility mode, and needs background filler. + obscured = true; + if (mBackgroundFillerSurface == null) { + try { + mBackgroundFillerSurface = new Surface(mFxSession, 0, + 0, dw, dh, + PixelFormat.OPAQUE, + Surface.FX_SURFACE_NORMAL); + } catch (Exception e) { + Log.e(TAG, "Exception creating filler surface", e); + } + } + try { + mBackgroundFillerSurface.setPosition(0, 0); + mBackgroundFillerSurface.setSize(dw, dh); + // Using the same layer as Dim because they will never be shown at the + // same time. + mBackgroundFillerSurface.setLayer(w.mAnimLayer - 1); + mBackgroundFillerSurface.show(); + } catch (RuntimeException e) { + Log.e(TAG, "Exception showing filler surface"); + } + backgroundFillerShown = true; + mBackgroundFillerShown = true; } else if (canBeSeen && !obscured && (attrFlags&FLAG_BLUR_BEHIND|FLAG_DIM_BEHIND) != 0) { if (localLOGV) Log.v(TAG, "Win " + w @@ -8386,56 +8506,12 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo if (!dimming) { //Log.i(TAG, "DIM BEHIND: " + w); dimming = true; - mDimShown = true; - if (mDimSurface == null) { - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " - + mDimSurface + ": CREATE"); - try { - mDimSurface = new Surface(mFxSession, 0, - -1, 16, 16, - PixelFormat.OPAQUE, - Surface.FX_SURFACE_DIM); - } catch (Exception e) { - Log.e(TAG, "Exception creating Dim surface", e); - } - } - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " - + mDimSurface + ": SHOW pos=(0,0) (" + - dw + "x" + dh + "), layer=" + (w.mAnimLayer-1)); - if (mDimSurface != null) { - try { - mDimSurface.setPosition(0, 0); - mDimSurface.setSize(dw, dh); - mDimSurface.show(); - } catch (RuntimeException e) { - Log.w(TAG, "Failure showing dim surface", e); - } - } - } - mDimSurface.setLayer(w.mAnimLayer-1); - final float target = w.mExiting ? 0 : attrs.dimAmount; - if (mDimTargetAlpha != target) { - // If the desired dim level has changed, then - // start an animation to it. - mLastDimAnimTime = currentTime; - long duration = (w.mAnimating && w.mAnimation != null) - ? w.mAnimation.computeDurationHint() - : DEFAULT_DIM_DURATION; - if (target > mDimTargetAlpha) { - // This is happening behind the activity UI, - // so we can make it run a little longer to - // give a stronger impression without disrupting - // the user. - duration *= DIM_DURATION_MULTIPLIER; - } - if (duration < 1) { - // Don't divide by zero - duration = 1; + if (mDimAnimator == null) { + mDimAnimator = new DimAnimator(mFxSession); } - mDimTargetAlpha = target; - mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) - / duration; + mDimAnimator.show(dw, dh); } + mDimAnimator.updateParameters(w, currentTime); } if ((attrFlags&FLAG_BLUR_BEHIND) != 0) { if (!blurring) { @@ -8472,59 +8548,19 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo } } } - - if (!dimming && mDimShown) { - // Time to hide the dim surface... start fading. - if (mDimTargetAlpha != 0) { - mLastDimAnimTime = currentTime; - mDimTargetAlpha = 0; - mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION; + + if (backgroundFillerShown == false && mBackgroundFillerShown) { + mBackgroundFillerShown = false; + if (SHOW_TRANSACTIONS) Log.d(TAG, "hiding background filler"); + try { + mBackgroundFillerSurface.hide(); + } catch (RuntimeException e) { + Log.e(TAG, "Exception hiding filler surface", e); } } - if (mDimShown && mLastDimAnimTime != 0) { - mDimCurrentAlpha += mDimDeltaPerMs - * (currentTime-mLastDimAnimTime); - boolean more = true; - if (mDisplayFrozen) { - // If the display is frozen, there is no reason to animate. - more = false; - } else if (mDimDeltaPerMs > 0) { - if (mDimCurrentAlpha > mDimTargetAlpha) { - more = false; - } - } else if (mDimDeltaPerMs < 0) { - if (mDimCurrentAlpha < mDimTargetAlpha) { - more = false; - } - } else { - more = false; - } - - // Do we need to continue animating? - if (more) { - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " - + mDimSurface + ": alpha=" + mDimCurrentAlpha); - mLastDimAnimTime = currentTime; - mDimSurface.setAlpha(mDimCurrentAlpha); - animating = true; - } else { - mDimCurrentAlpha = mDimTargetAlpha; - mLastDimAnimTime = 0; - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " - + mDimSurface + ": final alpha=" + mDimCurrentAlpha); - mDimSurface.setAlpha(mDimCurrentAlpha); - if (!dimming) { - if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface - + ": HIDE"); - try { - mDimSurface.hide(); - } catch (RuntimeException e) { - Log.w(TAG, "Illegal argument exception hiding dim surface"); - } - mDimShown = false; - } - } + if (mDimAnimator != null && mDimAnimator.mDimShown) { + animating |= mDimAnimator.updateSurface(dimming, currentTime, mDisplayFrozen); } if (!blurring && mBlurShown) { @@ -9067,11 +9103,11 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo pw.print(" mDisplayEnabled="); pw.println(mDisplayEnabled); pw.print(" mLayoutNeeded="); pw.print(mLayoutNeeded); pw.print(" mBlurShown="); pw.println(mBlurShown); - pw.print(" mDimShown="); pw.print(mDimShown); - pw.print(" current="); pw.print(mDimCurrentAlpha); - pw.print(" target="); pw.print(mDimTargetAlpha); - pw.print(" delta="); pw.print(mDimDeltaPerMs); - pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); + if (mDimAnimator != null) { + mDimAnimator.printTo(pw); + } else { + pw.print( " no DimAnimator "); + } pw.print(" mInputMethodAnimLayerAdjustment="); pw.println(mInputMethodAnimLayerAdjustment); pw.print(" mDisplayFrozen="); pw.print(mDisplayFrozen); @@ -9112,4 +9148,188 @@ public class WindowManagerService extends IWindowManager.Stub implements Watchdo synchronized (mKeyguardDisabled) { } synchronized (mKeyWaiter) { } } + + /** + * DimAnimator class that controls the dim animation. This holds the surface and + * all state used for dim animation. + */ + private static class DimAnimator { + Surface mDimSurface; + boolean mDimShown = false; + float mDimCurrentAlpha; + float mDimTargetAlpha; + float mDimDeltaPerMs; + long mLastDimAnimTime; + + DimAnimator (SurfaceSession session) { + if (mDimSurface == null) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + + mDimSurface + ": CREATE"); + try { + mDimSurface = new Surface(session, 0, -1, 16, 16, PixelFormat.OPAQUE, + Surface.FX_SURFACE_DIM); + } catch (Exception e) { + Log.e(TAG, "Exception creating Dim surface", e); + } + } + } + + /** + * Show the dim surface. + */ + void show(int dw, int dh) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface + ": SHOW pos=(0,0) (" + + dw + "x" + dh + ")"); + mDimShown = true; + try { + mDimSurface.setPosition(0, 0); + mDimSurface.setSize(dw, dh); + mDimSurface.show(); + } catch (RuntimeException e) { + Log.w(TAG, "Failure showing dim surface", e); + } + } + + /** + * Set's the dim surface's layer and update dim parameters that will be used in + * {@link updateSurface} after all windows are examined. + */ + void updateParameters(WindowState w, long currentTime) { + mDimSurface.setLayer(w.mAnimLayer-1); + + final float target = w.mExiting ? 0 : w.mAttrs.dimAmount; + if (SHOW_TRANSACTIONS) Log.i(TAG, "layer=" + (w.mAnimLayer-1) + ", target=" + target); + if (mDimTargetAlpha != target) { + // If the desired dim level has changed, then + // start an animation to it. + mLastDimAnimTime = currentTime; + long duration = (w.mAnimating && w.mAnimation != null) + ? w.mAnimation.computeDurationHint() + : DEFAULT_DIM_DURATION; + if (target > mDimTargetAlpha) { + // This is happening behind the activity UI, + // so we can make it run a little longer to + // give a stronger impression without disrupting + // the user. + duration *= DIM_DURATION_MULTIPLIER; + } + if (duration < 1) { + // Don't divide by zero + duration = 1; + } + mDimTargetAlpha = target; + mDimDeltaPerMs = (mDimTargetAlpha-mDimCurrentAlpha) / duration; + } + } + + /** + * Updating the surface's alpha. Returns true if the animation continues, or returns + * false when the animation is finished and the dim surface is hidden. + */ + boolean updateSurface(boolean dimming, long currentTime, boolean displayFrozen) { + if (!dimming) { + if (mDimTargetAlpha != 0) { + mLastDimAnimTime = currentTime; + mDimTargetAlpha = 0; + mDimDeltaPerMs = (-mDimCurrentAlpha) / DEFAULT_DIM_DURATION; + } + } + + boolean animating = false; + if (mLastDimAnimTime != 0) { + mDimCurrentAlpha += mDimDeltaPerMs + * (currentTime-mLastDimAnimTime); + boolean more = true; + if (displayFrozen) { + // If the display is frozen, there is no reason to animate. + more = false; + } else if (mDimDeltaPerMs > 0) { + if (mDimCurrentAlpha > mDimTargetAlpha) { + more = false; + } + } else if (mDimDeltaPerMs < 0) { + if (mDimCurrentAlpha < mDimTargetAlpha) { + more = false; + } + } else { + more = false; + } + + // Do we need to continue animating? + if (more) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + + mDimSurface + ": alpha=" + mDimCurrentAlpha); + mLastDimAnimTime = currentTime; + mDimSurface.setAlpha(mDimCurrentAlpha); + animating = true; + } else { + mDimCurrentAlpha = mDimTargetAlpha; + mLastDimAnimTime = 0; + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + + mDimSurface + ": final alpha=" + mDimCurrentAlpha); + mDimSurface.setAlpha(mDimCurrentAlpha); + if (!dimming) { + if (SHOW_TRANSACTIONS) Log.i(TAG, " DIM " + mDimSurface + + ": HIDE"); + try { + mDimSurface.hide(); + } catch (RuntimeException e) { + Log.w(TAG, "Illegal argument exception hiding dim surface"); + } + mDimShown = false; + } + } + } + return animating; + } + + public void printTo(PrintWriter pw) { + pw.print(" mDimShown="); pw.print(mDimShown); + pw.print(" current="); pw.print(mDimCurrentAlpha); + pw.print(" target="); pw.print(mDimTargetAlpha); + pw.print(" delta="); pw.print(mDimDeltaPerMs); + pw.print(" lastAnimTime="); pw.println(mLastDimAnimTime); + } + } + + /** + * Animation that fade in after 0.5 interpolate time, or fade out in reverse order. + * This is used for opening/closing transition for apps in compatible mode. + */ + private static class FadeInOutAnimation extends Animation { + int mWidth; + boolean mFadeIn; + + public FadeInOutAnimation(boolean fadeIn) { + setInterpolator(new AccelerateInterpolator()); + setDuration(DEFAULT_FADE_IN_OUT_DURATION); + mFadeIn = fadeIn; + } + + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + float x = interpolatedTime; + if (!mFadeIn) { + x = 1.0f - x; // reverse the interpolation for fade out + } + if (x < 0.5) { + // move the window out of the screen. + t.getMatrix().setTranslate(mWidth, 0); + } else { + t.getMatrix().setTranslate(0, 0);// show + t.setAlpha((x - 0.5f) * 2); + } + } + + @Override + public void initialize(int width, int height, int parentWidth, int parentHeight) { + // width is the screen width {@see AppWindowToken#stepAnimatinoLocked} + mWidth = width; + } + + @Override + public int getZAdjustment() { + return Animation.ZORDER_TOP; + } + } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 2fe4dd4..d9c40ec 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -32,6 +32,7 @@ import android.app.ActivityThread; import android.app.AlertDialog; import android.app.ApplicationErrorReport; import android.app.Dialog; +import android.app.IActivityController; import android.app.IActivityWatcher; import android.app.IApplicationThread; import android.app.IInstrumentationWatcher; @@ -56,6 +57,7 @@ import android.content.pm.IPackageDataObserver; import android.content.pm.IPackageManager; import android.content.pm.InstrumentationInfo; import android.content.pm.PackageManager; +import android.content.pm.PathPermission; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; @@ -75,6 +77,7 @@ import android.os.Parcel; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.Process; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SystemClock; @@ -824,8 +827,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen String mOrigDebugApp = null; boolean mOrigWaitForDebugger = false; boolean mAlwaysFinishActivities = false; - IActivityWatcher mWatcher = null; + IActivityController mController = null; + final RemoteCallbackList<IActivityWatcher> mWatchers + = new RemoteCallbackList<IActivityWatcher>(); + /** * Callback of last caller to {@link #requestPss}. */ @@ -1622,7 +1628,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen /** * This is a simplified version of topRunningActivityLocked that provides a number of - * optional skip-over modes. It is intended for use with the ActivityWatcher hook only. + * optional skip-over modes. It is intended for use with the ActivityController hook only. * * @param token If non-null, any history records matching this token will be skipped. * @param taskId If non-zero, we'll attempt to skip over records with the same task ID. @@ -1727,10 +1733,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } ensurePackageDexOpt(r.intent.getComponent().getPackageName()); app.thread.scheduleLaunchActivity(new Intent(r.intent), r, + System.identityHashCode(r), r.info, r.icicle, results, newIntents, !andResume, isNextTransitionForward()); - // Update usage stats for launched activity - updateUsageStats(r, true); } catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity @@ -2183,6 +2188,8 @@ public final class ActivityManagerService extends ActivityManagerNative implemen mHandler.sendMessage(msg); } + reportResumedActivity(next); + next.thumbnail = null; setFocusedActivityLocked(next); next.resumeKeyDispatchingLocked(); @@ -2453,6 +2460,26 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } + private void reportResumedActivity(HistoryRecord r) { + //Log.i(TAG, "**** REPORT RESUME: " + r); + + final int identHash = System.identityHashCode(r); + updateUsageStats(r, true); + + int i = mWatchers.beginBroadcast(); + while (i > 0) { + i--; + IActivityWatcher w = mWatchers.getBroadcastItem(i); + if (w != null) { + try { + w.activityResuming(identHash); + } catch (RemoteException e) { + } + } + } + mWatchers.finishBroadcast(); + } + /** * Ensure that the top activity in the stack is resumed. * @@ -2641,10 +2668,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen EventLog.writeEvent(LOG_AM_RESUME_ACTIVITY, System.identityHashCode(next), next.task.taskId, next.shortComponentName); - updateUsageStats(next, true); next.app.thread.scheduleResumeActivity(next, isNextTransitionForward()); + pauseIfSleepingLocked(); } catch (Exception e) { @@ -3061,16 +3088,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen throw new SecurityException(msg); } - if (mWatcher != null) { + if (mController != null) { boolean abort = false; try { // The Intent we give to the watcher has the extra data // stripped off, since it can contain private information. Intent watchIntent = intent.cloneFilter(); - abort = !mWatcher.activityStarting(watchIntent, + abort = !mController.activityStarting(watchIntent, aInfo.applicationInfo.packageName); } catch (RemoteException e) { - mWatcher = null; + mController = null; } if (abort) { @@ -3495,8 +3522,6 @@ public final class ActivityManagerService extends ActivityManagerNative implemen intent = new Intent(intent); // Collect information about the target of the Intent. - // Must do this before locking, because resolving the intent - // may require launching a process to run its content provider. ActivityInfo aInfo; try { ResolveInfo rInfo = @@ -3630,17 +3655,24 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - final int startActivityInPackage(int uid, + public final int startActivityInPackage(int uid, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, boolean onlyIfNeeded) { + + // This is so super not safe, that only the system (or okay root) + // can do it. + final int callingUid = Binder.getCallingUid(); + if (callingUid != 0 && callingUid != Process.myUid()) { + throw new SecurityException( + "startActivityInPackage only available to the system"); + } + final boolean componentSpecified = intent.getComponent() != null; // Don't modify the client's object! intent = new Intent(intent); // Collect information about the target of the Intent. - // Must do this before locking, because resolving the intent - // may require launching a process to run its content provider. ActivityInfo aInfo; try { ResolveInfo rInfo = @@ -3967,16 +3999,16 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } synchronized(this) { - if (mWatcher != null) { + if (mController != null) { // Find the first activity that is not finishing. HistoryRecord next = topRunningActivityLocked(token, 0); if (next != null) { // ask watcher if this is allowed boolean resumeOK = true; try { - resumeOK = mWatcher.activityResuming(next.packageName); + resumeOK = mController.activityResuming(next.packageName); } catch (RemoteException e) { - mWatcher = null; + mController = null; } if (!resumeOK) { @@ -4468,9 +4500,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - if (mWatcher != null) { + if (mController != null) { try { - int res = mWatcher.appNotResponding(app.processName, + int res = mController.appNotResponding(app.processName, app.pid, info.toString()); if (res != 0) { if (res < 0) { @@ -4486,7 +4518,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } } catch (RemoteException e) { - mWatcher = null; + mController = null; } } @@ -6611,7 +6643,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } /** - * TODO: Add mWatcher hook + * TODO: Add mController hook */ public void moveTaskToFront(int task) { enforceCallingPermission(android.Manifest.permission.REORDER_TASKS, @@ -6756,7 +6788,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // If we have a watcher, preflight the move before committing to it. First check // for *other* available tasks, but if none are available, then try again allowing the // current task to be selected. - if (mWatcher != null) { + if (mController != null) { HistoryRecord next = topRunningActivityLocked(null, task); if (next == null) { next = topRunningActivityLocked(null, 0); @@ -6765,9 +6797,9 @@ public final class ActivityManagerService extends ActivityManagerNative implemen // ask watcher if this is allowed boolean moveOK = true; try { - moveOK = mWatcher.activityResuming(next.packageName); + moveOK = mController.activityResuming(next.packageName); } catch (RemoteException e) { - mWatcher = null; + mController = null; } if (!moveOK) { return false; @@ -7072,6 +7104,27 @@ public final class ActivityManagerService extends ActivityManagerNative implemen == PackageManager.PERMISSION_GRANTED) { return null; } + + PathPermission[] pps = cpi.pathPermissions; + if (pps != null) { + int i = pps.length; + while (i > 0) { + i--; + PathPermission pp = pps[i]; + if (checkComponentPermission(pp.getReadPermission(), callingPid, callingUid, + cpi.exported ? -1 : cpi.applicationInfo.uid) + == PackageManager.PERMISSION_GRANTED + && mode == ParcelFileDescriptor.MODE_READ_ONLY || mode == -1) { + return null; + } + if (checkComponentPermission(pp.getWritePermission(), callingPid, callingUid, + cpi.exported ? -1 : cpi.applicationInfo.uid) + == PackageManager.PERMISSION_GRANTED) { + return null; + } + } + } + String msg = "Permission Denial: opening provider " + cpi.name + " from " + (r != null ? r : "(null)") + " (pid=" + callingPid + ", uid=" + callingUid + ") requires " @@ -7657,14 +7710,22 @@ public final class ActivityManagerService extends ActivityManagerNative implemen } } - public void setActivityWatcher(IActivityWatcher watcher) { + public void setActivityController(IActivityController controller) { enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER, - "setActivityWatcher()"); + "setActivityController()"); synchronized (this) { - mWatcher = watcher; + mController = controller; } } + public void registerActivityWatcher(IActivityWatcher watcher) { + mWatchers.register(watcher); + } + + public void unregisterActivityWatcher(IActivityWatcher watcher) { + mWatchers.unregister(watcher); + } + public final void enterSafeMode() { synchronized(this) { // It only makes sense to do this before the system is ready @@ -8225,11 +8286,11 @@ public final class ActivityManagerService extends ActivityManagerNative implemen //Process.sendSignal(MY_PID, Process.SIGNAL_QUIT); } - if (mWatcher != null) { + if (mController != null) { try { String name = r != null ? r.processName : null; int pid = r != null ? r.pid : Binder.getCallingPid(); - if (!mWatcher.appCrashed(name, pid, + if (!mController.appCrashed(name, pid, shortMsg, longMsg, crashData)) { Log.w(TAG, "Force-killing crashed app " + name + " at watcher's request"); @@ -8237,7 +8298,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen return 0; } } catch (RemoteException e) { - mWatcher = null; + mController = null; } } @@ -8663,7 +8724,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen + " mDebugTransient=" + mDebugTransient + " mOrigWaitForDebugger=" + mOrigWaitForDebugger); pw.println(" mAlwaysFinishActivities=" + mAlwaysFinishActivities - + " mWatcher=" + mWatcher); + + " mController=" + mController); } } @@ -10810,6 +10871,29 @@ public final class ActivityManagerService extends ActivityManagerNative implemen mHandler.sendEmptyMessage(UPDATE_TIME_ZONE); } + /* + * Prevent non-system code (defined here to be non-persistent + * processes) from sending protected broadcasts. + */ + if (callingUid == Process.SYSTEM_UID || callingUid == Process.PHONE_UID + || callingUid == Process.SHELL_UID || callingUid == 0) { + // Always okay. + } else if (callerApp == null || !callerApp.persistent) { + try { + if (ActivityThread.getPackageManager().isProtectedBroadcast( + intent.getAction())) { + String msg = "Permission Denial: not allowed to send broadcast " + + intent.getAction() + " from pid=" + + callingPid + ", uid=" + callingUid; + Log.w(TAG, msg); + throw new SecurityException(msg); + } + } catch (RemoteException e) { + Log.w(TAG, "Remote exception", e); + return BROADCAST_SUCCESS; + } + } + // Add to the sticky list if requested. if (sticky) { if (checkPermission(android.Manifest.permission.BROADCAST_STICKY, @@ -11755,10 +11839,12 @@ public final class ActivityManagerService extends ActivityManagerNative implemen config.reqTouchScreen = mConfiguration.touchscreen; config.reqKeyboardType = mConfiguration.keyboard; config.reqNavigation = mConfiguration.navigation; - if (mConfiguration.navigation != Configuration.NAVIGATION_NONAV) { + if (mConfiguration.navigation == Configuration.NAVIGATION_DPAD + || mConfiguration.navigation == Configuration.NAVIGATION_TRACKBALL) { config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV; } - if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED) { + if (mConfiguration.keyboard != Configuration.KEYBOARD_UNDEFINED + && mConfiguration.keyboard != Configuration.KEYBOARD_NOKEYS) { config.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD; } } diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index 39a1ee0..c834b34 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -41,7 +41,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub { final BatteryStatsImpl mStats; Context mContext; - + BatteryStatsService(String filename) { mStats = new BatteryStatsImpl(filename); } diff --git a/services/java/com/android/server/am/UsageStatsService.java b/services/java/com/android/server/am/UsageStatsService.java index 2d58659..d458911 100755 --- a/services/java/com/android/server/am/UsageStatsService.java +++ b/services/java/com/android/server/am/UsageStatsService.java @@ -39,6 +39,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -617,7 +618,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } private void collectDumpInfoFLOCK(PrintWriter pw, boolean isCompactOutput, - boolean deleteAfterPrint) { + boolean deleteAfterPrint, HashSet<String> packages) { List<String> fileList = getUsageStatsFileListFLOCK(); if (fileList == null) { return; @@ -633,7 +634,8 @@ public final class UsageStatsService extends IUsageStats.Stub { String dateStr = file.substring(FILE_PREFIX.length()); try { Parcel in = getParcelForFile(dFile); - collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput); + collectDumpInfoFromParcelFLOCK(in, pw, dateStr, isCompactOutput, + packages); if (deleteAfterPrint) { // Delete old file after collecting info only for checkin requests dFile.delete(); @@ -648,7 +650,7 @@ public final class UsageStatsService extends IUsageStats.Stub { } private void collectDumpInfoFromParcelFLOCK(Parcel in, PrintWriter pw, - String date, boolean isCompactOutput) { + String date, boolean isCompactOutput, HashSet<String> packages) { StringBuilder sb = new StringBuilder(512); if (isCompactOutput) { sb.append("D:"); @@ -678,7 +680,10 @@ public final class UsageStatsService extends IUsageStats.Stub { } sb.setLength(0); PkgUsageStatsExtended pus = new PkgUsageStatsExtended(in); - if (isCompactOutput) { + if (packages != null && !packages.contains(pkgName)) { + // This package has not been requested -- don't print + // anything for it. + } else if (isCompactOutput) { sb.append("P:"); sb.append(pkgName); sb.append(','); @@ -765,6 +770,25 @@ public final class UsageStatsService extends IUsageStats.Stub { return false; } + /** + * Searches array of arguments for the specified string's data + * @param args array of argument strings + * @param value value to search for + * @return the string of data after the arg, or null if there is none + */ + private static String scanArgsData(String[] args, String value) { + if (args != null) { + final int N = args.length; + for (int i=0; i<N; i++) { + if (value.equals(args[i])) { + i++; + return i < N ? args[i] : null; + } + } + } + return null; + } + @Override /* * The data persisted to file is parsed and the stats are computed. @@ -773,6 +797,7 @@ public final class UsageStatsService extends IUsageStats.Stub { final boolean isCheckinRequest = scanArgs(args, "--checkin"); final boolean isCompactOutput = isCheckinRequest || scanArgs(args, "-c"); final boolean deleteAfterPrint = isCheckinRequest || scanArgs(args, "-d"); + final String rawPackages = scanArgsData(args, "--packages"); // Make sure the current stats are written to the file. This // doesn't need to be done if we are deleting files after printing, @@ -781,8 +806,27 @@ public final class UsageStatsService extends IUsageStats.Stub { writeStatsToFile(true); } + HashSet<String> packages = null; + if (rawPackages != null) { + if (!"*".equals(rawPackages)) { + // A * is a wildcard to show all packages. + String[] names = rawPackages.split(","); + for (String n : names) { + if (packages == null) { + packages = new HashSet<String>(); + } + packages.add(n); + } + } + } else if (isCheckinRequest) { + // If checkin doesn't specify any packages, then we simply won't + // show anything. + Log.w(TAG, "Checkin without packages"); + return; + } + synchronized (mFileLock) { - collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint); + collectDumpInfoFLOCK(pw, isCompactOutput, deleteAfterPrint, packages); } } diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java index 7a8d4e5..a4b47b5 100644 --- a/services/java/com/android/server/status/StatusBarPolicy.java +++ b/services/java/com/android/server/status/StatusBarPolicy.java @@ -626,7 +626,9 @@ public class StatusBarPolicy { && mBatteryThreshold > BATTERY_THRESHOLD_WARNING))) { // Broadcast the low battery warning mSentLowBatteryBroadcast = true; - mContext.sendBroadcast(new Intent(Intent.ACTION_BATTERY_LOW)); + Intent batIntent = new Intent(Intent.ACTION_BATTERY_LOW); + batIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcast(batIntent); if (SHOW_LOW_BATTERY_WARNING) { if (false) { @@ -644,7 +646,9 @@ public class StatusBarPolicy { } else if (mBatteryThreshold < BATTERY_THRESHOLD_WARNING) { if (mSentLowBatteryBroadcast == true) { mSentLowBatteryBroadcast = false; - mContext.sendBroadcast(new Intent(Intent.ACTION_BATTERY_OKAY)); + Intent batIntent = new Intent(Intent.ACTION_BATTERY_OKAY); + batIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); + mContext.sendBroadcast(batIntent); } if (SHOW_LOW_BATTERY_WARNING) { if (mLowBatteryDialog != null) { |