diff options
Diffstat (limited to 'services/core/java/com/android/server')
29 files changed, 1410 insertions, 706 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 0e3867d..745c190 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -461,7 +461,7 @@ class AlarmManagerService extends SystemService { // to run during this time are placed in mPendingWhileIdleAlarms Alarm mPendingIdleUntil = null; Alarm mNextWakeFromIdle = null; - final ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>(); + ArrayList<Alarm> mPendingWhileIdleAlarms = new ArrayList<>(); public AlarmManagerService(Context context) { super(context); @@ -567,10 +567,14 @@ class AlarmManagerService extends SystemService { void restorePendingWhileIdleAlarmsLocked() { // Bring pending alarms back into the main list. - final long nowElapsed = SystemClock.elapsedRealtime(); - for (int i=mPendingWhileIdleAlarms.size() - 1; i >= 0 && mPendingIdleUntil == null; i--) { - Alarm a = mPendingWhileIdleAlarms.remove(i); - reAddAlarmLocked(a, nowElapsed, false); + if (mPendingWhileIdleAlarms.size() > 0) { + ArrayList<Alarm> alarms = mPendingWhileIdleAlarms; + mPendingWhileIdleAlarms = new ArrayList<>(); + final long nowElapsed = SystemClock.elapsedRealtime(); + for (int i=alarms.size() - 1; i >= 0; i--) { + Alarm a = alarms.get(i); + reAddAlarmLocked(a, nowElapsed, false); + } } // Reschedule everything. @@ -1053,11 +1057,16 @@ class AlarmManagerService extends SystemService { dumpAlarmList(pw, b.alarms, " ", nowELAPSED, nowRTC, sdf); } } - if (mPendingIdleUntil != null) { + if (mPendingIdleUntil != null || mPendingWhileIdleAlarms.size() > 0) { pw.println(); pw.println("Idle mode state:"); - pw.print(" Idling until: "); pw.println(mPendingIdleUntil); - mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf); + pw.print(" Idling until: "); + if (mPendingIdleUntil != null) { + pw.println(mPendingIdleUntil); + mPendingIdleUntil.dump(pw, " ", nowRTC, nowELAPSED, sdf); + } else { + pw.println("null"); + } pw.println(" Pending alarms:"); dumpAlarmList(pw, mPendingWhileIdleAlarms, " ", nowELAPSED, nowRTC, sdf); } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 12a99b0..1a75b8a 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -24,6 +24,7 @@ import static android.net.ConnectivityManager.TYPE_VPN; import static android.net.ConnectivityManager.getNetworkTypeName; import static android.net.ConnectivityManager.isNetworkTypeValid; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; +import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import android.annotation.Nullable; @@ -832,7 +833,8 @@ public class ConnectivityService extends IConnectivityManager.Stub uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); } - if (networkCostly && (uidRules & RULE_REJECT_METERED) != 0) { + if ((uidRules & RULE_REJECT_ALL) != 0 + || (networkCostly && (uidRules & RULE_REJECT_METERED) != 0)) { return true; } @@ -3490,7 +3492,7 @@ public class ConnectivityService extends IConnectivityManager.Stub synchronized(mRulesLock) { uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); } - if ((uidRules & RULE_REJECT_METERED) != 0) { + if ((uidRules & (RULE_REJECT_METERED | RULE_REJECT_ALL)) != 0) { // we could silently fail or we can filter the available nets to only give // them those they have access to. Chose the more useful networkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED); diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java new file mode 100644 index 0000000..b7bc0f0 --- /dev/null +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -0,0 +1,879 @@ +/* + * Copyright (C) 2015 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 the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.hardware.Sensor; +import android.hardware.SensorManager; +import android.hardware.TriggerEvent; +import android.hardware.TriggerEventListener; +import android.hardware.display.DisplayManager; +import android.net.INetworkPolicyManager; +import android.os.Binder; +import android.os.Environment; +import android.os.FileUtils; +import android.os.Handler; +import android.os.IDeviceIdleController; +import android.os.Looper; +import android.os.Message; +import android.os.PowerManager; +import android.os.PowerManagerInternal; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.os.UserHandle; +import android.util.ArrayMap; +import android.util.ArraySet; +import android.util.Slog; +import android.util.SparseBooleanArray; +import android.util.TimeUtils; +import android.util.Xml; +import android.view.Display; +import com.android.internal.app.IBatteryStats; +import com.android.internal.os.AtomicFile; +import com.android.internal.os.BackgroundThread; +import com.android.internal.util.FastXmlSerializer; +import com.android.internal.util.XmlUtils; +import com.android.server.am.BatteryStatsService; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileDescriptor; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintWriter; + +/** + * Keeps track of device idleness and drives low power mode based on that. + */ +public class DeviceIdleController extends SystemService { + private static final String TAG = "DeviceIdleController"; + + public static final String SERVICE_NAME = "deviceidle"; + + private static final String ACTION_STEP_IDLE_STATE = + "com.android.server.device_idle.STEP_IDLE_STATE"; + + // TODO: These need to be moved to system settings. + + /** + * This is the time, after becoming inactive, at which we start looking at the + * motion sensor to determine if the device is being left alone. We don't do this + * immediately after going inactive just because we don't want to be continually running + * the significant motion sensor whenever the screen is off. + */ + private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; + /** + * This is the time, after seeing motion, that we wait after becoming inactive from + * that until we start looking for motion again. + */ + private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L; + /** + * This is the time, after the inactive timeout elapses, that we will wait looking + * for significant motion until we truly consider the device to be idle. + */ + private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; + /** + * This is the initial time, after being idle, that we will allow ourself to be back + * in the IDLE_PENDING state allowing the system to run normally until we return to idle. + */ + private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L; + /** + * Maximum pending idle timeout (time spent running) we will be allowed to use. + */ + private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L; + /** + * Scaling factor to apply to current pending idle timeout each time we cycle through + * that state. + */ + private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f; + /** + * This is the initial time that we want to sit in the idle state before waking up + * again to return to pending idle and allowing normal work to run. + */ + private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; + /** + * Maximum idle duration we will be allowed to use. + */ + private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; + /** + * Scaling factor to apply to current idle timeout each time we cycle through that state. + */ + private static final float DEFAULT_IDLE_FACTOR = 2f; + /** + * This is the minimum time we will allow until the next upcoming alarm for us to + * actually go in to idle mode. + */ + private static final long DEFAULT_MIN_TIME_TO_ALARM = 60*60*1000L; + + private AlarmManager mAlarmManager; + private IBatteryStats mBatteryStats; + private PowerManagerInternal mLocalPowerManager; + private INetworkPolicyManager mNetworkPolicyManager; + private DisplayManager mDisplayManager; + private SensorManager mSensorManager; + private Sensor mSigMotionSensor; + private PendingIntent mAlarmIntent; + private Intent mIdleIntent; + private Display mCurDisplay; + private boolean mScreenOn; + private boolean mCharging; + private boolean mSigMotionActive; + + /** Device is currently active. */ + private static final int STATE_ACTIVE = 0; + /** Device is inactve (screen off, no motion) and we are waiting to for idle. */ + private static final int STATE_INACTIVE = 1; + /** Device is past the initial inactive period, and waiting for the next idle period. */ + private static final int STATE_IDLE_PENDING = 2; + /** Device is in the idle state, trying to stay asleep as much as possible. */ + private static final int STATE_IDLE = 3; + /** Device is in the idle state, but temporarily out of idle to do regular maintenance. */ + private static final int STATE_IDLE_MAINTENANCE = 4; + private static String stateToString(int state) { + switch (state) { + case STATE_ACTIVE: return "ACTIVE"; + case STATE_INACTIVE: return "INACTIVE"; + case STATE_IDLE_PENDING: return "IDLE_PENDING"; + case STATE_IDLE: return "IDLE"; + case STATE_IDLE_MAINTENANCE: return "IDLE_MAINTENANCE"; + default: return Integer.toString(state); + } + } + + private int mState; + + private long mInactiveTimeout; + private long mNextAlarmTime; + private long mNextIdlePendingDelay; + private long mNextIdleDelay; + + public final AtomicFile mConfigFile; + + /** + * Package names the system has white-listed to opt out of power save restrictions. + */ + private final ArrayMap<String, Integer> mPowerSaveWhitelistApps = new ArrayMap<>(); + + /** + * Package names the user has white-listed to opt out of power save restrictions. + */ + private final ArrayMap<String, Integer> mPowerSaveWhitelistUserApps = new ArrayMap<>(); + + /** + * UIDs that have been white-listed to opt out of power save restrictions. + */ + private final SparseBooleanArray mPowerSaveWhitelistAppIds = new SparseBooleanArray(); + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { + int plugged = intent.getIntExtra("plugged", 0); + updateChargingLocked(plugged != 0); + } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { + synchronized (DeviceIdleController.this) { + stepIdleStateLocked(); + } + } + } + }; + + private final DisplayManager.DisplayListener mDisplayListener + = new DisplayManager.DisplayListener() { + @Override public void onDisplayAdded(int displayId) { + } + + @Override public void onDisplayRemoved(int displayId) { + } + + @Override public void onDisplayChanged(int displayId) { + if (displayId == Display.DEFAULT_DISPLAY) { + synchronized (DeviceIdleController.this) { + updateDisplayLocked(); + } + } + } + }; + + private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { + @Override public void onTrigger(TriggerEvent event) { + synchronized (DeviceIdleController.this) { + significantMotionLocked(); + } + } + }; + + static final int MSG_WRITE_CONFIG = 1; + static final int MSG_REPORT_IDLE_ON = 2; + static final int MSG_REPORT_IDLE_OFF = 3; + static final int MSG_REPORT_ACTIVE = 4; + + final class MyHandler extends Handler { + MyHandler(Looper looper) { + super(looper); + } + + @Override public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_WRITE_CONFIG: { + handleWriteConfigFile(); + } break; + case MSG_REPORT_IDLE_ON: { + mLocalPowerManager.setDeviceIdleMode(true); + try { + mNetworkPolicyManager.setDeviceIdleMode(true); + mBatteryStats.noteDeviceIdleMode(true, false, false); + } catch (RemoteException e) { + } + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } break; + case MSG_REPORT_IDLE_OFF: { + mLocalPowerManager.setDeviceIdleMode(false); + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, false, false); + } catch (RemoteException e) { + } + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } break; + case MSG_REPORT_ACTIVE: { + boolean fromMotion = msg.arg1 != 0; + boolean needBroadcast = msg.arg2 != 0; + mLocalPowerManager.setDeviceIdleMode(false); + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, !fromMotion, fromMotion); + } catch (RemoteException e) { + } + if (needBroadcast) { + getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); + } + } break; + } + } + } + + final MyHandler mHandler; + + private final class BinderService extends IDeviceIdleController.Stub { + @Override public void addPowerSaveWhitelistApp(String name) { + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + addPowerSaveWhitelistAppInternal(name); + } + + @Override public void removePowerSaveWhitelistApp(String name) { + getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, + null); + removePowerSaveWhitelistAppInternal(name); + } + + @Override public String[] getSystemPowerWhitelist() { + return getSystemPowerWhitelistInternal(); + } + + @Override public String[] getFullPowerWhitelist() { + return getFullPowerWhitelistInternal(); + } + + @Override public int[] getAppIdWhitelist() { + return getAppIdWhitelistInternal(); + } + + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + DeviceIdleController.this.dump(fd, pw, args); + } + } + + public DeviceIdleController(Context context) { + super(context); + mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml")); + mHandler = new MyHandler(BackgroundThread.getHandler().getLooper()); + } + + private static File getSystemDir() { + return new File(Environment.getDataDirectory(), "system"); + } + + @Override + public void onStart() { + final PackageManager pm = getContext().getPackageManager(); + + synchronized (this) { + SystemConfig sysConfig = SystemConfig.getInstance(); + ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); + for (int i=0; i<allowPower.size(); i++) { + String pkg = allowPower.valueAt(i); + try { + ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); + if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { + mPowerSaveWhitelistApps.put(ai.packageName, + UserHandle.getAppId(ai.uid)); + } + } catch (PackageManager.NameNotFoundException e) { + } + } + + readConfigFileLocked(); + updateWhitelistAppIdsLocked(); + + mScreenOn = true; + // Start out assuming we are charging. If we aren't, we will at least get + // a battery update the next time the level drops. + mCharging = true; + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; + } + + publishBinderService(SERVICE_NAME, new BinderService()); + } + + @Override + public void onBootPhase(int phase) { + if (phase == PHASE_SYSTEM_SERVICES_READY) { + synchronized (this) { + mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); + mBatteryStats = BatteryStatsService.getService(); + mLocalPowerManager = getLocalService(PowerManagerInternal.class); + mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); + mDisplayManager = (DisplayManager) getContext().getSystemService( + Context.DISPLAY_SERVICE); + mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); + mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); + + Intent intent = new Intent(ACTION_STEP_IDLE_STATE) + .setPackage("android") + .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); + + mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); + mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(ACTION_STEP_IDLE_STATE); + getContext().registerReceiver(mReceiver, filter); + + mDisplayManager.registerDisplayListener(mDisplayListener, null); + updateDisplayLocked(); + } + } + } + + public boolean addPowerSaveWhitelistAppInternal(String name) { + synchronized (this) { + try { + ApplicationInfo ai = getContext().getPackageManager().getApplicationInfo(name, 0); + if (mPowerSaveWhitelistUserApps.put(name, UserHandle.getAppId(ai.uid)) == null) { + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + } + return true; + } catch (PackageManager.NameNotFoundException e) { + return false; + } + } + } + + public boolean removePowerSaveWhitelistAppInternal(String name) { + synchronized (this) { + if (mPowerSaveWhitelistUserApps.remove(name) != null) { + reportPowerSaveWhitelistChangedLocked(); + updateWhitelistAppIdsLocked(); + writeConfigFileLocked(); + return true; + } + } + return false; + } + + public String[] getSystemPowerWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistApps.size(); + String[] apps = new String[size]; + for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) { + apps[i] = mPowerSaveWhitelistApps.keyAt(i); + } + return apps; + } + } + + public String[] getFullPowerWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistApps.size() + mPowerSaveWhitelistUserApps.size(); + String[] apps = new String[size]; + int cur = 0; + for (int i = 0; i < mPowerSaveWhitelistApps.size(); i++) { + apps[cur] = mPowerSaveWhitelistApps.keyAt(i); + cur++; + } + for (int i = 0; i < mPowerSaveWhitelistUserApps.size(); i++) { + apps[cur] = mPowerSaveWhitelistUserApps.keyAt(i); + cur++; + } + return apps; + } + } + + public int[] getAppIdWhitelistInternal() { + synchronized (this) { + int size = mPowerSaveWhitelistAppIds.size(); + int[] appids = new int[size]; + for (int i = 0; i < size; i++) { + appids[i] = mPowerSaveWhitelistAppIds.keyAt(i); + } + return appids; + } + } + + void updateDisplayLocked() { + mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); + // We consider any situation where the display is showing something to be it on, + // because if there is anything shown we are going to be updating it at some + // frequency so can't be allowed to go into deep sleeps. + boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;; + if (!screenOn && mScreenOn) { + mScreenOn = false; + becomeInactiveIfAppropriateLocked(); + } else if (screenOn) { + mScreenOn = true; + becomeActiveLocked("screen"); + } + } + + void updateChargingLocked(boolean charging) { + if (!charging && mCharging) { + mCharging = false; + becomeInactiveIfAppropriateLocked(); + } else if (charging) { + mCharging = charging; + becomeActiveLocked("charging"); + } + } + + void scheduleReportActiveLocked(boolean fromMotion) { + Message msg = mHandler.obtainMessage(MSG_REPORT_ACTIVE, fromMotion ? 1 : 0, + mState == STATE_IDLE ? 1 : 0); + mHandler.sendMessage(msg); + } + + void becomeActiveLocked(String reason) { + if (mState != STATE_ACTIVE) { + EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason); + scheduleReportActiveLocked(false); + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; + mNextIdlePendingDelay = 0; + mNextIdleDelay = 0; + cancelAlarmLocked(); + stopMonitoringSignificantMotion(); + } + } + + void becomeInactiveIfAppropriateLocked() { + if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) { + // Screen has turned off; we are now going to become inactive and start + // waiting to see if we will ultimately go idle. + mState = STATE_INACTIVE; + mNextIdlePendingDelay = 0; + mNextIdleDelay = 0; + scheduleAlarmLocked(mInactiveTimeout, false); + EventLogTags.writeDeviceIdle(mState, "no activity"); + } + } + + void stepIdleStateLocked() { + EventLogTags.writeDeviceIdleStep(); + + final long now = SystemClock.elapsedRealtime(); + if ((now+DEFAULT_MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { + // Whoops, there is an upcoming alarm. We don't actually want to go idle. + if (mState != STATE_ACTIVE) { + becomeActiveLocked("alarm"); + } + return; + } + + switch (mState) { + case STATE_INACTIVE: + // We have now been inactive long enough, it is time to start looking + // for significant motion and sleep some more while doing so. + startMonitoringSignificantMotion(); + scheduleAlarmLocked(DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT, false); + // Reset the upcoming idle delays. + mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT; + mNextIdleDelay = DEFAULT_IDLE_TIMEOUT; + mState = STATE_IDLE_PENDING; + EventLogTags.writeDeviceIdle(mState, "step"); + break; + case STATE_IDLE_PENDING: + case STATE_IDLE_MAINTENANCE: + // We have been waiting to become idle, and now it is time! This is the + // only case where we want to use a wakeup alarm, because we do want to + // drag the device out of its sleep state in this case to do the next + // scheduled work. + scheduleAlarmLocked(mNextIdleDelay, true); + mNextIdleDelay = (long)(mNextIdleDelay*DEFAULT_IDLE_FACTOR); + if (mNextIdleDelay > DEFAULT_MAX_IDLE_TIMEOUT) { + mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT; + } + mState = STATE_IDLE; + EventLogTags.writeDeviceIdle(mState, "step"); + mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON); + break; + case STATE_IDLE: + // We have been idling long enough, now it is time to do some work. + scheduleAlarmLocked(mNextIdlePendingDelay, false); + mNextIdlePendingDelay = (long)(mNextIdlePendingDelay*DEFAULT_IDLE_PENDING_FACTOR); + if (mNextIdlePendingDelay > DEFAULT_MAX_IDLE_PENDING_TIMEOUT) { + mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT; + } + mState = STATE_IDLE_MAINTENANCE; + EventLogTags.writeDeviceIdle(mState, "step"); + mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF); + break; + } + } + + void significantMotionLocked() { + // When the sensor goes off, its trigger is automatically removed. + mSigMotionActive = false; + // The device is not yet active, so we want to go back to the pending idle + // state to wait again for no motion. Note that we only monitor for significant + // motion after moving out of the inactive state, so no need to worry about that. + if (mState != STATE_ACTIVE) { + scheduleReportActiveLocked(true); + mState = STATE_ACTIVE; + mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT; + EventLogTags.writeDeviceIdle(mState, "motion"); + becomeInactiveIfAppropriateLocked(); + } + } + + void startMonitoringSignificantMotion() { + if (mSigMotionSensor != null && !mSigMotionActive) { + mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); + mSigMotionActive = true; + } + } + + void stopMonitoringSignificantMotion() { + if (mSigMotionActive) { + mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); + mSigMotionActive = false; + } + } + + void cancelAlarmLocked() { + if (mNextAlarmTime != 0) { + mNextAlarmTime = 0; + mAlarmManager.cancel(mAlarmIntent); + } + } + + void scheduleAlarmLocked(long delay, boolean idleUntil) { + if (mSigMotionSensor == null) { + // If there is no significant motion sensor on this device, then we won't schedule + // alarms, because we can't determine if the device is not moving. This effectively + // turns off normal exeuction of device idling, although it is still possible to + // manually poke it by pretending like the alarm is going off. + return; + } + mNextAlarmTime = SystemClock.elapsedRealtime() + delay; + if (idleUntil) { + mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mNextAlarmTime, mAlarmIntent); + } else { + mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, + mNextAlarmTime, mAlarmIntent); + } + } + + private void updateWhitelistAppIdsLocked() { + mPowerSaveWhitelistAppIds.clear(); + for (int i=0; i<mPowerSaveWhitelistApps.size(); i++) { + mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistApps.valueAt(i), true); + } + for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { + mPowerSaveWhitelistAppIds.put(mPowerSaveWhitelistUserApps.valueAt(i), true); + } + } + + private void reportPowerSaveWhitelistChangedLocked() { + Intent intent = new Intent(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); + intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + getContext().sendBroadcast(intent); + } + + void readConfigFileLocked() { + Slog.d(TAG, "Reading config from " + mConfigFile.getBaseFile()); + mPowerSaveWhitelistUserApps.clear(); + FileInputStream stream; + try { + stream = mConfigFile.openRead(); + } catch (FileNotFoundException e) { + return; + } + try { + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(stream, null); + readConfigFileLocked(parser); + } catch (XmlPullParserException e) { + } finally { + try { + stream.close(); + } catch (IOException e) { + } + } + + } + + private void readConfigFileLocked(XmlPullParser parser) { + final PackageManager pm = getContext().getPackageManager(); + + try { + int type; + while ((type = parser.next()) != XmlPullParser.START_TAG + && type != XmlPullParser.END_DOCUMENT) { + ; + } + + if (type != XmlPullParser.START_TAG) { + throw new IllegalStateException("no start tag found"); + } + + int outerDepth = parser.getDepth(); + while ((type = parser.next()) != XmlPullParser.END_DOCUMENT + && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { + if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { + continue; + } + + String tagName = parser.getName(); + if (tagName.equals("wl")) { + String name = parser.getAttributeValue(null, "n"); + if (name != null) { + try { + ApplicationInfo ai = pm.getApplicationInfo(name, 0); + mPowerSaveWhitelistUserApps.put(ai.packageName, + UserHandle.getAppId(ai.uid)); + } catch (PackageManager.NameNotFoundException e) { + } + } + } else { + Slog.w(TAG, "Unknown element under <config>: " + + parser.getName()); + XmlUtils.skipCurrentTag(parser); + } + } + + } catch (IllegalStateException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (NullPointerException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (NumberFormatException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (XmlPullParserException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (IOException e) { + Slog.w(TAG, "Failed parsing config " + e); + } catch (IndexOutOfBoundsException e) { + Slog.w(TAG, "Failed parsing config " + e); + } + } + + void writeConfigFileLocked() { + mHandler.removeMessages(MSG_WRITE_CONFIG); + mHandler.sendEmptyMessageDelayed(MSG_WRITE_CONFIG, 5000); + } + + void handleWriteConfigFile() { + final ByteArrayOutputStream memStream = new ByteArrayOutputStream(); + + try { + synchronized (this) { + XmlSerializer out = new FastXmlSerializer(); + out.setOutput(memStream, "utf-8"); + writeConfigFileLocked(out); + } + } catch (IOException e) { + } + + synchronized (mConfigFile) { + FileOutputStream stream = null; + try { + stream = mConfigFile.startWrite(); + memStream.writeTo(stream); + stream.flush(); + FileUtils.sync(stream); + stream.close(); + mConfigFile.finishWrite(stream); + } catch (IOException e) { + Slog.w(TAG, "Error writing config file", e); + mConfigFile.failWrite(stream); + } + } + } + + void writeConfigFileLocked(XmlSerializer out) throws IOException { + out.startDocument(null, true); + out.startTag(null, "config"); + for (int i=0; i<mPowerSaveWhitelistUserApps.size(); i++) { + String name = mPowerSaveWhitelistUserApps.keyAt(i); + out.startTag(null, "wl"); + out.attribute(null, "n", name); + out.endTag(null, "wl"); + } + out.endTag(null, "config"); + out.endDocument(); + } + + private void dumpHelp(PrintWriter pw) { + pw.println("Device idle controller (deviceidle) dump options:"); + pw.println(" [-h] [CMD]"); + pw.println(" -h: print this help text."); + pw.println("Commands:"); + pw.println(" step"); + pw.println(" Immediately step to next state, without waiting for alarm."); + pw.println(" whitelist"); + pw.println(" Add (prefix with +) or remove (prefix with -) packages."); + } + + void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump DeviceIdleController from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + + if (args != null) { + for (int i=0; i<args.length; i++) { + String arg = args[i]; + if ("-h".equals(arg)) { + dumpHelp(pw); + return; + } else if ("step".equals(arg)) { + synchronized (this) { + stepIdleStateLocked(); + pw.print("Stepped to: "); pw.println(stateToString(mState)); + } + return; + } else if ("whitelist".equals(arg)) { + i++; + while (i < args.length) { + arg = args[i]; + i++; + if (arg.length() < 1 || (arg.charAt(0) != '-' + && arg.charAt(0) != '+')) { + pw.println("Package must be prefixed with + or -: " + arg); + return; + } + char op = arg.charAt(0); + String pkg = arg.substring(1); + if (op == '+') { + if (addPowerSaveWhitelistAppInternal(pkg)) { + pw.println("Added: " + pkg); + } else { + pw.println("Unknown package: " + pkg); + } + } else { + if (removePowerSaveWhitelistAppInternal(pkg)) { + pw.println("Removed: " + pkg); + } + } + } + return; + } else if (arg.length() > 0 && arg.charAt(0) == '-'){ + pw.println("Unknown option: " + arg); + return; + } else { + pw.println("Unknown command: " + arg); + return; + } + } + } + + synchronized (this) { + int size = mPowerSaveWhitelistApps.size(); + if (size > 0) { + pw.println(" Whitelist system apps:"); + for (int i = 0; i < size; i++) { + pw.print(" "); + pw.println(mPowerSaveWhitelistApps.keyAt(i)); + } + } + size = mPowerSaveWhitelistUserApps.size(); + if (size > 0) { + pw.println(" Whitelist user apps:"); + for (int i = 0; i < size; i++) { + pw.print(" "); + pw.println(mPowerSaveWhitelistUserApps.keyAt(i)); + } + } + size = mPowerSaveWhitelistAppIds.size(); + if (size > 0) { + pw.println(" Whitelist app uids:"); + for (int i = 0; i < size; i++) { + pw.print(" UID="); + pw.print(mPowerSaveWhitelistAppIds.keyAt(i)); + pw.print(": "); + pw.print(mPowerSaveWhitelistAppIds.valueAt(i)); + pw.println(); + } + } + pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); + pw.print(" mCurDisplay="); pw.println(mCurDisplay); + pw.print(" mScreenOn="); pw.println(mScreenOn); + pw.print(" mCharging="); pw.println(mCharging); + pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); + pw.print(" mState="); pw.println(stateToString(mState)); + pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw); + pw.println(); + if (mNextAlarmTime != 0) { + pw.print(" mNextAlarmTime="); + TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); + pw.println(); + } + if (mNextIdlePendingDelay != 0) { + pw.print(" mNextIdlePendingDelay="); + TimeUtils.formatDuration(mNextIdlePendingDelay, pw); + pw.println(); + } + if (mNextIdleDelay != 0) { + pw.print(" mNextIdleDelay="); + TimeUtils.formatDuration(mNextIdleDelay, pw); + pw.println(); + } + } + } +} diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 0f9090d..4fda370 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -1993,7 +1993,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (mHaveConnection && !mVisibleBound) { bindCurrentInputMethodService( mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE - | Context.BIND_TREAT_LIKE_ACTIVITY); + | Context.BIND_TREAT_LIKE_ACTIVITY + | Context.BIND_FOREGROUND_SERVICE); mVisibleBound = true; } res = true; diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 74adeb7..0925fa5 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -229,6 +229,7 @@ class MountService extends IMountService.Stub public static final int VOLUME_FS_UUID_CHANGED = 653; public static final int VOLUME_FS_LABEL_CHANGED = 654; public static final int VOLUME_PATH_CHANGED = 655; + public static final int VOLUME_INTERNAL_PATH_CHANGED = 656; public static final int VOLUME_DESTROYED = 659; public static final int MOVE_STATUS = 660; @@ -661,6 +662,9 @@ class MountService extends IMountService.Stub try { mConnector.execute("volume", "reset"); + for (int userId : mStartedUsers) { + mConnector.execute("volume", "start_user", userId); + } } catch (NativeDaemonConnectorException e) { Slog.w(TAG, "Failed to reset vold", e); } @@ -902,6 +906,14 @@ class MountService extends IMountService.Stub } break; } + case VoldResponseCode.VOLUME_INTERNAL_PATH_CHANGED: { + if (cooked.length != 3) break; + final VolumeInfo vol = mVolumes.get(cooked[1]); + if (vol != null) { + vol.internalPath = cooked[2]; + } + break; + } case VoldResponseCode.VOLUME_DESTROYED: { if (cooked.length != 2) break; mVolumes.remove(cooked[1]); @@ -1076,7 +1088,7 @@ class MountService extends IMountService.Stub // TODO: estimate remaining time try { - mMoveCallback.onStatusChanged(-1, null, status, -1); + mMoveCallback.onStatusChanged(-1, status, -1); } catch (RemoteException ignored) { } @@ -1433,10 +1445,11 @@ class MountService extends IMountService.Stub enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); + Preconditions.checkNotNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); rec.nickname = nickname; - mCallbacks.notifyVolumeMetadataChanged(fsUuid); + mCallbacks.notifyVolumeRecordChanged(rec); writeSettingsLocked(); } } @@ -1446,10 +1459,11 @@ class MountService extends IMountService.Stub enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); + Preconditions.checkNotNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); - mCallbacks.notifyVolumeMetadataChanged(fsUuid); + mCallbacks.notifyVolumeRecordChanged(rec); writeSettingsLocked(); } } @@ -1459,10 +1473,36 @@ class MountService extends IMountService.Stub enforcePermission(android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS); waitForReady(); + Preconditions.checkNotNull(fsUuid); synchronized (mLock) { mRecords.remove(fsUuid); - mCallbacks.notifyVolumeMetadataChanged(fsUuid); + + // TODO: tell vold to forget keys + + // If this had been primary storage, revert back to internal and + // reset vold so we bind into new volume into place. + if (Objects.equals(mPrimaryStorageUuid, fsUuid)) { + mPrimaryStorageUuid = StorageManager.UUID_PRIVATE_INTERNAL; + resetIfReadyAndConnected(); + } + + mCallbacks.notifyVolumeForgotten(fsUuid); + writeSettingsLocked(); + } + } + + private void forgetAll() { + synchronized (mLock) { + for (int i = 0; i < mRecords.size(); i++) { + final String fsUuid = mRecords.keyAt(i); + mCallbacks.notifyVolumeForgotten(fsUuid); + } + + mRecords.clear(); writeSettingsLocked(); + + mPrimaryStorageUuid = StorageManager.UUID_PRIVATE_INTERNAL; + resetIfReadyAndConnected(); } } @@ -2818,8 +2858,9 @@ class MountService extends IMountService.Stub private static class Callbacks extends Handler { private static final int MSG_STORAGE_STATE_CHANGED = 1; private static final int MSG_VOLUME_STATE_CHANGED = 2; - private static final int MSG_VOLUME_METADATA_CHANGED = 3; - private static final int MSG_DISK_SCANNED = 4; + private static final int MSG_VOLUME_RECORD_CHANGED = 3; + private static final int MSG_VOLUME_FORGOTTEN = 4; + private static final int MSG_DISK_SCANNED = 5; private final RemoteCallbackList<IMountServiceListener> mCallbacks = new RemoteCallbackList<>(); @@ -2863,8 +2904,12 @@ class MountService extends IMountService.Stub callback.onVolumeStateChanged((VolumeInfo) args.arg1, args.argi2, args.argi3); break; } - case MSG_VOLUME_METADATA_CHANGED: { - callback.onVolumeMetadataChanged((String) args.arg1); + case MSG_VOLUME_RECORD_CHANGED: { + callback.onVolumeRecordChanged((VolumeRecord) args.arg1); + break; + } + case MSG_VOLUME_FORGOTTEN: { + callback.onVolumeForgotten((String) args.arg1); break; } case MSG_DISK_SCANNED: { @@ -2890,10 +2935,16 @@ class MountService extends IMountService.Stub obtainMessage(MSG_VOLUME_STATE_CHANGED, args).sendToTarget(); } - private void notifyVolumeMetadataChanged(String fsUuid) { + private void notifyVolumeRecordChanged(VolumeRecord rec) { + final SomeArgs args = SomeArgs.obtain(); + args.arg1 = rec.clone(); + obtainMessage(MSG_VOLUME_RECORD_CHANGED, args).sendToTarget(); + } + + private void notifyVolumeForgotten(String fsUuid) { final SomeArgs args = SomeArgs.obtain(); args.arg1 = fsUuid; - obtainMessage(MSG_VOLUME_METADATA_CHANGED, args).sendToTarget(); + obtainMessage(MSG_VOLUME_FORGOTTEN, args).sendToTarget(); } private void notifyDiskScanned(DiskInfo disk, int volumeCount) { @@ -2909,11 +2960,8 @@ class MountService extends IMountService.Stub mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); for (String arg : args) { - if ("--clear".equals(arg)) { - synchronized (mLock) { - mRecords.clear(); - writeSettingsLocked(); - } + if ("--forget-all".equals(arg)) { + forgetAll(); } } diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index b5b62b4..f6998ca 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -43,6 +43,7 @@ import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; import android.net.Network; +import android.net.NetworkPolicyManager; import android.net.NetworkStats; import android.net.NetworkUtils; import android.net.RouteInfo; @@ -107,8 +108,8 @@ import java.util.concurrent.CountDownLatch; */ 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 TAG = "NetworkManagement"; + private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG); private static final String NETD_TAG = "NetdConnector"; private static final String NETD_SOCKET_NAME = "netd"; @@ -188,6 +189,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub /** Set of UIDs with cleartext penalties. */ @GuardedBy("mQuotaLock") private SparseIntArray mUidCleartextPolicy = new SparseIntArray(); + /** Set of UIDs that are to be blocked/allowed by firewall controller. */ + @GuardedBy("mQuotaLock") + private SparseIntArray mUidFirewallRules = new SparseIntArray(); private Object mIdleTimerLock = new Object(); /** Set of interfaces with active idle timers. */ @@ -563,10 +567,19 @@ public class NetworkManagementService extends INetworkManagementService.Stub setUidCleartextNetworkPolicy(local.keyAt(i), local.valueAt(i)); } } - } - // TODO: Push any existing firewall state - setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); + setFirewallEnabled(mFirewallEnabled || LockdownVpnTracker.isEnabled()); + + size = mUidFirewallRules.size(); + if (size > 0) { + Slog.d(TAG, "Pushing " + size + " active firewall UID rules"); + final SparseIntArray uidFirewallRules = mUidFirewallRules; + mUidFirewallRules = new SparseIntArray(); + for (int i = 0; i < uidFirewallRules.size(); i++) { + setFirewallUidRule(uidFirewallRules.keyAt(i), uidFirewallRules.valueAt(i)); + } + } + } } /** @@ -1899,7 +1912,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void setFirewallEnabled(boolean enabled) { enforceSystemUid(); try { - mConnector.execute("firewall", enabled ? "enable" : "disable"); + mConnector.execute("firewall", "enable", enabled ? "whitelist" : "blacklist"); mFirewallEnabled = enabled; } catch (NativeDaemonConnectorException e) { throw e.rethrowAsParcelableException(); @@ -1949,14 +1962,48 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override - public void setFirewallUidRule(int uid, boolean allow) { + public void setFirewallUidRule(int uid, int rule) { enforceSystemUid(); - Preconditions.checkState(mFirewallEnabled); - final String rule = allow ? "allow" : "deny"; - try { - mConnector.execute("firewall", "set_uid_rule", uid, rule); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { + Preconditions.checkState(mFirewallEnabled); + } + synchronized (mQuotaLock) { + final int oldUidFirewallRule = mUidFirewallRules.get(uid); + if (DBG) { + Slog.d(TAG, "oldRule = " + oldUidFirewallRule + + ", newRule=" + rule + " for uid=" + uid); + } + if (oldUidFirewallRule == rule) { + if (DBG) Slog.d(TAG, "!!!!! Skipping change"); + // TODO: eventually consider throwing + return; + } + + try { + String ruleName; + if (isFirewallEnabled()) { // Whitelist mode + if (rule == NetworkPolicyManager.FIREWALL_RULE_ALLOW) { + ruleName = "allow"; + } else { + ruleName = "deny"; + } + } else { // Blacklist mode + if (rule == NetworkPolicyManager.FIREWALL_RULE_DENY) { + ruleName = "deny"; + } else { + ruleName = "allow"; + } + } + + if (rule == NetworkPolicyManager.FIREWALL_RULE_DEFAULT) { + mUidFirewallRules.delete(uid); + } else { + mUidFirewallRules.put(uid, rule); + } + mConnector.execute("firewall", "set_uid_rule", uid, ruleName); + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } } } @@ -2072,6 +2119,18 @@ public class NetworkManagementService extends INetworkManagementService.Stub pw.println("]"); } + synchronized (mUidFirewallRules) { + pw.print("UID firewall rule: ["); + final int size = mUidFirewallRules.size(); + for (int i = 0; i < size; i++) { + pw.print(mUidFirewallRules.keyAt(i)); + pw.print(":"); + pw.print(mUidFirewallRules.valueAt(i)); + if (i < size - 1) pw.print(","); + } + pw.println("]"); + } + synchronized (mIdleTimerLock) { pw.println("Idle timers:"); for (HashMap.Entry<String, IdleTimerParams> ent : mActiveIdleTimers.entrySet()) { diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java index 9a6f696..5bce6eb 100644 --- a/services/core/java/com/android/server/TextServicesManagerService.java +++ b/services/core/java/com/android/server/TextServicesManagerService.java @@ -555,7 +555,8 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { if (DBG) { Slog.w(TAG, "bind service: " + info.getId()); } - if (!bindCurrentSpellCheckerService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) { + if (!bindCurrentSpellCheckerService(serviceIntent, connection, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE)) { Slog.e(TAG, "Failed to get a spell checker service."); return; } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index ac2f5b0..62f168d 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -2771,26 +2771,10 @@ public class AccountManagerService mAccountName, mAccountType }); } - result.putLong(AccountManager.KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH, + result.putLong(AccountManager.KEY_LAST_AUTHENTICATED_TIME, lastAuthenticatedTime); } } - if (mAuthDetailsRequired) { - long lastAuthenticatedTime = -1; - if (isAccountPresentForCaller(mAccountName, mAccountType)) { - lastAuthenticatedTime = DatabaseUtils.longForQuery( - mAccounts.openHelper.getReadableDatabase(), - "select " + ACCOUNTS_LAST_AUTHENTICATE_TIME_EPOCH_MILLIS + " from " - + - TABLE_ACCOUNTS + " WHERE " + ACCOUNTS_NAME + "=? AND " - + ACCOUNTS_TYPE + "=?", - new String[] { - mAccountName, mAccountType - }); - } - result.putLong(AccountManager.KEY_LAST_AUTHENTICATE_TIME_MILLIS_EPOCH, - lastAuthenticatedTime); - } } if (result != null && (intent = result.getParcelable(AccountManager.KEY_INTENT)) != null) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 15d7367..ddcfb15 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -699,12 +699,10 @@ public final class ActivityManagerService extends ActivityManagerNative private final StringBuilder mStrictModeBuffer = new StringBuilder(); /** - * Keeps track of all IIntentReceivers that have been registered for - * broadcasts. Hash keys are the receiver IBinder, hash value is - * a ReceiverList. + * Keeps track of all IIntentReceivers that have been registered for broadcasts. + * Hash keys are the receiver IBinder, hash value is a ReceiverList. */ - final HashMap<IBinder, ReceiverList> mRegisteredReceivers = - new HashMap<IBinder, ReceiverList>(); + final HashMap<IBinder, ReceiverList> mRegisteredReceivers = new HashMap<>(); /** * Resolver for broadcast intents to registered receivers. @@ -716,7 +714,7 @@ public final class ActivityManagerService extends ActivityManagerNative protected boolean allowFilterResult( BroadcastFilter filter, List<BroadcastFilter> dest) { IBinder target = filter.receiverList.receiver.asBinder(); - for (int i=dest.size()-1; i>=0; i--) { + for (int i = dest.size() - 1; i >= 0; i--) { if (dest.get(i).receiverList.receiver.asBinder() == target) { return false; } @@ -3115,8 +3113,16 @@ public final class ActivityManagerService extends ActivityManagerNative checkTime(startTime, "startProcess: done updating cpu stats"); try { - int uid = app.uid; + try { + if (AppGlobals.getPackageManager().isPackageFrozen(app.info.packageName)) { + // This is caught below as if we had failed to fork zygote + throw new RuntimeException("Package " + app.info.packageName + " is frozen!"); + } + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } + int uid = app.uid; int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_DEFAULT; if (!app.isolated) { @@ -3126,7 +3132,7 @@ public final class ActivityManagerService extends ActivityManagerNative permGids = AppGlobals.getPackageManager().getPackageGids(app.info.packageName, app.userId); } catch (RemoteException e) { - Slog.w(TAG, "Unable to retrieve gids", e); + throw e.rethrowAsRuntimeException(); } /* @@ -6603,6 +6609,12 @@ public final class ActivityManagerService extends ActivityManagerNative return mActivityManagerService.checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED; } + + @Override + public String[] getPackagesForUid(int uid) { + return mActivityManagerService.mContext.getPackageManager() + .getPackagesForUid(uid); + } } class IntentFirewallInterface implements IntentFirewall.AMSInterface { @@ -10874,8 +10886,8 @@ public final class ActivityManagerService extends ActivityManagerNative for (int i = mLruProcesses.size() - 1 ; i >= 0 ; i--) { ProcessRecord proc = mLruProcesses.get(i); if (proc.notCachedSinceIdle) { - if (proc.setProcState != ActivityManager.PROCESS_STATE_TOP - && proc.setProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND + if (proc.setProcState != ActivityManager.PROCESS_STATE_TOP_SLEEPING + && proc.setProcState >= ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE && proc.setProcState <= ActivityManager.PROCESS_STATE_SERVICE) { if (doKilling && proc.initialIdlePss != 0 && proc.lastPss > ((proc.initialIdlePss*3)/2)) { @@ -15656,8 +15668,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Original caller already died return null; } - ReceiverList rl - = (ReceiverList)mRegisteredReceivers.get(receiver.asBinder()); + ReceiverList rl = mRegisteredReceivers.get(receiver.asBinder()); if (rl == null) { rl = new ReceiverList(this, callerApp, callingPid, callingUid, userId, receiver); @@ -15689,7 +15700,7 @@ public final class ActivityManagerService extends ActivityManagerNative permission, callingUid, userId); rl.add(bf); if (!bf.debugCheck()) { - Slog.w(TAG, "==> For Dynamic broadast"); + Slog.w(TAG, "==> For Dynamic broadcast"); } mReceiverResolver.addFilter(bf); @@ -15699,9 +15710,9 @@ public final class ActivityManagerService extends ActivityManagerNative ArrayList receivers = new ArrayList(); receivers.add(bf); - int N = allSticky.size(); - for (int i=0; i<N; i++) { - Intent intent = (Intent)allSticky.get(i); + final int stickyCount = allSticky.size(); + for (int i = 0; i < stickyCount; i++) { + Intent intent = allSticky.get(i); BroadcastQueue queue = broadcastQueueForIntent(intent); BroadcastRecord r = new BroadcastRecord(queue, intent, null, null, -1, -1, null, null, AppOpsManager.OP_NONE, receivers, null, 0, @@ -15761,8 +15772,7 @@ public final class ActivityManagerService extends ActivityManagerNative void removeReceiverLocked(ReceiverList rl) { mRegisteredReceivers.remove(rl.receiver.asBinder()); - int N = rl.size(); - for (int i=0; i<N; i++) { + for (int i = rl.size() - 1; i >= 0; i--) { mReceiverResolver.removeFilter(rl.get(i)); } } @@ -16133,24 +16143,24 @@ public final class ActivityManagerService extends ActivityManagerNative } ArrayMap<String, ArrayList<Intent>> stickies = mStickyBroadcasts.get(userId); if (stickies == null) { - stickies = new ArrayMap<String, ArrayList<Intent>>(); + stickies = new ArrayMap<>(); mStickyBroadcasts.put(userId, stickies); } ArrayList<Intent> list = stickies.get(intent.getAction()); if (list == null) { - list = new ArrayList<Intent>(); + list = new ArrayList<>(); stickies.put(intent.getAction(), list); } - int N = list.size(); + final int stickiesCount = list.size(); int i; - for (i=0; i<N; i++) { + for (i = 0; i < stickiesCount; i++) { if (intent.filterEquals(list.get(i))) { // This sticky already exists, replace it. list.set(i, new Intent(intent)); break; } } - if (i >= N) { + if (i >= stickiesCount) { list.add(new Intent(intent)); } } @@ -17036,7 +17046,7 @@ public final class ActivityManagerService extends ActivityManagerNative adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = Process.THREAD_GROUP_DEFAULT; app.adjType = "instrumentation"; - procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; } else if ((queue = isReceivingBroadcast(app)) != null) { // An app that is currently receiving a broadcast also // counts as being in the foreground for OOM killer purposes. @@ -17374,8 +17384,19 @@ public final class ActivityManagerService extends ActivityManagerNative // processes). These should not bring the current process // into the top state, since they are not on top. Instead // give them the best state after that. - clientProcState = - ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + if ((cr.flags&Context.BIND_FOREGROUND_SERVICE) != 0) { + clientProcState = + ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; + } else if (mWakefulness + == PowerManagerInternal.WAKEFULNESS_AWAKE && + (cr.flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) + != 0) { + clientProcState = + ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; + } else { + clientProcState = + ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + } } } } else { @@ -17485,7 +17506,7 @@ public final class ActivityManagerService extends ActivityManagerNative // into the top state, since they are not on top. Instead // give them the best state after that. clientProcState = - ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; } } if (procState > clientProcState) { @@ -17525,7 +17546,7 @@ public final class ActivityManagerService extends ActivityManagerNative case ActivityManager.PROCESS_STATE_SERVICE: // These all are longer-term states, so pull them up to the top // of the background states, but not all the way to the top state. - procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; + procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; break; default: // Otherwise, top is a better choice, so take it. diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index a91a7ca..e5c5dff 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -309,7 +309,6 @@ public final class BroadcastQueue { } public void skipCurrentReceiverLocked(ProcessRecord app) { - boolean reschedule = false; BroadcastRecord r = app.curReceiver; if (r != null && r.queue == this) { // The current broadcast is waiting for this app's receiver @@ -318,7 +317,6 @@ public final class BroadcastQueue { logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); - reschedule = true; } if (r == null && mPendingBroadcast != null && mPendingBroadcast.curApp == app) { if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, diff --git a/services/core/java/com/android/server/am/ConnectionRecord.java b/services/core/java/com/android/server/am/ConnectionRecord.java index 423e540..cd37041 100644 --- a/services/core/java/com/android/server/am/ConnectionRecord.java +++ b/services/core/java/com/android/server/am/ConnectionRecord.java @@ -87,7 +87,16 @@ final class ConnectionRecord { sb.append("IMP "); } if ((flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) { - sb.append("ACT "); + sb.append("WACT "); + } + if ((flags&Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) != 0) { + sb.append("FGSA "); + } + if ((flags&Context.BIND_FOREGROUND_SERVICE) != 0) { + sb.append("FGS "); + } + if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) { + sb.append("LACT "); } if ((flags&Context.BIND_VISIBLE) != 0) { sb.append("VIS "); diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 3d478f9..a07591c9 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -529,8 +529,9 @@ public class Vpn { throw new IllegalArgumentException("At least one address must be specified"); } Connection connection = new Connection(); - if (!mContext.bindServiceAsUser(intent, connection, Context.BIND_AUTO_CREATE, - new UserHandle(mUserHandle))) { + if (!mContext.bindServiceAsUser(intent, connection, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, + new UserHandle(mUserHandle))) { throw new IllegalStateException("Cannot bind " + config.user); } diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java index 31c1eea..8932ca0 100644 --- a/services/core/java/com/android/server/display/WifiDisplayController.java +++ b/services/core/java/com/android/server/display/WifiDisplayController.java @@ -775,7 +775,7 @@ final class WifiDisplayController implements DumpUtils.Dump { handleConnectionFailure(false); } } - }, mHandler); + }, mHandler, mContext.getOpPackageName()); // Use extended timeout value for certification, as some tests require user inputs int rtspTimeout = mWifiDisplayCertMode ? diff --git a/services/core/java/com/android/server/dreams/DreamController.java b/services/core/java/com/android/server/dreams/DreamController.java index 768ccf2..cff4814 100644 --- a/services/core/java/com/android/server/dreams/DreamController.java +++ b/services/core/java/com/android/server/dreams/DreamController.java @@ -136,7 +136,8 @@ final class DreamController { intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); try { if (!mContext.bindServiceAsUser(intent, mCurrentDream, - Context.BIND_AUTO_CREATE, new UserHandle(userId))) { + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, + new UserHandle(userId))) { Slog.e(TAG, "Unable to bind dream service: " + intent); stopDream(true /*immediate*/); return; diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index d3240ec..6bd646d 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -952,13 +952,18 @@ public class GpsLocationProvider implements LocationProviderInterface { return GPS_POSITION_MODE_STANDALONE; } } + // MS-Based is the preferred mode for Assisted-GPS position computation, so we favor + // such mode when it is available + if (hasCapability(GPS_CAPABILITY_MSB) && (suplMode & AGPS_SUPL_MODE_MSB) != 0) { + return GPS_POSITION_MODE_MS_BASED; + } + // for now, just as the legacy code did, we fallback to MS-Assisted if it is available, + // do fallback only for single-shot requests, because it is too expensive to do for + // periodic requests as well if (singleShot && hasCapability(GPS_CAPABILITY_MSA) && (suplMode & AGPS_SUPL_MODE_MSA) != 0) { return GPS_POSITION_MODE_MS_ASSISTED; - } else if (hasCapability(GPS_CAPABILITY_MSB) - && (suplMode & AGPS_SUPL_MODE_MSB) != 0) { - return GPS_POSITION_MODE_MS_BASED; } } return GPS_POSITION_MODE_STANDALONE; diff --git a/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java b/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java index a5fe9f2..ba98a0a 100644 --- a/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java +++ b/services/core/java/com/android/server/media/RemoteDisplayProviderProxy.java @@ -190,7 +190,8 @@ final class RemoteDisplayProviderProxy implements ServiceConnection { Intent service = new Intent(RemoteDisplayState.SERVICE_INTERFACE); service.setComponent(mComponentName); try { - mBound = mContext.bindServiceAsUser(service, this, Context.BIND_AUTO_CREATE, + mBound = mContext.bindServiceAsUser(service, this, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(mUserId)); if (!mBound && DEBUG) { Slog.d(TAG, this + ": Bind failed"); diff --git a/services/core/java/com/android/server/net/LockdownVpnTracker.java b/services/core/java/com/android/server/net/LockdownVpnTracker.java index 6ffe6ac..0f88883 100644 --- a/services/core/java/com/android/server/net/LockdownVpnTracker.java +++ b/services/core/java/com/android/server/net/LockdownVpnTracker.java @@ -17,6 +17,8 @@ package com.android.server.net; import static android.Manifest.permission.CONNECTIVITY_INTERNAL; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_ALLOW; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import android.app.Notification; import android.app.NotificationManager; @@ -31,6 +33,7 @@ import android.net.LinkAddress; import android.net.NetworkInfo; import android.net.NetworkInfo.DetailedState; import android.net.NetworkInfo.State; +import android.net.NetworkPolicyManager; import android.os.INetworkManagementService; import android.os.RemoteException; import android.security.Credentials; @@ -198,8 +201,8 @@ public class LockdownVpnTracker { setFirewallEgressSourceRule(addr, true); } - mNetService.setFirewallUidRule(ROOT_UID, true); - mNetService.setFirewallUidRule(Os.getuid(), true); + mNetService.setFirewallUidRule(ROOT_UID, FIREWALL_RULE_ALLOW); + mNetService.setFirewallUidRule(Os.getuid(), FIREWALL_RULE_ALLOW); mErrorCount = 0; mAcceptedIface = iface; @@ -288,8 +291,8 @@ public class LockdownVpnTracker { setFirewallEgressSourceRule(addr, false); } - mNetService.setFirewallUidRule(ROOT_UID, false); - mNetService.setFirewallUidRule(Os.getuid(), false); + mNetService.setFirewallUidRule(ROOT_UID, FIREWALL_RULE_DEFAULT); + mNetService.setFirewallUidRule(Os.getuid(), FIREWALL_RULE_DEFAULT); mAcceptedSourceAddr = null; } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 818f0aa..0ae6735 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -36,11 +36,14 @@ import static android.net.NetworkPolicy.LIMIT_DISABLED; import static android.net.NetworkPolicy.SNOOZE_NEVER; import static android.net.NetworkPolicy.WARNING_DISABLED; import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY; +import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; +import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.computeLastCycleBoundary; import static android.net.NetworkPolicyManager.dumpPolicy; import static android.net.NetworkPolicyManager.dumpRules; @@ -80,6 +83,8 @@ import android.app.INotificationManager; import android.app.IProcessObserver; import android.app.Notification; import android.app.PendingIntent; +import android.app.usage.UsageStatsManagerInternal; +import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -88,6 +93,7 @@ import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; import android.content.res.Resources; import android.net.ConnectivityManager; @@ -110,13 +116,16 @@ import android.os.Binder; import android.os.Environment; import android.os.Handler; import android.os.HandlerThread; +import android.os.IDeviceIdleController; import android.os.INetworkManagementService; import android.os.IPowerManager; import android.os.Message; import android.os.MessageQueue.IdleHandler; +import android.os.PowerManager; import android.os.PowerManagerInternal; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; @@ -137,7 +146,6 @@ import android.util.SparseIntArray; import android.util.TrustedTime; import android.util.Xml; -import com.android.server.AppOpsService; import libcore.io.IoUtils; import com.android.internal.R; @@ -145,6 +153,8 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FastXmlSerializer; import com.android.internal.util.IndentingPrintWriter; +import com.android.server.AppOpsService; +import com.android.server.DeviceIdleController; import com.android.server.LocalServices; import com.android.server.SystemConfig; import com.google.android.collect.Lists; @@ -172,7 +182,8 @@ import java.util.List; * and delivers to listeners, such as {@link ConnectivityManager}, for * enforcement. */ -public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { +public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub + implements AppIdleStateChangeListener { private static final String TAG = "NetworkPolicy"; private static final boolean LOGD = false; private static final boolean LOGV = false; @@ -240,11 +251,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private final IPowerManager mPowerManager; private final INetworkStatsService mNetworkStats; private final INetworkManagementService mNetworkManager; + private UsageStatsManagerInternal mUsageStats; private final TrustedTime mTime; private IConnectivityManager mConnManager; private INotificationManager mNotifManager; private PowerManagerInternal mPowerManagerInternal; + private IDeviceIdleController mDeviceIdleController; final Object mRulesLock = new Object(); @@ -321,6 +334,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mPowerManager = checkNotNull(powerManager, "missing powerManager"); mNetworkStats = checkNotNull(networkStats, "missing networkStats"); mNetworkManager = checkNotNull(networkManagement, "missing networkManagement"); + mDeviceIdleController = IDeviceIdleController.Stub.asInterface(ServiceManager.getService( + DeviceIdleController.SERVICE_NAME)); mTime = checkNotNull(time, "missing TrustedTime"); HandlerThread thread = new HandlerThread(TAG); @@ -342,28 +357,31 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mNotifManager = checkNotNull(notifManager, "missing INotificationManager"); } + void updatePowerSaveWhitelistLocked() { + try { + final int[] whitelist = mDeviceIdleController.getAppIdWhitelist(); + mPowerSaveWhitelistAppIds.clear(); + if (whitelist != null) { + for (int uid : whitelist) { + mPowerSaveWhitelistAppIds.put(uid, true); + } + } + } catch (RemoteException e) { + } + } + public void systemReady() { if (!isBandwidthControlEnabled()) { Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy"); return; } + mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class); + final PackageManager pm = mContext.getPackageManager(); synchronized (mRulesLock) { - SystemConfig sysConfig = SystemConfig.getInstance(); - ArraySet<String> allowPower = sysConfig.getAllowInPowerSave(); - for (int i=0; i<allowPower.size(); i++) { - String pkg = allowPower.valueAt(i); - try { - ApplicationInfo ai = pm.getApplicationInfo(pkg, 0); - if ((ai.flags&ApplicationInfo.FLAG_SYSTEM) != 0) { - mPowerSaveWhitelistAppIds.put(UserHandle.getAppId(ai.uid), true); - } - } catch (PackageManager.NameNotFoundException e) { - } - } - + updatePowerSaveWhitelistLocked(); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mPowerManagerInternal.registerLowPowerModeObserver( new PowerManagerInternal.LowPowerModeListener() { @@ -406,6 +424,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { screenFilter.addAction(Intent.ACTION_SCREEN_OFF); mContext.registerReceiver(mScreenReceiver, screenFilter); + // listen for changes to power save whitelist + final IntentFilter whitelistFilter = new IntentFilter( + PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED); + mContext.registerReceiver(mPowerSaveWhitelistReceiver, whitelistFilter, null, mHandler); + // watch for network interfaces to be claimed final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION); mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); @@ -449,6 +472,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { WifiManager.NETWORK_STATE_CHANGED_ACTION); mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler); + mUsageStats.addAppIdleStateChangeListener(this); + } private IProcessObserver mProcessObserver = new IProcessObserver.Stub() { @@ -489,6 +514,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }; + private BroadcastReceiver mPowerSaveWhitelistReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // on background handler thread, and POWER_SAVE_WHITELIST_CHANGED is protected + synchronized (mRulesLock) { + updatePowerSaveWhitelistLocked(); + updateRulesForGlobalChangeLocked(false); + } + } + }; + private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -546,12 +582,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); if (userId == -1) return; - synchronized (mRulesLock) { - // Remove any policies for given user; both cleaning up after a - // USER_REMOVED, and one last sanity check during USER_ADDED - removePoliciesForUserLocked(userId); - // Update global restrict for new user - updateRulesForGlobalChangeLocked(true); + switch (action) { + case ACTION_USER_REMOVED: + case ACTION_USER_ADDED: + synchronized (mRulesLock) { + // Remove any policies for given user; both cleaning up after a + // USER_REMOVED, and one last sanity check during USER_ADDED + removePoliciesForUserLocked(userId); + // Update global restrict for new user + updateRulesForGlobalChangeLocked(true); + } + break; } } }; @@ -1528,20 +1569,6 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return uids; } - @Override - public int[] getPowerSaveAppIdWhitelist() { - mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); - - synchronized (mRulesLock) { - int size = mPowerSaveWhitelistAppIds.size(); - int[] appids = new int[size]; - for (int i = 0; i < size; i++) { - appids[i] = mPowerSaveWhitelistAppIds.keyAt(i); - } - return appids; - } - } - /** * Remove any policies associated with given {@link UserHandle}, persisting * if any changes are made. @@ -1996,7 +2023,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // to have data access. Otherwise, we restrict data access to only // the top apps. mCurForegroundState = (!mRestrictBackground && (mRestrictPower || mDeviceIdleMode)) - ? ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND + ? ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE : ActivityManager.PROCESS_STATE_TOP; // update rules for all installed applications @@ -2032,6 +2059,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return false; } + private boolean isUidIdle(int uid) { + final String[] packages = mContext.getPackageManager().getPackagesForUid(uid); + final int userId = UserHandle.getUserId(uid); + + for (String packageName : packages) { + if (!mUsageStats.isAppIdle(packageName, userId)) { + return false; + } + } + return true; + } + + /** + * Applies network rules to bandwidth and firewall controllers based on uid policy. + * @param uid The uid for which to apply the latest policy + */ void updateRulesForUidLocked(int uid) { if (!isUidValidForRules(uid)) return; @@ -2048,10 +2091,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE); final boolean uidForeground = isUidForegroundLocked(uid); + final boolean uidIdle = isUidIdle(uid); // derive active rules based on policy and active state + int uidRules = RULE_ALLOW_ALL; - if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { + if (uidIdle && !mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid))) { + uidRules = RULE_REJECT_ALL; + } else if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) { // uid in background, and policy says to block metered data uidRules = RULE_REJECT_METERED; } else if (mRestrictBackground) { @@ -2070,7 +2117,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } - // TODO: only dispatch when rules actually change + final int oldRules = mUidRules.get(uid); if (uidRules == RULE_ALLOW_ALL) { mUidRules.delete(uid); @@ -2078,11 +2125,24 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mUidRules.put(uid, uidRules); } + // Update bandwidth rules if necessary + final boolean oldRejectMetered = (oldRules & RULE_REJECT_METERED) != 0; final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0; - setUidNetworkRules(uid, rejectMetered); + if (oldRejectMetered != rejectMetered) { + setUidNetworkRules(uid, rejectMetered); + } + + // Update firewall rules if necessary + final boolean oldFirewallReject = (oldRules & RULE_REJECT_ALL) != 0; + final boolean firewallReject = (uidRules & RULE_REJECT_ALL) != 0; + if (oldFirewallReject != firewallReject) { + setUidFirewallRules(uid, firewallReject); + } // dispatch changed rule to existing listeners - mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); + if (oldRules != uidRules) { + mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget(); + } try { // adjust stats accounting based on foreground status @@ -2092,6 +2152,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @Override + public void onAppIdleStateChanged(String packageName, int userId, boolean idle) { + try { + int uid = mContext.getPackageManager().getPackageUid(packageName, userId); + synchronized (mRulesLock) { + updateRulesForUidLocked(uid); + } + } catch (NameNotFoundException nnfe) { + return; + } + } + private Handler.Callback mHandlerCallback = new Handler.Callback() { @Override public boolean handleMessage(Message msg) { @@ -2215,6 +2287,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + /** + * Add or remove a uid to the firewall blacklist for all network ifaces. + * @param uid + * @param rejectOnAll + */ + private void setUidFirewallRules(int uid, boolean rejectOnAll) { + try { + mNetworkManager.setFirewallUidRule(uid, + rejectOnAll ? FIREWALL_RULE_DENY : FIREWALL_RULE_DEFAULT); + } catch (IllegalStateException e) { + Log.wtf(TAG, "problem setting firewall uid rules", e); + } catch (RemoteException e) { + // ignored; service lives in system_server + } + } + private long getTotalBytes(NetworkTemplate template, long start, long end) { try { return mNetworkStats.getNetworkTotalBytes(template, start, end); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 50e03a2..0035d01 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -561,9 +561,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final int callingUid = Binder.getCallingUid(); final DevicePolicyManagerInternal dpmi = LocalServices.getService( DevicePolicyManagerInternal.class); - if (dpmi.isActiveAdminWithPolicy(callingUid, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) - || dpmi.isActiveAdminWithPolicy(callingUid, - DeviceAdminInfo.USES_POLICY_DEVICE_OWNER)) { + + // Device owners are also profile owners so it is enough to check for that. + if (dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid, + DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)) { return; } } diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 9ccb2ea..b92c734 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -495,7 +495,7 @@ abstract public class ManagedServices { Slog.v(TAG, getCaption() + " connection lost: " + name); } }, - Context.BIND_AUTO_CREATE, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, new UserHandle(userid))) { mServicesBinding.remove(servicesBindingTag); diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index a406175..09096ff 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -969,8 +969,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub { public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) { if (PackageManager.INSTALL_SUCCEEDED == returnCode && mShowNotification) { + boolean update = (extras != null) && extras.getBoolean(Intent.EXTRA_REPLACING); Notification notification = buildSuccessNotification(mContext, - mContext.getResources().getString(R.string.package_installed_device_owner), + mContext.getResources() + .getString(update ? R.string.package_updated_device_owner : + R.string.package_installed_device_owner), basePackageName, mUserId); if (notification != null) { @@ -980,6 +983,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { } } final Intent fillIn = new Intent(); + fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, basePackageName); fillIn.putExtra(PackageInstaller.EXTRA_SESSION_ID, mSessionId); fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageManager.installStatusToPublicStatus(returnCode)); @@ -1030,6 +1034,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { R.color.system_notification_accent_color)) .setContentTitle(packageLabel) .setContentText(contentText) + .setStyle(new Notification.BigTextStyle().bigText(contentText)) .setLargeIcon(packageIcon) .build(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 8a19056..11ab042 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -155,6 +155,7 @@ import android.os.storage.IMountService; import android.os.storage.StorageEventListener; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; +import android.os.storage.VolumeRecord; import android.security.KeyStore; import android.security.SystemKeyStore; import android.system.ErrnoException; @@ -298,7 +299,6 @@ public class PackageManagerService extends IPackageManager.Stub { static final int SCAN_BOOTING = 1<<8; static final int SCAN_TRUSTED_OVERLAY = 1<<9; static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10; - static final int SCAN_REPLACING = 1<<11; static final int SCAN_REQUIRE_KNOWN = 1<<12; static final int REMOVE_CHATTY = 1<<16; @@ -1558,6 +1558,11 @@ public class PackageManagerService extends IPackageManager.Stub { } } } + + @Override + public void onVolumeForgotten(String fsUuid) { + // TODO: remove all packages hosted on this uuid + } }; private void grantRequestedRuntimePermissions(PackageParser.Package pkg, int userId) { @@ -1597,6 +1602,12 @@ public class PackageManagerService extends IPackageManager.Stub { res.origPackage); break; } + case PackageManager.INSTALL_SUCCEEDED: { + extras = new Bundle(); + extras.putBoolean(Intent.EXTRA_REPLACING, + res.removedInfo != null && res.removedInfo.removedPackage != null); + break; + } } return extras; } @@ -2374,6 +2385,18 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override + public boolean isPackageFrozen(String packageName) { + synchronized (mPackages) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + return ps.frozen; + } + } + Slog.w(TAG, "Package " + packageName + " is missing; assuming frozen"); + return true; + } + + @Override public boolean isPackageAvailable(String packageName, int userId) { if (!sUserManager.exists(userId)) return false; enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "is package available"); @@ -6476,14 +6499,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - // Request the ActivityManager to kill the process(only for existing packages) - // so that we do not end up in a confused state while the user is still using the older - // version of the application while the new one gets installed. - if ((scanFlags & SCAN_REPLACING) != 0) { - killApplication(pkg.applicationInfo.packageName, - pkg.applicationInfo.uid, "update pkg"); - } - // Also need to kill any apps that are dependent on the library. if (clientLibPkgs != null) { for (int i=0; i<clientLibPkgs.size(); i++) { @@ -10791,16 +10806,17 @@ public class PackageManagerService extends IPackageManager.Stub { private void replacePackageLI(PackageParser.Package pkg, int parseFlags, int scanFlags, UserHandle user, String installerPackageName, String volumeUuid, PackageInstalledInfo res) { - PackageParser.Package oldPackage; - String pkgName = pkg.packageName; - int[] allUsers; - boolean[] perUserInstalled; + final PackageParser.Package oldPackage; + final String pkgName = pkg.packageName; + final int[] allUsers; + final boolean[] perUserInstalled; + final boolean weFroze; // First find the old package info and check signatures synchronized(mPackages) { oldPackage = mPackages.get(pkgName); if (DEBUG_INSTALL) Slog.d(TAG, "replacePackageLI: new=" + pkg + ", old=" + oldPackage); - PackageSetting ps = mSettings.mPackages.get(pkgName); + final PackageSetting ps = mSettings.mPackages.get(pkgName); if (ps == null || !ps.keySetData.isUsingUpgradeKeySets() || ps.sharedUser != null) { // default to original signature matching if (compareSignatures(oldPackage.mSignatures, pkg.mSignatures) @@ -10824,15 +10840,35 @@ public class PackageManagerService extends IPackageManager.Stub { for (int i = 0; i < allUsers.length; i++) { perUserInstalled[i] = ps != null ? ps.getInstalled(allUsers[i]) : false; } + + // Mark the app as frozen to prevent launching during the upgrade + // process, and then kill all running instances + if (!ps.frozen) { + ps.frozen = true; + weFroze = true; + } else { + weFroze = false; + } } - boolean sysPkg = (isSystemApp(oldPackage)); - if (sysPkg) { - replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags, - user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res); - } else { - replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags, - user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res); + // Now that we're guarded by frozen state, kill app during upgrade + killApplication(pkgName, oldPackage.applicationInfo.uid, "replace pkg"); + + try { + boolean sysPkg = (isSystemApp(oldPackage)); + if (sysPkg) { + replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags, + user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res); + } else { + replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanFlags, + user, allUsers, perUserInstalled, installerPackageName, volumeUuid, res); + } + } finally { + // Regardless of success or failure of upgrade steps above, always + // unfreeze the package if we froze it + if (weFroze) { + unfreezePackage(pkgName); + } } } @@ -10962,8 +10998,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } - killApplication(packageName, oldPkg.applicationInfo.uid, "replace sys pkg"); - res.removedInfo.uid = oldPkg.applicationInfo.uid; res.removedInfo.removedPackage = packageName; // Remove existing system package @@ -11308,7 +11342,7 @@ public class PackageManagerService extends IPackageManager.Stub { startIntentFilterVerifications(args.user.getIdentifier(), pkg); if (replace) { - replacePackageLI(pkg, parseFlags, scanFlags | SCAN_REPLACING, args.user, + replacePackageLI(pkg, parseFlags, scanFlags, args.user, installerPackageName, volumeUuid, res); } else { installNewPackageLI(pkg, parseFlags, scanFlags | SCAN_DELETE_DATA_ON_FAILURES, @@ -14194,6 +14228,15 @@ public class PackageManagerService extends IPackageManager.Stub { sendResourcesChangedBroadcast(false, false, unloaded, null); } + private void unfreezePackage(String packageName) { + synchronized (mPackages) { + final PackageSetting ps = mSettings.mPackages.get(packageName); + if (ps != null) { + ps.frozen = false; + } + } + } + @Override public int movePackage(final String packageName, final String volumeUuid) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null); @@ -14203,7 +14246,7 @@ public class PackageManagerService extends IPackageManager.Stub { movePackageInternal(packageName, volumeUuid, moveId); } catch (PackageManagerException e) { Slog.d(TAG, "Failed to move " + packageName, e); - mMoveCallbacks.notifyStatusChanged(moveId, null, + mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INTERNAL_ERROR); } return moveId; @@ -14221,7 +14264,7 @@ public class PackageManagerService extends IPackageManager.Stub { final String packageAbiOverride; final int appId; final String seinfo; - final String moveTitle; + final String label; // reader synchronized (mPackages) { @@ -14234,14 +14277,19 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkg.applicationInfo.isSystemApp()) { throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE, "Cannot move system application"); - } else if (pkg.mOperationPending) { - throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, - "Attempt to move package which has pending operations"); } - // TODO: yell if already in desired location + if (Objects.equals(ps.volumeUuid, volumeUuid)) { + throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, + "Package already moved to " + volumeUuid); + } - pkg.mOperationPending = true; + if (ps.frozen) { + throw new PackageManagerException(MOVE_FAILED_OPERATION_PENDING, + "Failed to move already frozen package"); + } + + ps.frozen = true; currentAsec = pkg.applicationInfo.isForwardLocked() || pkg.applicationInfo.isExternalAsec(); @@ -14251,9 +14299,17 @@ public class PackageManagerService extends IPackageManager.Stub { packageAbiOverride = ps.cpuAbiOverrideString; appId = UserHandle.getAppId(pkg.applicationInfo.uid); seinfo = pkg.applicationInfo.seinfo; - moveTitle = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo)); + label = String.valueOf(pm.getApplicationLabel(pkg.applicationInfo)); } + // Now that we're guarded by frozen state, kill app during upgrade + killApplication(packageName, appId, "move pkg"); + + final Bundle extras = new Bundle(); + extras.putString(Intent.EXTRA_PACKAGE_NAME, packageName); + extras.putString(Intent.EXTRA_TITLE, label); + mMoveCallbacks.notifyCreated(moveId, extras); + int installFlags; final boolean moveData; @@ -14268,6 +14324,7 @@ public class PackageManagerService extends IPackageManager.Stub { final VolumeInfo volume = storage.findVolumeByUuid(volumeUuid); if (volume == null || volume.getType() != VolumeInfo.TYPE_PRIVATE || !volume.isMountedWritable()) { + unfreezePackage(packageName); throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, "Move location not mounted private volume"); } @@ -14279,27 +14336,21 @@ public class PackageManagerService extends IPackageManager.Stub { } Slog.d(TAG, "Moving " + packageName + " from " + currentVolumeUuid + " to " + volumeUuid); - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, 10); + mMoveCallbacks.notifyStatusChanged(moveId, 10); if (moveData) { synchronized (mInstallLock) { // TODO: split this into separate copy and delete operations if (mInstaller.moveUserDataDirs(currentVolumeUuid, volumeUuid, packageName, appId, seinfo) != 0) { - synchronized (mPackages) { - final PackageParser.Package pkg = mPackages.get(packageName); - if (pkg != null) { - pkg.mOperationPending = false; - } - } - + unfreezePackage(packageName); throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR, - "Failed to move private data"); + "Failed to move private data to " + volumeUuid); } } } - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, 50); + mMoveCallbacks.notifyStatusChanged(moveId, 50); final IPackageInstallObserver2 installObserver = new IPackageInstallObserver2.Stub() { @Override @@ -14313,28 +14364,22 @@ public class PackageManagerService extends IPackageManager.Stub { Slog.d(TAG, "Install result for move: " + PackageManager.installStatusToString(returnCode, msg)); - // We usually have a new package now after the install, but if - // we failed we need to clear the pending flag on the original - // package object. - synchronized (mPackages) { - final PackageParser.Package pkg = mPackages.get(packageName); - if (pkg != null) { - pkg.mOperationPending = false; - } - } + // Regardless of success or failure of the move operation, + // always unfreeze the package + unfreezePackage(packageName); final int status = PackageManager.installStatusToPublicStatus(returnCode); switch (status) { case PackageInstaller.STATUS_SUCCESS: - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, + mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_SUCCEEDED); break; case PackageInstaller.STATUS_FAILURE_STORAGE: - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, + mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INSUFFICIENT_STORAGE); break; default: - mMoveCallbacks.notifyStatusChanged(moveId, moveTitle, + mMoveCallbacks.notifyStatusChanged(moveId, PackageManager.MOVE_FAILED_INTERNAL_ERROR); break; } @@ -14357,12 +14402,19 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null); final int realMoveId = mNextMoveId.getAndIncrement(); - final String realTitle = null; + final Bundle extras = new Bundle(); + extras.putString(VolumeRecord.EXTRA_FS_UUID, volumeUuid); + mMoveCallbacks.notifyCreated(realMoveId, extras); final IPackageMoveObserver callback = new IPackageMoveObserver.Stub() { @Override - public void onStatusChanged(int moveId, String title, int status, long estMillis) { - mMoveCallbacks.notifyStatusChanged(realMoveId, realTitle, status, estMillis); + public void onCreated(int moveId, Bundle extras) { + // Ignored + } + + @Override + public void onStatusChanged(int moveId, int status, long estMillis) { + mMoveCallbacks.notifyStatusChanged(realMoveId, status, estMillis); } }; @@ -14717,6 +14769,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private static class MoveCallbacks extends Handler { + private static final int MSG_CREATED = 1; private static final int MSG_STATUS_CHANGED = 2; private final RemoteCallbackList<IPackageMoveObserver> @@ -14754,26 +14807,37 @@ public class PackageManagerService extends IPackageManager.Stub { private void invokeCallback(IPackageMoveObserver callback, int what, SomeArgs args) throws RemoteException { switch (what) { + case MSG_CREATED: { + callback.onCreated(args.argi1, (Bundle) args.arg2); + break; + } case MSG_STATUS_CHANGED: { - callback.onStatusChanged(args.argi1, (String) args.arg2, args.argi3, - (long) args.arg4); + callback.onStatusChanged(args.argi1, args.argi2, (long) args.arg3); break; } } } - private void notifyStatusChanged(int moveId, String moveTitle, int status) { - notifyStatusChanged(moveId, moveTitle, status, -1); + private void notifyCreated(int moveId, Bundle extras) { + Slog.v(TAG, "Move " + moveId + " created " + extras.toString()); + + final SomeArgs args = SomeArgs.obtain(); + args.argi1 = moveId; + args.arg2 = extras; + obtainMessage(MSG_CREATED, args).sendToTarget(); + } + + private void notifyStatusChanged(int moveId, int status) { + notifyStatusChanged(moveId, status, -1); } - private void notifyStatusChanged(int moveId, String moveTitle, int status, long estMillis) { + private void notifyStatusChanged(int moveId, int status, long estMillis) { Slog.v(TAG, "Move " + moveId + " status " + status); final SomeArgs args = SomeArgs.obtain(); args.argi1 = moveId; - args.arg2 = moveTitle; - args.argi3 = status; - args.arg4 = estMillis; + args.argi2 = status; + args.arg3 = estMillis; obtainMessage(MSG_STATUS_CHANGED, args).sendToTarget(); synchronized (mLastStatus) { diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java index 5429517..f62c00c 100644 --- a/services/core/java/com/android/server/pm/PackageSettingBase.java +++ b/services/core/java/com/android/server/pm/PackageSettingBase.java @@ -108,6 +108,13 @@ abstract class PackageSettingBase extends SettingBase { int installStatus = PKG_INSTALL_COMPLETE; + /** + * Non-persisted value indicating this package has been temporarily frozen, + * usually during a critical section of the package update pipeline. The + * platform will refuse to launch packages in a frozen state. + */ + boolean frozen = false; + PackageSettingBase origPackage; /** Package name of the app that installed this package */ diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 252c16a..f9c248d 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3759,6 +3759,10 @@ final class Settings { pw.print(Integer.toHexString(System.identityHashCode(ps))); pw.println("):"); + if (ps.frozen) { + pw.print(prefix); pw.println(" FROZEN!"); + } + if (ps.realName != null) { pw.print(prefix); pw.print(" compat name="); pw.println(ps.name); @@ -3790,9 +3794,6 @@ final class Settings { pw.print(prefix); pw.print(" priavateFlags="); printFlags(pw, ps.pkg.applicationInfo.privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println(); pw.print(prefix); pw.print(" dataDir="); pw.println(ps.pkg.applicationInfo.dataDir); - if (ps.pkg.mOperationPending) { - pw.print(prefix); pw.println(" mOperationPending=true"); - } pw.print(prefix); pw.print(" supportsScreens=["); boolean first = true; if ((ps.pkg.applicationInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) { diff --git a/services/core/java/com/android/server/power/DeviceIdleController.java b/services/core/java/com/android/server/power/DeviceIdleController.java deleted file mode 100644 index 6b29b9a..0000000 --- a/services/core/java/com/android/server/power/DeviceIdleController.java +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (C) 2015 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 the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.power; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.hardware.Sensor; -import android.hardware.SensorManager; -import android.hardware.TriggerEvent; -import android.hardware.TriggerEventListener; -import android.hardware.display.DisplayManager; -import android.net.INetworkPolicyManager; -import android.os.Binder; -import android.os.PowerManager; -import android.os.PowerManagerInternal; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.SystemClock; -import android.os.UserHandle; -import android.util.TimeUtils; -import android.view.Display; -import com.android.internal.app.IBatteryStats; -import com.android.server.SystemService; -import com.android.server.am.BatteryStatsService; -import com.android.server.EventLogTags; - -import java.io.FileDescriptor; -import java.io.PrintWriter; - -/** - * Keeps track of device idleness and drives low power mode based on that. - */ -public class DeviceIdleController extends SystemService { - private static final String TAG = "DeviceIdleController"; - - private static final String ACTION_STEP_IDLE_STATE = - "com.android.server.device_idle.STEP_IDLE_STATE"; - - // TODO: These need to be moved to system settings. - - /** - * This is the time, after becoming inactive, at which we start looking at the - * motion sensor to determine if the device is being left alone. We don't do this - * immediately after going inactive just because we don't want to be continually running - * the significant motion sensor whenever the screen is off. - */ - private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; - /** - * This is the time, after seeing motion, that we wait after becoming inactive from - * that until we start looking for motion again. - */ - private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L; - /** - * This is the time, after the inactive timeout elapses, that we will wait looking - * for significant motion until we truly consider the device to be idle. - */ - private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; - /** - * This is the initial time, after being idle, that we will allow ourself to be back - * in the IDLE_PENDING state allowing the system to run normally until we return to idle. - */ - private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L; - /** - * Maximum pending idle timeout (time spent running) we will be allowed to use. - */ - private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L; - /** - * Scaling factor to apply to current pending idle timeout each time we cycle through - * that state. - */ - private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f; - /** - * This is the initial time that we want to sit in the idle state before waking up - * again to return to pending idle and allowing normal work to run. - */ - private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; - /** - * Maximum idle duration we will be allowed to use. - */ - private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; - /** - * Scaling factor to apply to current idle timeout each time we cycle through that state. - */ - private static final float DEFAULT_IDLE_FACTOR = 2f; - /** - * This is the minimum time we will allow until the next upcoming alarm for us to - * actually go in to idle mode. - */ - private static final long DEFAULT_MIN_TIME_TO_ALARM = 60*60*1000L; - - private AlarmManager mAlarmManager; - private IBatteryStats mBatteryStats; - private PowerManagerInternal mLocalPowerManager; - private INetworkPolicyManager mNetworkPolicyManager; - private DisplayManager mDisplayManager; - private SensorManager mSensorManager; - private Sensor mSigMotionSensor; - private PendingIntent mAlarmIntent; - private Intent mIdleIntent; - private Display mCurDisplay; - private boolean mScreenOn; - private boolean mCharging; - private boolean mSigMotionActive; - - /** Device is currently active. */ - private static final int STATE_ACTIVE = 0; - /** Device is inactve (screen off, no motion) and we are waiting to for idle. */ - private static final int STATE_INACTIVE = 1; - /** Device is past the initial inactive period, and waiting for the next idle period. */ - private static final int STATE_IDLE_PENDING = 2; - /** Device is in the idle state, trying to stay asleep as much as possible. */ - private static final int STATE_IDLE = 3; - private static String stateToString(int state) { - switch (state) { - case STATE_ACTIVE: return "ACTIVE"; - case STATE_INACTIVE: return "INACTIVE"; - case STATE_IDLE_PENDING: return "IDLE_PENDING"; - case STATE_IDLE: return "IDLE"; - default: return Integer.toString(state); - } - } - - private int mState; - - private long mInactiveTimeout; - private long mNextAlarmTime; - private long mNextIdlePendingDelay; - private long mNextIdleDelay; - - private final Binder mBinder = new Binder() { - @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - DeviceIdleController.this.dump(fd, pw, args); - } - }; - - private final BroadcastReceiver mReceiver = new BroadcastReceiver() { - @Override public void onReceive(Context context, Intent intent) { - if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { - int plugged = intent.getIntExtra("plugged", 0); - updateChargingLocked(plugged != 0); - } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { - synchronized (DeviceIdleController.this) { - stepIdleStateLocked(); - } - } - } - }; - - private final DisplayManager.DisplayListener mDisplayListener - = new DisplayManager.DisplayListener() { - @Override public void onDisplayAdded(int displayId) { - } - - @Override public void onDisplayRemoved(int displayId) { - } - - @Override public void onDisplayChanged(int displayId) { - if (displayId == Display.DEFAULT_DISPLAY) { - synchronized (DeviceIdleController.this) { - updateDisplayLocked(); - } - } - } - }; - - private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { - @Override public void onTrigger(TriggerEvent event) { - synchronized (DeviceIdleController.this) { - significantMotionLocked(); - } - } - }; - - public DeviceIdleController(Context context) { - super(context); - } - - @Override - public void onStart() { - synchronized (this) { - mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); - mBatteryStats = BatteryStatsService.getService(); - mLocalPowerManager = getLocalService(PowerManagerInternal.class); - mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( - ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); - mDisplayManager = (DisplayManager) getContext().getSystemService( - Context.DISPLAY_SERVICE); - mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); - mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); - - Intent intent = new Intent(ACTION_STEP_IDLE_STATE) - .setPackage("android") - .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); - - mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); - mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); - - IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_BATTERY_CHANGED); - filter.addAction(ACTION_STEP_IDLE_STATE); - getContext().registerReceiver(mReceiver, filter); - - mDisplayManager.registerDisplayListener(mDisplayListener, null); - - mScreenOn = true; - // Start out assuming we are charging. If we aren't, we will at least get - // a battery update the next time the level drops. - mCharging = true; - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; - updateDisplayLocked(); - } - - publishBinderService("deviceidle", mBinder); - } - - void updateDisplayLocked() { - mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); - // We consider any situation where the display is showing something to be it on, - // because if there is anything shown we are going to be updating it at some - // frequency so can't be allowed to go into deep sleeps. - boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;; - if (!screenOn && mScreenOn) { - mScreenOn = false; - becomeInactiveIfAppropriateLocked(); - } else if (screenOn) { - mScreenOn = true; - becomeActiveLocked("screen"); - } - } - - void updateChargingLocked(boolean charging) { - if (!charging && mCharging) { - mCharging = false; - becomeInactiveIfAppropriateLocked(); - } else if (charging) { - mCharging = charging; - becomeActiveLocked("charging"); - } - } - - void becomeActiveLocked(String reason) { - if (mState != STATE_ACTIVE) { - EventLogTags.writeDeviceIdle(STATE_ACTIVE, reason); - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, true, false); - } catch (RemoteException e) { - } - if (mState == STATE_IDLE) { - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - } - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT; - mNextIdlePendingDelay = 0; - mNextIdleDelay = 0; - cancelAlarmLocked(); - stopMonitoringSignificantMotion(); - } - } - - void becomeInactiveIfAppropriateLocked() { - if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) { - // Screen has turned off; we are now going to become inactive and start - // waiting to see if we will ultimately go idle. - mState = STATE_INACTIVE; - mNextIdlePendingDelay = 0; - mNextIdleDelay = 0; - scheduleAlarmLocked(mInactiveTimeout, false); - EventLogTags.writeDeviceIdle(mState, "no activity"); - } - } - - void stepIdleStateLocked() { - EventLogTags.writeDeviceIdleStep(); - - final long now = SystemClock.elapsedRealtime(); - if ((now+DEFAULT_MIN_TIME_TO_ALARM) > mAlarmManager.getNextWakeFromIdleTime()) { - // Whoops, there is an upcoming alarm. We don't actually want to go idle. - if (mState != STATE_ACTIVE) { - becomeActiveLocked("alarm"); - } - return; - } - - switch (mState) { - case STATE_INACTIVE: - // We have now been inactive long enough, it is time to start looking - // for significant motion and sleep some more while doing so. - startMonitoringSignificantMotion(); - scheduleAlarmLocked(DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT, false); - // Reset the upcoming idle delays. - mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT; - mNextIdleDelay = DEFAULT_IDLE_TIMEOUT; - mState = STATE_IDLE_PENDING; - EventLogTags.writeDeviceIdle(mState, "step"); - break; - case STATE_IDLE_PENDING: - // We have been waiting to become idle, and now it is time! This is the - // only case where we want to use a wakeup alarm, because we do want to - // drag the device out of its sleep state in this case to do the next - // scheduled work. - scheduleAlarmLocked(mNextIdleDelay, true); - mNextIdleDelay = (long)(mNextIdleDelay*DEFAULT_IDLE_FACTOR); - if (mNextIdleDelay > DEFAULT_MAX_IDLE_TIMEOUT) { - mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT; - } - mState = STATE_IDLE; - EventLogTags.writeDeviceIdle(mState, "step"); - mLocalPowerManager.setDeviceIdleMode(true); - try { - mNetworkPolicyManager.setDeviceIdleMode(true); - mBatteryStats.noteDeviceIdleMode(true, false, false); - } catch (RemoteException e) { - } - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - break; - case STATE_IDLE: - // We have been idling long enough, now it is time to do some work. - scheduleAlarmLocked(mNextIdlePendingDelay, false); - mNextIdlePendingDelay = (long)(mNextIdlePendingDelay*DEFAULT_IDLE_PENDING_FACTOR); - if (mNextIdlePendingDelay > DEFAULT_MAX_IDLE_PENDING_TIMEOUT) { - mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT; - } - mState = STATE_IDLE_PENDING; - EventLogTags.writeDeviceIdle(mState, "step"); - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, false, false); - } catch (RemoteException e) { - } - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - break; - } - } - - void significantMotionLocked() { - // When the sensor goes off, its trigger is automatically removed. - mSigMotionActive = false; - // The device is not yet active, so we want to go back to the pending idle - // state to wait again for no motion. Note that we only monitor for significant - // motion after moving out of the inactive state, so no need to worry about that. - if (mState != STATE_ACTIVE) { - mLocalPowerManager.setDeviceIdleMode(false); - try { - mNetworkPolicyManager.setDeviceIdleMode(false); - mBatteryStats.noteDeviceIdleMode(false, false, true); - } catch (RemoteException e) { - } - if (mState == STATE_IDLE) { - getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL); - } - mState = STATE_ACTIVE; - mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT; - EventLogTags.writeDeviceIdle(mState, "motion"); - becomeInactiveIfAppropriateLocked(); - } - } - - void startMonitoringSignificantMotion() { - if (mSigMotionSensor != null && !mSigMotionActive) { - mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = true; - } - } - - void stopMonitoringSignificantMotion() { - if (mSigMotionActive) { - mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = false; - } - } - - void cancelAlarmLocked() { - if (mNextAlarmTime != 0) { - mNextAlarmTime = 0; - mAlarmManager.cancel(mAlarmIntent); - } - } - - void scheduleAlarmLocked(long delay, boolean idleUntil) { - if (mSigMotionSensor == null) { - // If there is no significant motion sensor on this device, then we won't schedule - // alarms, because we can't determine if the device is not moving. This effectively - // turns off normal exeuction of device idling, although it is still possible to - // manually poke it by pretending like the alarm is going off. - return; - } - mNextAlarmTime = SystemClock.elapsedRealtime() + delay; - if (idleUntil) { - mAlarmManager.setIdleUntil(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mNextAlarmTime, mAlarmIntent); - } else { - mAlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, - mNextAlarmTime, mAlarmIntent); - } - } - - private void dumpHelp(PrintWriter pw) { - pw.println("Device idle controller (deviceidle) dump options:"); - pw.println(" [-h] [CMD]"); - pw.println(" -h: print this help text."); - pw.println("Commands:"); - pw.println(" step"); - pw.println(" Immediately step to next state, without waiting for alarm."); - } - - void dump(FileDescriptor fd, PrintWriter pw, String[] args) { - if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) - != PackageManager.PERMISSION_GRANTED) { - pw.println("Permission Denial: can't dump DeviceIdleController from from pid=" - + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() - + " without permission " + android.Manifest.permission.DUMP); - return; - } - - if (args != null) { - for (int i=0; i<args.length; i++) { - String arg = args[i]; - if ("-h".equals(arg)) { - dumpHelp(pw); - return; - } else if ("step".equals(arg)) { - synchronized (this) { - stepIdleStateLocked(); - pw.print("Stepped to: "); pw.println(stateToString(mState)); - } - return; - } else if (arg.length() > 0 && arg.charAt(0) == '-'){ - pw.println("Unknown option: " + arg); - dumpHelp(pw); - return; - } else { - pw.println("Unknown command: " + arg); - dumpHelp(pw); - return; - } - } - } - - synchronized (this) { - pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); - pw.print(" mCurDisplay="); pw.println(mCurDisplay); - pw.print(" mScreenOn="); pw.println(mScreenOn); - pw.print(" mCharging="); pw.println(mCharging); - pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); - pw.print(" mState="); pw.println(stateToString(mState)); - pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw); - pw.println(); - if (mNextAlarmTime != 0) { - pw.print(" mNextAlarmTime="); - TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); - pw.println(); - } - if (mNextIdlePendingDelay != 0) { - pw.print(" mNextIdlePendingDelay="); - TimeUtils.formatDuration(mNextIdlePendingDelay, pw); - pw.println(); - } - if (mNextIdleDelay != 0) { - pw.print(" mNextIdleDelay="); - TimeUtils.formatDuration(mNextIdleDelay, pw); - pw.println(); - } - } - } -} diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java index 22fee22..9abdf21 100644 --- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java +++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java @@ -96,7 +96,8 @@ public class TelecomLoaderService extends SystemService { TelecomServiceConnection serviceConnection = new TelecomServiceConnection(); Intent intent = new Intent(SERVICE_ACTION); intent.setComponent(SERVICE_COMPONENT); - int flags = Context.BIND_IMPORTANT | Context.BIND_AUTO_CREATE; + int flags = Context.BIND_IMPORTANT | Context.BIND_FOREGROUND_SERVICE + | Context.BIND_AUTO_CREATE; // Bind to Telecom and register the service if (mContext.bindServiceAsUser(intent, serviceConnection, flags, UserHandle.OWNER)) { diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java index fb7d186..e5c5b2b 100644 --- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java +++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java @@ -276,7 +276,8 @@ public class TrustAgentWrapper { // Schedules a restart for when connecting times out. If the connection succeeds, // the restart is canceled in mCallback's onConnected. scheduleRestart(); - mBound = context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user); + mBound = context.bindServiceAsUser(intent, mConnection, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE, user); if (mBound) { mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null); } else { diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 5972247..56816f9 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -529,7 +529,9 @@ public final class TvInputManagerService extends SystemService { Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(component); serviceState.bound = mContext.bindServiceAsUser( - i, serviceState.connection, Context.BIND_AUTO_CREATE, new UserHandle(userId)); + i, serviceState.connection, + Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, + new UserHandle(userId)); } else if (serviceState.service != null && !maintainConnection) { // This means that the service is already connected but its state indicates that we have // nothing to do with it. Then, disconnect the service. diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index 54be380..755c414 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -1038,7 +1038,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { mContext.getText(com.android.internal.R.string.chooser_wallpaper)), 0, null, new UserHandle(serviceUserId))); if (!mContext.bindServiceAsUser(intent, newConn, - Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI, + Context.BIND_AUTO_CREATE | Context.BIND_SHOWING_UI + | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE, new UserHandle(serviceUserId))) { String msg = "Unable to bind service: " + componentName; |