diff options
Diffstat (limited to 'services/java/com/android/server')
17 files changed, 927 insertions, 334 deletions
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 1341dd4..bfca851 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -72,7 +72,6 @@ import com.android.internal.net.VpnConfig; import com.android.internal.telephony.Phone; import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; - import com.google.android.collect.Lists; import com.google.android.collect.Sets; @@ -89,7 +88,6 @@ import java.util.Collection; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.List; -import java.util.concurrent.atomic.AtomicBoolean; /** * @hide @@ -251,6 +249,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { private static final int EVENT_SEND_STICKY_BROADCAST_INTENT = MAX_NETWORK_STATE_TRACKER_EVENT + 12; + /** + * Used internally to + * {@link NetworkStateTracker#setPolicyDataEnable(boolean)}. + */ + private static final int EVENT_SET_POLICY_DATA_ENABLE = MAX_NETWORK_STATE_TRACKER_EVENT + 13; + private Handler mHandler; // list of DeathRecipients used to make sure features are turned off when @@ -1282,7 +1286,25 @@ public class ConnectivityService extends IConnectivityManager.Stub { if (VDBG) { log(mNetTrackers[ConnectivityManager.TYPE_MOBILE].toString() + enabled); } - mNetTrackers[ConnectivityManager.TYPE_MOBILE].setDataEnable(enabled); + mNetTrackers[ConnectivityManager.TYPE_MOBILE].setUserDataEnable(enabled); + } + } + + @Override + public void setPolicyDataEnable(int networkType, boolean enabled) { + // only someone like NPMS should only be calling us + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + + mHandler.sendMessage(mHandler.obtainMessage( + EVENT_SET_POLICY_DATA_ENABLE, networkType, (enabled ? ENABLED : DISABLED))); + } + + private void handleSetPolicyDataEnable(int networkType, boolean enabled) { + if (isNetworkTypeValid(networkType)) { + final NetworkStateTracker tracker = mNetTrackers[networkType]; + if (tracker != null) { + tracker.setPolicyDataEnable(enabled); + } } } @@ -2263,6 +2285,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { sendStickyBroadcast(intent); break; } + case EVENT_SET_POLICY_DATA_ENABLE: { + final int networkType = msg.arg1; + final boolean enabled = msg.arg2 == ENABLED; + handleSetPolicyDataEnable(networkType, enabled); + } } } } diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index d549308..f1b8bae 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -1556,13 +1556,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return false; } } - - LockPatternUtils utils = new LockPatternUtils(mContext); - if(utils.checkPasswordHistory(password)) { - Slog.w(TAG, "resetPassword: password is the same as one of the last " - + getPasswordHistoryLength(null) + " passwords"); - return false; - } } int callingUid = Binder.getCallingUid(); diff --git a/services/java/com/android/server/DropBoxManagerService.java b/services/java/com/android/server/DropBoxManagerService.java index 5c878c9..d37c9ab 100644 --- a/services/java/com/android/server/DropBoxManagerService.java +++ b/services/java/com/android/server/DropBoxManagerService.java @@ -28,7 +28,6 @@ import android.os.Debug; import android.os.DropBoxManager; import android.os.FileUtils; import android.os.Handler; -import android.os.ParcelFileDescriptor; import android.os.StatFs; import android.os.SystemClock; import android.provider.Settings; @@ -45,14 +44,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.io.PrintWriter; -import java.io.UnsupportedEncodingException; import java.util.ArrayList; -import java.util.Comparator; import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; import java.util.SortedSet; import java.util.TreeSet; import java.util.zip.GZIPOutputStream; diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 73d790a..c11755b 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1,5 +1,4 @@ /* - * Copyright (C) 2006-2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of @@ -48,7 +47,6 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; @@ -57,7 +55,6 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.ContentObserver; -import android.graphics.BitmapFactory; import android.inputmethodservice.InputMethodService; import android.os.Binder; import android.os.Environment; @@ -98,12 +95,10 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.TreeMap; /** @@ -147,7 +142,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final Handler mHandler; final InputMethodSettings mSettings; final SettingsObserver mSettingsObserver; - final StatusBarManagerService mStatusBar; final IWindowManager mIWindowManager; final HandlerCaller mCaller; private final InputMethodFileManager mFileManager; @@ -162,10 +156,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE); // Ongoing notification - private final NotificationManager mNotificationManager; - private final KeyguardManager mKeyguardManager; - private final Notification mImeSwitcherNotification; - private final PendingIntent mImeSwitchPendingIntent; + private NotificationManager mNotificationManager; + private KeyguardManager mKeyguardManager; + private StatusBarManagerService mStatusBar; + private Notification mImeSwitcherNotification; + private PendingIntent mImeSwitchPendingIntent; private boolean mShowOngoingImeSwitcherForPhones; private boolean mNotificationShown; @@ -469,8 +464,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub // Pick another one... Slog.i(TAG, "Current input method removed: " + curInputMethodId); mImeWindowVis = 0; - mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, - mBackDisposition); + updateImeWindowStatusLocked(); if (!chooseNewDefaultIMELocked()) { changed = true; curIm = null; @@ -511,7 +505,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - public InputMethodManagerService(Context context, StatusBarManagerService statusBar) { + public InputMethodManagerService(Context context) { mContext = context; mRes = context.getResources(); mHandler = new Handler(this); @@ -524,10 +518,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } }); - mKeyguardManager = (KeyguardManager) - mContext.getSystemService(Context.KEYGUARD_SERVICE); - mNotificationManager = (NotificationManager) - mContext.getSystemService(Context.NOTIFICATION_SERVICE); mImeSwitcherNotification = new Notification(); mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default; mImeSwitcherNotification.when = 0; @@ -553,8 +543,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub screenOnOffFilt.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); mContext.registerReceiver(new ScreenOnOffReceiver(), screenOnOffFilt); - mStatusBar = statusBar; - statusBar.setIconVisibility("ime", false); mNotificationShown = false; // mSettings should be created before buildInputMethodListLocked @@ -608,10 +596,17 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - public void systemReady() { + public void systemReady(StatusBarManagerService statusBar) { synchronized (mMethodMap) { if (!mSystemReady) { mSystemReady = true; + mKeyguardManager = (KeyguardManager) + mContext.getSystemService(Context.KEYGUARD_SERVICE); + mNotificationManager = (NotificationManager) + mContext.getSystemService(Context.NOTIFICATION_SERVICE); + mStatusBar = statusBar; + statusBar.setIconVisibility("ime", false); + updateImeWindowStatusLocked(); mShowOngoingImeSwitcherForPhones = mRes.getBoolean( com.android.internal.R.bool.show_ongoing_ime_switcher); try { @@ -623,6 +618,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } + void updateImeWindowStatusLocked() { + setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition); + } + @Override public List<InputMethodInfo> getInputMethodList() { synchronized (mMethodMap) { @@ -993,6 +992,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub sessionState.session.finishSession(); } catch (RemoteException e) { Slog.w(TAG, "Session failed to close due to remote exception", e); + mImeWindowVis = 0; + updateImeWindowStatusLocked(); } } } @@ -1009,7 +1010,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mEnabledSession = null; mCurMethod = null; } - mStatusBar.setIconVisibility("ime", false); + if (mStatusBar != null) { + mStatusBar.setIconVisibility("ime", false); + } } @Override @@ -1046,7 +1049,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub synchronized (mMethodMap) { if (iconId == 0) { if (DEBUG) Slog.d(TAG, "hide the small icon for the input method"); - mStatusBar.setIconVisibility("ime", false); + if (mStatusBar != null) { + mStatusBar.setIconVisibility("ime", false); + } } else if (packageName != null) { if (DEBUG) Slog.d(TAG, "show a small icon for the input method"); CharSequence contentDescription = null; @@ -1057,9 +1062,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } catch (NameNotFoundException nnfe) { /* ignore */ } - mStatusBar.setIcon("ime", packageName, iconId, 0, - contentDescription != null ? contentDescription.toString() : null); - mStatusBar.setIconVisibility("ime", true); + if (mStatusBar != null) { + mStatusBar.setIcon("ime", packageName, iconId, 0, + contentDescription != null + ? contentDescription.toString() : null); + mStatusBar.setIconVisibility("ime", true); + } } } } finally { @@ -1112,6 +1120,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } + @SuppressWarnings("deprecation") @Override public void setImeWindowStatus(IBinder token, int vis, int backDisposition) { int uid = Binder.getCallingUid(); @@ -1125,7 +1134,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub synchronized (mMethodMap) { mImeWindowVis = vis; mBackDisposition = backDisposition; - mStatusBar.setImeWindowStatus(token, vis, backDisposition); + if (mStatusBar != null) { + mStatusBar.setImeWindowStatus(token, vis, backDisposition); + } final boolean iconVisibility = (vis & InputMethodService.IME_ACTIVE) != 0; final InputMethodInfo imi = mMethodMap.get(mCurMethodId); if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) { @@ -1142,12 +1153,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mImeSwitcherNotification.setLatestEventInfo( mContext, title, summary, mImeSwitchPendingIntent); - mNotificationManager.notify( - com.android.internal.R.string.select_input_method, - mImeSwitcherNotification); - mNotificationShown = true; + if (mNotificationManager != null) { + mNotificationManager.notify( + com.android.internal.R.string.select_input_method, + mImeSwitcherNotification); + mNotificationShown = true; + } } else { - if (mNotificationShown) { + if (mNotificationShown && mNotificationManager != null) { mNotificationManager.cancel( com.android.internal.R.string.select_input_method); mNotificationShown = false; @@ -1252,8 +1265,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mImeWindowVis = (mInputShown || hardKeyShown) ? ( InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE) : 0; - mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, - mBackDisposition); + updateImeWindowStatusLocked(); // If subtype is null, try to find the most applicable one from // getCurrentInputMethodSubtype. if (subtype == null) { @@ -1374,13 +1386,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid " + uid + ": " + client); mImeWindowVis = 0; - mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, - mBackDisposition); + updateImeWindowStatusLocked(); return false; } } catch (RemoteException e) { mImeWindowVis = 0; - mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition); + updateImeWindowStatusLocked(); return false; } } @@ -2151,7 +2162,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } }); - if (showSubtypes && !(mKeyguardManager.isKeyguardLocked() + if (showSubtypes && mKeyguardManager != null && !(mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure())) { mDialogBuilder.setPositiveButton( com.android.internal.R.string.configure_input_methods, @@ -2580,6 +2591,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } // TODO: We should change the return type from List to List<Parcelable> + @SuppressWarnings("rawtypes") @Override public List getShortcutInputMethodsAndSubtypes() { synchronized (mMethodMap) { diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 6edb132..7a3a344 100755 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -101,13 +101,8 @@ public class NotificationManagerService extends INotificationManager.Stub private Vibrator mVibrator = new Vibrator(); // for enabling and disabling notification pulse behavior - private boolean mScreenOn = true; private boolean mInCall = false; private boolean mNotificationPulseEnabled; - // This is true if we have received a new notification while the screen is off - // (that is, if mLedNotification was set while the screen was off) - // This is reset to false when the screen is turned on. - private boolean mPendingPulseNotification; private final ArrayList<NotificationRecord> mNotificationList = new ArrayList<NotificationRecord>(); @@ -349,12 +344,6 @@ public class NotificationManagerService extends INotificationManager.Stub cancelAllNotificationsInt(pkgName, 0, 0, !queryRestart); } } - } else if (action.equals(Intent.ACTION_SCREEN_ON)) { - mScreenOn = true; - updateNotificationPulse(); - } else if (action.equals(Intent.ACTION_SCREEN_OFF)) { - mScreenOn = false; - updateNotificationPulse(); } else if (action.equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) { mInCall = (intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_OFFHOOK)); updateNotificationPulse(); @@ -1059,11 +1048,6 @@ public class NotificationManagerService extends INotificationManager.Stub // lock on mNotificationList private void updateLightsLocked() { - // clear pending pulse notification if screen is on - if (mScreenOn || mLedNotification == null) { - mPendingPulseNotification = false; - } - // handle notification lights if (mLedNotification == null) { // get next notification, if any @@ -1071,14 +1055,10 @@ public class NotificationManagerService extends INotificationManager.Stub if (n > 0) { mLedNotification = mLights.get(n-1); } - if (mLedNotification != null && !mScreenOn) { - mPendingPulseNotification = true; - } } - // we only flash if screen is off and persistent pulsing is enabled - // and we are not currently in a call - if (!mPendingPulseNotification || mScreenOn || mInCall) { + // Don't flash while we are in a call + if (mLedNotification == null || mInCall) { mNotificationLight.turnOff(); } else { int ledARGB = mLedNotification.notification.ledARGB; diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index d80a2cd..cbd986f 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -161,6 +161,7 @@ public class PowerManagerService extends IPowerManager.Stub private int mStayOnConditions = 0; private final int[] mBroadcastQueue = new int[] { -1, -1, -1 }; private final int[] mBroadcastWhy = new int[3]; + private boolean mBroadcastingScreenOff = false; private int mPartialCount = 0; private int mPowerState; // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER, @@ -1342,6 +1343,10 @@ public class PowerManagerService extends IPowerManager.Stub mBroadcastWakeLock.release(); } + // The broadcast queue has changed; make sure the screen is on if it + // is now possible for it to be. + updateNativePowerStateLocked(); + // Now send the message. if (index >= 0) { // Acquire the broadcast wake lock before changing the power @@ -1370,6 +1375,9 @@ public class PowerManagerService extends IPowerManager.Stub mBroadcastWhy[i] = mBroadcastWhy[i+1]; } policy = getPolicyLocked(); + if (value == 0) { + mBroadcastingScreenOff = true; + } } if (value == 1) { mScreenOnStart = SystemClock.uptimeMillis(); @@ -1412,6 +1420,8 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (mLocks) { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, mBroadcastWakeLock.mCount); + mBroadcastingScreenOff = false; + updateNativePowerStateLocked(); mBroadcastWakeLock.release(); } } @@ -1442,6 +1452,10 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (mLocks) { EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0, SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount); + synchronized (mLocks) { + mBroadcastingScreenOff = false; + updateNativePowerStateLocked(); + } mBroadcastWakeLock.release(); } } @@ -1768,6 +1782,22 @@ public class PowerManagerService extends IPowerManager.Stub } private void updateNativePowerStateLocked() { + if ((mPowerState & SCREEN_ON_BIT) != 0) { + // Don't turn screen on if we are currently reporting a screen off. + // This is to avoid letting the screen go on before things like the + // lock screen have been displayed due to it going off. + if (mBroadcastingScreenOff) { + // Currently broadcasting that the screen is off. Don't + // allow screen to go on until that is done. + return; + } + for (int i=0; i<mBroadcastQueue.length; i++) { + if (mBroadcastQueue[i] == 0) { + // A screen off is currently enqueued. + return; + } + } + } nativeSetPowerState( (mPowerState & SCREEN_ON_BIT) != 0, (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT); diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 5dd3c5b..e6f92a5 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -40,6 +40,7 @@ import android.server.BluetoothService; import android.server.search.SearchManagerService; import android.util.DisplayMetrics; import android.util.EventLog; +import android.util.Log; import android.util.Slog; import android.view.WindowManager; @@ -66,6 +67,11 @@ class ServerThread extends Thread { ContentResolver mContentResolver; + void reportWtf(String msg, Throwable e) { + Slog.w(TAG, "***********************************************"); + Log.wtf(TAG, "BOOT FAILURE " + msg, e); + } + @Override public void run() { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, @@ -116,7 +122,6 @@ class ServerThread extends Thread { WindowManagerService wm = null; BluetoothService bluetooth = null; BluetoothA2dpService bluetoothA2dp = null; - WiredAccessoryObserver wiredAccessory = null; DockObserver dock = null; UsbService usb = null; UiModeManagerService uiMode = null; @@ -222,7 +227,8 @@ class ServerThread extends Thread { } } catch (RuntimeException e) { - Slog.e("System", "Failure starting core service", e); + Slog.e("System", "******************************************"); + Slog.e("System", "************ Failure starting core service", e); } DevicePolicyManagerService devicePolicy = null; @@ -235,13 +241,52 @@ class ServerThread extends Thread { CountryDetectorService countryDetector = null; TextServicesManagerService tsms = null; + // Bring up services needed for UI. + if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { + try { + Slog.i(TAG, "Input Method Service"); + imm = new InputMethodManagerService(context); + ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm); + } catch (Throwable e) { + reportWtf("starting Input Manager Service", e); + } + + try { + Slog.i(TAG, "Accessibility Manager"); + ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, + new AccessibilityManagerService(context)); + } catch (Throwable e) { + reportWtf("starting Accessibility Manager", e); + } + } + + try { + wm.displayReady(); + } catch (Throwable e) { + reportWtf("making display ready", e); + } + + try { + pm.performBootDexOpt(); + } catch (Throwable e) { + reportWtf("performing boot dexopt", e); + } + + try { + ActivityManagerNative.getDefault().showBootMessage( + context.getResources().getText( + com.android.internal.R.string.android_upgrading_starting_apps), + false); + } catch (RemoteException e) { + } + if (factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try { Slog.i(TAG, "Device Policy"); devicePolicy = new DevicePolicyManagerService(context); ServiceManager.addService(Context.DEVICE_POLICY_SERVICE, devicePolicy); } catch (Throwable e) { - Slog.e(TAG, "Failure starting DevicePolicyService", e); + reportWtf("starting DevicePolicyService", e); } try { @@ -249,7 +294,7 @@ class ServerThread extends Thread { statusBar = new StatusBarManagerService(context, wm); ServiceManager.addService(Context.STATUS_BAR_SERVICE, statusBar); } catch (Throwable e) { - Slog.e(TAG, "Failure starting StatusBarManagerService", e); + reportWtf("starting StatusBarManagerService", e); } try { @@ -257,15 +302,7 @@ class ServerThread extends Thread { ServiceManager.addService(Context.CLIPBOARD_SERVICE, new ClipboardService(context)); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Clipboard Service", e); - } - - try { - Slog.i(TAG, "Input Method Service"); - imm = new InputMethodManagerService(context, statusBar); - ServiceManager.addService(Context.INPUT_METHOD_SERVICE, imm); - } catch (Throwable e) { - Slog.e(TAG, "Failure starting Input Manager Service", e); + reportWtf("starting Clipboard Service", e); } try { @@ -273,7 +310,7 @@ class ServerThread extends Thread { networkManagement = NetworkManagementService.create(context); ServiceManager.addService(Context.NETWORKMANAGEMENT_SERVICE, networkManagement); } catch (Throwable e) { - Slog.e(TAG, "Failure starting NetworkManagement Service", e); + reportWtf("starting NetworkManagement Service", e); } try { @@ -281,7 +318,7 @@ class ServerThread extends Thread { tsms = new TextServicesManagerService(context); ServiceManager.addService(Context.TEXT_SERVICES_MANAGER_SERVICE, tsms); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Text Service Manager Service", e); + reportWtf("starting Text Service Manager Service", e); } try { @@ -289,7 +326,7 @@ class ServerThread extends Thread { networkStats = new NetworkStatsService(context, networkManagement, alarm); ServiceManager.addService(Context.NETWORK_STATS_SERVICE, networkStats); } catch (Throwable e) { - Slog.e(TAG, "Failure starting NetworkStats Service", e); + reportWtf("starting NetworkStats Service", e); } try { @@ -299,7 +336,7 @@ class ServerThread extends Thread { networkStats, networkManagement); ServiceManager.addService(Context.NETWORK_POLICY_SERVICE, networkPolicy); } catch (Throwable e) { - Slog.e(TAG, "Failure starting NetworkPolicy Service", e); + reportWtf("starting NetworkPolicy Service", e); } try { @@ -307,7 +344,7 @@ class ServerThread extends Thread { wifiP2p = new WifiP2pService(context); ServiceManager.addService(Context.WIFI_P2P_SERVICE, wifiP2p); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Wi-Fi P2pService", e); + reportWtf("starting Wi-Fi P2pService", e); } try { @@ -316,7 +353,7 @@ class ServerThread extends Thread { ServiceManager.addService(Context.WIFI_SERVICE, wifi); wifi.checkAndStartWifi(); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Wi-Fi Service", e); + reportWtf("starting Wi-Fi Service", e); } try { @@ -327,7 +364,7 @@ class ServerThread extends Thread { networkPolicy.bindConnectivityManager(connectivity); wifiP2p.connectivityServiceReady(); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Connectivity Service", e); + reportWtf("starting Connectivity Service", e); } try { @@ -336,15 +373,7 @@ class ServerThread extends Thread { ServiceManager.addService( Context.THROTTLE_SERVICE, throttle); } catch (Throwable e) { - Slog.e(TAG, "Failure starting ThrottleService", e); - } - - try { - Slog.i(TAG, "Accessibility Manager"); - ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, - new AccessibilityManagerService(context)); - } catch (Throwable e) { - Slog.e(TAG, "Failure starting Accessibility Manager", e); + reportWtf("starting ThrottleService", e); } try { @@ -355,7 +384,7 @@ class ServerThread extends Thread { Slog.i(TAG, "Mount Service"); ServiceManager.addService("mount", new MountService(context)); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Mount Service", e); + reportWtf("starting Mount Service", e); } try { @@ -364,7 +393,7 @@ class ServerThread extends Thread { ServiceManager.addService(Context.NOTIFICATION_SERVICE, notification); networkPolicy.bindNotificationManager(notification); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Notification Manager", e); + reportWtf("starting Notification Manager", e); } try { @@ -372,7 +401,7 @@ class ServerThread extends Thread { ServiceManager.addService(DeviceStorageMonitorService.SERVICE, new DeviceStorageMonitorService(context)); } catch (Throwable e) { - Slog.e(TAG, "Failure starting DeviceStorageMonitor service", e); + reportWtf("starting DeviceStorageMonitor service", e); } try { @@ -380,7 +409,7 @@ class ServerThread extends Thread { location = new LocationManagerService(context); ServiceManager.addService(Context.LOCATION_SERVICE, location); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Location Manager", e); + reportWtf("starting Location Manager", e); } try { @@ -388,7 +417,7 @@ class ServerThread extends Thread { countryDetector = new CountryDetectorService(context); ServiceManager.addService(Context.COUNTRY_DETECTOR, countryDetector); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Country Detector", e); + reportWtf("starting Country Detector", e); } try { @@ -396,7 +425,7 @@ class ServerThread extends Thread { ServiceManager.addService(Context.SEARCH_SERVICE, new SearchManagerService(context)); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Search Service", e); + reportWtf("starting Search Service", e); } try { @@ -404,7 +433,7 @@ class ServerThread extends Thread { ServiceManager.addService(Context.DROPBOX_SERVICE, new DropBoxManagerService(context, new File("/data/system/dropbox"))); } catch (Throwable e) { - Slog.e(TAG, "Failure starting DropBoxManagerService", e); + reportWtf("starting DropBoxManagerService", e); } try { @@ -412,14 +441,14 @@ class ServerThread extends Thread { wallpaper = new WallpaperManagerService(context); ServiceManager.addService(Context.WALLPAPER_SERVICE, wallpaper); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Wallpaper Service", e); + reportWtf("starting Wallpaper Service", e); } try { Slog.i(TAG, "Audio Service"); ServiceManager.addService(Context.AUDIO_SERVICE, new AudioService(context)); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Audio Service", e); + reportWtf("starting Audio Service", e); } try { @@ -427,15 +456,15 @@ class ServerThread extends Thread { // Listen for dock station changes dock = new DockObserver(context, power); } catch (Throwable e) { - Slog.e(TAG, "Failure starting DockObserver", e); + reportWtf("starting DockObserver", e); } try { Slog.i(TAG, "Wired Accessory Observer"); // Listen for wired headset changes - wiredAccessory = new WiredAccessoryObserver(context); + new WiredAccessoryObserver(context); } catch (Throwable e) { - Slog.e(TAG, "Failure starting WiredAccessoryObserver", e); + reportWtf("starting WiredAccessoryObserver", e); } try { @@ -444,7 +473,7 @@ class ServerThread extends Thread { usb = new UsbService(context); ServiceManager.addService(Context.USB_SERVICE, usb); } catch (Throwable e) { - Slog.e(TAG, "Failure starting UsbService", e); + reportWtf("starting UsbService", e); } try { @@ -452,7 +481,7 @@ class ServerThread extends Thread { // Listen for UI mode changes uiMode = new UiModeManagerService(context); } catch (Throwable e) { - Slog.e(TAG, "Failure starting UiModeManagerService", e); + reportWtf("starting UiModeManagerService", e); } try { @@ -468,21 +497,21 @@ class ServerThread extends Thread { appWidget = new AppWidgetService(context); ServiceManager.addService(Context.APPWIDGET_SERVICE, appWidget); } catch (Throwable e) { - Slog.e(TAG, "Failure starting AppWidget Service", e); + reportWtf("starting AppWidget Service", e); } try { Slog.i(TAG, "Recognition Service"); recognition = new RecognitionManagerService(context); } catch (Throwable e) { - Slog.e(TAG, "Failure starting Recognition Service", e); + reportWtf("starting Recognition Service", e); } try { Slog.i(TAG, "DiskStats Service"); ServiceManager.addService("diskstats", new DiskStatsService(context)); } catch (Throwable e) { - Slog.e(TAG, "Failure starting DiskStats Service", e); + reportWtf("starting DiskStats Service", e); } try { @@ -494,14 +523,14 @@ class ServerThread extends Thread { ServiceManager.addService("samplingprofiler", new SamplingProfilerService(context)); } catch (Throwable e) { - Slog.e(TAG, "Failure starting SamplingProfiler Service", e); + reportWtf("starting SamplingProfiler Service", e); } try { Slog.i(TAG, "NetworkTimeUpdateService"); networkTimeUpdater = new NetworkTimeUpdateService(context); } catch (Throwable e) { - Slog.e(TAG, "Failure starting NetworkTimeUpdate service"); + reportWtf("starting NetworkTimeUpdate service", e); } } @@ -522,14 +551,26 @@ class ServerThread extends Thread { // It is now time to start up the app processes... if (devicePolicy != null) { - devicePolicy.systemReady(); + try { + devicePolicy.systemReady(); + } catch (Throwable e) { + reportWtf("making Device Policy Service ready", e); + } } if (notification != null) { - notification.systemReady(); + try { + notification.systemReady(); + } catch (Throwable e) { + reportWtf("making Notification Service ready", e); + } } - wm.systemReady(); + try { + wm.systemReady(); + } catch (Throwable e) { + reportWtf("making Window Manager Service ready", e); + } if (safeMode) { ActivityManagerService.self().showSafeModeOverlay(); @@ -547,7 +588,8 @@ class ServerThread extends Thread { power.systemReady(); try { pm.systemReady(); - } catch (RemoteException e) { + } catch (Throwable e) { + reportWtf("making Package Manager Service ready", e); } // These are needed to propagate to the runnable below. @@ -569,6 +611,7 @@ class ServerThread extends Thread { final CountryDetectorService countryDetectorF = countryDetector; final NetworkTimeUpdateService networkTimeUpdaterF = networkTimeUpdater; final TextServicesManagerService textServiceManagerServiceF = tsms; + final StatusBarManagerService statusBarF = statusBar; // We now tell the activity manager it is okay to run third party // code. It will call back into us once it has gotten to the state @@ -581,28 +624,96 @@ class ServerThread extends Thread { Slog.i(TAG, "Making services ready"); startSystemUi(contextF); - if (batteryF != null) batteryF.systemReady(); - if (networkManagementF != null) networkManagementF.systemReady(); - if (networkStatsF != null) networkStatsF.systemReady(); - if (networkPolicyF != null) networkPolicyF.systemReady(); - if (connectivityF != null) connectivityF.systemReady(); - if (dockF != null) dockF.systemReady(); - if (usbF != null) usbF.systemReady(); - if (uiModeF != null) uiModeF.systemReady(); - if (recognitionF != null) recognitionF.systemReady(); + try { + if (batteryF != null) batteryF.systemReady(); + } catch (Throwable e) { + reportWtf("making Battery Service ready", e); + } + try { + if (networkManagementF != null) networkManagementF.systemReady(); + } catch (Throwable e) { + reportWtf("making Network Managment Service ready", e); + } + try { + if (networkStatsF != null) networkStatsF.systemReady(); + } catch (Throwable e) { + reportWtf("making Network Stats Service ready", e); + } + try { + if (networkPolicyF != null) networkPolicyF.systemReady(); + } catch (Throwable e) { + reportWtf("making Network Policy Service ready", e); + } + try { + if (connectivityF != null) connectivityF.systemReady(); + } catch (Throwable e) { + reportWtf("making Connectivity Service ready", e); + } + try { + if (dockF != null) dockF.systemReady(); + } catch (Throwable e) { + reportWtf("making Dock Service ready", e); + } + try { + if (usbF != null) usbF.systemReady(); + } catch (Throwable e) { + reportWtf("making USB Service ready", e); + } + try { + if (uiModeF != null) uiModeF.systemReady(); + } catch (Throwable e) { + reportWtf("making UI Mode Service ready", e); + } + try { + if (recognitionF != null) recognitionF.systemReady(); + } catch (Throwable e) { + reportWtf("making Recognition Service ready", e); + } Watchdog.getInstance().start(); // It is now okay to let the various system services start their // third party code... - if (appWidgetF != null) appWidgetF.systemReady(safeMode); - if (wallpaperF != null) wallpaperF.systemReady(); - if (immF != null) immF.systemReady(); - if (locationF != null) locationF.systemReady(); - if (countryDetectorF != null) countryDetectorF.systemReady(); - if (throttleF != null) throttleF.systemReady(); - if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemReady(); - if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady(); + try { + if (appWidgetF != null) appWidgetF.systemReady(safeMode); + } catch (Throwable e) { + reportWtf("making App Widget Service ready", e); + } + try { + if (wallpaperF != null) wallpaperF.systemReady(); + } catch (Throwable e) { + reportWtf("making Wallpaper Service ready", e); + } + try { + if (immF != null) immF.systemReady(statusBarF); + } catch (Throwable e) { + reportWtf("making Input Method Service ready", e); + } + try { + if (locationF != null) locationF.systemReady(); + } catch (Throwable e) { + reportWtf("making Location Service ready", e); + } + try { + if (countryDetectorF != null) countryDetectorF.systemReady(); + } catch (Throwable e) { + reportWtf("making Country Detector Service ready", e); + } + try { + if (throttleF != null) throttleF.systemReady(); + } catch (Throwable e) { + reportWtf("making Throttle Service ready", e); + } + try { + if (networkTimeUpdaterF != null) networkTimeUpdaterF.systemReady(); + } catch (Throwable e) { + reportWtf("making Network Time Service ready", e); + } + try { + if (textServiceManagerServiceF != null) textServiceManagerServiceF.systemReady(); + } catch (Throwable e) { + reportWtf("making Text Services Manager Service ready", e); + } } }); diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java index 90824a6..321274f 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -41,6 +41,7 @@ import android.service.textservice.SpellCheckerService; import android.text.TextUtils; import android.util.Slog; import android.view.textservice.SpellCheckerInfo; +import android.view.textservice.SpellCheckerSubtype; import java.io.IOException; import java.util.ArrayList; @@ -172,9 +173,9 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { @Override public SpellCheckerInfo getCurrentSpellChecker(String locale) { synchronized (mSpellCheckerMap) { - String curSpellCheckerId = + final String curSpellCheckerId = Settings.Secure.getString(mContext.getContentResolver(), - Settings.Secure.SPELL_CHECKER_SERVICE); + Settings.Secure.SELECTED_SPELL_CHECKER); if (DBG) { Slog.w(TAG, "getCurrentSpellChecker: " + curSpellCheckerId); } @@ -185,6 +186,47 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } + // TODO: Save SpellCheckerSubtype by supported languages. + @Override + public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String locale) { + synchronized (mSpellCheckerMap) { + final String subtypeHashCodeStr = + Settings.Secure.getString(mContext.getContentResolver(), + Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE); + if (DBG) { + Slog.w(TAG, "getCurrentSpellChecker: " + subtypeHashCodeStr); + } + final SpellCheckerInfo sci = getCurrentSpellChecker(null); + if (sci == null || sci.getSubtypeCount() == 0) { + if (DBG) { + Slog.w(TAG, "Subtype not found."); + } + return null; + } + if (TextUtils.isEmpty(subtypeHashCodeStr)) { + if (DBG) { + Slog.w(TAG, "Return first subtype in " + sci.getId()); + } + // Return the first Subtype if there is no settings for the current subtype. + return sci.getSubtypeAt(0); + } + final int hashCode = Integer.valueOf(subtypeHashCodeStr); + for (int i = 0; i < sci.getSubtypeCount(); ++i) { + final SpellCheckerSubtype scs = sci.getSubtypeAt(i); + if (scs.hashCode() == hashCode) { + if (DBG) { + Slog.w(TAG, "Return subtype " + scs.hashCode()); + } + return scs; + } + } + if (DBG) { + Slog.w(TAG, "Return first subtype in " + sci.getId()); + } + return sci.getSubtypeAt(0); + } + } + @Override public void getSpellCheckerService(String sciId, String locale, ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener, @@ -253,6 +295,13 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { return; } + @Override + public boolean isSpellCheckerEnabled() { + synchronized(mSpellCheckerMap) { + return isSpellCheckerEnabledLocked(); + } + } + private void startSpellCheckerServiceInnerLocked(SpellCheckerInfo info, String locale, ITextServicesSessionListener tsListener, ISpellCheckerSessionListener scListener, int uid, Bundle bundle) { @@ -301,7 +350,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } @Override - public void setCurrentSpellChecker(String sciId) { + public void setCurrentSpellChecker(String locale, String sciId) { synchronized(mSpellCheckerMap) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.WRITE_SECURE_SETTINGS) @@ -314,6 +363,34 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } + @Override + public void setCurrentSpellCheckerSubtype(String locale, int hashCode) { + synchronized(mSpellCheckerMap) { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.WRITE_SECURE_SETTINGS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "Requires permission " + + android.Manifest.permission.WRITE_SECURE_SETTINGS); + } + setCurrentSpellCheckerSubtypeLocked(hashCode); + } + } + + @Override + public void setSpellCheckerEnabled(boolean enabled) { + synchronized(mSpellCheckerMap) { + if (mContext.checkCallingOrSelfPermission( + android.Manifest.permission.WRITE_SECURE_SETTINGS) + != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException( + "Requires permission " + + android.Manifest.permission.WRITE_SECURE_SETTINGS); + } + setSpellCheckerEnabledLocked(enabled); + } + } + private void setCurrentSpellCheckerLocked(String sciId) { if (DBG) { Slog.w(TAG, "setCurrentSpellChecker: " + sciId); @@ -322,7 +399,59 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { final long ident = Binder.clearCallingIdentity(); try { Settings.Secure.putString(mContext.getContentResolver(), - Settings.Secure.SPELL_CHECKER_SERVICE, sciId); + Settings.Secure.SELECTED_SPELL_CHECKER, sciId); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private void setCurrentSpellCheckerSubtypeLocked(int hashCode) { + if (DBG) { + Slog.w(TAG, "setCurrentSpellCheckerSubtype: " + hashCode); + } + final SpellCheckerInfo sci = getCurrentSpellChecker(null); + if (sci == null) return; + boolean found = false; + for (int i = 0; i < sci.getSubtypeCount(); ++i) { + if(sci.getSubtypeAt(i).hashCode() == hashCode) { + found = true; + break; + } + } + if (!found) { + return; + } + final long ident = Binder.clearCallingIdentity(); + try { + Settings.Secure.putString(mContext.getContentResolver(), + Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode)); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private void setSpellCheckerEnabledLocked(boolean enabled) { + if (DBG) { + Slog.w(TAG, "setSpellCheckerEnabled: " + enabled); + } + final long ident = Binder.clearCallingIdentity(); + try { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.SPELL_CHECKER_ENABLED, enabled ? 1 : 0); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + private boolean isSpellCheckerEnabledLocked() { + final long ident = Binder.clearCallingIdentity(); + try { + final boolean retval = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.SPELL_CHECKER_ENABLED, 1) == 1; + if (DBG) { + Slog.w(TAG, "getSpellCheckerEnabled: " + retval); + } + return retval; } finally { Binder.restoreCallingIdentity(ident); } diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index 9765f2a..6ceccaf 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -75,7 +75,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub { static final String TAG = "WallpaperService"; static final boolean DEBUG = false; - Object mLock = new Object(); + final Object mLock = new Object[0]; /** * Minimum time between crashes of a wallpaper service for us to consider @@ -118,9 +118,10 @@ class WallpaperManagerService extends IWallpaperManager.Stub { File changedFile = new File(WALLPAPER_DIR, path); if (WALLPAPER_FILE.equals(changedFile)) { notifyCallbacksLocked(); - if (mWallpaperComponent == null || - mWallpaperComponent.equals(mImageWallpaperComponent)) { - bindWallpaperComponentLocked(mWallpaperComponent, true); + if (mWallpaperComponent == null || mImageWallpaperPending) { + mImageWallpaperPending = false; + bindWallpaperComponentLocked(mImageWallpaperComponent, true); + saveSettingsLocked(); } } } @@ -133,7 +134,12 @@ class WallpaperManagerService extends IWallpaperManager.Stub { int mWidth = -1; int mHeight = -1; - + + /** + * Client is currently writing a new image wallpaper. + */ + boolean mImageWallpaperPending; + /** * Resource name if using a picture from the wallpaper gallery */ @@ -343,6 +349,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub { } final long ident = Binder.clearCallingIdentity(); try { + mImageWallpaperPending = false; bindWallpaperComponentLocked(null, false); } catch (IllegalArgumentException e) { // This can happen if the default wallpaper component doesn't @@ -433,9 +440,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub { try { ParcelFileDescriptor pfd = updateWallpaperBitmapLocked(name); if (pfd != null) { - // Bind the wallpaper to an ImageWallpaper - bindWallpaperComponentLocked(mImageWallpaperComponent, false); - saveSettingsLocked(); + mImageWallpaperPending = true; } return pfd; } finally { @@ -463,6 +468,7 @@ class WallpaperManagerService extends IWallpaperManager.Stub { synchronized (mLock) { final long ident = Binder.clearCallingIdentity(); try { + mImageWallpaperPending = false; bindWallpaperComponentLocked(name, false); } finally { Binder.restoreCallingIdentity(ident); diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 800c4fc..7232a94 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -91,6 +91,7 @@ import android.os.Environment; import android.os.FileObserver; import android.os.FileUtils; import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; import android.os.IPermissionController; import android.os.Looper; @@ -3748,6 +3749,10 @@ public final class ActivityManagerService extends ActivityManagerNative mWindowManager.enableScreenAfterBoot(); } + public void showBootMessage(final CharSequence msg, final boolean always) { + mWindowManager.showBootMessage(msg, always); + } + final void finishBooting() { IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); @@ -6446,7 +6451,9 @@ public final class ActivityManagerService extends ActivityManagerNative File fname = new File(systemDir, "called_pre_boots.dat"); return fname; } - + + static final int LAST_DONE_VERSION = 10000; + private static ArrayList<ComponentName> readLastDonePreBootReceivers() { ArrayList<ComponentName> lastDoneReceivers = new ArrayList<ComponentName>(); File file = getCalledPreBootReceiversFile(); @@ -6454,16 +6461,21 @@ public final class ActivityManagerService extends ActivityManagerNative try { fis = new FileInputStream(file); DataInputStream dis = new DataInputStream(new BufferedInputStream(fis, 2048)); - int vers = dis.readInt(); - String codename = dis.readUTF(); - if (vers == android.os.Build.VERSION.SDK_INT - && codename.equals(android.os.Build.VERSION.CODENAME)) { - int num = dis.readInt(); - while (num > 0) { - num--; - String pkg = dis.readUTF(); - String cls = dis.readUTF(); - lastDoneReceivers.add(new ComponentName(pkg, cls)); + int fvers = dis.readInt(); + if (fvers == LAST_DONE_VERSION) { + String vers = dis.readUTF(); + String codename = dis.readUTF(); + String build = dis.readUTF(); + if (android.os.Build.VERSION.RELEASE.equals(vers) + && android.os.Build.VERSION.CODENAME.equals(codename) + && android.os.Build.VERSION.INCREMENTAL.equals(build)) { + int num = dis.readInt(); + while (num > 0) { + num--; + String pkg = dis.readUTF(); + String cls = dis.readUTF(); + lastDoneReceivers.add(new ComponentName(pkg, cls)); + } } } } catch (FileNotFoundException e) { @@ -6488,8 +6500,10 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.i(TAG, "Writing new set of last done pre-boot receivers..."); fos = new FileOutputStream(file); dos = new DataOutputStream(new BufferedOutputStream(fos, 2048)); - dos.writeInt(android.os.Build.VERSION.SDK_INT); + dos.writeInt(LAST_DONE_VERSION); + dos.writeUTF(android.os.Build.VERSION.RELEASE); dos.writeUTF(android.os.Build.VERSION.CODENAME); + dos.writeUTF(android.os.Build.VERSION.INCREMENTAL); dos.writeInt(list.size()); for (int i=0; i<list.size(); i++) { dos.writeUTF(list.get(i).getPackageName()); @@ -6550,7 +6564,7 @@ public final class ActivityManagerService extends ActivityManagerNative i--; } } - + for (int i=0; i<ris.size(); i++) { ActivityInfo ai = ris.get(i).activityInfo; ComponentName comp = new ComponentName(ai.packageName, ai.name); @@ -6571,6 +6585,9 @@ public final class ActivityManagerService extends ActivityManagerNative mDidUpdate = true; } writeLastDonePreBootReceivers(doneReceivers); + showBootMessage(mContext.getText( + R.string.android_upgrading_complete), + false); systemReady(goingCallback); } }); @@ -9009,6 +9026,7 @@ public final class ActivityManagerService extends ActivityManagerNative final static class MemItem { final String label; final long pss; + ArrayList<MemItem> subitems; public MemItem(String _label, long _pss) { label = _label; @@ -9034,7 +9052,10 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i=0; i<items.size(); i++) { MemItem mi = items.get(i); - pw.print(prefix); pw.printf("%8d Kb: ", mi.pss); pw.println(mi.label); + pw.print(prefix); pw.printf("%7d Kb: ", mi.pss); pw.println(mi.label); + if (mi.subitems != null) { + dumpMemItems(pw, prefix + " ", mi.subitems, true); + } } } @@ -9102,6 +9123,7 @@ public final class ActivityManagerService extends ActivityManagerNative "Backup", "Services", "Home", "Background" }; long oomPss[] = new long[oomLabel.length]; + ArrayList<MemItem>[] oomProcs = (ArrayList<MemItem>[])new ArrayList[oomLabel.length]; long totalPss = 0; @@ -9130,7 +9152,9 @@ public final class ActivityManagerService extends ActivityManagerNative if (!isCheckinRequest && mi != null) { long myTotalPss = mi.getTotalPss(); totalPss += myTotalPss; - procMems.add(new MemItem(r.processName + " (pid " + r.pid + ")", myTotalPss)); + MemItem pssItem = new MemItem(r.processName + " (pid " + r.pid + ")", + myTotalPss); + procMems.add(pssItem); nativePss += mi.nativePss; dalvikPss += mi.dalvikPss; @@ -9144,6 +9168,10 @@ public final class ActivityManagerService extends ActivityManagerNative for (int oomIndex=0; oomIndex<oomPss.length; oomIndex++) { if (r.setAdj <= oomAdj[oomIndex] || oomIndex == (oomPss.length-1)) { oomPss[oomIndex] += myTotalPss; + if (oomProcs[oomIndex] == null) { + oomProcs[oomIndex] = new ArrayList<MemItem>(); + } + oomProcs[oomIndex].add(pssItem); break; } } @@ -9164,7 +9192,9 @@ public final class ActivityManagerService extends ActivityManagerNative ArrayList<MemItem> oomMems = new ArrayList<MemItem>(); for (int j=0; j<oomPss.length; j++) { if (oomPss[j] != 0) { - oomMems.add(new MemItem(oomLabel[j], oomPss[j])); + MemItem item = new MemItem(oomLabel[j], oomPss[j]); + item.subitems = oomProcs[j]; + oomMems.add(item); } } diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java index 6f0779f..4ad0f45 100644 --- a/services/java/com/android/server/am/ActivityStack.java +++ b/services/java/com/android/server/am/ActivityStack.java @@ -3163,7 +3163,7 @@ final class ActivityStack { //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); if (mMainStack) { - if (!mService.mBooted && !fromTimeout) { + if (!mService.mBooted) { mService.mBooted = true; enableScreen = true; } diff --git a/services/java/com/android/server/am/TaskRecord.java b/services/java/com/android/server/am/TaskRecord.java index e61a7f4..87129ea 100644 --- a/services/java/com/android/server/am/TaskRecord.java +++ b/services/java/com/android/server/am/TaskRecord.java @@ -116,6 +116,8 @@ class TaskRecord extends ThumbnailHolder { if (!askedCompatMode) { pw.print(prefix); pw.print("askedCompatMode="); pw.println(askedCompatMode); } + pw.print(prefix); pw.print("lastThumbnail="); pw.print(lastThumbnail); + pw.print(" lastDescription="); pw.println(lastDescription); pw.print(prefix); pw.print("lastActiveTime="); pw.print(lastActiveTime); pw.print(" (inactive for "); pw.print((getInactiveDuration()/1000)); pw.println("s)"); diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index 6b65e07..55e0678 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -388,6 +388,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { private final VpnConfig mConfig; private final String[] mDaemons; private final String[][] mArguments; + private final LocalSocket[] mSockets; private final String mOuterInterface; private final LegacyVpnInfo mInfo; @@ -398,6 +399,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mConfig = config; mDaemons = new String[] {"racoon", "mtpd"}; mArguments = new String[][] {racoon, mtpd}; + mSockets = new LocalSocket[mDaemons.length]; mInfo = new LegacyVpnInfo(); // This is the interface which VPN is running on. @@ -416,10 +418,14 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } public void exit() { - // We assume that everything is reset after the daemons die. + // We assume that everything is reset after stopping the daemons. interrupt(); - for (String daemon : mDaemons) { - SystemProperties.set("ctl.stop", daemon); + for (LocalSocket socket : mSockets) { + try { + socket.close(); + } catch (Exception e) { + // ignore + } } } @@ -462,15 +468,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub { checkpoint(false); mInfo.state = LegacyVpnInfo.STATE_INITIALIZING; - // First stop the daemons. - for (String daemon : mDaemons) { - SystemProperties.set("ctl.stop", daemon); - } - // Wait for the daemons to stop. for (String daemon : mDaemons) { String key = "init.svc." + daemon; - while (!"stopped".equals(SystemProperties.get(key))) { + while (!"stopped".equals(SystemProperties.get(key, "stopped"))) { checkpoint(true); } } @@ -511,27 +512,27 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } // Create the control socket. - LocalSocket socket = new LocalSocket(); + mSockets[i] = new LocalSocket(); LocalSocketAddress address = new LocalSocketAddress( daemon, LocalSocketAddress.Namespace.RESERVED); // Wait for the socket to connect. while (true) { try { - socket.connect(address); + mSockets[i].connect(address); break; } catch (Exception e) { // ignore } checkpoint(true); } - socket.setSoTimeout(500); + mSockets[i].setSoTimeout(500); // Send over the arguments. - OutputStream out = socket.getOutputStream(); + OutputStream out = mSockets[i].getOutputStream(); for (String argument : arguments) { byte[] bytes = argument.getBytes(Charsets.UTF_8); - if (bytes.length > 0xFFFF) { + if (bytes.length >= 0xFFFF) { throw new IllegalArgumentException("Argument is too large"); } out.write(bytes.length >> 8); @@ -539,11 +540,12 @@ public class Vpn extends INetworkManagementEventObserver.Stub { out.write(bytes); checkpoint(false); } + out.write(0xFF); + out.write(0xFF); out.flush(); - socket.shutdownOutput(); // Wait for End-of-File. - InputStream in = socket.getInputStream(); + InputStream in = mSockets[i].getInputStream(); while (true) { try { if (in.read() == -1) { @@ -554,7 +556,6 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } checkpoint(true); } - socket.close(); } // Wait for the daemons to create the new state. @@ -631,6 +632,13 @@ public class Vpn extends INetworkManagementEventObserver.Stub { Log.i(TAG, "Aborting", e); exit(); } finally { + // Kill the daemons if they fail to stop. + if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING) { + for (String daemon : mDaemons) { + SystemProperties.set("ctl.stop", daemon); + } + } + // Do not leave an unstable state. if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING || mInfo.state == LegacyVpnInfo.STATE_CONNECTING) { diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 14d9665..84880f9 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -27,7 +27,10 @@ import static android.content.Intent.ACTION_PACKAGE_ADDED; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; +import static android.net.ConnectivityManager.TYPE_ETHERNET; import static android.net.ConnectivityManager.TYPE_MOBILE; +import static android.net.ConnectivityManager.TYPE_WIFI; +import static android.net.ConnectivityManager.TYPE_WIMAX; import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; @@ -40,8 +43,11 @@ import static android.net.NetworkPolicyManager.computeLastCycleBoundary; import static android.net.NetworkPolicyManager.dumpPolicy; import static android.net.NetworkPolicyManager.dumpRules; import static android.net.NetworkPolicyManager.isUidValidForPolicy; +import static android.net.NetworkTemplate.MATCH_ETHERNET; import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER; import static android.net.NetworkTemplate.MATCH_MOBILE_4G; +import static android.net.NetworkTemplate.MATCH_MOBILE_ALL; +import static android.net.NetworkTemplate.MATCH_WIFI; import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.text.format.DateUtils.DAY_IN_MILLIS; import static com.android.internal.util.Preconditions.checkNotNull; @@ -104,6 +110,7 @@ import android.util.Xml; import com.android.internal.R; import com.android.internal.os.AtomicFile; import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.Objects; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import com.google.android.collect.Sets; @@ -129,8 +136,8 @@ import java.util.List; import libcore.io.IoUtils; /** - * Service that maintains low-level network policy rules and collects usage - * statistics to drive those rules. + * Service that maintains low-level network policy rules, using + * {@link NetworkStatsService} statistics to drive those rules. * <p> * Derives active rules by combining a given policy with other system status, * and delivers to listeners, such as {@link ConnectivityManager}, for @@ -195,6 +202,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private volatile boolean mScreenOn; private volatile boolean mRestrictBackground; + private final boolean mSuppressDefaultPolicy; + /** Defined network policies. */ private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap(); /** Currently active network rules for ifaces. */ @@ -210,6 +219,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** Set of over-limit templates that have been notified. */ private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet(); + /** Set of currently active {@link Notification} tags. */ + private HashSet<String> mActiveNotifs = Sets.newHashSet(); + /** Current values from {@link #setPolicyDataEnable(int, boolean)}. */ + private SparseBooleanArray mActiveNetworkEnabled = new SparseBooleanArray(); + /** Foreground at both UID and PID granularity. */ private SparseBooleanArray mUidForeground = new SparseBooleanArray(); private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray< @@ -232,7 +246,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { IPowerManager powerManager, INetworkStatsService networkStats, INetworkManagementService networkManagement) { this(context, activityManager, powerManager, networkStats, networkManagement, - NtpTrustedTime.getInstance(context), getSystemDir()); + NtpTrustedTime.getInstance(context), getSystemDir(), false); } private static File getSystemDir() { @@ -241,8 +255,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { public NetworkPolicyManagerService(Context context, IActivityManager activityManager, IPowerManager powerManager, INetworkStatsService networkStats, - INetworkManagementService networkManagement, - TrustedTime time, File systemDir) { + INetworkManagementService networkManagement, TrustedTime time, File systemDir, + boolean suppressDefaultPolicy) { mContext = checkNotNull(context, "missing context"); mActivityManager = checkNotNull(activityManager, "missing activityManager"); mPowerManager = checkNotNull(powerManager, "missing powerManager"); @@ -254,6 +268,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mHandlerThread.start(); mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); + mSuppressDefaultPolicy = suppressDefaultPolicy; + mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); } @@ -408,6 +424,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // READ_NETWORK_USAGE_HISTORY permission above. synchronized (mRulesLock) { + updateNetworkEnabledLocked(); updateNotificationsLocked(); } } @@ -446,6 +463,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { Slog.w(TAG, "problem updating network stats"); } + updateNetworkEnabledLocked(); updateNotificationsLocked(); } } @@ -459,74 +477,70 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private void updateNotificationsLocked() { if (LOGV) Slog.v(TAG, "updateNotificationsLocked()"); - // try refreshing time source when stale - if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { - mTime.forceRefresh(); - } - - final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() - : System.currentTimeMillis(); + // keep track of previously active notifications + final HashSet<String> beforeNotifs = Sets.newHashSet(); + beforeNotifs.addAll(mActiveNotifs); + mActiveNotifs.clear(); // TODO: when switching to kernel notifications, compute next future // cycle boundary to recompute notifications. // examine stats for each active policy - for (NetworkPolicy policy : mNetworkRules.keySet()) { + final long currentTime = currentTimeMillis(true); + for (NetworkPolicy policy : mNetworkPolicy.values()) { + // ignore policies that aren't relevant to user + if (!isTemplateRelevant(policy.template)) continue; + final long start = computeLastCycleBoundary(currentTime, policy); final long end = currentTime; - final long totalBytes; - try { - final NetworkStats stats = mNetworkStats.getSummaryForNetwork( - policy.template, start, end); - final NetworkStats.Entry entry = stats.getValues(0, null); - totalBytes = entry.rxBytes + entry.txBytes; - } catch (RemoteException e) { - Slog.w(TAG, "problem reading summary for template " + policy.template); - continue; - } + final long totalBytes = getTotalBytes(policy.template, start, end); + if (totalBytes == UNKNOWN_BYTES) continue; if (policy.limitBytes != LIMIT_DISABLED && totalBytes >= policy.limitBytes) { - cancelNotification(policy, TYPE_WARNING); - if (policy.lastSnooze >= start) { - cancelNotification(policy, TYPE_LIMIT); enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes); } else { - cancelNotification(policy, TYPE_LIMIT_SNOOZED); enqueueNotification(policy, TYPE_LIMIT, totalBytes); notifyOverLimitLocked(policy.template); } } else { - cancelNotification(policy, TYPE_LIMIT); - cancelNotification(policy, TYPE_LIMIT_SNOOZED); notifyUnderLimitLocked(policy.template); if (policy.warningBytes != WARNING_DISABLED && totalBytes >= policy.warningBytes) { enqueueNotification(policy, TYPE_WARNING, totalBytes); - } else { - cancelNotification(policy, TYPE_WARNING); } } } - // clear notifications for non-active policies - for (NetworkPolicy policy : mNetworkPolicy.values()) { - if (!mNetworkRules.containsKey(policy)) { - cancelNotification(policy, TYPE_WARNING); - cancelNotification(policy, TYPE_LIMIT); - cancelNotification(policy, TYPE_LIMIT_SNOOZED); - notifyUnderLimitLocked(policy.template); - } - } - // ongoing notification when restricting background data if (mRestrictBackground) { enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND); - } else { - cancelNotification(TAG_ALLOW_BACKGROUND); } + + // cancel stale notifications that we didn't renew above + for (String tag : beforeNotifs) { + if (!mActiveNotifs.contains(tag)) { + cancelNotification(tag); + } + } + } + + /** + * Test if given {@link NetworkTemplate} is relevant to user based on + * current device state, such as when {@link #getActiveSubscriberId()} + * matches. This is regardless of data connection status. + */ + private boolean isTemplateRelevant(NetworkTemplate template) { + switch (template.getMatchRule()) { + case MATCH_MOBILE_3G_LOWER: + case MATCH_MOBILE_4G: + case MATCH_MOBILE_ALL: + // mobile templates are relevant when subscriberid is active + return Objects.equal(getActiveSubscriberId(), template.getSubscriberId()); + } + return true; } /** @@ -590,9 +604,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { case MATCH_MOBILE_4G: title = res.getText(R.string.data_usage_4g_limit_title); break; - default: + case MATCH_MOBILE_ALL: title = res.getText(R.string.data_usage_mobile_limit_title); break; + case MATCH_WIFI: + title = res.getText(R.string.data_usage_wifi_limit_title); + break; + default: + title = null; + break; } builder.setSmallIcon(com.android.internal.R.drawable.ic_menu_block); @@ -618,9 +638,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { case MATCH_MOBILE_4G: title = res.getText(R.string.data_usage_4g_limit_snoozed_title); break; - default: + case MATCH_MOBILE_ALL: title = res.getText(R.string.data_usage_mobile_limit_snoozed_title); break; + case MATCH_WIFI: + title = res.getText(R.string.data_usage_wifi_limit_snoozed_title); + break; + default: + title = null; + break; } builder.setSmallIcon(R.drawable.ic_menu_info_details); @@ -641,6 +667,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int[] idReceived = new int[1]; mNotifManager.enqueueNotificationWithTag( packageName, tag, 0x0, builder.getNotification(), idReceived); + mActiveNotifs.add(tag); } catch (RemoteException e) { Slog.w(TAG, "problem during enqueueNotification: " + e); } @@ -674,19 +701,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int[] idReceived = new int[1]; mNotifManager.enqueueNotificationWithTag(packageName, tag, 0x0, builder.getNotification(), idReceived); + mActiveNotifs.add(tag); } catch (RemoteException e) { Slog.w(TAG, "problem during enqueueNotification: " + e); } } - /** - * Cancel any notification for combined {@link NetworkPolicy} and specific - * type, like {@link #TYPE_LIMIT}. - */ - private void cancelNotification(NetworkPolicy policy, int type) { - cancelNotification(buildNotificationTag(policy, type)); - } - private void cancelNotification(String tag) { // TODO: move to NotificationManager once we can mock it try { @@ -709,6 +729,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // permission above. synchronized (mRulesLock) { ensureActiveMobilePolicyLocked(); + updateNetworkEnabledLocked(); updateNetworkRulesLocked(); updateNotificationsLocked(); } @@ -716,6 +737,65 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { }; /** + * Proactively control network data connections when they exceed + * {@link NetworkPolicy#limitBytes}. + */ + private void updateNetworkEnabledLocked() { + if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()"); + + // TODO: reset any policy-disabled networks when any policy is removed + // completely, which is currently rare case. + + final long currentTime = currentTimeMillis(true); + for (NetworkPolicy policy : mNetworkPolicy.values()) { + // shortcut when policy has no limit + if (policy.limitBytes == LIMIT_DISABLED) { + setNetworkTemplateEnabled(policy.template, true); + continue; + } + + final long start = computeLastCycleBoundary(currentTime, policy); + final long end = currentTime; + + final long totalBytes = getTotalBytes(policy.template, start, end); + if (totalBytes == UNKNOWN_BYTES) continue; + + // disable data connection when over limit and not snoozed + final boolean overLimit = policy.limitBytes != LIMIT_DISABLED + && totalBytes > policy.limitBytes && policy.lastSnooze < start; + setNetworkTemplateEnabled(policy.template, !overLimit); + } + } + + /** + * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)} + * for the given {@link NetworkTemplate}. + */ + private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) { + if (LOGD) Slog.d(TAG, "setting template=" + template + " enabled=" + enabled); + switch (template.getMatchRule()) { + case MATCH_MOBILE_3G_LOWER: + case MATCH_MOBILE_4G: + case MATCH_MOBILE_ALL: + // TODO: offer more granular control over radio states once + // 4965893 is available. + if (Objects.equal(getActiveSubscriberId(), template.getSubscriberId())) { + setPolicyDataEnable(TYPE_MOBILE, enabled); + setPolicyDataEnable(TYPE_WIMAX, enabled); + } + break; + case MATCH_WIFI: + setPolicyDataEnable(TYPE_WIFI, enabled); + break; + case MATCH_ETHERNET: + setPolicyDataEnable(TYPE_ETHERNET, enabled); + break; + default: + throw new IllegalArgumentException("unexpected template"); + } + } + + /** * Examine all connected {@link NetworkState}, looking for * {@link NetworkPolicy} that need to be enforced. When matches found, set * remaining quota based on usage cycle and historical stats. @@ -763,34 +843,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - // try refreshing time source when stale - if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { - mTime.forceRefresh(); - } - - final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() - : System.currentTimeMillis(); - final HashSet<String> newMeteredIfaces = Sets.newHashSet(); // apply each policy that we found ifaces for; compute remaining data // based on current cycle and historical stats, and push to kernel. + final long currentTime = currentTimeMillis(true); for (NetworkPolicy policy : mNetworkRules.keySet()) { final String[] ifaces = mNetworkRules.get(policy); final long start = computeLastCycleBoundary(currentTime, policy); final long end = currentTime; - final NetworkStats stats; - final long total; - try { - stats = mNetworkStats.getSummaryForNetwork(policy.template, start, end); - final NetworkStats.Entry entry = stats.getValues(0, null); - total = entry.rxBytes + entry.txBytes; - } catch (RemoteException e) { - Slog.w(TAG, "problem reading summary for template " + policy.template); - continue; - } + final long totalBytes = getTotalBytes(policy.template, start, end); + if (totalBytes == UNKNOWN_BYTES) continue; if (LOGD) { Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces " @@ -798,11 +863,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED; - final boolean hasWarning = policy.warningBytes != WARNING_DISABLED; - if (hasLimit) { - // remaining "quota" is based on usage in current cycle - final long quotaBytes = Math.max(0, policy.limitBytes - total); + final long quotaBytes; + if (policy.lastSnooze >= start) { + // snoozing past quota, but we still need to restrict apps, + // so push really high quota. + quotaBytes = Long.MAX_VALUE; + } else { + // remaining "quota" bytes are based on total usage in + // current cycle. kernel doesn't like 0-byte rules, so we + // set 1-byte quota and disable the radio later. + quotaBytes = Math.max(1, policy.limitBytes - totalBytes); + } if (ifaces.length > 1) { // TODO: switch to shared quota once NMS supports @@ -811,10 +883,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { for (String iface : ifaces) { removeInterfaceQuota(iface); - if (quotaBytes > 0) { - setInterfaceQuota(iface, quotaBytes); - newMeteredIfaces.add(iface); - } + setInterfaceQuota(iface, quotaBytes); + newMeteredIfaces.add(iface); } } } @@ -837,6 +907,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { */ private void ensureActiveMobilePolicyLocked() { if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()"); + if (mSuppressDefaultPolicy) return; + final String subscriberId = getActiveSubscriberId(); final NetworkIdentity probeIdent = new NetworkIdentity( TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, false); @@ -1073,6 +1145,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mNetworkPolicy.put(policy.template, policy); } + updateNetworkEnabledLocked(); updateNetworkRulesLocked(); updateNotificationsLocked(); writePolicyLocked(); @@ -1093,14 +1166,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { public void snoozePolicy(NetworkTemplate template) { mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); - // try refreshing time source when stale - if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) { - mTime.forceRefresh(); - } - - final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() - : System.currentTimeMillis(); - + final long currentTime = currentTimeMillis(true); synchronized (mRulesLock) { // find and snooze local policy that matches final NetworkPolicy policy = mNetworkPolicy.get(template); @@ -1110,6 +1176,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { policy.lastSnooze = currentTime; + updateNetworkEnabledLocked(); updateNetworkRulesLocked(); updateNotificationsLocked(); writePolicyLocked(); @@ -1173,22 +1240,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return null; } - final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() - : System.currentTimeMillis(); + final long currentTime = currentTimeMillis(false); final long start = computeLastCycleBoundary(currentTime, policy); final long end = currentTime; // find total bytes used under policy - long totalBytes = 0; - try { - final NetworkStats stats = mNetworkStats.getSummaryForNetwork( - policy.template, start, end); - final NetworkStats.Entry entry = stats.getValues(0, null); - totalBytes = entry.rxBytes + entry.txBytes; - } catch (RemoteException e) { - Slog.w(TAG, "problem reading summary for template " + policy.template); - } + final long totalBytes = getTotalBytes(policy.template, start, end); + if (totalBytes == UNKNOWN_BYTES) return null; // report soft and hard limits under policy final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes @@ -1481,12 +1540,54 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + /** + * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}, + * dispatching only when actually changed. + */ + private void setPolicyDataEnable(int networkType, boolean enabled) { + synchronized (mActiveNetworkEnabled) { + final boolean prevEnabled = mActiveNetworkEnabled.get(networkType, true); + if (prevEnabled == enabled) return; + + try { + mConnManager.setPolicyDataEnable(networkType, enabled); + } catch (RemoteException e) { + Slog.e(TAG, "problem setting network enabled", e); + } + + mActiveNetworkEnabled.put(networkType, enabled); + } + } + private String getActiveSubscriberId() { final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); return telephony.getSubscriberId(); } + private static final long UNKNOWN_BYTES = -1; + + private long getTotalBytes(NetworkTemplate template, long start, long end) { + try { + final NetworkStats stats = mNetworkStats.getSummaryForNetwork( + template, start, end); + final NetworkStats.Entry entry = stats.getValues(0, null); + return entry.rxBytes + entry.txBytes; + } catch (RemoteException e) { + Slog.w(TAG, "problem reading summary for template " + template); + return UNKNOWN_BYTES; + } + } + + private long currentTimeMillis(boolean allowRefresh) { + // try refreshing time source when stale + if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE && allowRefresh) { + mTime.forceRefresh(); + } + + return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); + } + private static Intent buildAllowBackgroundDataIntent() { return new Intent(ACTION_ALLOW_BACKGROUND); } diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index dbb8164..b8797d1 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -187,13 +187,15 @@ public class PackageManagerService extends IPackageManager.Stub { static final int SCAN_NEW_INSTALL = 1<<4; static final int SCAN_NO_PATHS = 1<<5; static final int SCAN_UPDATE_TIME = 1<<6; + static final int SCAN_DEFER_DEX = 1<<7; static final int REMOVE_CHATTY = 1<<16; /** * Whether verification is enabled by default. */ - private static final boolean DEFAULT_VERIFY_ENABLE = true; + // STOPSHIP: change this to true + private static final boolean DEFAULT_VERIFY_ENABLE = false; /** * The default maximum time to wait for the verification agent to return in @@ -349,6 +351,9 @@ public class PackageManagerService extends IPackageManager.Stub { /** List of packages waiting for verification. */ final SparseArray<InstallArgs> mPendingVerification = new SparseArray<InstallArgs>(); + final ArrayList<PackageParser.Package> mDeferredDexOpt = + new ArrayList<PackageParser.Package>(); + /** Token for keys in mPendingVerification. */ private int mPendingVerificationToken = 0; @@ -907,7 +912,7 @@ public class PackageManagerService extends IPackageManager.Stub { // Set flag to monitor and not change apk file paths when // scanning install directories. - int scanMode = SCAN_MONITOR | SCAN_NO_PATHS; + int scanMode = SCAN_MONITOR | SCAN_NO_PATHS | SCAN_DEFER_DEX; if (mNoDexOpt) { Slog.w(TAG, "Running ENG build: no pre-dexopt!"); scanMode |= SCAN_NO_DEX; @@ -2899,6 +2904,33 @@ public class PackageManagerService extends IPackageManager.Stub { } } + public void performBootDexOpt() { + ArrayList<PackageParser.Package> pkgs = null; + synchronized (mPackages) { + if (mDeferredDexOpt.size() > 0) { + pkgs = new ArrayList<PackageParser.Package>(mDeferredDexOpt); + mDeferredDexOpt.clear(); + } + } + if (pkgs != null) { + for (int i=0; i<pkgs.size(); i++) { + try { + ActivityManagerNative.getDefault().showBootMessage( + mContext.getResources().getString( + com.android.internal.R.string.android_upgrading_apk, + i+1, pkgs.size()), true); + } catch (RemoteException e) { + } + PackageParser.Package p = pkgs.get(i); + synchronized (mInstallLock) { + if (!p.mDidDexOpt) { + performDexOptLI(p, false, false); + } + } + } + } + } + public boolean performDexOpt(String packageName) { enforceSystemOrRoot("Only the system can request dexopt be performed"); @@ -2914,25 +2946,32 @@ public class PackageManagerService extends IPackageManager.Stub { } } synchronized (mInstallLock) { - return performDexOptLI(p, false) == DEX_OPT_PERFORMED; + return performDexOptLI(p, false, false) == DEX_OPT_PERFORMED; } } static final int DEX_OPT_SKIPPED = 0; static final int DEX_OPT_PERFORMED = 1; + static final int DEX_OPT_DEFERRED = 2; static final int DEX_OPT_FAILED = -1; - private int performDexOptLI(PackageParser.Package pkg, boolean forceDex) { + private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer) { boolean performed = false; if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) { String path = pkg.mScanPath; int ret = 0; try { if (forceDex || dalvik.system.DexFile.isDexOptNeeded(path)) { - ret = mInstaller.dexopt(path, pkg.applicationInfo.uid, - !isForwardLocked(pkg)); - pkg.mDidDexOpt = true; - performed = true; + if (!forceDex && defer) { + mDeferredDexOpt.add(pkg); + return DEX_OPT_DEFERRED; + } else { + Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName); + ret = mInstaller.dexopt(path, pkg.applicationInfo.uid, + !isForwardLocked(pkg)); + pkg.mDidDexOpt = true; + performed = true; + } } } catch (FileNotFoundException e) { Slog.w(TAG, "Apk not found for dexopt: " + path); @@ -3487,7 +3526,8 @@ public class PackageManagerService extends IPackageManager.Stub { pkg.mScanPath = path; if ((scanMode&SCAN_NO_DEX) == 0) { - if (performDexOptLI(pkg, forceDex) == DEX_OPT_FAILED) { + if (performDexOptLI(pkg, forceDex, (scanMode&SCAN_DEFER_DEX) != 0) + == DEX_OPT_FAILED) { mLastScanError = PackageManager.INSTALL_FAILED_DEXOPT; return null; } diff --git a/services/java/com/android/server/usb/UsbDeviceManager.java b/services/java/com/android/server/usb/UsbDeviceManager.java index a01c975..8f51466 100644 --- a/services/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/java/com/android/server/usb/UsbDeviceManager.java @@ -568,12 +568,9 @@ public class UsbDeviceManager { notification.sound = null; notification.vibrate = null; - Intent intent = new Intent( - Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); - intent.setComponent(new ComponentName("com.android.settings", - "com.android.settings.UsbSettings")); + Intent intent = Intent.makeRestartActivityTask( + new ComponentName("com.android.settings", + "com.android.settings.UsbSettings")); PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); notification.setLatestEventInfo(mContext, title, message, pi); @@ -604,12 +601,9 @@ public class UsbDeviceManager { notification.sound = null; notification.vibrate = null; - Intent intent = new Intent( - Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | - Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED); - intent.setComponent(new ComponentName("com.android.settings", - "com.android.settings.DevelopmentSettings")); + Intent intent = Intent.makeRestartActivityTask( + new ComponentName("com.android.settings", + "com.android.settings.DevelopmentSettings")); PendingIntent pi = PendingIntent.getActivity(mContext, 0, intent, 0); notification.setLatestEventInfo(mContext, title, message, pi); diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 8fd4f95..e258b1a 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -53,7 +53,6 @@ import android.app.IActivityManager; import android.app.StatusBarManager; import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -163,6 +162,8 @@ public class WindowManagerService extends IWindowManager.Stub static final boolean DEBUG_REORDER = false; static final boolean DEBUG_WALLPAPER = false; static final boolean DEBUG_DRAG = false; + static final boolean DEBUG_SCREEN_ON = false; + static final boolean DEBUG_SCREENSHOT = false; static final boolean SHOW_SURFACE_ALLOC = false; static final boolean SHOW_TRANSACTIONS = false; static final boolean HIDE_STACK_CRAWLS = true; @@ -407,6 +408,8 @@ public class WindowManagerService extends IWindowManager.Stub boolean mSafeMode; boolean mDisplayEnabled = false; boolean mSystemBooted = false; + boolean mForceDisplayEnabled = false; + boolean mShowingBootMessages = false; int mInitialDisplayWidth = 0; int mInitialDisplayHeight = 0; int mBaseDisplayWidth = 0; @@ -2187,7 +2190,7 @@ public class WindowManagerService extends IWindowManager.Stub // to hold off on removing the window until the animation is done. // If the display is frozen, just remove immediately, since the // animation wouldn't be seen. - if (win.mSurface != null && !mDisplayFrozen && mPolicy.isScreenOn()) { + if (win.mSurface != null && !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) { // If we are not currently running the exit animation, we // need to see about starting one. if (wasVisible=win.isWinVisibleLw()) { @@ -2534,6 +2537,12 @@ public class WindowManagerService extends IWindowManager.Stub win.mRelayoutCalled = true; final int oldVisibility = win.mViewVisibility; win.mViewVisibility = viewVisibility; + if (DEBUG_SCREEN_ON) { + RuntimeException stack = new RuntimeException(); + stack.fillInStackTrace(); + Slog.i(TAG, "Relayout " + win + ": oldVis=" + oldVisibility + + " newVis=" + viewVisibility, stack); + } if (viewVisibility == View.VISIBLE && (win.mAppToken == null || !win.mAppToken.clientHidden)) { displayed = !win.isVisibleLw(); @@ -2554,7 +2563,7 @@ public class WindowManagerService extends IWindowManager.Stub if (displayed) { if (win.mSurface != null && !win.mDrawPending && !win.mCommitDrawPending && !mDisplayFrozen - && mPolicy.isScreenOn()) { + && mDisplayEnabled && mPolicy.isScreenOn()) { applyEnterAnimationLocked(win); } if ((win.mAttrs.flags @@ -2847,7 +2856,7 @@ public class WindowManagerService extends IWindowManager.Stub // 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()) { + if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) { int anim = mPolicy.selectAnimationLw(win, transit); int attr = -1; Animation a = null; @@ -2933,7 +2942,7 @@ public class WindowManagerService extends IWindowManager.Stub // 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()) { + if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) { Animation a; if (mNextAppTransitionPackage != null) { a = loadAnimation(mNextAppTransitionPackage, enter ? @@ -3499,7 +3508,7 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_APP_TRANSITIONS) Slog.v( TAG, "Prepare app transition: transit=" + transit + " mNextAppTransition=" + mNextAppTransition); - if (!mDisplayFrozen && mPolicy.isScreenOn()) { + if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) { if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) { mNextAppTransition = transit; @@ -3583,7 +3592,7 @@ public class WindowManagerService extends IWindowManager.Stub // If the display is frozen, we won't do anything until the // actual window is displayed so there is no reason to put in // the starting window. - if (mDisplayFrozen || !mPolicy.isScreenOn()) { + if (mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOn()) { return; } @@ -3865,7 +3874,7 @@ public class WindowManagerService extends IWindowManager.Stub // If we are preparing an app transition, then delay changing // the visibility of this token until we execute that transition. - if (!mDisplayFrozen && mPolicy.isScreenOn() + if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn() && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) { // Already in requested state, don't do anything more. if (wtoken.hiddenRequested != visible) { @@ -4685,43 +4694,95 @@ public class WindowManagerService extends IWindowManager.Stub return; } mSystemBooted = true; + hideBootMessagesLocked(); + // If the screen still doesn't come up after 30 seconds, give + // up and turn it on. + Message msg = mH.obtainMessage(H.BOOT_TIMEOUT); + mH.sendMessageDelayed(msg, 30*1000); } performEnableScreen(); } - public void enableScreenIfNeededLocked() { + void enableScreenIfNeededLocked() { if (mDisplayEnabled) { return; } - if (!mSystemBooted) { + if (!mSystemBooted && !mShowingBootMessages) { return; } mH.sendMessage(mH.obtainMessage(H.ENABLE_SCREEN)); } + public void performBootTimeout() { + synchronized(mWindowMap) { + if (mDisplayEnabled) { + return; + } + Slog.w(TAG, "***** BOOT TIMEOUT: forcing display enabled"); + mForceDisplayEnabled = true; + } + performEnableScreen(); + } + public void performEnableScreen() { synchronized(mWindowMap) { if (mDisplayEnabled) { return; } - if (!mSystemBooted) { + if (!mSystemBooted && !mShowingBootMessages) { return; } - // Don't enable the screen until all existing windows - // have been drawn. - final int N = mWindows.size(); - for (int i=0; i<N; i++) { - WindowState w = mWindows.get(i); - if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { + if (!mForceDisplayEnabled) { + // Don't enable the screen until all existing windows + // have been drawn. + boolean haveBootMsg = false; + boolean haveApp = false; + boolean haveWallpaper = false; + boolean haveKeyguard = false; + final int N = mWindows.size(); + for (int i=0; i<N; i++) { + WindowState w = mWindows.get(i); + if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { + return; + } + if (w.isDrawnLw()) { + if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_BOOT_PROGRESS) { + haveBootMsg = true; + } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION) { + haveApp = true; + } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_WALLPAPER) { + haveWallpaper = true; + } else if (w.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD) { + haveKeyguard = true; + } + } + } + + if (DEBUG_SCREEN_ON) { + Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages + + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp + + " haveWall=" + haveWallpaper + " haveKeyguard=" + haveKeyguard); + } + + // If we are turning on the screen to show the boot message, + // don't do it until the boot message is actually displayed. + if (!mSystemBooted && !haveBootMsg) { + return; + } + + // If we are turning on the screen after the boot is completed + // normally, don't do so until we have the application and + // wallpaper. + if (mSystemBooted && ((!haveApp && !haveKeyguard) || !haveWallpaper)) { return; } } mDisplayEnabled = true; + if (DEBUG_SCREEN_ON) Slog.i(TAG, "******************** ENABLING SCREEN!"); if (false) { - Slog.i(TAG, "ENABLING SCREEN!"); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); this.dump(null, pw, null); @@ -4749,6 +4810,33 @@ public class WindowManagerService extends IWindowManager.Stub mLastRotationFlags | Surface.FLAGS_ORIENTATION_ANIMATION_DISABLE); } + public void showBootMessage(final CharSequence msg, final boolean always) { + boolean first = false; + synchronized(mWindowMap) { + if (!mShowingBootMessages) { + if (!always) { + return; + } + first = true; + } + if (mSystemBooted) { + return; + } + mShowingBootMessages = true; + mPolicy.showBootMessage(msg, always); + } + if (first) { + performEnableScreen(); + } + } + + public void hideBootMessagesLocked() { + if (mShowingBootMessages) { + mShowingBootMessages = false; + mPolicy.hideBootMessages(); + } + } + public void setInTouchMode(boolean mode) { synchronized(mWindowMap) { mInTouchMode = mode; @@ -4909,6 +4997,14 @@ public class WindowManagerService extends IWindowManager.Stub dh = tmp; rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; } + if (DEBUG_SCREENSHOT) { + Slog.i(TAG, "Screenshot: " + dw + "x" + dh + " from 0 to " + maxLayer); + for (int i=0; i<mWindows.size(); i++) { + Slog.i(TAG, mWindows.get(i) + ": " + mWindows.get(i).mLayer + + " animLayer=" + mWindows.get(i).mAnimLayer + + " surfaceLayer=" + mWindows.get(i).mSurfaceLayer); + } + } rawss = Surface.screenshot(dw, dh, 0, maxLayer); } @@ -6136,7 +6232,7 @@ public class WindowManagerService extends IWindowManager.Stub return mSafeMode; } - public void systemReady() { + public void displayReady() { synchronized(mWindowMap) { if (mDisplay != null) { throw new IllegalStateException("Display already initialized"); @@ -6165,14 +6261,16 @@ public class WindowManagerService extends IWindowManager.Stub mActivityManager.updateConfiguration(null); } catch (RemoteException e) { } - - mPolicy.systemReady(); - + synchronized (mWindowMap) { readForcedDisplaySizeLocked(); } } + public void systemReady() { + mPolicy.systemReady(); + } + // This is an animation that does nothing: it just immediately finishes // itself every time it is called. It is used as a stub animation in cases // where we want to synchronize multiple things that may be animating. @@ -6207,6 +6305,7 @@ public class WindowManagerService extends IWindowManager.Stub public static final int DRAG_START_TIMEOUT = 20; public static final int DRAG_END_TIMEOUT = 21; public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22; + public static final int BOOT_TIMEOUT = 23; private Session mLastReportedHold; @@ -6517,6 +6616,11 @@ public class WindowManagerService extends IWindowManager.Stub break; } + case BOOT_TIMEOUT: { + performBootTimeout(); + break; + } + case APP_FREEZE_TIMEOUT: { synchronized (mWindowMap) { Slog.w(TAG, "App freeze timeout expired."); @@ -8268,7 +8372,7 @@ public class WindowManagerService extends IWindowManager.Stub if (mDimAnimator != null && mDimAnimator.mDimShown) { animating |= mDimAnimator.updateSurface(dimming, currentTime, - mDisplayFrozen || !mPolicy.isScreenOn()); + mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOn()); } if (!blurring && mBlurShown) { @@ -8466,12 +8570,44 @@ public class WindowManagerService extends IWindowManager.Stub mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION); } } - + + mWindowMap.notifyAll(); + // Check to see if we are now in a state where the screen should // be enabled, because the window obscured flags have changed. enableScreenIfNeededLocked(); } - + + public void waitForAllDrawn() { + synchronized (mWindowMap) { + while (true) { + final int N = mWindows.size(); + boolean okay = true; + for (int i=0; i<N && okay; i++) { + WindowState w = mWindows.get(i); + if (DEBUG_SCREEN_ON) { + Slog.i(TAG, "Window " + w + " vis=" + w.isVisibleLw() + + " obscured=" + w.mObscured + " drawn=" + w.isDrawnLw()); + } + if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { + if (DEBUG_SCREEN_ON) { + Slog.i(TAG, "Window not yet drawn: " + w); + } + okay = false; + break; + } + } + if (okay) { + return; + } + try { + mWindowMap.wait(); + } catch (InterruptedException e) { + } + } + } + } + /** * Must be called with the main window manager lock held. */ |