diff options
Diffstat (limited to 'services')
19 files changed, 611 insertions, 368 deletions
diff --git a/services/java/com/android/server/AlarmManagerService.java b/services/java/com/android/server/AlarmManagerService.java index 5e54d61..5ffcdc5 100644 --- a/services/java/com/android/server/AlarmManagerService.java +++ b/services/java/com/android/server/AlarmManagerService.java @@ -764,12 +764,18 @@ class AlarmManagerService extends IAlarmManager.Stub { public void scheduleTimeTickEvent() { Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(System.currentTimeMillis()); + final long currentTime = System.currentTimeMillis(); + calendar.setTimeInMillis(currentTime); calendar.add(Calendar.MINUTE, 1); calendar.set(Calendar.SECOND, 0); calendar.set(Calendar.MILLISECOND, 0); - - set(AlarmManager.RTC, calendar.getTimeInMillis(), mTimeTickSender); + + // Schedule this event for the amount of time that it would take to get to + // the top of the next minute. + final long tickEventDelay = calendar.getTimeInMillis() - currentTime; + + set(AlarmManager.ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, + mTimeTickSender); } public void scheduleDateChangedEvent() { diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 6b64dd0..38bcebc 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -619,10 +619,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } void updateImeWindowStatusLocked() { - if (mStatusBar != null) { - mStatusBar.setImeWindowStatus(mCurToken, mImeWindowVis, - mBackDisposition); - } + setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition); } @Override @@ -995,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(); } } } @@ -1121,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(); @@ -2018,8 +2018,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (DEBUG) Slog.v(TAG, "Show switching menu"); final Context context = mContext; - final PackageManager pm = context.getPackageManager(); + final boolean isScreenLocked = mKeyguardManager != null + && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure(); String lastInputMethodId = Settings.Secure.getString(context .getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD); @@ -2075,7 +2076,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub final String subtypeHashCode = String.valueOf(subtype.hashCode()); // We show all enabled IMEs and subtypes when an IME is shown. if (enabledSubtypeSet.contains(subtypeHashCode) - && (mInputShown || !subtype.isAuxiliary())) { + && ((mInputShown && !isScreenLocked) || !subtype.isAuxiliary())) { final CharSequence title; final String mode = subtype.getMode(); title = TextUtils.concat(subtype.getDisplayName(context, @@ -2162,8 +2163,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } }); - if (showSubtypes && mKeyguardManager != null && !(mKeyguardManager.isKeyguardLocked() - && mKeyguardManager.isKeyguardSecure())) { + if (showSubtypes && !isScreenLocked) { mDialogBuilder.setPositiveButton( com.android.internal.R.string.configure_input_methods, new DialogInterface.OnClickListener() { @@ -2591,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/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 06077dd..85d8cece 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -16,6 +16,7 @@ package com.android.server; +import static android.Manifest.permission.DUMP; import static android.Manifest.permission.MANAGE_NETWORK_POLICY; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_DEFAULT; @@ -51,10 +52,12 @@ import com.google.android.collect.Sets; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.File; +import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; +import java.io.PrintWriter; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; @@ -69,7 +72,8 @@ import libcore.io.IoUtils; /** * @hide */ -class NetworkManagementService extends INetworkManagementService.Stub implements Watchdog.Monitor { +public class NetworkManagementService extends INetworkManagementService.Stub + implements Watchdog.Monitor { private static final String TAG = "NetworkManagementService"; private static final boolean DBG = false; private static final String NETD_TAG = "NetdConnector"; @@ -87,6 +91,12 @@ class NetworkManagementService extends INetworkManagementService.Stub implements /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */ private final File mStatsXtIface; + /** + * Name representing {@link #setGlobalAlert(long)} limit when delivered to + * {@link INetworkManagementEventObserver#limitReached(String, String)}. + */ + public static final String LIMIT_GLOBAL_ALERT = "globalAlert"; + /** {@link #mStatsXtUid} headers. */ private static final String KEY_IFACE = "iface"; private static final String KEY_UID = "uid_tag_int"; @@ -281,7 +291,6 @@ class NetworkManagementService extends INetworkManagementService.Stub implements for (INetworkManagementEventObserver obs : mObservers) { try { obs.limitReached(limitName, iface); - Slog.d(TAG, "Observer notified limit reached for " + limitName + " " + iface); } catch (Exception ex) { Slog.w(TAG, "Observer notifier failed", ex); } @@ -1024,7 +1033,6 @@ class NetworkManagementService extends INetworkManagementService.Stub implements final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); final NetworkStats.Entry entry = new NetworkStats.Entry(); - final HashSet<String> activeIfaces = Sets.newHashSet(); final ArrayList<String> values = Lists.newArrayList(); BufferedReader reader = null; @@ -1050,26 +1058,24 @@ class NetworkManagementService extends INetworkManagementService.Stub implements entry.txBytes = Long.parseLong(values.get(9)); entry.txPackets = Long.parseLong(values.get(10)); - activeIfaces.add(entry.iface); stats.addValues(entry); } catch (NumberFormatException e) { Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); } } + } catch (NullPointerException e) { + throw new IllegalStateException("problem parsing stats: " + e); + } catch (NumberFormatException e) { + throw new IllegalStateException("problem parsing stats: " + e); } catch (IOException e) { - Slog.w(TAG, "problem parsing stats: " + e); + throw new IllegalStateException("problem parsing stats: " + e); } finally { IoUtils.closeQuietly(reader); } - if (DBG) Slog.d(TAG, "recorded active stats from " + activeIfaces); - - // splice in stats from any disabled ifaces + // splice in historical stats not reflected in mStatsIface if (mBandwidthControlEnabled) { - final HashSet<String> xtIfaces = Sets.newHashSet(fileListWithoutNull(mStatsXtIface)); - xtIfaces.removeAll(activeIfaces); - - for (String iface : xtIfaces) { + for (String iface : fileListWithoutNull(mStatsXtIface)) { final File ifacePath = new File(mStatsXtIface, iface); entry.iface = iface; @@ -1081,10 +1087,8 @@ class NetworkManagementService extends INetworkManagementService.Stub implements entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes")); entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets")); - stats.addValues(entry); + stats.combineValues(entry); } - - if (DBG) Slog.d(TAG, "recorded stale stats from " + xtIfaces); } return stats; @@ -1338,8 +1342,12 @@ class NetworkManagementService extends INetworkManagementService.Stub implements Slog.w(TAG, "problem parsing stats row '" + line + "': " + e); } } + } catch (NullPointerException e) { + throw new IllegalStateException("problem parsing stats: " + e); + } catch (NumberFormatException e) { + throw new IllegalStateException("problem parsing stats: " + e); } catch (IOException e) { - Slog.w(TAG, "problem parsing stats: " + e); + throw new IllegalStateException("problem parsing stats: " + e); } finally { IoUtils.closeQuietly(reader); } @@ -1568,4 +1576,26 @@ class NetworkManagementService extends INetworkManagementService.Stub implements mConnector.monitor(); } } + + @Override + protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + mContext.enforceCallingOrSelfPermission(DUMP, TAG); + + pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled); + + synchronized (mQuotaLock) { + pw.print("Active quota ifaces: "); pw.println(mActiveQuotaIfaces.toString()); + pw.print("Active alert ifaces: "); pw.println(mActiveAlertIfaces.toString()); + } + + synchronized (mUidRejectOnQuota) { + pw.print("UID reject on quota ifaces: ["); + final int size = mUidRejectOnQuota.size(); + for (int i = 0; i < size; i++) { + pw.print(mUidRejectOnQuota.keyAt(i)); + if (i < size - 1) pw.print(","); + } + pw.println("]"); + } + } } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index e6f92a5..d0e8b5e 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -182,7 +182,7 @@ class ServerThread extends Thread { // only initialize the power service after we have started the // lights service, content providers and the battery service. - power.init(context, lights, ActivityManagerService.getDefault(), battery); + power.init(context, lights, ActivityManagerService.self(), battery); Slog.i(TAG, "Alarm Manager"); alarm = new AlarmManagerService(context); @@ -197,8 +197,7 @@ class ServerThread extends Thread { factoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL); ServiceManager.addService(Context.WINDOW_SERVICE, wm); - ((ActivityManagerService)ServiceManager.getService("activity")) - .setWindowManager(wm); + ActivityManagerService.self().setWindowManager(wm); // Skip Bluetooth if we have an emulator kernel // TODO: Use a more reliable check to see if this product should @@ -265,7 +264,7 @@ class ServerThread extends Thread { } catch (Throwable e) { reportWtf("making display ready", e); } - + try { pm.performBootDexOpt(); } catch (Throwable e) { @@ -618,8 +617,7 @@ class ServerThread extends Thread { // where third party code can really run (but before it has actually // started launching the initial applications), for us to complete our // initialization. - ((ActivityManagerService)ActivityManagerNative.getDefault()) - .systemReady(new Runnable() { + ActivityManagerService.self().systemReady(new Runnable() { public void run() { Slog.i(TAG, "Making services ready"); diff --git a/services/java/com/android/server/TelephonyRegistry.java b/services/java/com/android/server/TelephonyRegistry.java index dd54c16..4447ad0 100644 --- a/services/java/com/android/server/TelephonyRegistry.java +++ b/services/java/com/android/server/TelephonyRegistry.java @@ -421,11 +421,13 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { modified = true; } if (modified) { - Slog.d(TAG, "onDataConnectionStateChanged(" + state + ", " + networkType + ")"); + Slog.d(TAG, "onDataConnectionStateChanged(" + mDataConnectionState + + ", " + mDataConnectionNetworkType + ")"); for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) { try { - r.callback.onDataConnectionStateChanged(state, networkType); + r.callback.onDataConnectionStateChanged(mDataConnectionState, + mDataConnectionNetworkType); } catch (RemoteException ex) { mRemoveList.add(r.binder); } diff --git a/services/java/com/android/server/TextServicesManagerService.java b/services/java/com/android/server/TextServicesManagerService.java index 18ddabd..f6c369e 100644 --- a/services/java/com/android/server/TextServicesManagerService.java +++ b/services/java/com/android/server/TextServicesManagerService.java @@ -131,6 +131,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (DBG) Slog.d(TAG, "Add: " + compName); try { final SpellCheckerInfo sci = new SpellCheckerInfo(context, ri); + if (sci.getSubtypeCount() <= 0) { + Slog.w(TAG, "Skipping text service " + compName + + ": it does not contain subtypes."); + continue; + } list.add(sci); map.put(sci.getId(), sci); } catch (XmlPullParserException e) { @@ -173,7 +178,7 @@ 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.SELECTED_SPELL_CHECKER); if (DBG) { @@ -186,9 +191,11 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } + // TODO: Respect allowImplicitlySelectedSubtype // TODO: Save SpellCheckerSubtype by supported languages. @Override - public SpellCheckerSubtype getCurrentSpellCheckerSubtype(String locale) { + public SpellCheckerSubtype getCurrentSpellCheckerSubtype( + String locale, boolean allowImplicitlySelectedSubtype) { synchronized (mSpellCheckerMap) { final String subtypeHashCodeStr = Settings.Secure.getString(mContext.getContentResolver(), @@ -197,21 +204,46 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { Slog.w(TAG, "getCurrentSpellChecker: " + subtypeHashCodeStr); } final SpellCheckerInfo sci = getCurrentSpellChecker(null); - if (sci.getSubtypeCount() == 0) { + if (sci == null || sci.getSubtypeCount() == 0) { + if (DBG) { + Slog.w(TAG, "Subtype not found."); + } return null; } - if (TextUtils.isEmpty(subtypeHashCodeStr)) { - // Return the first Subtype if there is no settings for the current subtype. - return sci.getSubtypeAt(0); + final int hashCode; + if (!TextUtils.isEmpty(subtypeHashCodeStr)) { + hashCode = Integer.valueOf(subtypeHashCodeStr); + } else { + hashCode = 0; } - final int hashCode = Integer.valueOf(subtypeHashCodeStr); + if (hashCode == 0 && !allowImplicitlySelectedSubtype) { + return null; + } + final String systemLocale = + mContext.getResources().getConfiguration().locale.toString(); + SpellCheckerSubtype candidate = null; for (int i = 0; i < sci.getSubtypeCount(); ++i) { final SpellCheckerSubtype scs = sci.getSubtypeAt(i); - if (scs.hashCode() == hashCode) { + if (hashCode == 0) { + if (systemLocale.equals(locale)) { + return scs; + } else if (candidate == null) { + final String scsLocale = scs.getLocale(); + if (systemLocale.length() >= 2 + && scsLocale.length() >= 2 + && systemLocale.substring(0, 2).equals( + scsLocale.substring(0, 2))) { + candidate = scs; + } + } + } else if (scs.hashCode() == hashCode) { + if (DBG) { + Slog.w(TAG, "Return subtype " + scs.hashCode()); + } return scs; } } - return sci.getSubtypeAt(0); + return candidate; } } @@ -283,6 +315,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) { @@ -354,7 +393,21 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { "Requires permission " + android.Manifest.permission.WRITE_SECURE_SETTINGS); } - setCurrentSpellCheckerLocked(hashCode); + 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); } } @@ -363,35 +416,64 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { Slog.w(TAG, "setCurrentSpellChecker: " + sciId); } if (TextUtils.isEmpty(sciId) || !mSpellCheckerMap.containsKey(sciId)) return; + final SpellCheckerInfo currentSci = getCurrentSpellChecker(null); + if (currentSci != null && currentSci.getId().equals(sciId)) { + // Do nothing if the current spell checker is same as new spell checker. + return; + } final long ident = Binder.clearCallingIdentity(); try { Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.SELECTED_SPELL_CHECKER, sciId); + setCurrentSpellCheckerSubtypeLocked(0); } finally { Binder.restoreCallingIdentity(ident); } } - private void setCurrentSpellCheckerLocked(int hashCode) { + 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) { + int tempHashCode = 0; + for (int i = 0; sci != null && i < sci.getSubtypeCount(); ++i) { if(sci.getSubtypeAt(i).hashCode() == hashCode) { - found = true; + tempHashCode = hashCode; break; } } - if (!found) { - return; - } final long ident = Binder.clearCallingIdentity(); try { Settings.Secure.putString(mContext.getContentResolver(), - Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(hashCode)); + Settings.Secure.SELECTED_SPELL_CHECKER_SUBTYPE, String.valueOf(tempHashCode)); + } 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/ThrottleService.java b/services/java/com/android/server/ThrottleService.java index 24b6ac3..2155147 100644 --- a/services/java/com/android/server/ThrottleService.java +++ b/services/java/com/android/server/ThrottleService.java @@ -532,9 +532,12 @@ public class ThrottleService extends IThrottleManager.Stub { mLastRead = 0; mLastWrite = 0; } + } catch (IllegalStateException e) { + Slog.e(TAG, "problem during onPollAlarm: " + e); } catch (RemoteException e) { - Slog.e(TAG, "got remoteException in onPollAlarm:" + e); + Slog.e(TAG, "problem during onPollAlarm: " + e); } + // don't count this data if we're roaming. boolean roaming = "true".equals( SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING)); diff --git a/services/java/com/android/server/WallpaperManagerService.java b/services/java/com/android/server/WallpaperManagerService.java index 565063a..6ceccaf 100644 --- a/services/java/com/android/server/WallpaperManagerService.java +++ b/services/java/com/android/server/WallpaperManagerService.java @@ -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/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java index af01c5b..09ddc2f 100644 --- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java +++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java @@ -40,7 +40,6 @@ import android.os.IBinder; import android.os.Message; import android.os.RemoteException; import android.os.ServiceManager; -import android.os.SystemClock; import android.provider.Settings; import android.text.TextUtils; import android.text.TextUtils.SimpleStringSplitter; @@ -72,7 +71,6 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; /** * This class is instantiated by the system as a system level service and can be @@ -871,10 +869,6 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub boolean mIsAutomation; - final Callback mCallback = new Callback(); - - final AtomicInteger mInteractionIdCounter = new AtomicInteger(); - final Rect mTempBounds = new Rect(); // the events pending events to be dispatched to this service @@ -974,14 +968,16 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } - public AccessibilityNodeInfo findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId) + public float findAccessibilityNodeInfoByViewIdInActiveWindow(int viewId, + int interactionId, IAccessibilityInteractionConnectionCallback callback, + long interrogatingTid) throws RemoteException { IAccessibilityInteractionConnection connection = null; synchronized (mLock) { mSecurityPolicy.enforceCanRetrieveWindowContent(this); final boolean permissionGranted = mSecurityPolicy.canRetrieveWindowContent(this); if (!permissionGranted) { - return null; + return 0; } else { connection = getConnectionToRetrievalAllowingWindowLocked(); if (connection == null) { @@ -989,22 +985,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub Slog.e(LOG_TAG, "No interaction connection to a retrieve " + "allowing window."); } - return null; + return 0; } } } + final int interrogatingPid = Binder.getCallingPid(); final long identityToken = Binder.clearCallingIdentity(); try { - final int interactionId = mInteractionIdCounter.getAndIncrement(); - connection.findAccessibilityNodeInfoByViewId(viewId, interactionId, mCallback); - AccessibilityNodeInfo info = mCallback.getFindAccessibilityNodeInfoResultAndClear( - interactionId); - if (info != null) { - applyCompatibilityScaleIfNeeded(info); - info.setConnection(this); - info.setSealed(true); - } - return info; + connection.findAccessibilityNodeInfoByViewId(viewId, interactionId, callback, + interrogatingPid, interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error finding node."); @@ -1012,51 +1001,44 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } finally { Binder.restoreCallingIdentity(identityToken); } - return null; + return getCompatibilityScale(mSecurityPolicy.getRetrievalAllowingWindowLocked()); } - public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewTextInActiveWindow( - String text) throws RemoteException { + public float findAccessibilityNodeInfosByViewTextInActiveWindow( + String text, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long threadId) + throws RemoteException { return findAccessibilityNodeInfosByViewText(text, - mSecurityPolicy.mRetrievalAlowingWindowId, View.NO_ID); + mSecurityPolicy.mRetrievalAlowingWindowId, View.NO_ID, interactionId, callback, + threadId); } - public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewText(String text, - int accessibilityWindowId, int accessibilityViewId) throws RemoteException { + public float findAccessibilityNodeInfosByViewText(String text, + int accessibilityWindowId, int accessibilityViewId, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) + throws RemoteException { IAccessibilityInteractionConnection connection = null; synchronized (mLock) { mSecurityPolicy.enforceCanRetrieveWindowContent(this); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId); if (!permissionGranted) { - return null; + return 0; } else { connection = getConnectionToRetrievalAllowingWindowLocked(); if (connection == null) { if (DEBUG) { Slog.e(LOG_TAG, "No interaction connection to focused window."); } - return null; + return 0; } } } + final int interrogatingPid = Binder.getCallingPid(); final long identityToken = Binder.clearCallingIdentity(); try { - final int interactionId = mInteractionIdCounter.getAndIncrement(); connection.findAccessibilityNodeInfosByViewText(text, accessibilityViewId, - interactionId, mCallback); - List<AccessibilityNodeInfo> infos = - mCallback.getFindAccessibilityNodeInfosResultAndClear(interactionId); - if (infos != null) { - final int infoCount = infos.size(); - for (int i = 0; i < infoCount; i++) { - AccessibilityNodeInfo info = infos.get(i); - applyCompatibilityScaleIfNeeded(info); - info.setConnection(this); - info.setSealed(true); - } - } - return infos; + interactionId, callback, interrogatingPid, interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error finding node."); @@ -1064,18 +1046,20 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } finally { Binder.restoreCallingIdentity(identityToken); } - return null; + return getCompatibilityScale(accessibilityWindowId); } - public AccessibilityNodeInfo findAccessibilityNodeInfoByAccessibilityId( - int accessibilityWindowId, int accessibilityViewId) throws RemoteException { + public float findAccessibilityNodeInfoByAccessibilityId(int accessibilityWindowId, + int accessibilityViewId, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) + throws RemoteException { IAccessibilityInteractionConnection connection = null; synchronized (mLock) { mSecurityPolicy.enforceCanRetrieveWindowContent(this); final boolean permissionGranted = mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, accessibilityWindowId); if (!permissionGranted) { - return null; + return 0; } else { connection = mWindowIdToInteractionConnectionMap.get(accessibilityWindowId); if (connection == null) { @@ -1083,23 +1067,15 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub Slog.e(LOG_TAG, "No interaction connection to window: " + accessibilityWindowId); } - return null; + return 0; } } } + final int interrogatingPid = Binder.getCallingPid(); final long identityToken = Binder.clearCallingIdentity(); try { - final int interactionId = mInteractionIdCounter.getAndIncrement(); connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityViewId, - interactionId, mCallback); - AccessibilityNodeInfo info = - mCallback.getFindAccessibilityNodeInfoResultAndClear(interactionId); - if (info != null) { - applyCompatibilityScaleIfNeeded(info); - info.setConnection(this); - info.setSealed(true); - } - return info; + interactionId, callback, interrogatingPid, interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error requesting node with accessibilityViewId: " @@ -1108,11 +1084,12 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } finally { Binder.restoreCallingIdentity(identityToken); } - return null; + return getCompatibilityScale(accessibilityWindowId); } public boolean performAccessibilityAction(int accessibilityWindowId, - int accessibilityViewId, int action) { + int accessibilityViewId, int action, int interactionId, + IAccessibilityInteractionConnectionCallback callback, long interrogatingTid) { IAccessibilityInteractionConnection connection = null; synchronized (mLock) { final boolean permissionGranted = mSecurityPolicy.canPerformActionLocked(this, @@ -1130,12 +1107,11 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } } + final int interrogatingPid = Binder.getCallingPid(); final long identityToken = Binder.clearCallingIdentity(); try { - final int interactionId = mInteractionIdCounter.getAndIncrement(); connection.performAccessibilityAction(accessibilityViewId, action, interactionId, - mCallback); - return mCallback.getPerformAccessibilityActionResult(interactionId); + callback, interrogatingPid, interrogatingTid); } catch (RemoteException re) { if (DEBUG) { Slog.e(LOG_TAG, "Error requesting node with accessibilityViewId: " @@ -1144,7 +1120,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } finally { Binder.restoreCallingIdentity(identityToken); } - return false; + return true; } public void onServiceDisconnected(ComponentName componentName) { @@ -1173,22 +1149,9 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub return mWindowIdToInteractionConnectionMap.get(windowId); } - private void applyCompatibilityScaleIfNeeded(AccessibilityNodeInfo info) { - IBinder windowToken = mWindowIdToWindowTokenMap.get(info.getWindowId()); - final float scale = mWindowManagerService.getWindowCompatibilityScale(windowToken); - - if (scale == 1.0f) { - return; - } - - Rect bounds = mTempBounds; - info.getBoundsInParent(bounds); - bounds.scale(scale); - info.setBoundsInParent(bounds); - - info.getBoundsInScreen(bounds); - bounds.scale(scale); - info.setBoundsInScreen(bounds); + private float getCompatibilityScale(int windowId) { + IBinder windowToken = mWindowIdToWindowTokenMap.get(windowId); + return mWindowManagerService.getWindowCompatibilityScale(windowToken); } } @@ -1275,99 +1238,4 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub } } } - - final class Callback extends IAccessibilityInteractionConnectionCallback.Stub { - private static final long TIMEOUT_INTERACTION_MILLIS = 5000; - - private int mInteractionId = -1; - private AccessibilityNodeInfo mFindAccessibilityNodeInfoResult; - private List<AccessibilityNodeInfo> mFindAccessibilityNodeInfosResult; - private boolean mPerformAccessibilityActionResult; - - public void setFindAccessibilityNodeInfoResult(AccessibilityNodeInfo info, - int interactionId) { - synchronized (mLock) { - if (interactionId > mInteractionId) { - mFindAccessibilityNodeInfoResult = info; - mInteractionId = interactionId; - } - mLock.notifyAll(); - } - } - - public AccessibilityNodeInfo getFindAccessibilityNodeInfoResultAndClear(int interactionId) { - synchronized (mLock) { - waitForResultTimedLocked(TIMEOUT_INTERACTION_MILLIS, interactionId); - AccessibilityNodeInfo result = mFindAccessibilityNodeInfoResult; - clearLocked(); - return result; - } - } - - public void setFindAccessibilityNodeInfosResult(List<AccessibilityNodeInfo> infos, - int interactionId) { - synchronized (mLock) { - if (interactionId > mInteractionId) { - mFindAccessibilityNodeInfosResult = infos; - mInteractionId = interactionId; - } - mLock.notifyAll(); - } - } - - public List<AccessibilityNodeInfo> getFindAccessibilityNodeInfosResultAndClear( - int interactionId) { - synchronized (mLock) { - waitForResultTimedLocked(TIMEOUT_INTERACTION_MILLIS, interactionId); - List<AccessibilityNodeInfo> result = mFindAccessibilityNodeInfosResult; - clearLocked(); - return result; - } - } - - public void setPerformAccessibilityActionResult(boolean succeeded, int interactionId) { - synchronized (mLock) { - if (interactionId > mInteractionId) { - mPerformAccessibilityActionResult = succeeded; - mInteractionId = interactionId; - } - mLock.notifyAll(); - } - } - - public boolean getPerformAccessibilityActionResult(int interactionId) { - synchronized (mLock) { - waitForResultTimedLocked(TIMEOUT_INTERACTION_MILLIS, interactionId); - final boolean result = mPerformAccessibilityActionResult; - clearLocked(); - return result; - } - } - - public void clearLocked() { - mInteractionId = -1; - mFindAccessibilityNodeInfoResult = null; - mFindAccessibilityNodeInfosResult = null; - mPerformAccessibilityActionResult = false; - } - - private void waitForResultTimedLocked(long waitTimeMillis, int interactionId) { - final long startTimeMillis = SystemClock.uptimeMillis(); - while (true) { - try { - if (mInteractionId == interactionId) { - return; - } - final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; - waitTimeMillis = TIMEOUT_INTERACTION_MILLIS - elapsedTimeMillis; - if (waitTimeMillis <= 0) { - return; - } - mLock.wait(waitTimeMillis); - } catch (InterruptedException ie) { - /* ignore */ - } - } - } - } } diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java index 7232a94..bb5e989 100644 --- a/services/java/com/android/server/am/ActivityManagerService.java +++ b/services/java/com/android/server/am/ActivityManagerService.java @@ -91,7 +91,6 @@ 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; @@ -5518,6 +5517,48 @@ public final class ActivityManagerService extends ActivityManagerNative return msg; } + boolean incProviderCount(ProcessRecord r, ContentProviderRecord cpr) { + if (r != null) { + Integer cnt = r.conProviders.get(cpr); + if (DEBUG_PROVIDER) Slog.v(TAG, + "Adding provider requested by " + + r.processName + " from process " + + cpr.info.processName + ": " + cpr.name.flattenToShortString() + + " cnt=" + (cnt == null ? 1 : cnt)); + if (cnt == null) { + cpr.clients.add(r); + r.conProviders.put(cpr, new Integer(1)); + return true; + } else { + r.conProviders.put(cpr, new Integer(cnt.intValue()+1)); + } + } else { + cpr.externals++; + } + return false; + } + + boolean decProviderCount(ProcessRecord r, ContentProviderRecord cpr) { + if (r != null) { + Integer cnt = r.conProviders.get(cpr); + if (DEBUG_PROVIDER) Slog.v(TAG, + "Removing provider requested by " + + r.processName + " from process " + + cpr.info.processName + ": " + cpr.name.flattenToShortString() + + " cnt=" + cnt); + if (cnt == null || cnt.intValue() <= 1) { + cpr.clients.remove(r); + r.conProviders.remove(cpr); + return true; + } else { + r.conProviders.put(cpr, new Integer(cnt.intValue()-1)); + } + } else { + cpr.externals++; + } + return false; + } + private final ContentProviderHolder getContentProviderImpl( IApplicationThread caller, String name) { ContentProviderRecord cpr; @@ -5537,7 +5578,8 @@ public final class ActivityManagerService extends ActivityManagerNative // First check if this content provider has been published... cpr = mProvidersByName.get(name); - if (cpr != null) { + boolean providerRunning = cpr != null; + if (providerRunning) { cpi = cpr.info; String msg; if ((msg=checkContentProviderPermissionLocked(cpi, r)) != null) { @@ -5561,18 +5603,8 @@ public final class ActivityManagerService extends ActivityManagerNative // In this case the provider instance already exists, so we can // return it right away. - if (r != null) { - if (DEBUG_PROVIDER) Slog.v(TAG, - "Adding provider requested by " - + r.processName + " from process " - + cpr.info.processName); - Integer cnt = r.conProviders.get(cpr); - if (cnt == null) { - r.conProviders.put(cpr, new Integer(1)); - } else { - r.conProviders.put(cpr, new Integer(cnt.intValue()+1)); - } - cpr.clients.add(r); + final boolean countChanged = incProviderCount(r, cpr); + if (countChanged) { if (cpr.app != null && r.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { // If this is a perceptible app accessing the provider, // make sure to count it as being accessed and thus @@ -5580,17 +5612,46 @@ public final class ActivityManagerService extends ActivityManagerNative // content providers are often expensive to start. updateLruProcessLocked(cpr.app, false, true); } - } else { - cpr.externals++; } if (cpr.app != null) { - updateOomAdjLocked(cpr.app); + if (false) { + if (cpr.name.flattenToShortString().equals( + "com.android.providers.calendar/.CalendarProvider2")) { + Slog.v(TAG, "****************** KILLING " + + cpr.name.flattenToShortString()); + Process.killProcess(cpr.app.pid); + } + } + boolean success = updateOomAdjLocked(cpr.app); + if (DEBUG_PROVIDER) Slog.i(TAG, "Adjust success: " + success); + // NOTE: there is still a race here where a signal could be + // pending on the process even though we managed to update its + // adj level. Not sure what to do about this, but at least + // the race is now smaller. + if (!success) { + // Uh oh... it looks like the provider's process + // has been killed on us. We need to wait for a new + // process to be started, and make sure its death + // doesn't kill our process. + Slog.i(TAG, + "Existing provider " + cpr.name.flattenToShortString() + + " is crashing; detaching " + r); + boolean lastRef = decProviderCount(r, cpr); + appDiedLocked(cpr.app, cpr.app.pid, cpr.app.thread); + if (!lastRef) { + // This wasn't the last ref our process had on + // the provider... we have now been killed, bail. + return null; + } + providerRunning = false; + } } Binder.restoreCallingIdentity(origId); + } - } else { + if (!providerRunning) { try { cpi = AppGlobals.getPackageManager(). resolveContentProvider(name, @@ -5701,22 +5762,7 @@ public final class ActivityManagerService extends ActivityManagerNative mProvidersByClass.put(comp, cpr); } mProvidersByName.put(name, cpr); - - if (r != null) { - if (DEBUG_PROVIDER) Slog.v(TAG, - "Adding provider requested by " - + r.processName + " from process " - + cpr.info.processName); - Integer cnt = r.conProviders.get(cpr); - if (cnt == null) { - r.conProviders.put(cpr, new Integer(1)); - } else { - r.conProviders.put(cpr, new Integer(cnt.intValue()+1)); - } - cpr.clients.add(r); - } else { - cpr.externals++; - } + incProviderCount(r, cpr); } } @@ -5780,24 +5826,16 @@ public final class ActivityManagerService extends ActivityManagerNative //update content provider record entry info ComponentName comp = new ComponentName(cpr.info.packageName, cpr.info.name); ContentProviderRecord localCpr = mProvidersByClass.get(comp); - if (DEBUG_PROVIDER) Slog.v(TAG, "Removing provider requested by " - + r.info.processName + " from process " - + localCpr.appInfo.processName); if (localCpr.app == r) { //should not happen. taken care of as a local provider Slog.w(TAG, "removeContentProvider called on local provider: " + cpr.info.name + " in process " + r.processName); return; } else { - Integer cnt = r.conProviders.get(localCpr); - if (cnt == null || cnt.intValue() <= 1) { - localCpr.clients.remove(r); - r.conProviders.remove(localCpr); - } else { - r.conProviders.put(localCpr, new Integer(cnt.intValue()-1)); + if (decProviderCount(r, localCpr)) { + updateOomAdjLocked(); } } - updateOomAdjLocked(); } } @@ -13458,16 +13496,18 @@ public final class ActivityManagerService extends ActivityManagerNative } } - private final void updateOomAdjLocked( + private final boolean updateOomAdjLocked( ProcessRecord app, int hiddenAdj, ProcessRecord TOP_APP) { app.hiddenAdj = hiddenAdj; if (app.thread == null) { - return; + return false; } final boolean wasKeeping = app.keeping; + boolean success = true; + computeOomAdjLocked(app, hiddenAdj, TOP_APP, false); if (app.curRawAdj != app.setRawAdj) { @@ -13504,6 +13544,7 @@ public final class ActivityManagerService extends ActivityManagerNative " oom adj to " + app.curAdj + " because " + app.adjType); app.setAdj = app.curAdj; } else { + success = false; Slog.w(TAG, "Failed setting oom adj of " + app + " to " + app.curAdj); } } @@ -13518,6 +13559,7 @@ public final class ActivityManagerService extends ActivityManagerNative EventLog.writeEvent(EventLogTags.AM_KILL, app.pid, app.processName, app.setAdj, app.waitingToKill); Process.killProcessQuiet(app.pid); + success = false; } else { if (true) { long oldId = Binder.clearCallingIdentity(); @@ -13540,6 +13582,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } } + return success; } private final ActivityRecord resumedAppLocked() { @@ -13553,7 +13596,7 @@ public final class ActivityManagerService extends ActivityManagerNative return resumedActivity; } - private final void updateOomAdjLocked(ProcessRecord app) { + private final boolean updateOomAdjLocked(ProcessRecord app) { final ActivityRecord TOP_ACT = resumedAppLocked(); final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null; int curAdj = app.curAdj; @@ -13562,7 +13605,7 @@ public final class ActivityManagerService extends ActivityManagerNative mAdjSeq++; - updateOomAdjLocked(app, app.hiddenAdj, TOP_APP); + boolean success = updateOomAdjLocked(app, app.hiddenAdj, TOP_APP); final boolean nowHidden = app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ && app.curAdj <= ProcessList.HIDDEN_APP_MAX_ADJ; if (nowHidden != wasHidden) { @@ -13570,6 +13613,7 @@ public final class ActivityManagerService extends ActivityManagerNative // list may also be changed. updateOomAdjLocked(); } + return success; } final void updateOomAdjLocked() { diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java index dfcc0bf..131255f 100644 --- a/services/java/com/android/server/am/ProcessList.java +++ b/services/java/com/android/server/am/ProcessList.java @@ -163,7 +163,7 @@ class ProcessList { int minSize = 320*480; // 153600 int maxSize = 1280*800; // 1024000 230400 870400 .264 float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize); - Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight); + //Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight); StringBuilder adjString = new StringBuilder(); StringBuilder memString = new StringBuilder(); diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java index 84880f9..77f53c2 100644 --- a/services/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java @@ -60,6 +60,7 @@ import static com.android.server.net.NetworkPolicyManagerService.XmlUtils.writeL import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.START_TAG; +import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; import android.app.IActivityManager; import android.app.INotificationManager; @@ -132,6 +133,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import libcore.io.IoUtils; @@ -454,7 +456,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); synchronized (mRulesLock) { - if (mMeteredIfaces.contains(iface)) { + if (mMeteredIfaces.contains(iface) && !LIMIT_GLOBAL_ALERT.equals(limitName)) { try { // force stats update to make sure we have numbers that // caused alert to trigger. @@ -763,7 +765,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // 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); + final boolean enabled = !overLimit; + + setNetworkTemplateEnabled(policy.template, enabled); } } @@ -772,7 +776,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * 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: @@ -830,9 +833,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // collect all active ifaces that match this template ifaceList.clear(); - for (NetworkIdentity ident : networks.keySet()) { + for (Map.Entry<NetworkIdentity, String> entry : networks.entrySet()) { + final NetworkIdentity ident = entry.getKey(); if (policy.template.matches(ident)) { - final String iface = networks.get(ident); + final String iface = entry.getValue(); ifaceList.add(iface); } } diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index c911687..bb0a0d1 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -43,6 +43,7 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS; import static android.text.format.DateUtils.HOUR_IN_MILLIS; import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static com.android.internal.util.Preconditions.checkNotNull; +import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; @@ -56,6 +57,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.net.IConnectivityManager; +import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.NetworkIdentity; import android.net.NetworkInfo; @@ -121,7 +123,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private static final int VERSION_UID_WITH_TAG = 3; private static final int VERSION_UID_WITH_SET = 4; - private static final int MSG_FORCE_UPDATE = 0x1; + private static final int MSG_PERFORM_POLL = 0x1; + private static final int MSG_PERFORM_POLL_DETAILED = 0x2; private final Context mContext; private final INetworkManagementService mNetworkManager; @@ -141,7 +144,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private PendingIntent mPollIntent; - // TODO: listen for kernel push events through netd instead of polling // TODO: trim empty history objects entirely private static final long KB_IN_BYTES = 1024; @@ -174,17 +176,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Flag if {@link #mUidStats} have been loaded from disk. */ private boolean mUidStatsLoaded = false; - private NetworkStats mLastNetworkSnapshot; - private NetworkStats mLastPersistNetworkSnapshot; + private NetworkStats mLastPollNetworkSnapshot; + private NetworkStats mLastPollUidSnapshot; + private NetworkStats mLastPollOperationsSnapshot; - private NetworkStats mLastUidSnapshot; + private NetworkStats mLastPersistNetworkSnapshot; + private NetworkStats mLastPersistUidSnapshot; /** Current counter sets for each UID. */ private SparseIntArray mActiveUidCounterSet = new SparseIntArray(); /** Data layer operation counters for splicing into other structures. */ private NetworkStats mOperations = new NetworkStats(0L, 10); - private NetworkStats mLastOperationsSnapshot; private final HandlerThread mHandlerThread; private final Handler mHandler; @@ -252,13 +255,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mContext.registerReceiver(mShutdownReceiver, shutdownFilter); try { - registerPollAlarmLocked(); + mNetworkManager.registerObserver(mAlertObserver); } catch (RemoteException e) { - Slog.w(TAG, "unable to register poll alarm"); + // ouch, no push updates means we fall back to + // ACTION_NETWORK_STATS_POLL intervals. + Slog.e(TAG, "unable to register INetworkManagementEventObserver", e); } - // kick off background poll to bootstrap deltas - mHandler.obtainMessage(MSG_FORCE_UPDATE).sendToTarget(); + registerPollAlarmLocked(); + registerGlobalAlert(); + + // bootstrap initial stats to prevent double-counting later + bootstrapStats(); } private void shutdownLocked() { @@ -280,17 +288,37 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}. */ - private void registerPollAlarmLocked() throws RemoteException { - if (mPollIntent != null) { - mAlarmManager.remove(mPollIntent); - } + private void registerPollAlarmLocked() { + try { + if (mPollIntent != null) { + mAlarmManager.remove(mPollIntent); + } - mPollIntent = PendingIntent.getBroadcast( - mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); + mPollIntent = PendingIntent.getBroadcast( + mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); - final long currentRealtime = SystemClock.elapsedRealtime(); - mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, - mSettings.getPollInterval(), mPollIntent); + final long currentRealtime = SystemClock.elapsedRealtime(); + mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, + mSettings.getPollInterval(), mPollIntent); + } catch (RemoteException e) { + Slog.w(TAG, "problem registering for poll alarm: " + e); + } + } + + /** + * Register for a global alert that is delivered through + * {@link INetworkManagementEventObserver} once a threshold amount of data + * has been transferred. + */ + private void registerGlobalAlert() { + try { + final long alertBytes = mSettings.getPersistThreshold(); + mNetworkManager.setGlobalAlert(alertBytes); + } catch (IllegalStateException e) { + Slog.w(TAG, "problem registering for global alert: " + e); + } catch (RemoteException e) { + Slog.w(TAG, "problem registering for global alert: " + e); + } } @Override @@ -475,10 +503,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { @Override public void forceUpdate() { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); - - synchronized (mStatsLock) { - performPollLocked(true, false); - } + performPoll(true, false); } /** @@ -507,14 +532,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { public void onReceive(Context context, Intent intent) { // on background handler thread, and verified UPDATE_DEVICE_STATS // permission above. - synchronized (mStatsLock) { - mWakeLock.acquire(); - try { - performPollLocked(true, false); - } finally { - mWakeLock.release(); - } - } + performPoll(true, false); + + // verify that we're watching global alert + registerGlobalAlert(); } }; @@ -547,6 +568,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub { }; /** + * Observer that watches for {@link INetworkManagementService} alerts. + */ + private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { + @Override + public void limitReached(String limitName, String iface) { + // only someone like NMS should be calling us + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + if (LIMIT_GLOBAL_ALERT.equals(limitName)) { + // kick off background poll to collect network stats; UID stats + // are handled during normal polling interval. + mHandler.obtainMessage(MSG_PERFORM_POLL).sendToTarget(); + + // re-arm global alert for next update + registerGlobalAlert(); + } + } + }; + + /** * Inspect all current {@link NetworkState} to derive mapping from {@code * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo} * are active on a single {@code iface}, they are combined under a single @@ -588,6 +629,33 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } /** + * Bootstrap initial stats snapshot, usually during {@link #systemReady()} + * so we have baseline values without double-counting. + */ + private void bootstrapStats() { + try { + mLastPollNetworkSnapshot = mNetworkManager.getNetworkStatsSummary(); + mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); + mLastPollOperationsSnapshot = new NetworkStats(0L, 0); + } catch (IllegalStateException e) { + Slog.w(TAG, "problem reading network stats: " + e); + } catch (RemoteException e) { + Slog.w(TAG, "problem reading network stats: " + e); + } + } + + private void performPoll(boolean detailedPoll, boolean forcePersist) { + synchronized (mStatsLock) { + mWakeLock.acquire(); + try { + performPollLocked(detailedPoll, forcePersist); + } finally { + mWakeLock.release(); + } + } + } + + /** * Periodic poll operation, reading current statistics and recording into * {@link NetworkStatsHistory}. * @@ -596,6 +664,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { */ private void performPollLocked(boolean detailedPoll, boolean forcePersist) { if (LOGV) Slog.v(TAG, "performPollLocked()"); + final long startRealtime = SystemClock.elapsedRealtime(); // try refreshing time source when stale if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) { @@ -605,6 +674,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // TODO: consider marking "untrusted" times in historical stats final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); + final long persistThreshold = mSettings.getPersistThreshold(); final NetworkStats networkSnapshot; final NetworkStats uidSnapshot; @@ -620,30 +690,32 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } performNetworkPollLocked(networkSnapshot, currentTime); - if (detailedPoll) { - performUidPollLocked(uidSnapshot, currentTime); - } - // decide if enough has changed to trigger persist - final NetworkStats persistDelta = computeStatsDelta( + // persist when enough network data has occurred + final NetworkStats persistNetworkDelta = computeStatsDelta( mLastPersistNetworkSnapshot, networkSnapshot, true); - final long persistThreshold = mSettings.getPersistThreshold(); + if (forcePersist || persistNetworkDelta.getTotalBytes() > persistThreshold) { + writeNetworkStatsLocked(); + mLastPersistNetworkSnapshot = networkSnapshot; + } - NetworkStats.Entry entry = null; - for (String iface : persistDelta.getUniqueIfaces()) { - final int index = persistDelta.findIndex(iface, UID_ALL, SET_DEFAULT, TAG_NONE); - entry = persistDelta.getValues(index, entry); - if (forcePersist || entry.rxBytes > persistThreshold - || entry.txBytes > persistThreshold) { - writeNetworkStatsLocked(); - if (mUidStatsLoaded) { - writeUidStatsLocked(); - } - mLastPersistNetworkSnapshot = networkSnapshot; - break; + if (detailedPoll) { + performUidPollLocked(uidSnapshot, currentTime); + + // persist when enough network data has occurred + final NetworkStats persistUidDelta = computeStatsDelta( + mLastPersistUidSnapshot, uidSnapshot, true); + if (forcePersist || persistUidDelta.getTotalBytes() > persistThreshold) { + writeUidStatsLocked(); + mLastPersistUidSnapshot = networkSnapshot; } } + if (LOGV) { + final long duration = SystemClock.elapsedRealtime() - startRealtime; + Slog.v(TAG, "performPollLocked() took " + duration + "ms"); + } + // finally, dispatch updated event to any listeners final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); @@ -656,7 +728,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void performNetworkPollLocked(NetworkStats networkSnapshot, long currentTime) { final HashSet<String> unknownIface = Sets.newHashSet(); - final NetworkStats delta = computeStatsDelta(mLastNetworkSnapshot, networkSnapshot, false); + final NetworkStats delta = computeStatsDelta(mLastPollNetworkSnapshot, networkSnapshot, false); final long timeStart = currentTime - delta.getElapsedRealtime(); NetworkStats.Entry entry = null; @@ -678,7 +750,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { history.removeBucketsBefore(currentTime - maxHistory); } - mLastNetworkSnapshot = networkSnapshot; + mLastPollNetworkSnapshot = networkSnapshot; if (LOGD && unknownIface.size() > 0) { Slog.w(TAG, "unknown interfaces " + unknownIface.toString() + ", ignoring those stats"); @@ -691,9 +763,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) { ensureUidStatsLoadedLocked(); - final NetworkStats delta = computeStatsDelta(mLastUidSnapshot, uidSnapshot, false); + final NetworkStats delta = computeStatsDelta(mLastPollUidSnapshot, uidSnapshot, false); final NetworkStats operationsDelta = computeStatsDelta( - mLastOperationsSnapshot, mOperations, false); + mLastPollOperationsSnapshot, mOperations, false); final long timeStart = currentTime - delta.getElapsedRealtime(); NetworkStats.Entry entry = null; @@ -731,8 +803,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } - mLastUidSnapshot = uidSnapshot; - mLastOperationsSnapshot = mOperations; + mLastPollUidSnapshot = uidSnapshot; + mLastPollOperationsSnapshot = mOperations; mOperations = new NetworkStats(0L, 10); } @@ -1162,8 +1234,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** {@inheritDoc} */ public boolean handleMessage(Message msg) { switch (msg.what) { - case MSG_FORCE_UPDATE: { - forceUpdate(); + case MSG_PERFORM_POLL: { + performPoll(false, false); + return true; + } + case MSG_PERFORM_POLL_DETAILED: { + performPoll(true, false); return true; } default: { @@ -1226,10 +1302,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } public long getPollInterval() { - return getSecureLong(NETSTATS_POLL_INTERVAL, 15 * MINUTE_IN_MILLIS); + return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); } public long getPersistThreshold() { - return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 16 * KB_IN_BYTES); + return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 512 * KB_IN_BYTES); } public long getNetworkBucketDuration() { return getSecureLong(NETSTATS_NETWORK_BUCKET_DURATION, HOUR_IN_MILLIS); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index 2f19a46..b8797d1 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -194,7 +194,8 @@ public class PackageManagerService extends IPackageManager.Stub { /** * 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 diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp index ff4786b..0ab86c3 100644 --- a/services/sensorservice/Fusion.cpp +++ b/services/sensorservice/Fusion.cpp @@ -47,9 +47,46 @@ static const float biasVAR = 1e-8; // (rad/s)^2 / s (guessed) static const float accSTDEV = 0.05f; // m/s^2 (measured 0.08 / CDD 0.05) static const float magSTDEV = 0.5f; // uT (measured 0.7 / CDD 0.5) -static const float FREE_FALL_THRESHOLD = 0.981f; static const float SYMMETRY_TOLERANCE = 1e-10f; +/* + * Accelerometer updates will not be performed near free fall to avoid + * ill-conditioning and div by zeros. + * Threshhold: 10% of g, in m/s^2 + */ +static const float FREE_FALL_THRESHOLD = 0.981f; +static const float FREE_FALL_THRESHOLD_SQ = + FREE_FALL_THRESHOLD*FREE_FALL_THRESHOLD; + +/* + * The geomagnetic-field should be between 30uT and 60uT. + * Fields strengths greater than this likely indicate a local magnetic + * disturbance which we do not want to update into the fused frame. + */ +static const float MAX_VALID_MAGNETIC_FIELD = 100; // uT +static const float MAX_VALID_MAGNETIC_FIELD_SQ = + MAX_VALID_MAGNETIC_FIELD*MAX_VALID_MAGNETIC_FIELD; + +/* + * Values of the field smaller than this should be ignored in fusion to avoid + * ill-conditioning. This state can happen with anomalous local magnetic + * disturbances canceling the Earth field. + */ +static const float MIN_VALID_MAGNETIC_FIELD = 10; // uT +static const float MIN_VALID_MAGNETIC_FIELD_SQ = + MIN_VALID_MAGNETIC_FIELD*MIN_VALID_MAGNETIC_FIELD; + +/* + * If the cross product of two vectors has magnitude squared less than this, + * we reject it as invalid due to alignment of the vectors. + * This threshold is used to check for the case where the magnetic field sample + * is parallel to the gravity field, which can happen in certain places due + * to magnetic field disturbances. + */ +static const float MIN_VALID_CROSS_PRODUCT_MAG = 1.0e-3; +static const float MIN_VALID_CROSS_PRODUCT_MAG_SQ = + MIN_VALID_CROSS_PRODUCT_MAG*MIN_VALID_CROSS_PRODUCT_MAG; + // ----------------------------------------------------------------------- template <typename TYPE, size_t C, size_t R> @@ -240,8 +277,9 @@ void Fusion::handleGyro(const vec3_t& w, float dT) { status_t Fusion::handleAcc(const vec3_t& a) { // ignore acceleration data if we're close to free-fall - if (length(a) < FREE_FALL_THRESHOLD) + if (length_squared(a) < FREE_FALL_THRESHOLD_SQ) { return BAD_VALUE; + } if (!checkInitComplete(ACC, a)) return BAD_VALUE; @@ -253,15 +291,34 @@ status_t Fusion::handleAcc(const vec3_t& a) { status_t Fusion::handleMag(const vec3_t& m) { // the geomagnetic-field should be between 30uT and 60uT - // reject obviously wrong magnetic-fields - if (length(m) > 100) + // reject if too large to avoid spurious magnetic sources + const float magFieldSq = length_squared(m); + if (magFieldSq > MAX_VALID_MAGNETIC_FIELD_SQ) { + return BAD_VALUE; + } else if (magFieldSq < MIN_VALID_MAGNETIC_FIELD_SQ) { + // Also reject if too small since we will get ill-defined (zero mag) + // cross-products below return BAD_VALUE; + } if (!checkInitComplete(MAG, m)) return BAD_VALUE; + // Orthogonalize the magnetic field to the gravity field, mapping it into + // tangent to Earth. const vec3_t up( getRotationMatrix() * Ba ); const vec3_t east( cross_product(m, up) ); + + // If the m and up vectors align, the cross product magnitude will + // approach 0. + // Reject this case as well to avoid div by zero problems and + // ill-conditioning below. + if (length_squared(east) < MIN_VALID_CROSS_PRODUCT_MAG_SQ) { + return BAD_VALUE; + } + + // If we have created an orthogonal magnetic field successfully, + // then pass it in as the update. vec3_t north( cross_product(up, east) ); const float l = 1 / length(north); diff --git a/services/sensorservice/vec.h b/services/sensorservice/vec.h index f74ccc5..24f30ff 100644 --- a/services/sensorservice/vec.h +++ b/services/sensorservice/vec.h @@ -212,6 +212,15 @@ template < typename TYPE, size_t SIZE > +TYPE PURE length_squared(const V<TYPE, SIZE>& v) { + return dot_product(v, v); +} + +template < + template<typename T, size_t S> class V, + typename TYPE, + size_t SIZE +> V<TYPE, SIZE> PURE normalize(const V<TYPE, SIZE>& v) { return v * (1/length(v)); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6fde361..598220f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2211,10 +2211,13 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, const size_t count = layers.size(); for (size_t i=0 ; i<count ; ++i) { const sp<LayerBase>& layer(layers[i]); - const uint32_t z = layer->drawingState().z; - if (z >= minLayerZ && z <= maxLayerZ) { - if (layer->isProtected()) { - return INVALID_OPERATION; + const uint32_t flags = layer->drawingState().flags; + if (!(flags & ISurfaceComposer::eLayerHidden)) { + const uint32_t z = layer->drawingState().z; + if (z >= minLayerZ && z <= maxLayerZ) { + if (layer->isProtected()) { + return INVALID_OPERATION; + } } } } @@ -2270,9 +2273,12 @@ status_t SurfaceFlinger::captureScreenImplLocked(DisplayID dpy, for (size_t i=0 ; i<count ; ++i) { const sp<LayerBase>& layer(layers[i]); - const uint32_t z = layer->drawingState().z; - if (z >= minLayerZ && z <= maxLayerZ) { - layer->drawForSreenShot(); + const uint32_t flags = layer->drawingState().flags; + if (!(flags & ISurfaceComposer::eLayerHidden)) { + const uint32_t z = layer->drawingState().z; + if (z >= minLayerZ && z <= maxLayerZ) { + layer->drawForSreenShot(); + } } } diff --git a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java index 5f35697..ecf78d9 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkManagementServiceTest.java @@ -117,6 +117,18 @@ public class NetworkManagementServiceTest extends AndroidTestCase { assertStatsEntry(stats, "wlan0", UID_ALL, SET_DEFAULT, TAG_NONE, 1024L, 2048L); } + public void testNetworkStatsCombined() throws Exception { + stageFile(R.raw.net_dev_typical, new File(mTestProc, "net/dev")); + stageLong(10L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_bytes")); + stageLong(20L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/rx_packets")); + stageLong(30L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_bytes")); + stageLong(40L, new File(mTestProc, "net/xt_qtaguid/iface_stat/rmnet0/tx_packets")); + + final NetworkStats stats = mService.getNetworkStatsSummary(); + assertStatsEntry(stats, "rmnet0", UID_ALL, SET_DEFAULT, TAG_NONE, 1507570L + 10L, + 2205L + 20L, 489339L + 30L, 2237L + 40L); + } + public void testKernelTags() throws Exception { assertEquals("0", tagToKernel(0x0)); assertEquals("214748364800", tagToKernel(0x32)); diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java index 6138490..6dd8cd6 100644 --- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java @@ -38,6 +38,7 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import static android.text.format.DateUtils.WEEK_IN_MILLIS; import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL; import static org.easymock.EasyMock.anyLong; +import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.createMock; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; @@ -49,6 +50,7 @@ import android.app.IAlarmManager; import android.app.PendingIntent; import android.content.Intent; import android.net.IConnectivityManager; +import android.net.INetworkManagementEventObserver; import android.net.LinkProperties; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; @@ -65,10 +67,10 @@ import android.util.TrustedTime; import com.android.server.net.NetworkStatsService; import com.android.server.net.NetworkStatsService.NetworkStatsSettings; +import org.easymock.Capture; import org.easymock.EasyMock; import java.io.File; -import java.util.concurrent.Future; import libcore.io.IoUtils; @@ -105,6 +107,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { private IConnectivityManager mConnManager; private NetworkStatsService mService; + private INetworkManagementEventObserver mNetworkObserver; @Override public void setUp() throws Exception { @@ -132,13 +135,20 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - final Future<?> firstPoll = expectSystemReady(); + expectSystemReady(); + + // catch INetworkManagementEventObserver during systemReady() + final Capture<INetworkManagementEventObserver> networkObserver = new Capture< + INetworkManagementEventObserver>(); + mNetManager.registerObserver(capture(networkObserver)); + expectLastCall().atLeastOnce(); replay(); mService.systemReady(); - firstPoll.get(); verifyAndReset(); + mNetworkObserver = networkObserver.getValue(); + } @Override @@ -183,6 +193,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 1024L, 1L, 2048L, 2L)); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); @@ -199,6 +210,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 4096L, 4L, 8192L, 8L)); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); @@ -238,6 +250,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 512L, 4L, 256L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 256L, 2L, 128L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 128L, 1L, 0L)); + expectNetworkStatsPoll(); mService.setUidForeground(UID_RED, false); mService.incrementOperationCount(UID_RED, 0xFAAD, 4); @@ -273,11 +286,18 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectDefaultSettings(); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); - final Future<?> firstPoll = expectSystemReady(); + expectSystemReady(); + + // catch INetworkManagementEventObserver during systemReady() + final Capture<INetworkManagementEventObserver> networkObserver = new Capture< + INetworkManagementEventObserver>(); + mNetManager.registerObserver(capture(networkObserver)); + expectLastCall().atLeastOnce(); replay(); mService.systemReady(); - firstPoll.get(); + + mNetworkObserver = networkObserver.getValue(); // after systemReady(), we should have historical stats loaded again assertNetworkTotal(sTemplateWifi, 1024L, 8L, 2048L, 16L, 0); @@ -312,6 +332,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) .addIfaceValues(TEST_IFACE, 512L, 4L, 512L, 4L)); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); @@ -329,6 +350,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectSettings(0L, 30 * MINUTE_IN_MILLIS, WEEK_IN_MILLIS); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); @@ -363,6 +385,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1536L, 12L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 512L, 4L, 0L, 0L, 0L)); + expectNetworkStatsPoll(); mService.incrementOperationCount(UID_RED, 0xF00D, 10); @@ -384,6 +407,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkState(buildMobile3gState(IMSI_2)); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); replay(); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); @@ -399,6 +423,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 128L, 1L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, 0xFAAD, 128L, 1L, 1024L, 8L, 0L)); + expectNetworkStatsPoll(); mService.incrementOperationCount(UID_BLUE, 0xFAAD, 10); @@ -441,6 +466,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 16L, 1L, 16L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 4096L, 258L, 512L, 32L, 0L) .addValues(TEST_IFACE, UID_GREEN, SET_DEFAULT, TAG_NONE, 16L, 1L, 16L, 1L, 0L)); + expectNetworkStatsPoll(); mService.incrementOperationCount(UID_RED, 0xFAAD, 10); @@ -494,6 +520,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1024L, 8L, 1024L, 8L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 512L, 4L, 512L, 4L, 0L)); + expectNetworkStatsPoll(); mService.incrementOperationCount(UID_RED, 0xF00D, 5); @@ -511,6 +538,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkState(buildMobile4gState()); expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(buildEmptyStats()); + expectNetworkStatsPoll(); replay(); mServiceContext.sendBroadcast(new Intent(CONNECTIVITY_ACTION)); @@ -525,6 +553,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 512L, 4L, 256L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xFAAD, 512L, 4L, 256L, 2L, 0L)); + expectNetworkStatsPoll(); mService.incrementOperationCount(UID_RED, 0xFAAD, 5); @@ -558,6 +587,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 50L, 5L, 50L, 5L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 10L, 1L, 10L, 1L, 0L) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1024L, 8L, 512L, 4L, 0L)); + expectNetworkStatsPoll(); mService.incrementOperationCount(UID_RED, 0xF00D, 1); @@ -576,6 +606,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkStatsSummary(buildEmptyStats()); expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 2048L, 16L, 1024L, 8L, 0L)); + expectNetworkStatsPoll(); replay(); mServiceContext.sendBroadcast(new Intent(ACTION_NETWORK_STATS_POLL)); @@ -617,6 +648,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L)); + expectNetworkStatsPoll(); mService.incrementOperationCount(UID_RED, 0xF00D, 1); @@ -637,6 +669,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, 0xF00D, 64L, 1L, 64L, 1L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, TAG_NONE, 32L, 2L, 32L, 2L, 0L) .addValues(TEST_IFACE, UID_RED, SET_FOREGROUND, 0xFAAD, 1L, 1L, 1L, 1L, 0L)); + expectNetworkStatsPoll(); mService.setUidForeground(UID_RED, true); mService.incrementOperationCount(UID_RED, 0xFAAD, 1); @@ -679,7 +712,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase { txPackets, operations); } - private Future<?> expectSystemReady() throws Exception { + private void expectSystemReady() throws Exception { mAlarmManager.remove(isA(PendingIntent.class)); expectLastCall().anyTimes(); @@ -687,8 +720,8 @@ public class NetworkStatsServiceTest extends AndroidTestCase { eq(AlarmManager.ELAPSED_REALTIME), anyLong(), anyLong(), isA(PendingIntent.class)); expectLastCall().atLeastOnce(); - return mServiceContext.nextBroadcastIntent( - NetworkStatsService.ACTION_NETWORK_STATS_UPDATED); + mNetManager.setGlobalAlert(anyLong()); + expectLastCall().atLeastOnce(); } private void expectNetworkState(NetworkState... state) throws Exception { @@ -727,6 +760,11 @@ public class NetworkStatsServiceTest extends AndroidTestCase { expect(mTime.getCacheCertainty()).andReturn(0L).anyTimes(); } + private void expectNetworkStatsPoll() throws Exception { + mNetManager.setGlobalAlert(anyLong()); + expectLastCall().anyTimes(); + } + private void assertStatsFilesExist(boolean exist) { final File networkFile = new File(mStatsDir, "netstats.bin"); final File uidFile = new File(mStatsDir, "netstats_uid.bin"); |