Enable NSRM (network socket request manager)
NSRM is a feature to synchronize app socket requests
to reduce network signalling and there by save some power.
Change-Id: Ice992713994045d0582f8cfb7b6761e2689f2555
Conflicts:
services/core/java/com/android/server/AlarmManagerService.java
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index c15e6c2..e894f63 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -114,6 +115,9 @@
final Object mLock = new Object();
+ private final ArrayList<Integer> mTriggeredUids = new ArrayList<Integer>();
+ private final ArrayList<Integer> mBlockedUids = new ArrayList<Integer>();
+
long mNativeData;
private long mNextWakeup;
private long mNextRtcWakeup;
@@ -560,9 +564,10 @@
final BroadcastStats mBroadcastStats;
final FilterStats mFilterStats;
final int mAlarmType;
+ final int mUid;
InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
- int alarmType, String tag) {
+ int alarmType, String tag, int uid) {
mPendingIntent = pendingIntent;
mWorkSource = workSource;
mTag = tag;
@@ -574,6 +579,7 @@
}
mFilterStats = fs;
mAlarmType = alarmType;
+ mUid = uid;
}
}
@@ -1280,6 +1286,44 @@
}
}
+ /* updates the blocked uids, so if a wake lock is acquired to only fire
+ * alarm for it, it can be released.
+ */
+ void updateBlockedUids(int uid, boolean isBlocked) {
+ if (localLOGV) Slog.v(TAG, "UpdateBlockedUids: uid = "+uid +" isBlocked = "+isBlocked);
+ synchronized(mLock) {
+ if(isBlocked) {
+ mBlockedUids.add(new Integer(uid));
+ if (checkReleaseWakeLock()) {
+ /* all the uids for which the alarms are triggered
+ * are either blocked or have called onSendFinished.
+ */
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ if (localLOGV)
+ Slog.v(TAG, "AM WakeLock Released Internally in updateBlockedUids");
+ }
+ }
+ } else {
+ mBlockedUids.clear();
+ }
+ }
+ }
+
+ boolean checkReleaseWakeLock() {
+ if (mTriggeredUids.size() == 0 || mBlockedUids.size() == 0)
+ return false;
+
+ int uid;
+ for (int i = 0; i < mTriggeredUids.size(); i++) {
+ uid = mTriggeredUids.get(i);
+ if (!mBlockedUids.contains(uid)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private void removeLocked(PendingIntent operation) {
boolean didRemove = false;
for (int i = mAlarmBatches.size() - 1; i >= 0; i--) {
@@ -1555,6 +1599,8 @@
public final AlarmManager.AlarmClockInfo alarmClock;
public final int userId;
public PriorityClass priorityClass;
+ public int uid;
+ public int pid;
public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
long _interval, PendingIntent _op, WorkSource _ws,
@@ -1573,6 +1619,8 @@
workSource = _ws;
alarmClock = _info;
userId = _userId;
+ uid = Binder.getCallingUid();
+ pid = Binder.getCallingPid();
}
public static String makeTag(PendingIntent pi, int type) {
@@ -1680,15 +1728,16 @@
mResultReceiver, mHandler);
// we have an active broadcast so stay awake.
- if (mBroadcastRefCount == 0) {
+ if (mBroadcastRefCount == 0 || !mWakeLock.isHeld()) {
setWakelockWorkSource(alarm.operation, alarm.workSource,
alarm.type, alarm.tag, true);
mWakeLock.acquire();
}
final InFlight inflight = new InFlight(AlarmManagerService.this,
- alarm.operation, alarm.workSource, alarm.type, alarm.tag);
+ alarm.operation, alarm.workSource, alarm.type, alarm.tag, alarm.uid);
mInFlight.add(inflight);
mBroadcastRefCount++;
+ mTriggeredUids.add(new Integer(alarm.uid));
final BroadcastStats bs = inflight.mBroadcastStats;
bs.count++;
@@ -1876,11 +1925,10 @@
mWakeLock.setWorkSource(new WorkSource(uid));
return;
}
+ // Something went wrong; fall back to attributing the lock to the OS
+ mWakeLock.setWorkSource(null);
} catch (Exception e) {
}
-
- // Something went wrong; fall back to attributing the lock to the OS
- mWakeLock.setWorkSource(null);
}
private class AlarmHandler extends Handler {
@@ -2113,9 +2161,11 @@
public void onSendFinished(PendingIntent pi, Intent intent, int resultCode,
String resultData, Bundle resultExtras) {
synchronized (mLock) {
+ int uid = 0;
InFlight inflight = null;
for (int i=0; i<mInFlight.size(); i++) {
if (mInFlight.get(i).mPendingIntent == pi) {
+ uid = mInFlight.get(i).mUid;
inflight = mInFlight.remove(i);
break;
}
@@ -2138,8 +2188,19 @@
mLog.w("No in-flight alarm for " + pi + " " + intent);
}
mBroadcastRefCount--;
+ mTriggeredUids.remove(new Integer(uid));
+
+ if (checkReleaseWakeLock()) {
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ if (localLOGV) Slog.v(TAG, "AM WakeLock Released Internally onSendFinish");
+ }
+ }
+
if (mBroadcastRefCount == 0) {
- mWakeLock.release();
+ if (mWakeLock.isHeld()) {
+ mWakeLock.release();
+ }
if (mInFlight.size() > 0) {
mLog.w("Finished all broadcasts with " + mInFlight.size()
+ " remaining inflights");
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a76615a..8da1973 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2007 The Android Open Source Project
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -155,6 +156,9 @@
private static final int POWER_HINT_INTERACTION = 2;
private static final int POWER_HINT_LOW_POWER = 5;
+ // Config value for NSRM
+ private static final int DPM_CONFIG_FEATURE_MASK_NSRM = 0x00000004;
+
private final Context mContext;
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
@@ -425,6 +429,9 @@
private final ArrayList<PowerManagerInternal.LowPowerModeListener> mLowPowerModeListeners
= new ArrayList<PowerManagerInternal.LowPowerModeListener>();
+ //track the blocked uids.
+ private final ArrayList<Integer> mBlockedUids = new ArrayList<Integer>();
+
private native void nativeInit();
private static native void nativeAcquireSuspendBlocker(String name);
@@ -722,6 +729,15 @@
private void acquireWakeLockInternal(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag, int uid, int pid) {
synchronized (mLock) {
+ if(mBlockedUids.contains(new Integer(uid)) && uid != Process.myUid()) {
+ //wakelock acquisition for blocked uid, do not acquire.
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "uid is blocked not acquiring wakeLock flags=0x" +
+ Integer.toHexString(flags) + " tag=" + tag + " uid=" + uid +
+ " pid =" + pid);
+ }
+ return;
+ }
if (DEBUG_SPEW) {
Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
+ ", flags=0x" + Integer.toHexString(flags)
@@ -848,13 +864,23 @@
int callingUid) {
synchronized (mLock) {
int index = findWakeLockIndexLocked(lock);
+ int value = SystemProperties.getInt("persist.dpm.feature", 0);
+ boolean isNsrmEnabled = false;
+
+ if ((value & DPM_CONFIG_FEATURE_MASK_NSRM) == DPM_CONFIG_FEATURE_MASK_NSRM)
+ isNsrmEnabled = true;
+
if (index < 0) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockWorkSourceInternal: lock=" + Objects.hashCode(lock)
+ " [not found], ws=" + ws);
}
+ if (!isNsrmEnabled) {
throw new IllegalArgumentException("Wake lock not active: " + lock
+ " from uid " + callingUid);
+ } else {
+ return;
+ }
}
WakeLock wakeLock = mWakeLocks.get(index);
@@ -873,6 +899,54 @@
}
}
+ /* updates the blocked uids, so if a wake lock is acquired for it
+ * can be released.
+ */
+ public void updateBlockedUids(int uid, boolean isBlocked) {
+ synchronized(mLock) {
+ if (DEBUG_SPEW) Slog.v(TAG, "updateBlockedUids: uid = "+uid +"isBlocked = "+isBlocked);
+ if(isBlocked) {
+ mBlockedUids.add(new Integer(uid));
+ for (int index = 0; index < mWakeLocks.size(); index++) {
+ WakeLock wl = mWakeLocks.get(index);
+ if(wl != null) {
+ if(wl.mTag.startsWith("*sync*") && wl.mOwnerUid == Process.SYSTEM_UID) {
+ releaseWakeLockInternal(wl.mLock, wl.mFlags);
+ index--;
+ if (DEBUG_SPEW) Slog.v(TAG, "Internally releasing the wakelock"
+ + "acquired by SyncManager");
+ continue;
+ }
+ // release the wakelock for the blocked uid
+ if (wl.mOwnerUid == uid || checkWorkSourceObjectId(uid, wl)) {
+ releaseWakeLockInternal(wl.mLock, wl.mFlags);
+ index--;
+ if (DEBUG_SPEW) Slog.v(TAG, "Internally releasing it");
+ }
+ }
+ }
+ }
+ else {
+ mBlockedUids.remove(new Integer(uid));
+ }
+ }
+ }
+
+ private boolean checkWorkSourceObjectId(int uid, WakeLock wl) {
+ try {
+ for (int index = 0; index < wl.mWorkSource.size(); index++) {
+ if (uid == wl.mWorkSource.get(index)) {
+ if (DEBUG_SPEW) Slog.v(TAG, "WS uid matched");
+ return true;
+ }
+ }
+ }
+ catch (Exception e) {
+ return false;
+ }
+ return false;
+ }
+
private int findWakeLockIndexLocked(IBinder lock) {
final int count = mWakeLocks.size();
for (int i = 0; i < count; i++) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 751ba42..c765154 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 The Android Open Source Project
+ * Copyright (c) 2014, The Linux Foundation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -99,6 +100,8 @@
import com.android.server.wm.WindowManagerService;
import dalvik.system.VMRuntime;
+import dalvik.system.PathClassLoader;
+import java.lang.reflect.Constructor;
import java.io.File;
import java.util.Timer;
@@ -152,6 +155,7 @@
// TODO: remove all of these references by improving dependency resolution and boot phases
private Installer mInstaller;
private PowerManagerService mPowerManagerService;
+ private AlarmManagerService mAlarmManagerService;
private ActivityManagerService mActivityManagerService;
private DisplayManagerService mDisplayManagerService;
private PackageManagerService mPackageManagerService;
@@ -462,7 +466,7 @@
consumerIr = new ConsumerIrService(context);
ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
- mSystemServiceManager.startService(AlarmManagerService.class);
+ mAlarmManagerService = mSystemServiceManager.startService(AlarmManagerService.class);
alarm = IAlarmManager.Stub.asInterface(
ServiceManager.getService(Context.ALARM_SERVICE));
@@ -695,6 +699,12 @@
} catch (Throwable e) {
reportWtf("starting Service Discovery Service", e);
}
+ try {
+ Slog.i(TAG, "DPM Service");
+ startDpmService(context, this);
+ } catch (Throwable e) {
+ reportWtf("starting DpmService", e);
+ }
}
if (!disableNonCoreServices) {
@@ -1217,4 +1227,46 @@
//Slog.d(TAG, "Starting service: " + intent);
context.startServiceAsUser(intent, UserHandle.OWNER);
}
+
+ private static final void startDpmService(Context context, SystemServer systemServer) {
+ try {
+ Object dpmObj = null;
+ int dpmFeature = SystemProperties.getInt("persist.dpm.feature", 0);
+ Slog.i(TAG, "DPM configuration set to " + dpmFeature);
+
+ if (dpmFeature > 0 && dpmFeature < 8) {
+ PathClassLoader dpmClassLoader =
+ new PathClassLoader("/system/framework/com.qti.dpmframework.jar",
+ ClassLoader.getSystemClassLoader());
+ Class dpmClass = dpmClassLoader.loadClass("com.qti.dpm.DpmService");
+ Constructor dpmConstructor = dpmClass.getConstructor(
+ new Class[] {Context.class, SystemServer.class});
+ dpmObj = dpmConstructor.newInstance(context, systemServer);
+ try {
+ if(dpmObj != null && (dpmObj instanceof IBinder)) {
+ ServiceManager.addService("dpmservice", (IBinder)dpmObj);
+ Slog.i(TAG, "Created DPM Service");
+ }
+ } catch (Exception e) {
+ Slog.i(TAG, "starting DPM Service", e);
+ }
+ }
+ } catch (Throwable e) {
+ Slog.i(TAG, "starting DPM Service", e);
+ }
+ }
+
+
+ public void updateBlockedUids(int uid, boolean isBlocked) {
+ try {
+ mAlarmManagerService.updateBlockedUids(uid, isBlocked);
+ } catch (NullPointerException e) {
+ Slog.w(TAG, "Could Not Update blocked Uids with alarmManager" + e);
+ }
+ try {
+ mPowerManagerService.updateBlockedUids(uid, isBlocked);
+ } catch (NullPointerException e) {
+ Slog.w(TAG, "Could Not Update blocked Uids with powerManager" + e);
+ }
+ }
}