diff options
Diffstat (limited to 'services/core/java/com/android')
40 files changed, 1705 insertions, 1857 deletions
diff --git a/services/core/java/com/android/server/AnyMotionDetector.java b/services/core/java/com/android/server/AnyMotionDetector.java index 6a67316..a0b5c15 100644 --- a/services/core/java/com/android/server/AnyMotionDetector.java +++ b/services/core/java/com/android/server/AnyMotionDetector.java @@ -58,9 +58,6 @@ public class AnyMotionDetector { /** Current measurement state. */ private int mState; - /** Threshold angle in degrees beyond which the device is considered moving. */ - private final float THRESHOLD_ANGLE = 2f; - /** Threshold energy above which the device is considered moving. */ private final float THRESHOLD_ENERGY = 5f; @@ -88,6 +85,9 @@ public class AnyMotionDetector { private SensorManager mSensorManager; private PowerManager.WakeLock mWakeLock; + /** Threshold angle in degrees beyond which the device is considered moving. */ + private final float mThresholdAngle; + /** The minimum number of samples required to detect AnyMotion. */ private int mNumSufficientSamples; @@ -106,7 +106,7 @@ public class AnyMotionDetector { private DeviceIdleCallback mCallback = null; public AnyMotionDetector(PowerManager pm, Handler handler, SensorManager sm, - DeviceIdleCallback callback) { + DeviceIdleCallback callback, float thresholdAngle) { if (DEBUG) Slog.d(TAG, "AnyMotionDetector instantiated."); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); mWakeLock.setReferenceCounted(false); @@ -116,6 +116,7 @@ public class AnyMotionDetector { mMeasurementInProgress = false; mState = STATE_INACTIVE; mCallback = callback; + mThresholdAngle = thresholdAngle; mRunningStats = new RunningSignalStats(); mNumSufficientSamples = (int) Math.ceil( ((double)ORIENTATION_MEASUREMENT_DURATION_MILLIS / SAMPLING_INTERVAL_MILLIS)); @@ -224,8 +225,9 @@ public class AnyMotionDetector { Vector3 previousGravityVectorNormalized = mPreviousGravityVector.normalized(); Vector3 currentGravityVectorNormalized = mCurrentGravityVector.normalized(); float angle = previousGravityVectorNormalized.angleBetween(currentGravityVectorNormalized); - if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle); - if ((angle < THRESHOLD_ANGLE) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) { + if (DEBUG) Slog.d(TAG, "getStationaryStatus: angle = " + angle + + " energy = " + mRunningStats.getEnergy()); + if ((angle < mThresholdAngle) && (mRunningStats.getEnergy() < THRESHOLD_ENERGY)) { return RESULT_STATIONARY; } else if (Float.isNaN(angle)) { /** diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 63c3e97..f20cfe9 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2006 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +26,7 @@ import com.android.server.lights.Light; import com.android.server.lights.LightsManager; import android.app.ActivityManagerNative; +import android.app.IBatteryService; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -87,6 +89,21 @@ import cyanogenmod.providers.CMSettings; * a degree Centigrade</p> * <p>"technology" - String, the type of battery installed, e.g. "Li-ion"</p> * + * <p>If a dock battery is present, then this Intent data will be present too related + * to dock battery information:</p> + * <p>"dock_scale" - int, the maximum value for the charge level</p> + * <p>"dock_level" - int, charge level, from 0 through "scale" inclusive</p> + * <p>"dock_status" - String, the current charging status.<br /> + * <p>"dock_health" - String, the current battery health.<br /> + * <p>"dock_present" - boolean, true if the battery is present<br /> + * <p>"dock_icon-small" - int, suggested small icon to use for this state</p> + * <p>"dock_plugged" - int, 0 if the device is not plugged in; 1 if plugged + * into an AC power adapter; 2 if plugged in via USB.</p> + * <p>"dock_voltage" - int, current battery voltage in millivolts</p> + * <p>"dock_temperature" - int, current battery temperature in tenths of + * a degree Centigrade</p> + * <p>"dock_technology" - String, the type of battery installed, e.g. "Li-ion"</p> + * * <p> * The battery service may be called by the power manager while holding its locks so * we take care to post all outcalls into the activity manager to a handler. @@ -135,6 +152,14 @@ public final class BatteryService extends SystemService { private boolean mLastBatteryLevelCritical; private int mLastMaxChargingCurrent; + private boolean mDockBatterySupported; + private int mLastDockBatteryStatus; + private int mLastDockBatteryHealth; + private boolean mLastDockBatteryPresent; + private int mLastDockBatteryLevel; + private int mLastDockBatteryVoltage; + private int mLastDockBatteryTemperature; + private int mInvalidCharger; private int mLastInvalidCharger; @@ -150,8 +175,11 @@ public final class BatteryService extends SystemService { private int mPlugType; private int mLastPlugType = -1; // Extra state so we can detect first run + private int mDockPlugType; + private int mLastDockPlugType = -1; // Extra state so we can detect first run private boolean mBatteryLevelLow; + private boolean mDockBatteryLevelLow; private long mDischargeStartTime; private int mDischargeStartLevel; @@ -180,6 +208,10 @@ public final class BatteryService extends SystemService { mLed = new Led(context, getLocalService(LightsManager.class)); mBatteryStats = BatteryStatsService.getService(); + // By default dock battery are not supported. The first events will refresh + // this status from the battery property bag + mDockBatterySupported = false; + mCriticalBatteryLevel = mContext.getResources().getInteger( com.android.internal.R.integer.config_criticalBatteryWarningLevel); mLowBatteryWarningLevel = mContext.getResources().getInteger( @@ -209,7 +241,7 @@ public final class BatteryService extends SystemService { // Should never happen. } - publishBinderService("battery", new BinderService()); + publishBinderService(Context.BATTERY_SERVICE, new BinderService()); publishLocalService(BatteryManagerInternal.class, new LocalService()); } @@ -344,21 +376,31 @@ public final class BatteryService extends SystemService { boolean logOutlier = false; long dischargeDuration = 0; + mDockBatterySupported = mBatteryProps.dockBatterySupported; + mBatteryLevelCritical = (mBatteryProps.batteryLevel <= mCriticalBatteryLevel); + mPlugType = BATTERY_PLUGGED_NONE; if (mBatteryProps.chargerAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mBatteryProps.chargerUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_USB; } else if (mBatteryProps.chargerWirelessOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS; - } else { - mPlugType = BATTERY_PLUGGED_NONE; + } + mDockPlugType = BATTERY_PLUGGED_NONE; + if (mBatteryProps.chargerDockAcOnline && mBatteryProps.chargerAcOnline) { + mDockPlugType = BatteryManager.BATTERY_DOCK_PLUGGED_AC; + } else if (mBatteryProps.chargerDockAcOnline && mBatteryProps.chargerUsbOnline) { + mDockPlugType = BatteryManager.BATTERY_DOCK_PLUGGED_USB; } if (DEBUG) { - Slog.d(TAG, "Processing new values: " - + "chargerAcOnline=" + mBatteryProps.chargerAcOnline - + ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline + String msg = "Processing new values: " + + "chargerAcOnline=" + mBatteryProps.chargerAcOnline; + if (mDockBatterySupported) { + msg += ", chargerDockAcOnline=" + mBatteryProps.chargerDockAcOnline; + } + msg += ", chargerUsbOnline=" + mBatteryProps.chargerUsbOnline + ", chargerWirelessOnline=" + mBatteryProps.chargerWirelessOnline + ", maxChargingCurrent" + mBatteryProps.maxChargingCurrent + ", batteryStatus=" + mBatteryProps.batteryStatus @@ -368,8 +410,22 @@ public final class BatteryService extends SystemService { + ", batteryTechnology=" + mBatteryProps.batteryTechnology + ", batteryVoltage=" + mBatteryProps.batteryVoltage + ", batteryTemperature=" + mBatteryProps.batteryTemperature - + ", mBatteryLevelCritical=" + mBatteryLevelCritical - + ", mPlugType=" + mPlugType); + + ", mBatteryLevelCritical=" + mBatteryLevelCritical; + if (mDockBatterySupported) { + msg += ", dockBatteryStatus=" + mBatteryProps.dockBatteryStatus + + ", dockBatteryHealth=" + mBatteryProps.dockBatteryHealth + + ", dockBatteryPresent=" + mBatteryProps.dockBatteryPresent + + ", dockBatteryLevel=" + mBatteryProps.dockBatteryLevel + + ", dockBatteryTechnology=" + mBatteryProps.dockBatteryTechnology + + ", dockBatteryVoltage=" + mBatteryProps.dockBatteryVoltage + + ", dockBatteryTemperature=" + mBatteryProps.dockBatteryTemperature; + } + msg += ", mPlugType=" + mPlugType; + if (mDockBatterySupported) { + msg += ", mDockPlugType=" + mDockPlugType; + } + + Slog.d(TAG, msg); } // Let the battery stats keep track of the current level. @@ -380,19 +436,40 @@ public final class BatteryService extends SystemService { } catch (RemoteException e) { // Should never happen. } + if (mDockBatterySupported) { + try { + mBatteryStats.setDockBatteryState(mBatteryProps.dockBatteryStatus, + mBatteryProps.dockBatteryHealth, mDockPlugType, + mBatteryProps.dockBatteryLevel, mBatteryProps.dockBatteryTemperature, + mBatteryProps.dockBatteryVoltage); + } catch (RemoteException e) { + // Should never happen. + } + } shutdownIfNoPowerLocked(); shutdownIfOverTempLocked(); - if (force || (mBatteryProps.batteryStatus != mLastBatteryStatus || + final boolean batteryChanged = mBatteryProps.batteryStatus != mLastBatteryStatus || mBatteryProps.batteryHealth != mLastBatteryHealth || mBatteryProps.batteryPresent != mLastBatteryPresent || mBatteryProps.batteryLevel != mLastBatteryLevel || mPlugType != mLastPlugType || mBatteryProps.batteryVoltage != mLastBatteryVoltage || mBatteryProps.batteryTemperature != mLastBatteryTemperature || - mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent || - mInvalidCharger != mLastInvalidCharger)) { + mBatteryProps.maxChargingCurrent != mLastMaxChargingCurrent; + + final boolean dockBatteryChanged = mDockBatterySupported && + (mBatteryProps.dockBatteryStatus != mLastDockBatteryStatus || + mBatteryProps.dockBatteryHealth != mLastDockBatteryHealth || + mBatteryProps.dockBatteryPresent != mLastDockBatteryPresent || + mBatteryProps.dockBatteryLevel != mLastDockBatteryLevel || + mDockPlugType != mLastDockPlugType || + mBatteryProps.dockBatteryVoltage != mLastDockBatteryVoltage || + mBatteryProps.dockBatteryTemperature != mLastDockBatteryTemperature); + + if (force || batteryChanged || dockBatteryChanged || + mInvalidCharger != mLastInvalidCharger) { if (mPlugType != mLastPlugType) { if (mLastPlugType == BATTERY_PLUGGED_NONE) { @@ -422,12 +499,30 @@ public final class BatteryService extends SystemService { mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mBatteryProps.batteryPresent ? 1 : 0, mPlugType, mBatteryProps.batteryTechnology); } + if (mDockBatterySupported && + (mBatteryProps.dockBatteryStatus != mLastDockBatteryStatus || + mBatteryProps.dockBatteryHealth != mLastDockBatteryHealth || + mBatteryProps.dockBatteryPresent != mLastDockBatteryPresent || + mDockPlugType != mLastDockPlugType)) { + EventLog.writeEvent(EventLogTags.DOCK_BATTERY_STATUS, + mBatteryProps.dockBatteryStatus, mBatteryProps.dockBatteryHealth, + mBatteryProps.dockBatteryPresent ? 1 : 0, + mDockPlugType, mBatteryProps.dockBatteryTechnology); + } if (mBatteryProps.batteryLevel != mLastBatteryLevel) { // Don't do this just from voltage or temperature changes, that is // too noisy. EventLog.writeEvent(EventLogTags.BATTERY_LEVEL, mBatteryProps.batteryLevel, mBatteryProps.batteryVoltage, mBatteryProps.batteryTemperature); } + if (mDockBatterySupported && + (mBatteryProps.dockBatteryLevel != mLastDockBatteryLevel)) { + // Don't do this just from voltage or temperature changes, that is + // too noisy. + EventLog.writeEvent(EventLogTags.DOCK_BATTERY_LEVEL, + mBatteryProps.dockBatteryLevel, mBatteryProps.dockBatteryVoltage, + mBatteryProps.dockBatteryTemperature); + } if (mBatteryLevelCritical && !mLastBatteryLevelCritical && mPlugType == BATTERY_PLUGGED_NONE) { // We want to make sure we log discharge cycle outliers @@ -454,13 +549,34 @@ public final class BatteryService extends SystemService { mBatteryLevelLow = false; } } + if (mDockBatterySupported) { + if (!mDockBatteryLevelLow) { + // Should we now switch in to low battery mode? + if (mDockPlugType == BATTERY_PLUGGED_NONE + && mBatteryProps.dockBatteryLevel <= mLowBatteryWarningLevel) { + mDockBatteryLevelLow = true; + } + } else { + // Should we now switch out of low battery mode? + if (mDockPlugType != BATTERY_PLUGGED_NONE) { + mDockBatteryLevelLow = false; + } else if (mBatteryProps.dockBatteryLevel >= mLowBatteryCloseWarningLevel) { + mDockBatteryLevelLow = false; + } else if (force && mBatteryProps.batteryLevel >= mLowBatteryWarningLevel) { + // If being forced, the previous state doesn't matter, we will just + // absolutely check to see if we are now above the warning level. + mDockBatteryLevelLow = false; + } + } + } sendIntentLocked(); // Separate broadcast is sent for power connected / not connected // since the standard intent will not wake any applications and some // applications may want to have smart behavior based on this. - if (mPlugType != 0 && mLastPlugType == 0) { + if (mPlugType != 0 && mLastPlugType == 0 || + (mLastPlugType == 0 && mDockPlugType != 0 && mLastDockPlugType == 0)) { mHandler.post(new Runnable() { @Override public void run() { @@ -470,7 +586,8 @@ public final class BatteryService extends SystemService { } }); } - else if (mPlugType == 0 && mLastPlugType != 0) { + else if (mPlugType == 0 && mLastPlugType != 0 || + (mLastPlugType != 0 && mDockPlugType == 0 && mLastDockPlugType != 0)) { mHandler.post(new Runnable() { @Override public void run() { @@ -526,6 +643,14 @@ public final class BatteryService extends SystemService { mLastBatteryTemperature = mBatteryProps.batteryTemperature; mLastMaxChargingCurrent = mBatteryProps.maxChargingCurrent; mLastBatteryLevelCritical = mBatteryLevelCritical; + mLastDockBatteryStatus = mBatteryProps.dockBatteryStatus; + mLastDockBatteryHealth = mBatteryProps.dockBatteryHealth; + mLastDockBatteryPresent = mBatteryProps.dockBatteryPresent; + mLastDockBatteryLevel = mBatteryProps.dockBatteryLevel; + mLastDockPlugType = mDockPlugType; + mLastDockBatteryVoltage = mBatteryProps.dockBatteryVoltage; + mLastDockBatteryTemperature = mBatteryProps.dockBatteryTemperature; + mLastInvalidCharger = mInvalidCharger; } } @@ -537,6 +662,7 @@ public final class BatteryService extends SystemService { | Intent.FLAG_RECEIVER_REPLACE_PENDING); int icon = getIconLocked(mBatteryProps.batteryLevel); + int dockIcon = 0; intent.putExtra(BatteryManager.EXTRA_STATUS, mBatteryProps.batteryStatus); intent.putExtra(BatteryManager.EXTRA_HEALTH, mBatteryProps.batteryHealth); @@ -551,19 +677,62 @@ public final class BatteryService extends SystemService { intent.putExtra(BatteryManager.EXTRA_INVALID_CHARGER, mInvalidCharger); intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mBatteryProps.maxChargingCurrent); + if (mDockBatterySupported) { + dockIcon = getDockIconLocked(mBatteryProps.dockBatteryLevel); + + intent.putExtra(BatteryManager.EXTRA_DOCK_STATUS, mBatteryProps.dockBatteryStatus); + intent.putExtra(BatteryManager.EXTRA_DOCK_HEALTH, mBatteryProps.dockBatteryHealth); + intent.putExtra(BatteryManager.EXTRA_DOCK_PRESENT, mBatteryProps.dockBatteryPresent); + intent.putExtra(BatteryManager.EXTRA_DOCK_LEVEL, mBatteryProps.dockBatteryLevel); + intent.putExtra(BatteryManager.EXTRA_DOCK_SCALE, BATTERY_SCALE); + intent.putExtra(BatteryManager.EXTRA_DOCK_ICON_SMALL, dockIcon); + intent.putExtra(BatteryManager.EXTRA_DOCK_PLUGGED, mDockPlugType); + intent.putExtra(BatteryManager.EXTRA_DOCK_VOLTAGE, mBatteryProps.dockBatteryVoltage); + intent.putExtra(BatteryManager.EXTRA_DOCK_TEMPERATURE, + mBatteryProps.dockBatteryTemperature); + intent.putExtra(BatteryManager.EXTRA_DOCK_TECHNOLOGY, + mBatteryProps.dockBatteryTechnology); + + // EEPAD legacy data + intent.putExtra("usb_wakeup", mBatteryProps.chargerUsbOnline); + intent.putExtra("ac_online", mBatteryProps.chargerAcOnline); + intent.putExtra("dock_ac_online", mBatteryProps.chargerDockAcOnline); + } + + if (DEBUG) { - Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel + - ", scale:" + BATTERY_SCALE + ", status:" + mBatteryProps.batteryStatus + + String msg = "Sending ACTION_BATTERY_CHANGED. level:" + mBatteryProps.batteryLevel + + ", scale:" + BATTERY_SCALE + + ", status:" + mBatteryProps.batteryStatus + ", health:" + mBatteryProps.batteryHealth + ", present:" + mBatteryProps.batteryPresent + ", voltage: " + mBatteryProps.batteryVoltage + ", temperature: " + mBatteryProps.batteryTemperature + ", technology: " + mBatteryProps.batteryTechnology + - ", AC powered:" + mBatteryProps.chargerAcOnline + - ", USB powered:" + mBatteryProps.chargerUsbOnline + - ", Wireless powered:" + mBatteryProps.chargerWirelessOnline + - ", icon:" + icon + ", invalid charger:" + mInvalidCharger + - ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent); + ", maxChargingCurrent:" + mBatteryProps.maxChargingCurrent; + + if (mDockBatterySupported) { + msg += ", dock_level:" + mBatteryProps.dockBatteryLevel + + ", dock_status:" + mBatteryProps.dockBatteryStatus + + ", dock_health:" + mBatteryProps.dockBatteryHealth + + ", dock_present:" + mBatteryProps.dockBatteryPresent + + ", dock_voltage: " + mBatteryProps.dockBatteryVoltage + + ", dock_temperature: " + mBatteryProps.dockBatteryTemperature + + ", dock_technology: " + mBatteryProps.dockBatteryTechnology; + } + msg += ", AC powered:" + mBatteryProps.chargerAcOnline; + if (mDockBatterySupported) { + msg += ", Dock AC powered:" + mBatteryProps.chargerDockAcOnline; + } + msg += ", USB powered:" + mBatteryProps.chargerUsbOnline + + ", Wireless powered:" + mBatteryProps.chargerWirelessOnline; + msg += ", icon:" + icon; + if (mDockBatterySupported) { + msg += ", dock_icon:" + dockIcon; + } + msg += ", invalid charger:" + mInvalidCharger; + + Slog.d(TAG, msg); } mHandler.post(new Runnable() { @@ -658,6 +827,22 @@ public final class BatteryService extends SystemService { } } + private int getDockIconLocked(int level) { + if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) { + return com.android.internal.R.drawable.stat_sys_battery_charge; + } else if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_DISCHARGING) { + return com.android.internal.R.drawable.stat_sys_battery; + } else if (mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_NOT_CHARGING + || mBatteryProps.dockBatteryStatus == BatteryManager.BATTERY_STATUS_FULL) { + if (isPoweredLocked(BatteryManager.BATTERY_PLUGGED_ANY) + && mBatteryProps.dockBatteryLevel >= 100) { + return com.android.internal.R.drawable.stat_sys_battery_charge; + } + return com.android.internal.R.drawable.stat_sys_battery; + } + return com.android.internal.R.drawable.stat_sys_battery_unknown; + } + private void dumpInternal(PrintWriter pw, String[] args) { synchronized (mLock) { if (args == null || args.length == 0 || "-a".equals(args[0])) { @@ -666,6 +851,9 @@ public final class BatteryService extends SystemService { pw.println(" (UPDATES STOPPED -- use 'reset' to restart)"); } pw.println(" AC powered: " + mBatteryProps.chargerAcOnline); + if (mDockBatterySupported) { + pw.println(" Dock AC powered: " + mBatteryProps.chargerDockAcOnline); + } pw.println(" USB powered: " + mBatteryProps.chargerUsbOnline); pw.println(" Wireless powered: " + mBatteryProps.chargerWirelessOnline); pw.println(" Max charging current: " + mBatteryProps.maxChargingCurrent); @@ -677,7 +865,15 @@ public final class BatteryService extends SystemService { pw.println(" voltage: " + mBatteryProps.batteryVoltage); pw.println(" temperature: " + mBatteryProps.batteryTemperature); pw.println(" technology: " + mBatteryProps.batteryTechnology); - + if (mDockBatterySupported) { + pw.println(" dock_status: " + mBatteryProps.dockBatteryStatus); + pw.println(" dock_health: " + mBatteryProps.dockBatteryHealth); + pw.println(" dock_present: " + mBatteryProps.dockBatteryPresent); + pw.println(" dock_level: " + mBatteryProps.dockBatteryLevel); + pw.println(" dock_voltage: " + mBatteryProps.dockBatteryVoltage); + pw.println(" dock_temperature: " + mBatteryProps.dockBatteryTemperature); + pw.println(" dock_technology: " + mBatteryProps.dockBatteryTechnology); + } } else if ("unplug".equals(args[0])) { if (!mUpdatesStopped) { mLastBatteryProps.set(mBatteryProps); @@ -703,6 +899,8 @@ public final class BatteryService extends SystemService { boolean update = true; if ("ac".equals(key)) { mBatteryProps.chargerAcOnline = Integer.parseInt(value) != 0; + } else if (mDockBatterySupported && "dockac".equals(key)) { + mBatteryProps.chargerDockAcOnline = Integer.parseInt(value) != 0; } else if ("usb".equals(key)) { mBatteryProps.chargerUsbOnline = Integer.parseInt(value) != 0; } else if ("wireless".equals(key)) { @@ -711,6 +909,10 @@ public final class BatteryService extends SystemService { mBatteryProps.batteryStatus = Integer.parseInt(value); } else if ("level".equals(key)) { mBatteryProps.batteryLevel = Integer.parseInt(value); + } else if (mDockBatterySupported && "dockstatus".equals(key)) { + mBatteryProps.dockBatteryStatus = Integer.parseInt(value); + } else if (mDockBatterySupported && "docklevel".equals(key)) { + mBatteryProps.dockBatteryLevel = Integer.parseInt(value); } else if ("invalid".equals(key)) { mInvalidCharger = Integer.parseInt(value); } else { @@ -743,7 +945,12 @@ public final class BatteryService extends SystemService { } } else { pw.println("Dump current battery state, or:"); - pw.println(" set [ac|usb|wireless|status|level|invalid] <value>"); + if (mDockBatterySupported) { + pw.println(" set [ac|dockac|usb|wireless|status|level|dockstatus" + + "|docklevel|invalid] <value>"); + } else { + pw.println(" set [ac|usb|wireless|status|level|invalid] <value>"); + } pw.println(" unplug"); pw.println(" reset"); } @@ -935,7 +1142,12 @@ public final class BatteryService extends SystemService { } } - private final class BinderService extends Binder { + private final class BinderService extends IBatteryService.Stub { + @Override + public boolean isDockBatterySupported() throws RemoteException { + return getLocalService(BatteryManagerInternal.class).isDockBatterySupported(); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -981,11 +1193,39 @@ public final class BatteryService extends SystemService { } @Override + public int getDockPlugType() { + synchronized (mLock) { + return mDockPlugType; + } + } + + @Override + public int getDockBatteryLevel() { + synchronized (mLock) { + return mBatteryProps.dockBatteryLevel; + } + } + + @Override + public boolean getDockBatteryLevelLow() { + synchronized (mLock) { + return mDockBatteryLevelLow; + } + } + + @Override public int getInvalidCharger() { synchronized (mLock) { return mInvalidCharger; } } + + @Override + public boolean isDockBatterySupported() { + synchronized (mLock) { + return mDockBatterySupported; + } + } } class SettingsObserver extends ContentObserver { diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 6067bd2..5a76227 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -266,7 +266,8 @@ class BluetoothManagerService extends IBluetoothManager.Stub { sysUiUid = mContext.getPackageManager().getPackageUid("com.android.systemui", UserHandle.USER_OWNER); } catch (PackageManager.NameNotFoundException e) { - Log.wtf(TAG, "Unable to resolve SystemUI's UID.", e); + // Some platforms, such as wearables do not have a system ui. + Log.w(TAG, "Unable to resolve SystemUI's UID.", e); } mSystemUiUid = sysUiUid; } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index b053c3a..2a47460 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -171,6 +171,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private static final boolean VDBG = false; private static final boolean LOGD_RULES = false; + private static final boolean LOGD_BLOCKED_NETWORKINFO = true; // TODO: create better separation between radio types and network types @@ -964,6 +965,21 @@ public class ConnectivityService extends IConnectivityManager.Stub } } + private void maybeLogBlockedNetworkInfo(NetworkInfo ni, int uid) { + if (ni == null || !LOGD_BLOCKED_NETWORKINFO) return; + boolean removed = false; + boolean added = false; + synchronized (mBlockedAppUids) { + if (ni.getDetailedState() == DetailedState.BLOCKED && mBlockedAppUids.add(uid)) { + added = true; + } else if (ni.isConnected() && mBlockedAppUids.remove(uid)) { + removed = true; + } + } + if (added) log("Returning blocked NetworkInfo to uid=" + uid); + else if (removed) log("Returning unblocked NetworkInfo to uid=" + uid); + } + /** * Return a filtered {@link NetworkInfo}, potentially marked * {@link DetailedState#BLOCKED} based on @@ -974,10 +990,6 @@ public class ConnectivityService extends IConnectivityManager.Stub // network is blocked; clone and override state info = new NetworkInfo(info); info.setDetailedState(DetailedState.BLOCKED, null, null); - if (VDBG) { - log("returning Blocked NetworkInfo for ifname=" + - lp.getInterfaceName() + ", uid=" + uid); - } } if (info != null && mLockdownTracker != null) { info = mLockdownTracker.augmentNetworkInfo(info); @@ -998,7 +1010,9 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceAccessPermission(); final int uid = Binder.getCallingUid(); NetworkState state = getUnfilteredActiveNetworkState(uid); - return getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid); + NetworkInfo ni = getFilteredNetworkInfo(state.networkInfo, state.linkProperties, uid); + maybeLogBlockedNetworkInfo(ni, uid); + return ni; } @Override @@ -3927,6 +3941,9 @@ public class ConnectivityService extends IConnectivityManager.Stub private final HashMap<Messenger, NetworkAgentInfo> mNetworkAgentInfos = new HashMap<Messenger, NetworkAgentInfo>(); + @GuardedBy("mBlockedAppUids") + private final HashSet<Integer> mBlockedAppUids = new HashSet(); + // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated. private final NetworkRequest mDefaultRequest; diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java index abe8f5c..71650c3 100644 --- a/services/core/java/com/android/server/DeviceIdleController.java +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -31,6 +31,8 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.database.ContentObserver; import android.hardware.Sensor; import android.hardware.SensorManager; +import android.hardware.SensorEvent; +import android.hardware.SensorEventListener; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; import android.hardware.display.DisplayManager; @@ -111,7 +113,7 @@ public class DeviceIdleController extends SystemService private INetworkPolicyManager mNetworkPolicyManager; private DisplayManager mDisplayManager; private SensorManager mSensorManager; - private Sensor mSigMotionSensor; + private Sensor mMotionSensor; private LocationManager mLocationManager; private LocationRequest mLocationRequest; private PendingIntent mSensingAlarmIntent; @@ -123,12 +125,12 @@ public class DeviceIdleController extends SystemService private boolean mForceIdle; private boolean mScreenOn; private boolean mCharging; - private boolean mSigMotionActive; private boolean mSensing; private boolean mNotMoving; private boolean mLocating; private boolean mLocated; - private boolean mHaveGps; + private boolean mHasGps; + private boolean mHasNetworkLocation; private Location mLastGenericLocation; private Location mLastGpsLocation; @@ -275,13 +277,57 @@ public class DeviceIdleController extends SystemService } }; - private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { - @Override public void onTrigger(TriggerEvent event) { + private final class MotionListener extends TriggerEventListener + implements SensorEventListener { + + boolean active = false; + + @Override + public void onTrigger(TriggerEvent event) { synchronized (DeviceIdleController.this) { - significantMotionLocked(); + active = false; + motionLocked(); } } - }; + + @Override + public void onSensorChanged(SensorEvent event) { + synchronized (DeviceIdleController.this) { + mSensorManager.unregisterListener(this, mMotionSensor); + active = false; + motionLocked(); + } + } + + @Override + public void onAccuracyChanged(Sensor sensor, int accuracy) {} + + public boolean registerLocked() { + boolean success = false; + if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { + success = mSensorManager.requestTriggerSensor(mMotionListener, mMotionSensor); + } else { + success = mSensorManager.registerListener( + mMotionListener, mMotionSensor, SensorManager.SENSOR_DELAY_NORMAL); + } + if (success) { + active = true; + } else { + Slog.e(TAG, "Unable to register for " + mMotionSensor); + } + return success; + } + + public void unregisterLocked() { + if (mMotionSensor.getReportingMode() == Sensor.REPORTING_MODE_ONE_SHOT) { + mSensorManager.cancelTriggerSensor(mMotionListener, mMotionSensor); + } else { + mSensorManager.unregisterListener(mMotionListener); + } + active = false; + } + } + private final MotionListener mMotionListener = new MotionListener(); private final LocationListener mGenericLocationListener = new LocationListener() { @Override @@ -356,7 +402,7 @@ public class DeviceIdleController extends SystemService * 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. + * the motion sensor whenever the screen is off. * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_INACTIVE_TIMEOUT */ @@ -399,7 +445,7 @@ public class DeviceIdleController extends SystemService /** * 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. + * for motion until we truly consider the device to be idle. * @see Settings.Global#DEVICE_IDLE_CONSTANTS * @see #KEY_IDLE_AFTER_INACTIVE_TIMEOUT */ @@ -896,17 +942,38 @@ public class DeviceIdleController extends SystemService mDisplayManager = (DisplayManager) getContext().getSystemService( Context.DISPLAY_SERVICE); mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); - mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); - mLocationManager = (LocationManager) getContext().getSystemService( - Context.LOCATION_SERVICE); - mLocationRequest = new LocationRequest() - .setQuality(LocationRequest.ACCURACY_FINE) - .setInterval(0) - .setFastestInterval(0) - .setNumUpdates(1); + int sigMotionSensorId = getContext().getResources().getInteger( + com.android.internal.R.integer.config_autoPowerModeAnyMotionSensor); + if (sigMotionSensorId > 0) { + mMotionSensor = mSensorManager.getDefaultSensor(sigMotionSensorId, true); + } + if (mMotionSensor == null && getContext().getResources().getBoolean( + com.android.internal.R.bool.config_autoPowerModePreferWristTilt)) { + mMotionSensor = mSensorManager.getDefaultSensor( + Sensor.TYPE_WRIST_TILT_GESTURE, true); + } + if (mMotionSensor == null) { + // As a last ditch, fall back to SMD. + mMotionSensor = mSensorManager.getDefaultSensor( + Sensor.TYPE_SIGNIFICANT_MOTION, true); + } + + if (getContext().getResources().getBoolean( + com.android.internal.R.bool.config_autoPowerModePrefetchLocation)) { + mLocationManager = (LocationManager) getContext().getSystemService( + Context.LOCATION_SERVICE); + mLocationRequest = new LocationRequest() + .setQuality(LocationRequest.ACCURACY_FINE) + .setInterval(0) + .setFastestInterval(0) + .setNumUpdates(1); + } + + float angleThreshold = getContext().getResources().getInteger( + com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f; mAnyMotionDetector = new AnyMotionDetector( (PowerManager) getContext().getSystemService(Context.POWER_SERVICE), - mHandler, mSensorManager, this); + mHandler, mSensorManager, this, angleThreshold); Intent intent = new Intent(ACTION_STEP_IDLE_STATE) .setPackage("android") @@ -1242,7 +1309,7 @@ public class DeviceIdleController extends SystemService cancelAlarmLocked(); cancelSensingAlarmLocked(); cancelLocatingLocked(); - stopMonitoringSignificantMotion(); + stopMonitoringMotionLocked(); mAnyMotionDetector.stop(); } @@ -1271,8 +1338,8 @@ public class DeviceIdleController extends SystemService 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(); + // for motion and sleep some more while doing so. + startMonitoringMotionLocked(); scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false); // Reset the upcoming idle delays. mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT; @@ -1298,17 +1365,30 @@ public class DeviceIdleController extends SystemService if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING."); EventLogTags.writeDeviceIdle(mState, "step"); scheduleSensingAlarmLocked(mConstants.LOCATING_TIMEOUT); - mLocating = true; - mLocationManager.requestLocationUpdates(mLocationRequest, mGenericLocationListener, - mHandler.getLooper()); - if (mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { - mHaveGps = true; + if (mLocationManager != null + && mLocationManager.getProvider(LocationManager.NETWORK_PROVIDER) != null) { + mLocationManager.requestLocationUpdates(mLocationRequest, + mGenericLocationListener, mHandler.getLooper()); + mLocating = true; + } else { + mHasNetworkLocation = false; + } + if (mLocationManager != null + && mLocationManager.getProvider(LocationManager.GPS_PROVIDER) != null) { + mHasGps = true; mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 5, mGpsLocationListener, mHandler.getLooper()); + mLocating = true; } else { - mHaveGps = false; + mHasGps = false; } - break; + // If we have a location provider, we're all set, the listeners will move state + // forward. + if (mLocating) { + break; + } + + // Otherwise, we have to move from locating into idle maintenance. case STATE_LOCATING: cancelSensingAlarmLocked(); cancelLocatingLocked(); @@ -1338,17 +1418,16 @@ public class DeviceIdleController extends SystemService } } - void significantMotionLocked() { - if (DEBUG) Slog.d(TAG, "significantMotionLocked()"); - // When the sensor goes off, its trigger is automatically removed. - mSigMotionActive = false; + void motionLocked() { + if (DEBUG) Slog.d(TAG, "motionLocked()"); + // The motion sensor will have been disabled at this point handleMotionDetectedLocked(mConstants.MOTION_INACTIVE_TIMEOUT, "motion"); } void handleMotionDetectedLocked(long timeout, String type) { // 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. + // state to wait again for no motion. Note that we only monitor for motion + // after moving out of the inactive state, so no need to worry about that. if (mState != STATE_ACTIVE) { scheduleReportActiveLocked(type, Process.myUid()); mState = STATE_ACTIVE; @@ -1366,7 +1445,7 @@ public class DeviceIdleController extends SystemService } if (DEBUG) Slog.d(TAG, "Generic location: " + location); mLastGenericLocation = new Location(location); - if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHaveGps) { + if (location.getAccuracy() > mConstants.LOCATION_ACCURACY && mHasGps) { return; } mLocated = true; @@ -1391,19 +1470,17 @@ public class DeviceIdleController extends SystemService } } - void startMonitoringSignificantMotion() { - if (DEBUG) Slog.d(TAG, "startMonitoringSignificantMotion()"); - if (mSigMotionSensor != null && !mSigMotionActive) { - mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = true; + void startMonitoringMotionLocked() { + if (DEBUG) Slog.d(TAG, "startMonitoringMotionLocked()"); + if (mMotionSensor != null && !mMotionListener.active) { + mMotionListener.registerLocked(); } } - void stopMonitoringSignificantMotion() { - if (DEBUG) Slog.d(TAG, "stopMonitoringSignificantMotion()"); - if (mSigMotionActive) { - mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); - mSigMotionActive = false; + void stopMonitoringMotionLocked() { + if (DEBUG) Slog.d(TAG, "stopMonitoringMotionLocked()"); + if (mMotionSensor != null && mMotionListener.active) { + mMotionListener.unregisterLocked(); } } @@ -1432,10 +1509,10 @@ public class DeviceIdleController extends SystemService void scheduleAlarmLocked(long delay, boolean idleUntil) { if (DEBUG) Slog.d(TAG, "scheduleAlarmLocked(" + delay + ", " + idleUntil + ")"); - if (mSigMotionSensor == null) { - // If there is no significant motion sensor on this device, then we won't schedule + if (mMotionSensor == null) { + // If there is no 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 + // turns off normal execution of device idling, although it is still possible to // manually poke it by pretending like the alarm is going off. return; } @@ -1917,15 +1994,16 @@ public class DeviceIdleController extends SystemService pw.print(" mEnabled="); pw.println(mEnabled); pw.print(" mForceIdle="); pw.println(mForceIdle); - pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); + pw.print(" mMotionSensor="); pw.println(mMotionSensor); 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(" mMotionActive="); pw.println(mMotionListener.active); pw.print(" mSensing="); pw.print(mSensing); pw.print(" mNotMoving="); pw.println(mNotMoving); - pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHaveGps="); - pw.print(mHaveGps); pw.print(" mLocated="); pw.println(mLocated); + pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps="); + pw.print(mHasGps); pw.print(" mHasNetwork="); + pw.print(mHasNetworkLocation); pw.print(" mLocated="); pw.println(mLocated); if (mLastGenericLocation != null) { pw.print(" mLastGenericLocation="); pw.println(mLastGenericLocation); } diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags index ab2ea8b..8bb158e 100644 --- a/services/core/java/com/android/server/EventLogTags.logtags +++ b/services/core/java/com/android/server/EventLogTags.logtags @@ -11,6 +11,10 @@ option java_package com.android.server # It lets us count the total amount of time between charges and the discharge level 2730 battery_discharge (duration|2|3),(minLevel|1|6),(maxLevel|1|6) +# dock battery +2738 dock_battery_level (level|1|6),(voltage|1|1),(temperature|1|1) +2739 dock_battery_status (status|1|5),(health|1|5),(present|1|5),(plugged|1|5),(technology|3) + # --------------------------- # PowerManagerService.java @@ -29,9 +33,13 @@ option java_package com.android.server # This is logged when the partial wake lock (keeping the device awake # regardless of whether the screen is off) is acquired or released. 2729 power_partial_wake_state (releasedorAcquired|1|5),(tag|3) +# The device is being asked to go into a soft sleep (typically by the ungaze gesture). +# It logs the time remaining before the device would've normally gone to sleep without the request. +2731 power_soft_sleep_requested (savedwaketimems|2) # -# Leave IDs through 2739 for more power logs (2730 used by battery_discharge above) +# Leave IDs through 2739 for more power logs (2730 used by battery_discharge and +# 2738-2739 used by dock battery above) # diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 4f9f972..a9f6e40 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -143,6 +143,7 @@ import java.util.HashSet; import java.util.List; import java.util.Locale; +import cyanogenmod.hardware.CMHardwareManager; import cyanogenmod.providers.CMSettings; import org.cyanogenmod.internal.util.QSUtils; @@ -239,6 +240,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub private boolean mShowOngoingImeSwitcherForPhones; private boolean mNotificationShown; private final boolean mImeSelectedOnBoot; + private CMHardwareManager mCMHardware; static class SessionState { final ClientState client; @@ -506,15 +508,32 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } }, userId); + if (mCMHardware.isSupported(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { + resolver.registerContentObserver(CMSettings.System.getUriFor( + CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE), false, this, userId); + } + if (mCMHardware.isSupported(CMHardwareManager.FEATURE_TOUCH_HOVERING)) { + resolver.registerContentObserver(CMSettings.Secure.getUriFor( + CMSettings.Secure.FEATURE_TOUCH_HOVERING), false, this, userId); + } + mRegistered = true; } @Override public void onChange(boolean selfChange, Uri uri) { final Uri showImeUri = Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD); + final Uri touchSensitivityUri = + CMSettings.System.getUriFor(CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE); + final Uri touchHoveringUri = + CMSettings.Secure.getUriFor(CMSettings.Secure.FEATURE_TOUCH_HOVERING); synchronized (mMethodMap) { if (showImeUri.equals(uri)) { updateKeyboardFromSettingsLocked(); + } else if (touchSensitivityUri.equals(uri)) { + updateTouchSensitivity(); + } else if (touchHoveringUri.equals(uri)) { + updateTouchHovering(); } else { boolean enabledChanged = false; String newEnabled = mSettings.getEnabledInputMethodsStr(); @@ -943,11 +962,6 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } } - synchronized (mMethodMap) { - mSettingsObserver.registerContentObserverLocked(userId); - updateFromSettingsLocked(true); - } - // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME // according to the new system locale. final IntentFilter filter = new IntentFilter(); @@ -1072,6 +1086,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mContext.getBasePackageName()); } + updateTouchHovering(); + updateTouchSensitivity(); + if (DEBUG) Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId + " selectedIme=" + mSettings.getSelectedInputMethod()); } @@ -1108,6 +1125,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } if (!mSystemReady) { mSystemReady = true; + // Must happen before registerContentObserverLocked + mCMHardware = CMHardwareManager.getInstance(mContext); + + mSettingsObserver.registerContentObserverLocked( + mSettings.getCurrentUserId()); + updateFromSettingsLocked(true); + + updateTouchHovering(); + updateTouchSensitivity(); + mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE); mNotificationManager = (NotificationManager) @@ -1836,8 +1863,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub com.android.internal.R.string.select_input_method, mImeSwitcherNotification.build(), UserHandle.ALL); mNotificationShown = true; - publishImeSelectorCustomTile(imi); } + publishImeSelectorCustomTile(imi); } else { if (mNotificationShown && mNotificationManager != null) { if (DEBUG) { @@ -1846,8 +1873,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub mNotificationManager.cancelAsUser(null, com.android.internal.R.string.select_input_method, UserHandle.ALL); mNotificationShown = false; - unpublishImeSelectorCustomTile(); } + unpublishImeSelectorCustomTile(); } } finally { Binder.restoreCallingIdentity(ident); @@ -1970,6 +1997,26 @@ public class InputMethodManagerService extends IInputMethodManager.Stub } + private void updateTouchSensitivity() { + if (!mCMHardware.isSupported(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY)) { + return; + } + boolean touchSensitivityEnable = CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.HIGH_TOUCH_SENSITIVITY_ENABLE, 0) == 1; + mCMHardware.set(CMHardwareManager.FEATURE_HIGH_TOUCH_SENSITIVITY, + touchSensitivityEnable); + } + + private void updateTouchHovering() { + if (!mCMHardware.isSupported(CMHardwareManager.FEATURE_TOUCH_HOVERING)) { + return; + } + boolean touchHovering = CMSettings.Secure.getInt(mContext.getContentResolver(), + CMSettings.Secure.FEATURE_TOUCH_HOVERING, 0) == 1; + mCMHardware.set(CMHardwareManager.FEATURE_TOUCH_HOVERING, + touchHovering); + } + public void updateKeyboardFromSettingsLocked() { mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled(); if (mSwitchingDialog != null @@ -3633,9 +3680,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub imi = mMethodMap.get(mCurMethodId); } } - final boolean hasInputMethod = isIMEVisible && imi != null && mCurrentSubtype != null; - boolean enabled = hasInputMethod; - if (enabled) { + if (shouldShowImeSwitcherLocked(isIMEVisible ? 1 : 0)) { publishImeSelectorCustomTile(imi); } else { unpublishImeSelectorCustomTile(); diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index bb0615d..274adf8 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -61,6 +61,8 @@ import java.util.List; import java.util.Timer; import java.util.TimerTask; +import cyanogenmod.providers.CMSettings; + /** * Keeps the lock pattern/password data and related settings for each user. * Used by LockPatternUtils. Needs to be a service because Settings app also needs @@ -356,6 +358,10 @@ public class LockSettingsService extends ILockSettings.Stub { } } + if (LockPatternUtils.LEGACY_LOCK_PATTERN_ENABLED.equals(key)) { + key = Settings.Secure.LOCK_PATTERN_ENABLED; + } + return mStorage.readKeyValue(key, defaultValue, userId); } @@ -810,6 +816,7 @@ public class LockSettingsService extends ILockSettings.Stub { Secure.LOCK_BIOMETRIC_WEAK_FLAGS, Secure.LOCK_PATTERN_VISIBLE, Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, + CMSettings.Secure.LOCK_PASS_TO_SECURITY_VIEW, Secure.LOCK_PATTERN_SIZE, Secure.LOCK_DOTS_VISIBLE, Secure.LOCK_SHOW_ERROR_PATH, diff --git a/services/core/java/com/android/server/ThemeService.java b/services/core/java/com/android/server/ThemeService.java deleted file mode 100644 index 96d1c5d..0000000 --- a/services/core/java/com/android/server/ThemeService.java +++ /dev/null @@ -1,1277 +0,0 @@ -/* - * Copyright (C) 2014 The CyanogenMod 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.Manifest; -import android.app.ActivityManager; -import android.app.ActivityManagerNative; -import android.app.IActivityManager; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.WallpaperManager; -import android.content.BroadcastReceiver; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; -import android.content.pm.ResolveInfo; -import android.content.pm.ThemeUtils; -import android.content.res.AssetManager; -import android.content.res.Configuration; -import android.content.res.IThemeProcessingListener; -import android.content.res.ThemeChangeRequest; -import android.content.res.ThemeConfig; -import android.content.res.IThemeChangeListener; -import android.content.res.IThemeService; -import android.graphics.Bitmap; -import android.media.RingtoneManager; -import android.os.Binder; -import android.os.Environment; -import android.os.FileUtils; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.os.Process; -import android.os.RemoteCallbackList; -import android.os.RemoteException; -import android.os.SystemProperties; -import android.os.UserHandle; -import android.provider.Settings; -import android.provider.Settings.SettingNotFoundException; -import android.provider.ThemesContract; -import android.provider.ThemesContract.MixnMatchColumns; -import android.provider.ThemesContract.ThemesColumns; -import android.text.TextUtils; -import android.util.Log; - -import com.android.internal.R; -import com.android.internal.util.cm.ImageUtils; -import cyanogenmod.providers.CMSettings; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -import static android.content.pm.ThemeUtils.SYSTEM_THEME_PATH; -import static android.content.pm.ThemeUtils.THEME_BOOTANIMATION_PATH; -import static android.content.res.ThemeConfig.SYSTEM_DEFAULT; - -import java.util.List; - -/** - * {@hide} - */ -public class ThemeService extends IThemeService.Stub { - private static final String TAG = ThemeService.class.getName(); - - private static final boolean DEBUG = false; - - private static final String GOOGLE_SETUPWIZARD_PACKAGE = "com.google.android.setupwizard"; - private static final String CM_SETUPWIZARD_PACKAGE = "com.cyanogenmod.setupwizard"; - private static final String MANAGED_PROVISIONING_PACKAGE = "com.android.managedprovisioning"; - - private static final long MAX_ICON_CACHE_SIZE = 33554432L; // 32MB - private static final long PURGED_ICON_CACHE_SIZE = 25165824L; // 24 MB - - // Defines a min and max compatible api level for themes on this system. - private static final int MIN_COMPATIBLE_VERSION = 21; - - private HandlerThread mWorker; - private ThemeWorkerHandler mHandler; - private ResourceProcessingHandler mResourceProcessingHandler; - private Context mContext; - private PackageManager mPM; - private int mProgress; - private boolean mWallpaperChangedByUs = false; - private long mIconCacheSize = 0L; - private int mCurrentUserId = UserHandle.USER_OWNER; - - private boolean mIsThemeApplying = false; - - private final RemoteCallbackList<IThemeChangeListener> mClients = - new RemoteCallbackList<IThemeChangeListener>(); - - private final RemoteCallbackList<IThemeProcessingListener> mProcessingListeners = - new RemoteCallbackList<IThemeProcessingListener>(); - - final private ArrayList<String> mThemesToProcessQueue = new ArrayList<String>(0); - - private class ThemeWorkerHandler extends Handler { - private static final int MESSAGE_CHANGE_THEME = 1; - private static final int MESSAGE_APPLY_DEFAULT_THEME = 2; - private static final int MESSAGE_REBUILD_RESOURCE_CACHE = 3; - - public ThemeWorkerHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_CHANGE_THEME: - final ThemeChangeRequest request = (ThemeChangeRequest) msg.obj; - doApplyTheme(request, msg.arg1 == 1); - break; - case MESSAGE_APPLY_DEFAULT_THEME: - doApplyDefaultTheme(); - break; - case MESSAGE_REBUILD_RESOURCE_CACHE: - doRebuildResourceCache(); - break; - default: - Log.w(TAG, "Unknown message " + msg.what); - break; - } - } - } - - private class ResourceProcessingHandler extends Handler { - private static final int MESSAGE_QUEUE_THEME_FOR_PROCESSING = 3; - private static final int MESSAGE_DEQUEUE_AND_PROCESS_THEME = 4; - - public ResourceProcessingHandler(Looper looper) { - super(looper); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MESSAGE_QUEUE_THEME_FOR_PROCESSING: - String pkgName = (String) msg.obj; - synchronized (mThemesToProcessQueue) { - if (!mThemesToProcessQueue.contains(pkgName)) { - if (DEBUG) Log.d(TAG, "Adding " + pkgName + " for processing"); - mThemesToProcessQueue.add(pkgName); - if (mThemesToProcessQueue.size() == 1) { - this.sendEmptyMessage(MESSAGE_DEQUEUE_AND_PROCESS_THEME); - } - } - } - break; - case MESSAGE_DEQUEUE_AND_PROCESS_THEME: - synchronized (mThemesToProcessQueue) { - pkgName = mThemesToProcessQueue.get(0); - } - if (pkgName != null) { - if (DEBUG) Log.d(TAG, "Processing " + pkgName); - String name; - try { - PackageInfo pi = mPM.getPackageInfo(pkgName, 0); - name = getThemeName(pi); - } catch (PackageManager.NameNotFoundException e) { - name = null; - } - - int result = mPM.processThemeResources(pkgName); - if (result < 0) { - postFailedThemeInstallNotification(name != null ? name : pkgName); - } - sendThemeResourcesCachedBroadcast(pkgName, result); - - synchronized (mThemesToProcessQueue) { - mThemesToProcessQueue.remove(0); - if (mThemesToProcessQueue.size() > 0 && - !hasMessages(MESSAGE_DEQUEUE_AND_PROCESS_THEME)) { - this.sendEmptyMessage(MESSAGE_DEQUEUE_AND_PROCESS_THEME); - } - } - postFinishedProcessing(pkgName); - } - break; - default: - Log.w(TAG, "Unknown message " + msg.what); - break; - } - } - } - - public ThemeService(Context context) { - super(); - mContext = context; - mWorker = new HandlerThread("ThemeServiceWorker", Process.THREAD_PRIORITY_BACKGROUND); - mWorker.start(); - mHandler = new ThemeWorkerHandler(mWorker.getLooper()); - Log.i(TAG, "Spawned worker thread"); - - HandlerThread processingThread = new HandlerThread("ResourceProcessingThread", - Process.THREAD_PRIORITY_BACKGROUND); - processingThread.start(); - mResourceProcessingHandler = - new ResourceProcessingHandler(processingThread.getLooper()); - - // create the theme directory if it does not exist - ThemeUtils.createThemeDirIfNotExists(); - ThemeUtils.createFontDirIfNotExists(); - ThemeUtils.createAlarmDirIfNotExists(); - ThemeUtils.createNotificationDirIfNotExists(); - ThemeUtils.createRingtoneDirIfNotExists(); - ThemeUtils.createIconCacheDirIfNotExists(); - } - - public void systemRunning() { - // listen for wallpaper changes - IntentFilter filter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED); - mContext.registerReceiver(mWallpaperChangeReceiver, filter); - - filter = new IntentFilter(Intent.ACTION_USER_SWITCHED); - mContext.registerReceiver(mUserChangeReceiver, filter); - - mPM = mContext.getPackageManager(); - - processInstalledThemes(); - - if (!isThemeApiUpToDate()) { - Log.d(TAG, "The system has been upgraded to a theme new api, " + - "checking if currently set theme is compatible"); - removeObsoleteThemeOverlayIfExists(); - updateThemeApi(); - } - } - - private void removeObsoleteThemeOverlayIfExists() { - // Get the current overlay theme so we can see it it's overlay should be unapplied - final IActivityManager am = ActivityManagerNative.getDefault(); - ThemeConfig config = null; - try { - if (am != null) { - config = am.getConfiguration().themeConfig; - } else { - Log.e(TAG, "ActivityManager getDefault() " + - "returned null, cannot remove obsolete theme"); - } - } catch(RemoteException e) { - Log.e(TAG, "Failed to get the theme config ", e); - } - if (config == null) return; // No need to unapply a theme if one isn't set - - // Populate the currentTheme map for the components we care about, we'll look - // at the compatibility of each pkg below. - HashMap<String, String> currentThemeMap = new HashMap<String, String>(); - currentThemeMap.put(ThemesColumns.MODIFIES_STATUS_BAR, config.getOverlayForStatusBar()); - currentThemeMap.put(ThemesColumns.MODIFIES_NAVIGATION_BAR, - config.getOverlayForNavBar()); - currentThemeMap.put(ThemesColumns.MODIFIES_OVERLAYS, config.getOverlayPkgName()); - - // Look at each component's theme (that we care about at least) and check compatibility - // of the pkg with the system. If it is not compatible then we will add it to a theme - // change request. - Map<String, String> defaults = ThemeUtils.getDefaultComponents(mContext); - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - for(Map.Entry<String, String> entry : currentThemeMap.entrySet()) { - String component = entry.getKey(); - String pkgName = entry.getValue(); - String defaultPkg = defaults.get(component); - - // Check that the default overlay theme is not currently set - if (defaultPkg.equals(pkgName)) { - Log.d(TAG, "Current overlay theme is same as default. " + - "Not doing anything for " + component); - continue; - } - - // No need to unapply a system theme since it is always compatible - if (ThemeConfig.SYSTEM_DEFAULT.equals(pkgName)) { - Log.d(TAG, "Current overlay theme for " - + component + " was system. no need to unapply"); - continue; - } - - if (!isThemeCompatibleWithUpgradedApi(pkgName)) { - Log.d(TAG, pkgName + "is incompatible with latest theme api for component " + - component + ", Applying " + defaultPkg); - builder.setComponent(component, pkgName); - } - } - - // Now actually unapply the incompatible themes - ThemeChangeRequest request = builder.build(); - if (!request.getThemeComponentsMap().isEmpty()) { - try { - requestThemeChange(request, true); - } catch(RemoteException e) { - // This cannot happen - } - } else { - Log.d(TAG, "Current theme is compatible with the system. Not unapplying anything"); - } - } - - private boolean isThemeCompatibleWithUpgradedApi(String pkgName) { - // Note this function does not cover the case of a downgrade. That case is out of scope and - // would require predicting whether the future API levels will be compatible or not. - boolean compatible = false; - try { - PackageInfo pi = mPM.getPackageInfo(pkgName, 0); - Log.d(TAG, "Comparing theme target: " + pi.applicationInfo.targetSdkVersion + - "to " + android.os.Build.VERSION.SDK_INT); - compatible = pi.applicationInfo.targetSdkVersion >= MIN_COMPATIBLE_VERSION; - } catch (NameNotFoundException e) { - Log.e(TAG, "Unable to get package info for " + pkgName, e); - } - return compatible; - } - - private boolean isThemeApiUpToDate() { - // We can't be 100% sure its an upgrade. If the field is undefined it - // could have been a factory reset. - final ContentResolver resolver = mContext.getContentResolver(); - int recordedApiLevel = android.os.Build.VERSION.SDK_INT; - try { - recordedApiLevel = CMSettings.Secure.getInt(resolver, - CMSettings.Secure.THEME_PREV_BOOT_API_LEVEL); - } catch (CMSettings.CMSettingNotFoundException e) { - recordedApiLevel = -1; - Log.d(TAG, "Previous api level not found. First time booting?"); - } - Log.d(TAG, "Prev api level was: " + recordedApiLevel - + ", api is now: " + android.os.Build.VERSION.SDK_INT); - - return recordedApiLevel == android.os.Build.VERSION.SDK_INT; - } - - private void updateThemeApi() { - final ContentResolver resolver = mContext.getContentResolver(); - boolean success = CMSettings.Secure.putInt(resolver, - CMSettings.Secure.THEME_PREV_BOOT_API_LEVEL, android.os.Build.VERSION.SDK_INT); - if (!success) { - Log.e(TAG, "Unable to store latest API level to secure settings"); - } - } - - private void doApplyTheme(ThemeChangeRequest request, boolean removePerAppTheme) { - synchronized(this) { - mProgress = 0; - } - - if (request == null || request.getNumChangesRequested() == 0) { - postFinish(true, request, 0); - return; - } - mIsThemeApplying = true; - long updateTime = System.currentTimeMillis(); - - incrementProgress(5); - - // TODO: provide progress updates that reflect the time needed for each component - final int progressIncrement = 75 / request.getNumChangesRequested(); - - if (request.getIconsThemePackageName() != null) { - updateIcons(request.getIconsThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getWallpaperThemePackageName() != null) { - if (updateWallpaper(request.getWallpaperThemePackageName(), - request.getWallpaperId())) { - mWallpaperChangedByUs = true; - } - incrementProgress(progressIncrement); - } - - if (request.getLockWallpaperThemePackageName() != null) { - updateLockscreen(request.getLockWallpaperThemePackageName()); - incrementProgress(progressIncrement); - } - - Environment.setUserRequired(false); - if (request.getNotificationThemePackageName() != null) { - updateNotifications(request.getNotificationThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getAlarmThemePackageName() != null) { - updateAlarms(request.getAlarmThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getRingtoneThemePackageName() != null) { - updateRingtones(request.getRingtoneThemePackageName()); - incrementProgress(progressIncrement); - } - Environment.setUserRequired(true); - - if (request.getBootanimationThemePackageName() != null) { - updateBootAnim(request.getBootanimationThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getFontThemePackageName() != null) { - updateFonts(request.getFontThemePackageName()); - incrementProgress(progressIncrement); - } - - if (request.getLiveLockScreenThemePackageName() != null) { - updateLiveLockScreen(request.getLiveLockScreenThemePackageName()); - incrementProgress(progressIncrement); - } - - try { - updateProvider(request, updateTime); - } catch(IllegalArgumentException e) { - // Safeguard against provider not being ready yet. - Log.e(TAG, "Not updating the theme provider since it is unavailable"); - } - - if (shouldUpdateConfiguration(request)) { - updateConfiguration(request, removePerAppTheme); - } - - killLaunchers(request); - - postFinish(true, request, updateTime); - mIsThemeApplying = false; - } - - private void doApplyDefaultTheme() { - final ContentResolver resolver = mContext.getContentResolver(); - final String defaultThemePkg = CMSettings.Secure.getString(resolver, - CMSettings.Secure.DEFAULT_THEME_PACKAGE); - if (!TextUtils.isEmpty(defaultThemePkg)) { - String defaultThemeComponents = CMSettings.Secure.getString(resolver, - CMSettings.Secure.DEFAULT_THEME_COMPONENTS); - List<String> components; - if (TextUtils.isEmpty(defaultThemeComponents)) { - components = ThemeUtils.getAllComponents(); - } else { - components = new ArrayList<String>( - Arrays.asList(defaultThemeComponents.split("\\|"))); - } - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - for (String component : components) { - builder.setComponent(component, defaultThemePkg); - } - try { - requestThemeChange(builder.build(), true); - } catch (RemoteException e) { - Log.w(TAG, "Unable to set default theme", e); - } - } - } - - private void doRebuildResourceCache() { - FileUtils.deleteContents(new File(ThemeUtils.RESOURCE_CACHE_DIR)); - processInstalledThemes(); - } - - private void updateProvider(ThemeChangeRequest request, long updateTime) { - ContentValues values = new ContentValues(); - values.put(MixnMatchColumns.COL_UPDATE_TIME, updateTime); - Map<String, String> componentMap = request.getThemeComponentsMap(); - for (String component : componentMap.keySet()) { - values.put(ThemesContract.MixnMatchColumns.COL_VALUE, componentMap.get(component)); - String where = ThemesContract.MixnMatchColumns.COL_KEY + "=?"; - String[] selectionArgs = { MixnMatchColumns.componentToMixNMatchKey(component) }; - if (selectionArgs[0] == null) { - continue; // No equivalence between mixnmatch and theme - } - - // Add component ID for multiwallpaper - if (ThemesColumns.MODIFIES_LAUNCHER.equals(component)) { - values.put(MixnMatchColumns.COL_COMPONENT_ID, request.getWallpaperId()); - } - - mContext.getContentResolver().update(MixnMatchColumns.CONTENT_URI, values, where, - selectionArgs); - } - } - - private boolean updateIcons(String pkgName) { - ThemeUtils.clearIconCache(); - try { - if (pkgName.equals(SYSTEM_DEFAULT)) { - mPM.updateIconMaps(null); - } else { - mPM.updateIconMaps(pkgName); - } - } catch (Exception e) { - Log.w(TAG, "Changing icons failed", e); - return false; - } - return true; - } - - private boolean updateFonts(String pkgName) { - //Clear the font dir - FileUtils.deleteContents(new File(ThemeUtils.SYSTEM_THEME_FONT_PATH)); - - if (!pkgName.equals(SYSTEM_DEFAULT)) { - //Get Font Assets - Context themeCtx; - String[] assetList; - try { - themeCtx = mContext.createPackageContext(pkgName, Context.CONTEXT_IGNORE_SECURITY); - AssetManager assetManager = themeCtx.getAssets(); - assetList = assetManager.list("fonts"); - } catch (Exception e) { - Log.e(TAG, "There was an error getting assets for pkg " + pkgName, e); - return false; - } - if (assetList == null || assetList.length == 0) { - Log.e(TAG, "Could not find any font assets"); - return false; - } - - //Copy font assets to font dir - for(String asset : assetList) { - InputStream is = null; - OutputStream os = null; - try { - is = ThemeUtils.getInputStreamFromAsset(themeCtx, - "file:///android_asset/fonts/" + asset); - File outFile = new File(ThemeUtils.SYSTEM_THEME_FONT_PATH, asset); - FileUtils.copyToFile(is, outFile); - FileUtils.setPermissions(outFile, - FileUtils.S_IRWXU|FileUtils.S_IRGRP|FileUtils.S_IRWXO, -1, -1); - } catch (Exception e) { - Log.e(TAG, "There was an error installing the new fonts for pkg " + pkgName, e); - return false; - } finally { - ThemeUtils.closeQuietly(is); - ThemeUtils.closeQuietly(os); - } - } - } - - //Notify zygote that themes need a refresh - SystemProperties.set("sys.refresh_theme", "1"); - return true; - } - - private boolean updateBootAnim(String pkgName) { - if (SYSTEM_DEFAULT.equals(pkgName)) { - clearBootAnimation(); - return true; - } - - try { - final ApplicationInfo ai = mPM.getApplicationInfo(pkgName, 0); - applyBootAnimation(ai.sourceDir); - } catch (PackageManager.NameNotFoundException e) { - Log.w(TAG, "Changing boot animation failed", e); - return false; - } - return true; - } - - private boolean updateAlarms(String pkgName) { - return updateAudible(ThemeUtils.SYSTEM_THEME_ALARM_PATH, "alarms", - RingtoneManager.TYPE_ALARM, pkgName); - } - - private boolean updateNotifications(String pkgName) { - return updateAudible(ThemeUtils.SYSTEM_THEME_NOTIFICATION_PATH, "notifications", - RingtoneManager.TYPE_NOTIFICATION, pkgName); - } - - private boolean updateRingtones(String pkgName) { - return updateAudible(ThemeUtils.SYSTEM_THEME_RINGTONE_PATH, "ringtones", - RingtoneManager.TYPE_RINGTONE, pkgName); - } - - private boolean updateAudible(String dirPath, String assetPath, int type, String pkgName) { - //Clear the dir - ThemeUtils.clearAudibles(mContext, dirPath); - if (pkgName.equals(SYSTEM_DEFAULT)) { - if (!ThemeUtils.setDefaultAudible(mContext, type)) { - Log.e(TAG, "There was an error installing the default audio file"); - return false; - } - return true; - } - - PackageInfo pi = null; - try { - pi = mPM.getPackageInfo(pkgName, 0); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Unable to update audible " + dirPath, e); - return false; - } - - //Get theme Assets - Context themeCtx; - String[] assetList; - try { - themeCtx = mContext.createPackageContext(pkgName, Context.CONTEXT_IGNORE_SECURITY); - AssetManager assetManager = themeCtx.getAssets(); - assetList = assetManager.list(assetPath); - } catch (Exception e) { - Log.e(TAG, "There was an error getting assets for pkg " + pkgName, e); - return false; - } - if (assetList == null || assetList.length == 0) { - Log.e(TAG, "Could not find any audio assets"); - return false; - } - - // TODO: right now we just load the first file but this will need to be changed - // in the future if multiple audio files are supported. - final String asset = assetList[0]; - if (!ThemeUtils.isValidAudible(asset)) return false; - - InputStream is = null; - OutputStream os = null; - try { - is = ThemeUtils.getInputStreamFromAsset(themeCtx, "file:///android_asset/" - + assetPath + File.separator + asset); - File outFile = new File(dirPath, asset); - FileUtils.copyToFile(is, outFile); - FileUtils.setPermissions(outFile, - FileUtils.S_IRWXU|FileUtils.S_IRGRP|FileUtils.S_IRWXO,-1, -1); - ThemeUtils.setAudible(mContext, outFile, type, pi.themeInfo.name); - } catch (Exception e) { - Log.e(TAG, "There was an error installing the new audio file for pkg " + pkgName, e); - return false; - } finally { - ThemeUtils.closeQuietly(is); - ThemeUtils.closeQuietly(os); - } - return true; - } - - private boolean updateLockscreen(String pkgName) { - boolean success; - success = setCustomLockScreenWallpaper(pkgName); - - if (success) { - mContext.sendBroadcastAsUser(new Intent(Intent.ACTION_KEYGUARD_WALLPAPER_CHANGED), - UserHandle.ALL); - } - return success; - } - - private boolean setCustomLockScreenWallpaper(String pkgName) { - WallpaperManager wm = WallpaperManager.getInstance(mContext); - try { - if (SYSTEM_DEFAULT.equals(pkgName) || TextUtils.isEmpty(pkgName)) { - wm.clearKeyguardWallpaper(); - } else { - InputStream in = ImageUtils.getCroppedKeyguardStream(pkgName, mContext); - if (in != null) { - wm.setKeyguardStream(in); - ThemeUtils.closeQuietly(in); - } - } - } catch (Exception e) { - Log.e(TAG, "There was an error setting lockscreen wp for pkg " + pkgName, e); - return false; - } - return true; - } - - private boolean updateWallpaper(String pkgName, long id) { - WallpaperManager wm = WallpaperManager.getInstance(mContext); - if (SYSTEM_DEFAULT.equals(pkgName)) { - try { - wm.clear(); - } catch (IOException e) { - return false; - } - } else if (TextUtils.isEmpty(pkgName)) { - try { - wm.clear(false); - } catch (IOException e) { - return false; - } - } else { - InputStream in = null; - try { - in = ImageUtils.getCroppedWallpaperStream(pkgName, id, mContext); - if (in != null) - wm.setStream(in); - } catch (Exception e) { - return false; - } finally { - ThemeUtils.closeQuietly(in); - } - } - return true; - } - - private boolean updateLiveLockScreen(String pkgName) { - // TODO: do something meaningful here once ready - return true; - } - - private boolean updateConfiguration(ThemeChangeRequest request, - boolean removePerAppThemes) { - final IActivityManager am = ActivityManagerNative.getDefault(); - if (am != null) { - final long token = Binder.clearCallingIdentity(); - try { - Configuration config = am.getConfiguration(); - ThemeConfig.Builder themeBuilder = createBuilderFrom(config, request, null, - removePerAppThemes); - ThemeConfig newConfig = themeBuilder.build(); - - config.themeConfig = newConfig; - am.updateConfiguration(config); - } catch (RemoteException e) { - return false; - } finally { - Binder.restoreCallingIdentity(token); - } - } - return true; - } - - private boolean updateConfiguration(ThemeConfig themeConfig) { - final IActivityManager am = ActivityManagerNative.getDefault(); - if (am != null) { - final long token = Binder.clearCallingIdentity(); - try { - Configuration config = am.getConfiguration(); - - config.themeConfig = themeConfig; - am.updateConfiguration(config); - } catch (RemoteException e) { - return false; - } finally { - Binder.restoreCallingIdentity(token); - } - } - return true; - } - - private boolean shouldUpdateConfiguration(ThemeChangeRequest request) { - return request.getOverlayThemePackageName() != null || - request.getFontThemePackageName() != null || - request.getIconsThemePackageName() != null || - request.getStatusBarThemePackageName() != null || - request.getNavBarThemePackageName() != null || - request.getPerAppOverlays().size() > 0; - } - - private static ThemeConfig.Builder createBuilderFrom(Configuration config, - ThemeChangeRequest request, String pkgName, boolean removePerAppThemes) { - ThemeConfig.Builder builder = new ThemeConfig.Builder(config.themeConfig); - - if (removePerAppThemes) removePerAppThemesFromConfig(builder, config.themeConfig); - - if (request.getIconsThemePackageName() != null) { - builder.defaultIcon(pkgName == null ? request.getIconsThemePackageName() : pkgName); - } - - if (request.getOverlayThemePackageName() != null) { - builder.defaultOverlay(pkgName == null ? - request.getOverlayThemePackageName() : pkgName); - } - - if (request.getFontThemePackageName() != null) { - builder.defaultFont(pkgName == null ? request.getFontThemePackageName() : pkgName); - } - - if (request.getStatusBarThemePackageName() != null) { - builder.overlay(ThemeConfig.SYSTEMUI_STATUS_BAR_PKG, pkgName == null ? - request.getStatusBarThemePackageName() : pkgName); - } - - if (request.getNavBarThemePackageName() != null) { - builder.overlay(ThemeConfig.SYSTEMUI_NAVBAR_PKG, pkgName == null ? - request.getNavBarThemePackageName() : pkgName); - } - - // check for any per app overlays being applied - Map<String, String> appOverlays = request.getPerAppOverlays(); - for (String appPkgName : appOverlays.keySet()) { - if (appPkgName != null) { - builder.overlay(appPkgName, appOverlays.get(appPkgName)); - } - } - - builder.setLastThemeChangeRequestType(request.getReqeustType()); - - return builder; - } - - private static void removePerAppThemesFromConfig(ThemeConfig.Builder builder, - ThemeConfig themeConfig) { - if (themeConfig != null) { - Map<String, ThemeConfig.AppTheme> themes = themeConfig.getAppThemes(); - for (String appPkgName : themes.keySet()) { - if (ThemeUtils.isPerAppThemeComponent(appPkgName)) { - builder.overlay(appPkgName, null); - } - } - } - } - - // Kill the current Home process, they tend to be evil and cache - // drawable references in all apps - private void killLaunchers(ThemeChangeRequest request) { - if (request.getOverlayThemePackageName() == null - && request.getIconsThemePackageName() == null) { - return; - } - - final ActivityManager am = - (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); - - Intent homeIntent = new Intent(); - homeIntent.setAction(Intent.ACTION_MAIN); - homeIntent.addCategory(Intent.CATEGORY_HOME); - - List<ResolveInfo> infos = mPM.queryIntentActivities(homeIntent, 0); - List<ResolveInfo> themeChangeInfos = mPM.queryBroadcastReceivers( - new Intent(ThemeUtils.ACTION_THEME_CHANGED), 0); - for(ResolveInfo info : infos) { - if (info.activityInfo != null && info.activityInfo.applicationInfo != null && - !isSetupActivity(info) && !handlesThemeChanges( - info.activityInfo.applicationInfo.packageName, themeChangeInfos)) { - String pkgToStop = info.activityInfo.applicationInfo.packageName; - Log.d(TAG, "Force stopping " + pkgToStop + " for theme change"); - try { - am.forceStopPackage(pkgToStop); - } catch(Exception e) { - Log.e(TAG, "Unable to force stop package, did you forget platform signature?", - e); - } - } - } - } - - private boolean isSetupActivity(ResolveInfo info) { - return GOOGLE_SETUPWIZARD_PACKAGE.equals(info.activityInfo.packageName) || - MANAGED_PROVISIONING_PACKAGE.equals(info.activityInfo.packageName) || - CM_SETUPWIZARD_PACKAGE.equals(info.activityInfo.packageName); - } - - private boolean handlesThemeChanges(String pkgName, List<ResolveInfo> infos) { - if (infos != null && infos.size() > 0) { - for (ResolveInfo info : infos) { - if (info.activityInfo.applicationInfo.packageName.equals(pkgName)) { - return true; - } - } - } - return false; - } - - private void postProgress() { - int N = mClients.beginBroadcast(); - for(int i=0; i < N; i++) { - IThemeChangeListener listener = mClients.getBroadcastItem(0); - try { - listener.onProgress(mProgress); - } catch(RemoteException e) { - Log.w(TAG, "Unable to post progress to client listener", e); - } - } - mClients.finishBroadcast(); - } - - private void postFinish(boolean isSuccess, ThemeChangeRequest request, long updateTime) { - synchronized(this) { - mProgress = 0; - } - - int N = mClients.beginBroadcast(); - for(int i=0; i < N; i++) { - IThemeChangeListener listener = mClients.getBroadcastItem(0); - try { - listener.onFinish(isSuccess); - } catch(RemoteException e) { - Log.w(TAG, "Unable to post progress to client listener", e); - } - } - mClients.finishBroadcast(); - - // if successful, broadcast that the theme changed - if (isSuccess) { - broadcastThemeChange(request, updateTime); - } - } - - private void postFinishedProcessing(String pkgName) { - int N = mProcessingListeners.beginBroadcast(); - for(int i=0; i < N; i++) { - IThemeProcessingListener listener = mProcessingListeners.getBroadcastItem(0); - try { - listener.onFinishedProcessing(pkgName); - } catch(RemoteException e) { - Log.w(TAG, "Unable to post progress to listener", e); - } - } - mProcessingListeners.finishBroadcast(); - } - - private void broadcastThemeChange(ThemeChangeRequest request, long updateTime) { - Map<String, String> componentMap = request.getThemeComponentsMap(); - if (componentMap == null || componentMap.size() == 0) return; - - final Intent intent = new Intent(ThemeUtils.ACTION_THEME_CHANGED); - ArrayList componentsArrayList = new ArrayList(componentMap.keySet()); - intent.putStringArrayListExtra(ThemeUtils.EXTRA_COMPONENTS, componentsArrayList); - intent.putExtra(ThemeUtils.EXTRA_REQUEST_TYPE, request.getReqeustType().ordinal()); - intent.putExtra(ThemeUtils.EXTRA_UPDATE_TIME, updateTime); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - private void incrementProgress(int increment) { - synchronized(this) { - mProgress += increment; - if (mProgress > 100) mProgress = 100; - } - postProgress(); - } - - @Override - public void requestThemeChangeUpdates(IThemeChangeListener listener) throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mClients.register(listener); - } - - @Override - public void removeUpdates(IThemeChangeListener listener) throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mClients.unregister(listener); - } - - @Override - public void requestThemeChange(ThemeChangeRequest request, boolean removePerAppThemes) - throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - Message msg; - - /** - * Since the ThemeService handles compiling theme resource we need to make sure that any - * of the components we are trying to apply are either already processed or put to the - * front of the queue and handled before the theme change takes place. - * - * TODO: create a callback that can be sent to any ThemeChangeListeners to notify them that - * the theme will be applied once the processing is done. - */ - synchronized (mThemesToProcessQueue) { - Map<String, String> componentMap = request.getThemeComponentsMap(); - for (Object key : componentMap.keySet()) { - if (ThemesColumns.MODIFIES_OVERLAYS.equals(key) || - ThemesColumns.MODIFIES_NAVIGATION_BAR.equals(key) || - ThemesColumns.MODIFIES_STATUS_BAR.equals(key) || - ThemesColumns.MODIFIES_ICONS.equals(key)) { - String pkgName = (String) componentMap.get(key); - if (mThemesToProcessQueue.indexOf(pkgName) > 0) { - mThemesToProcessQueue.remove(pkgName); - mThemesToProcessQueue.add(0, pkgName); - // We want to make sure these resources are taken care of first so - // send the dequeue message and place it in the front of the queue - msg = mResourceProcessingHandler.obtainMessage( - ResourceProcessingHandler.MESSAGE_DEQUEUE_AND_PROCESS_THEME); - mResourceProcessingHandler.sendMessageAtFrontOfQueue(msg); - } - } - } - } - msg = Message.obtain(); - msg.what = ThemeWorkerHandler.MESSAGE_CHANGE_THEME; - msg.obj = request; - msg.arg1 = removePerAppThemes ? 1 : 0; - mHandler.sendMessage(msg); - } - - @Override - public void applyDefaultTheme() { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - Message msg = Message.obtain(); - msg.what = ThemeWorkerHandler.MESSAGE_APPLY_DEFAULT_THEME; - mHandler.sendMessage(msg); - } - - @Override - public boolean isThemeApplying() throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_THEME_MANAGER, null); - return mIsThemeApplying; - } - - @Override - public int getProgress() throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_THEME_MANAGER, null); - synchronized(this) { - return mProgress; - } - } - - @Override - public boolean cacheComposedIcon(Bitmap icon, String fileName) throws RemoteException { - final long token = Binder.clearCallingIdentity(); - boolean success; - FileOutputStream os; - final File cacheDir = new File(ThemeUtils.SYSTEM_THEME_ICON_CACHE_DIR); - if (cacheDir.listFiles().length == 0) { - mIconCacheSize = 0; - } - try { - File outFile = new File(cacheDir, fileName); - os = new FileOutputStream(outFile); - icon.compress(Bitmap.CompressFormat.PNG, 90, os); - os.close(); - FileUtils.setPermissions(outFile, - FileUtils.S_IRWXU | FileUtils.S_IRWXG | FileUtils.S_IROTH, - -1, -1); - mIconCacheSize += outFile.length(); - if (mIconCacheSize > MAX_ICON_CACHE_SIZE) { - purgeIconCache(); - } - success = true; - } catch (Exception e) { - success = false; - Log.w(TAG, "Unable to cache icon " + fileName, e); - } - Binder.restoreCallingIdentity(token); - return success; - } - - @Override - public boolean processThemeResources(String themePkgName) throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - try { - mPM.getPackageInfo(themePkgName, 0); - } catch (PackageManager.NameNotFoundException e) { - // Package doesn't exist so nothing to process - return false; - } - // Obtain a message and send it to the handler to process this theme - Message msg = mResourceProcessingHandler.obtainMessage( - ResourceProcessingHandler.MESSAGE_QUEUE_THEME_FOR_PROCESSING, 0, 0, themePkgName); - mResourceProcessingHandler.sendMessage(msg); - return true; - } - - @Override - public boolean isThemeBeingProcessed(String themePkgName) throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - synchronized (mThemesToProcessQueue) { - return mThemesToProcessQueue.contains(themePkgName); - } - } - - @Override - public void registerThemeProcessingListener(IThemeProcessingListener listener) - throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mProcessingListeners.register(listener); - } - - @Override - public void unregisterThemeProcessingListener(IThemeProcessingListener listener) - throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mProcessingListeners.unregister(listener); - } - - @Override - public void rebuildResourceCache() throws RemoteException { - mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - mHandler.sendEmptyMessage(ThemeWorkerHandler.MESSAGE_REBUILD_RESOURCE_CACHE); - } - - private void purgeIconCache() { - Log.d(TAG, "Purging icon cahe of size " + mIconCacheSize); - File cacheDir = new File(ThemeUtils.SYSTEM_THEME_ICON_CACHE_DIR); - File[] files = cacheDir.listFiles(); - Arrays.sort(files, mOldestFilesFirstComparator); - for (File f : files) { - if (!f.isDirectory()) { - final long size = f.length(); - if(f.delete()) mIconCacheSize -= size; - } - if (mIconCacheSize <= PURGED_ICON_CACHE_SIZE) break; - } - } - - private boolean applyBootAnimation(String themePath) { - boolean success = false; - try { - ZipFile zip = new ZipFile(new File(themePath)); - ZipEntry ze = zip.getEntry(THEME_BOOTANIMATION_PATH); - if (ze != null) { - clearBootAnimation(); - BufferedInputStream is = new BufferedInputStream(zip.getInputStream(ze)); - final String bootAnimationPath = SYSTEM_THEME_PATH + File.separator - + "bootanimation.zip"; - ThemeUtils.copyAndScaleBootAnimation(mContext, is, bootAnimationPath); - FileUtils.setPermissions(bootAnimationPath, - FileUtils.S_IRWXU|FileUtils.S_IRGRP|FileUtils.S_IROTH, -1, -1); - } - zip.close(); - success = true; - } catch (Exception e) { - Log.w(TAG, "Unable to load boot animation for " + themePath, e); - } - - return success; - } - - private void clearBootAnimation() { - File anim = new File(SYSTEM_THEME_PATH + File.separator + "bootanimation.zip"); - if (anim.exists()) - anim.delete(); - } - - private BroadcastReceiver mWallpaperChangeReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (!mWallpaperChangedByUs) { - // In case the mixnmatch table has a mods_launcher entry, we'll clear it - ThemeChangeRequest.Builder builder = new ThemeChangeRequest.Builder(); - builder.setWallpaper(""); - updateProvider(builder.build(), System.currentTimeMillis()); - } else { - mWallpaperChangedByUs = false; - } - } - }; - - private BroadcastReceiver mUserChangeReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - int userHandle = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); - if (userHandle >= 0 && userHandle != mCurrentUserId) { - mCurrentUserId = userHandle; - ThemeConfig config = ThemeConfig.getBootThemeForUser(mContext.getContentResolver(), - userHandle); - if (DEBUG) { - Log.d(TAG, - "Changing theme for user " + userHandle + " to " + config.toString()); - } - ThemeChangeRequest request = new ThemeChangeRequest.Builder(config).build(); - try { - requestThemeChange(request, true); - } catch (RemoteException e) { - Log.e(TAG, "Unable to change theme for user change", e); - } - } - } - }; - - private Comparator<File> mOldestFilesFirstComparator = new Comparator<File>() { - @Override - public int compare(File lhs, File rhs) { - return (int) (lhs.lastModified() - rhs.lastModified()); - } - }; - - private void processInstalledThemes() { - final String defaultTheme = getDefaultThemePackageName(mContext); - Message msg; - // Make sure the default theme is the first to get processed! - if (!ThemeConfig.SYSTEM_DEFAULT.equals(defaultTheme)) { - msg = mHandler.obtainMessage( - ResourceProcessingHandler.MESSAGE_QUEUE_THEME_FOR_PROCESSING, - 0, 0, defaultTheme); - mResourceProcessingHandler.sendMessage(msg); - } - // Iterate over all installed packages and queue up the ones that are themes or icon packs - List<PackageInfo> packages = mPM.getInstalledPackages(0); - for (PackageInfo info : packages) { - if (!defaultTheme.equals(info.packageName) && - (info.isThemeApk || info.isLegacyIconPackApk)) { - msg = mHandler.obtainMessage( - ResourceProcessingHandler.MESSAGE_QUEUE_THEME_FOR_PROCESSING, - 0, 0, info.packageName); - mResourceProcessingHandler.sendMessage(msg); - } - } - } - - private void sendThemeResourcesCachedBroadcast(String themePkgName, int resultCode) { - final Intent intent = new Intent(Intent.ACTION_THEME_RESOURCES_CACHED); - intent.putExtra(Intent.EXTRA_THEME_PACKAGE_NAME, themePkgName); - intent.putExtra(Intent.EXTRA_THEME_RESULT, resultCode); - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); - } - - /** - * Posts a notification to let the user know the theme was not installed. - * @param name - */ - private void postFailedThemeInstallNotification(String name) { - NotificationManager nm = - (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE); - Notification notice = new Notification.Builder(mContext) - .setAutoCancel(true) - .setOngoing(false) - .setContentTitle( - mContext.getString(R.string.theme_install_error_title)) - .setContentText(String.format(mContext.getString( - R.string.theme_install_error_message), - name)) - .setSmallIcon(android.R.drawable.stat_notify_error) - .setWhen(System.currentTimeMillis()) - .build(); - nm.notify(name.hashCode(), notice); - } - - private String getThemeName(PackageInfo pi) { - if (pi.themeInfo != null) { - return pi.themeInfo.name; - } else if (pi.isLegacyIconPackApk) { - return pi.applicationInfo.name; - } - - return null; - } - - /** - * Get the default theme package name - * Historically this was done using {@link ThemeUtils#getDefaultThemePackageName(Context)} but - * the setting that is queried in that method uses the AOSP settings provider but the setting - * is now in CMSettings. Since {@link ThemeUtils} is in the core framework we cannot access - * CMSettings. - * @param context - * @return Default theme package name - */ - private static String getDefaultThemePackageName(Context context) { - final String defaultThemePkg = CMSettings.Secure.getString(context.getContentResolver(), - CMSettings.Secure.DEFAULT_THEME_PACKAGE); - if (!TextUtils.isEmpty(defaultThemePkg)) { - PackageManager pm = context.getPackageManager(); - try { - if (pm.getPackageInfo(defaultThemePkg, 0) != null) { - return defaultThemePkg; - } - } catch (PackageManager.NameNotFoundException e) { - // doesn't exist so system will be default - Log.w(TAG, "Default theme " + defaultThemePkg + " not found", e); - } - } - - return SYSTEM_DEFAULT; - } -} diff --git a/services/core/java/com/android/server/ThermalObserver.java b/services/core/java/com/android/server/ThermalObserver.java new file mode 100644 index 0000000..aee28fb --- /dev/null +++ b/services/core/java/com/android/server/ThermalObserver.java @@ -0,0 +1,146 @@ +/* + * 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.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.Binder; +import android.os.Handler; +import android.os.Message; +import android.os.PowerManager; +import android.os.UEventObserver; +import android.os.UserHandle; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +/** + * ThermalObserver for monitoring temperature changes. + */ +public class ThermalObserver extends SystemService { + private static final String TAG = "ThermalObserver"; + + private static final String CALLSTATE_UEVENT_MATCH = + "DEVPATH=/devices/virtual/switch/thermalstate"; + + private static final int MSG_THERMAL_STATE_CHANGED = 0; + + private static final int SWITCH_STATE_NORMAL = 0; + private static final int SWITCH_STATE_WARNING = 1; + private static final int SWITCH_STATE_EXCEEDED = 2; + + private final PowerManager mPowerManager; + private final PowerManager.WakeLock mWakeLock; + + private final Object mLock = new Object(); + private Integer mLastState; + + private final UEventObserver mThermalWarningObserver = new UEventObserver() { + @Override + public void onUEvent(UEventObserver.UEvent event) { + updateLocked(Integer.parseInt(event.get("SWITCH_STATE"))); + } + }; + + private final Handler mHandler = new Handler(true /*async*/) { + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case MSG_THERMAL_STATE_CHANGED: + handleThermalStateChange(msg.arg1); + mWakeLock.release(); + break; + } + } + }; + + public ThermalObserver(Context context) { + super(context); + mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); + + mThermalWarningObserver.startObserving(CALLSTATE_UEVENT_MATCH); + } + + private void updateLocked(int state) { + Message message = new Message(); + message.what = MSG_THERMAL_STATE_CHANGED; + message.arg1 = state; + + mWakeLock.acquire(); + mHandler.sendMessage(message); + } + + private void handleThermalStateChange(int state) { + synchronized (mLock) { + mLastState = state; + Intent intent = new Intent(Intent.ACTION_THERMAL_EVENT); + intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); + + final int thermalState; + + switch (state) { + case SWITCH_STATE_WARNING: + thermalState = Intent.EXTRA_THERMAL_STATE_WARNING; + break; + case SWITCH_STATE_EXCEEDED: + thermalState = Intent.EXTRA_THERMAL_STATE_EXCEEDED; + break; + case SWITCH_STATE_NORMAL: + default: + thermalState = Intent.EXTRA_THERMAL_STATE_NORMAL; + break; + } + + intent.putExtra(Intent.EXTRA_THERMAL_STATE, thermalState); + + getContext().sendBroadcastAsUser(intent, UserHandle.ALL); + } + } + + @Override + public void onStart() { + publishBinderService(TAG, new BinderService()); + } + + private final class BinderService extends Binder { + @Override + protected 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 thermal observer service from from pid=" + + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid()); + return; + } + + final long ident = Binder.clearCallingIdentity(); + try { + synchronized (mLock) { + if (args == null || args.length == 0 || "-a".equals(args[0])) { + pw.println("Current Thermal Observer Service state:"); + pw.println(" last state change: " + + (mLastState != null ? mLastState : "none")); + } + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } +} diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java index c228422..f637c4f 100644 --- a/services/core/java/com/android/server/VibratorService.java +++ b/services/core/java/com/android/server/VibratorService.java @@ -24,6 +24,7 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.database.ContentObserver; import android.hardware.input.InputManager; +import android.net.Uri; import android.os.BatteryStats; import android.os.Handler; import android.os.IVibratorService; @@ -55,6 +56,9 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.ListIterator; +import cyanogenmod.hardware.CMHardwareManager; +import cyanogenmod.providers.CMSettings; + public class VibratorService extends IVibratorService.Stub implements InputManager.InputDeviceListener { private static final String TAG = "VibratorService"; @@ -86,6 +90,10 @@ public class VibratorService extends IVibratorService.Stub private int mCurVibUid = -1; private boolean mLowPowerMode; private SettingsObserver mSettingObserver; + private CMHardwareManager mHardware; + private int mMinVibratorIntensity; + private int mMaxVibratorIntensity; + private int mVibratorIntensity; native static boolean vibratorExists(); native static void vibratorOn(long milliseconds); @@ -241,9 +249,20 @@ public class VibratorService extends IVibratorService.Stub @Override public void onReceive(Context context, Intent intent) { updateInputDeviceVibrators(); + updateVibratorIntensity(); } }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mH); + mHardware = CMHardwareManager.getInstance(mContext); + if (mHardware.isSupported(CMHardwareManager.FEATURE_VIBRATOR)) { + mContext.getContentResolver().registerContentObserver( + CMSettings.Secure.getUriFor(CMSettings.Secure.VIBRATOR_INTENSITY), + true, mSettingObserver, UserHandle.USER_ALL); + mMinVibratorIntensity = mHardware.getVibratorMinIntensity(); + mMaxVibratorIntensity = mHardware.getVibratorMaxIntensity(); + updateVibratorIntensity(); + } + updateInputDeviceVibrators(); } @@ -253,11 +272,22 @@ public class VibratorService extends IVibratorService.Stub } @Override - public void onChange(boolean SelfChange) { - updateInputDeviceVibrators(); + public void onChange(boolean selfChange, Uri uri) { + if (uri.equals(CMSettings.Secure.getUriFor(CMSettings.Secure.VIBRATOR_INTENSITY))) { + updateVibratorIntensity(); + } else { + updateInputDeviceVibrators(); + } } } + private void updateVibratorIntensity() { + mVibratorIntensity = CMSettings.Secure.getIntForUser(mContext.getContentResolver(), + CMSettings.Secure.VIBRATOR_INTENSITY, mHardware.getVibratorDefaultIntensity(), + UserHandle.USER_CURRENT); + mHardware.setVibratorIntensity(mVibratorIntensity); + } + @Override // Binder call public boolean hasVibrator() { return doVibratorExists(); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 542268e..db3d474 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -121,6 +121,10 @@ public final class ActiveServices { // at the same time. final int mMaxStartingBackground; + // Flag to reschedule the services during app launch. Disable by default. + private static final boolean SERVICE_RESCHEDULE + = SystemProperties.getBoolean("ro.am.reschedule_service", false); + final SparseArray<ServiceMap> mServiceMap = new SparseArray<>(); /** @@ -1229,6 +1233,14 @@ public final class ActiveServices { r.pendingStarts.add(0, si); long dur = SystemClock.uptimeMillis() - si.deliveredTime; dur *= 2; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"Can add more delay !!!" + +" si.deliveredTime "+si.deliveredTime + +" dur "+dur + +" si.deliveryCount "+si.deliveryCount + +" si.doneExecutingCount "+si.doneExecutingCount + +" allowCancel "+allowCancel); + } if (minDuration < dur) minDuration = dur; if (resetTime < dur) resetTime = dur; } else { @@ -1241,6 +1253,13 @@ public final class ActiveServices { } r.totalRestartCount++; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration + +" resetTime "+resetTime+" now "+now + +" r.restartDelay "+r.restartDelay + +" r.restartTime+resetTime "+(r.restartTime+resetTime) + +" allowCancel "+allowCancel); + } if (r.restartDelay == 0) { r.restartCount++; r.restartDelay = minDuration; @@ -1262,6 +1281,14 @@ public final class ActiveServices { } r.nextRestartTime = now + r.restartDelay; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG,"r.name "+r.name+" N "+N+" minDuration "+minDuration + +" resetTime "+resetTime+" now "+now + +" r.restartDelay "+r.restartDelay + +" r.restartTime+resetTime "+(r.restartTime+resetTime) + +" r.nextRestartTime "+r.nextRestartTime + +" allowCancel "+allowCancel); + } // Make sure that we don't end up restarting a bunch of services // all at the same time. @@ -1304,6 +1331,15 @@ public final class ActiveServices { r.nextRestartTime = SystemClock.uptimeMillis() + r.restartDelay; Slog.w(TAG, "Scheduling restart of crashed service " + r.shortName + " in " + r.restartDelay + "ms"); + + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + for (int i=mRestartingServices.size()-1; i>=0; i--) { + ServiceRecord r2 = mRestartingServices.get(i); + Slog.w(TAG,"Restarting list - i "+i+" r2.nextRestartTime " + +r2.nextRestartTime+" r2.name "+r2.name); + } + } + EventLog.writeEvent(EventLogTags.AM_SCHEDULE_SERVICE_RESTART, r.userId, r.shortName, r.restartDelay); @@ -1324,7 +1360,31 @@ public final class ActiveServices { return; } try { - bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true); + if(SERVICE_RESCHEDULE == true) { + boolean shouldDelay = false; + ActivityRecord top_rc = null; + ActivityStack stack = mAm.getFocusedStack(); + if(stack != null) { + top_rc = stack.topRunningActivityLocked(null); + } + if(top_rc != null) { + if(!top_rc.nowVisible && !r.shortName.contains(top_rc.packageName)) { + shouldDelay = true; + } + } + if(!shouldDelay) { + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true); + } else { + if (DEBUG_DELAYED_SERVICE) { + Slog.v(TAG, "Reschedule service restart due to app launch" + +" r.shortName "+r.shortName+" r.app = "+r.app); + } + r.resetRestartCounter(); + scheduleServiceRestartLocked(r, true); + } + } else { + bringUpServiceLocked(r, r.intent.getIntent().getFlags(), r.createdFromFg, true); + } } catch (TransactionTooLargeException e) { // Ignore, it's been logged and nothing upstack cares. } @@ -1547,6 +1607,11 @@ public final class ActiveServices { if (newService) { app.services.remove(r); r.app = null; + if (SERVICE_RESCHEDULE && DEBUG_DELAYED_SERVICE) { + Slog.w(TAG, " Failed to create Service !!!! ." + +"This will introduce huge delay... " + +r.shortName + " in " + r.restartDelay + "ms"); + } } // Retry. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index f6c3bf5..def4c59 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -174,7 +174,6 @@ import android.content.pm.InstrumentationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; -import android.content.pm.ThemeUtils; import android.content.pm.UserInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PathPermission; @@ -268,6 +267,8 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.Date; import java.text.SimpleDateFormat; +import org.cyanogenmod.internal.util.ThemeUtils; + public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { @@ -333,6 +334,11 @@ public final class ActivityManagerService extends ActivityManagerNative // before we decide it must be hung. static final int CONTENT_PROVIDER_PUBLISH_TIMEOUT = 10*1000; + // How long we will retain processes hosting content providers in the "last activity" + // state before allowing them to drop down to the regular cached LRU list. This is + // to avoid thrashing of provider processes under low memory situations. + static final int CONTENT_PROVIDER_RETAIN_TIME = 20*1000; + // How long we wait for a launched process to attach to the activity manager // before we decide it's never going to come up for real, when the process was // started with a wrapper for instrumentation (such as Valgrind) because it @@ -1400,6 +1406,7 @@ public final class ActivityManagerService extends ActivityManagerNative static final int POST_PRIVACY_NOTIFICATION_MSG = 60; static final int CANCEL_PRIVACY_NOTIFICATION_MSG = 61; static final int POST_COMPONENT_PROTECTED_MSG = 62; + static final int CANCEL_PROTECTED_APP_NOTIFICATION = 63; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -2237,6 +2244,20 @@ public final class ActivityManagerService extends ActivityManagerNative Slog.w(TAG, "Unable to create context for protected app notification", e); } } break; + case CANCEL_PROTECTED_APP_NOTIFICATION: { + INotificationManager inm = NotificationManager.getService(); + if (inm == null) { + return; + } + try { + inm.cancelNotificationWithTag("android", null, + R.string.notify_package_component_protected_title, msg.arg1); + } catch (RuntimeException e) { + Slog.w(ActivityManagerService.TAG, + "Error canceling notification for service", e); + } catch (RemoteException e) { + } + } break; } } }; @@ -8584,6 +8605,14 @@ public final class ActivityManagerService extends ActivityManagerNative return list; } + @Override + public boolean isPackageInForeground(String packageName) { + synchronized (this) { + ActivityRecord activity = mStackSupervisor.topRunningActivityLocked(); + return activity != null && activity.packageName.equals(packageName); + } + } + /** * Creates a new RecentTaskInfo from a TaskRecord. */ @@ -9693,6 +9722,14 @@ public final class ActivityManagerService extends ActivityManagerNative if (conn.stableCount == 0 && conn.unstableCount == 0) { cpr.connections.remove(conn); conn.client.conProviders.remove(conn); + if (conn.client.setProcState < ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { + // The client is more important than last activity -- note the time this + // is happening, so we keep the old provider process around a bit as last + // activity to avoid thrashing it. + if (cpr.proc != null) { + cpr.proc.lastProviderTime = SystemClock.uptimeMillis(); + } + } stopAssociationLocked(conn.client.uid, conn.client.processName, cpr.uid, cpr.name); return true; } @@ -12272,7 +12309,7 @@ public final class ActivityManagerService extends ActivityManagerNative } private void sendAppFailureBroadcast(String pkgName) { - Intent intent = new Intent(Intent.ACTION_APP_FAILURE, + Intent intent = new Intent(cyanogenmod.content.Intent.ACTION_APP_FAILURE, (pkgName != null)? Uri.fromParts("package", pkgName, null) : null); mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT_OR_SELF); } @@ -15382,6 +15419,10 @@ public final class ActivityManagerService extends ActivityManagerNative pw.print(" Lost RAM: "); pw.print(memInfo.getTotalSizeKb() - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() - memInfo.getKernelUsedSizeKb()); pw.println(" kB"); + } else { + pw.print("lostram,"); pw.println(memInfo.getTotalSizeKb() + - totalPss - memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb() + - memInfo.getKernelUsedSizeKb()); } if (!brief) { if (memInfo.getZramTotalSizeKb() != 0) { @@ -18539,6 +18580,18 @@ public final class ActivityManagerService extends ActivityManagerNative } } + if (app.lastProviderTime > 0 && (app.lastProviderTime+CONTENT_PROVIDER_RETAIN_TIME) > now) { + if (adj > ProcessList.PREVIOUS_APP_ADJ) { + adj = ProcessList.PREVIOUS_APP_ADJ; + schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; + app.cached = false; + app.adjType = "provider"; + } + if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { + procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; + } + } + if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) { // A client of one of our services or providers is in the top state. We // *may* want to be in the top state, but not if we are already running in diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index f48b448..f439966 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -25,6 +25,7 @@ import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; +import android.text.TextUtils; import android.util.ArraySet; import com.android.internal.app.IVoiceInteractor; import com.android.internal.content.ReferrerIntent; @@ -271,6 +272,8 @@ final class ActivityStack { } private final PerformanceManagerInternal mPerf; + private static final String PROTECTED_APPS_TARGET_VALIDATION_COMPONENT = + "com.android.settings/com.android.settings.applications.ProtectedAppsActivity"; final Handler mHandler; @@ -1144,6 +1147,7 @@ final class ActivityStack { } updatePrivacyGuardNotificationLocked(next); + updateProtectedAppNotificationLocked(next); } private void setVisible(ActivityRecord r, boolean visible) { @@ -2100,6 +2104,16 @@ final class ActivityStack { updateTaskMovement(task, true); } + private final void updateProtectedAppNotificationLocked(ActivityRecord next) { + ComponentName componentName = ComponentName.unflattenFromString(next.shortComponentName); + if (TextUtils.equals(componentName.flattenToString(), + PROTECTED_APPS_TARGET_VALIDATION_COMPONENT)) { + Message msg = mService.mHandler.obtainMessage( + ActivityManagerService.CANCEL_PROTECTED_APP_NOTIFICATION, next); + msg.sendToTarget(); + } + } + private final void updatePrivacyGuardNotificationLocked(ActivityRecord next) { String privacyGuardPackageName = mStackSupervisor.mPrivacyGuardPackageName; diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 62768c3..5fd3510 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -1,5 +1,6 @@ /* * Copyright (C) 2006-2007 The Android Open Source Project + * Copyright (C) 2016 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -50,6 +51,8 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsImpl; +import com.android.internal.os.DockBatteryStatsImpl; + import com.android.internal.os.PowerProfile; import com.android.server.FgThread; import com.android.server.LocalServices; @@ -75,6 +78,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub static IBatteryStats sService; final BatteryStatsImpl mStats; + // The dock stats only collect statistics about battery (no wakelocks, no counters, ...), + // just the dock battery history + final DockBatteryStatsImpl mDockStats; final BatteryStatsHandler mHandler; Context mContext; PowerManagerInternal mPowerManagerInternal; @@ -167,6 +173,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through. mStats = new BatteryStatsImpl(systemDir, handler, mHandler); + mDockStats = new DockBatteryStatsImpl(systemDir, handler, mHandler); } public void publish(Context context) { @@ -196,6 +203,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub synchronized (mStats) { mStats.shutdownLocked(); } + synchronized (mDockStats) { + mDockStats.shutdownLocked(); + } } public static IBatteryStats getService() { @@ -231,6 +241,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK); } + /** + * @return the current dock statistics object, which may be modified + * to reflect events that affect battery usage. You must lock the + * stats object before doing anything with it. + * @hide + */ + public BatteryStatsImpl getActiveDockStatistics() { + return mDockStats; + } + // These are for direct use by the activity manager... /** @@ -327,6 +347,48 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } + /** @hide */ + public byte[] getDockStatistics() { + mContext.enforceCallingPermission( + android.Manifest.permission.BATTERY_STATS, null); + //Slog.i("foo", "SENDING DOCK BATTERY INFO:"); + //mDockStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); + Parcel out = Parcel.obtain(); + mDockStats.writeToParcel(out, 0); + byte[] data = out.marshall(); + out.recycle(); + return data; + } + + /** @hide */ + public ParcelFileDescriptor getDockStatisticsStream() { + mContext.enforceCallingPermission( + android.Manifest.permission.BATTERY_STATS, null); + //Slog.i("foo", "SENDING DOCK BATTERY INFO:"); + //mDockStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM)); + Parcel out = Parcel.obtain(); + mDockStats.writeToParcel(out, 0); + byte[] data = out.marshall(); + out.recycle(); + try { + return ParcelFileDescriptor.fromData(data, "dock-battery-stats"); + } catch (IOException e) { + Slog.w(TAG, "Unable to create shared memory", e); + return null; + } + } + + public void resetStatistics() { + mContext.enforceCallingPermission( + android.Manifest.permission.RESET_BATTERY_STATS, null); + synchronized (mStats) { + mStats.resetAllStatsCmdLocked(); + } + synchronized (mDockStats) { + mDockStats.resetAllStatsCmdLocked(); + } + } + public long computeBatteryTimeRemaining() { synchronized (mStats) { long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime()); @@ -901,6 +963,31 @@ public final class BatteryStatsService extends IBatteryStats.Stub return mStats.getAwakeTimePlugged(); } + /** @hide */ + public boolean isOnDockBattery() { + return mDockStats.isOnBattery(); + } + + /** @hide */ + public void setDockBatteryState(int status, int health, int plugType, int level, + int temp, int volt) { + enforceCallingPermission(); + mDockStats.setBatteryStateLocked(status, health, plugType, level, temp, volt); + } + + /** @hide */ + public long getAwakeTimeDockBattery() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.BATTERY_STATS, null); + return mDockStats.getAwakeTimeBattery(); + } + + public long getAwakeTimeDockPlugged() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.BATTERY_STATS, null); + return mDockStats.getAwakeTimePlugged(); + } + public void enforceCallingPermission() { if (Binder.getCallingPid() == Process.myPid()) { return; @@ -1065,6 +1152,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub } else if ("--reset".equals(arg)) { synchronized (mStats) { mStats.resetAllStatsCmdLocked(); + mDockStats.resetAllStatsCmdLocked(); pw.println("Battery stats reset."); noOutput = true; } @@ -1073,6 +1161,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub updateExternalStats("dump", UPDATE_ALL); synchronized (mStats) { mStats.writeSyncLocked(); + mDockStats.writeSyncLocked(); pw.println("Battery stats written."); noOutput = true; } @@ -1176,19 +1265,44 @@ public final class BatteryStatsService extends IBatteryStats.Stub + mStats.mCheckinFile.getBaseFile(), e); } } + if (mDockStats.mCheckinFile.exists()) { + try { + byte[] raw = mDockStats.mCheckinFile.readFully(); + if (raw != null) { + Parcel in = Parcel.obtain(); + in.unmarshall(raw, 0, raw.length); + in.setDataPosition(0); + DockBatteryStatsImpl checkinStats = new DockBatteryStatsImpl( + null, mStats.mHandler, null); + checkinStats.readSummaryFromParcel(in); + in.recycle(); + checkinStats.dumpCheckinLocked(mContext, pw, apps, flags, + historyStart); + mDockStats.mCheckinFile.delete(); + return; + } + } catch (IOException e) { + Slog.w(TAG, "Failure reading dock checkin file " + + mDockStats.mCheckinFile.getBaseFile(), e); + } + } } } synchronized (mStats) { mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); + mDockStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart); if (writeData) { mStats.writeAsyncLocked(); + mDockStats.writeAsyncLocked(); } } } else { synchronized (mStats) { mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); + mDockStats.dumpLocked(mContext, pw, flags, reqUid, historyStart); if (writeData) { mStats.writeAsyncLocked(); + mDockStats.writeAsyncLocked(); } } } diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java index d1917db..055e33e 100644 --- a/services/core/java/com/android/server/am/LockTaskNotify.java +++ b/services/core/java/com/android/server/am/LockTaskNotify.java @@ -21,13 +21,13 @@ import android.content.Context; import android.os.Handler; import android.os.Message; import android.os.RemoteException; -import android.view.IWindowManager; +import android.os.UserHandle; import android.view.WindowManager; -import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import android.widget.Toast; import com.android.internal.R; +import cyanogenmod.providers.CMSettings; /** * Helper to manage showing/hiding a image to notify them that they are entering @@ -40,23 +40,19 @@ public class LockTaskNotify { private final H mHandler; private AccessibilityManager mAccessibilityManager; private Toast mLastToast; - private final IWindowManager mWindowManagerService; public LockTaskNotify(Context context) { mContext = context; mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(Context.ACCESSIBILITY_SERVICE); mHandler = new H(); - mWindowManagerService = WindowManagerGlobal.getWindowManagerService(); } private boolean hasNavigationBar() { - try { - return mWindowManagerService.hasNavigationBar(); - } catch (RemoteException e) { - //ignore - } - return false; + return mContext.getResources().getBoolean( + com.android.internal.R.bool.config_showNavigationBar) + || CMSettings.Secure.getIntForUser(mContext.getContentResolver(), + CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; } public void showToast(int lockTaskModeState) { @@ -67,9 +63,9 @@ public class LockTaskNotify { final int textResId; if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_LOCKED) { textResId = R.string.lock_to_app_toast_locked; - } else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED) { - textResId = mAccessibilityManager.isEnabled() - ? R.string.lock_to_app_toast_accessible : R.string.lock_to_app_toast; + } else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED && + mAccessibilityManager.isEnabled() && hasNavigationBar()) { + textResId = R.string.lock_to_app_toast_accessible; } else { textResId = hasNavigationBar() ? R.string.lock_to_app_toast : R.string.lock_to_app_toast_no_navbar; diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 9cab95b..33f1a1c 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -136,6 +136,7 @@ final class ProcessRecord { long curCpuTime; // How long proc has run CPU most recently long lastRequestedGc; // When we last asked the app to do a gc long lastLowMemory; // When we last told the app that memory is low + long lastProviderTime; // The last time someone else was using a provider in this process. boolean reportLowMemory; // Set to true when waiting to report low mem boolean empty; // Is this an empty background process? boolean cached; // Is this a cached process? @@ -317,6 +318,11 @@ final class ProcessRecord { pw.print(" foregroundActivities="); pw.print(foregroundActivities); pw.print(" (rep="); pw.print(repForegroundActivities); pw.println(")"); } + if (lastProviderTime > 0) { + pw.print(prefix); pw.print("lastProviderTime="); + TimeUtils.formatDuration(lastProviderTime, now, pw); + pw.println(); + } if (hasStartedServices) { pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices); } diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 82c658e..92643ba 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -35,6 +35,7 @@ import android.bluetooth.BluetoothClass; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; +import android.content.ActivityNotFoundException; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; @@ -713,6 +714,7 @@ public class AudioService extends IAudioService.Stub { intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); + intentFilter.addAction(Intent.ACTION_SHUTDOWN); // TODO merge orientation and rotation mMonitorOrientation = SystemProperties.getBoolean("ro.audio.monitorOrientation", false); if (mMonitorOrientation) { @@ -5083,12 +5085,18 @@ public class AudioService extends IAudioService.Stub { connType = AudioRoutesInfo.MAIN_HEADSET; intent.setAction(Intent.ACTION_HEADSET_PLUG); intent.putExtra("microphone", 1); + if (state == 1) { + startMusicPlayer(); + } } else if (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE || device == AudioSystem.DEVICE_OUT_LINE) { /*do apps care about line-out vs headphones?*/ connType = AudioRoutesInfo.MAIN_HEADPHONES; intent.setAction(Intent.ACTION_HEADSET_PLUG); intent.putExtra("microphone", 0); + if (state == 1) { + startMusicPlayer(); + } } else if (device == AudioSystem.DEVICE_OUT_HDMI || device == AudioSystem.DEVICE_OUT_HDMI_ARC) { connType = AudioRoutesInfo.MAIN_HDMI; @@ -5121,6 +5129,23 @@ public class AudioService extends IAudioService.Stub { } } + private void startMusicPlayer() { + boolean launchPlayer = CMSettings.System.getIntForUser(mContext.getContentResolver(), + CMSettings.System.HEADSET_CONNECT_PLAYER, 0, UserHandle.USER_CURRENT) != 0; + TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); + + if (launchPlayer && !tm.isInCall()) { + try { + Intent playerIntent = new Intent(Intent.ACTION_MAIN); + playerIntent.addCategory(Intent.CATEGORY_APP_MUSIC); + playerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mContext.startActivity(playerIntent); + } catch (ActivityNotFoundException | IllegalArgumentException e) { + Log.w(TAG, "No music player Activity could be found"); + } + } + } + private void onSetWiredDeviceConnectionState(int device, int state, String address, String deviceName, String caller) { if (DEBUG_DEVICES) { @@ -5378,6 +5403,8 @@ public class AudioService extends IAudioService.Stub { int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); UserManagerService.getInstance().setSystemControlledUserRestriction( UserManager.DISALLOW_RECORD_AUDIO, false, userId); + } else if (action.equals(Intent.ACTION_SHUTDOWN)) { + AudioSystem.setParameters("dev_shutdown=true"); } } } // end class AudioServiceBroadcastReceiver diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index 3ec0bee..ef086da 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -2604,32 +2604,17 @@ public class SyncManager { } continue; } - if (!isOperationValidLocked(op)) { - operationIterator.remove(); - mSyncStorageEngine.deleteFromPending(op.pendingOperation); - continue; - } - // If the next run time is in the future, even given the flexible scheduling, - // return the time. - if (op.effectiveRunTime - op.flexTime > now) { - if (nextReadyToRunTime > op.effectiveRunTime) { - nextReadyToRunTime = op.effectiveRunTime; - } - if (isLoggable) { - Log.v(TAG, " Not running sync operation: Sync too far in future." - + "effective: " + op.effectiveRunTime + " flex: " + op.flexTime - + " now: " + now); - } - continue; - } String packageName = getPackageName(op.target); ApplicationInfo ai = null; if (packageName != null) { try { ai = mContext.getPackageManager().getApplicationInfo(packageName, PackageManager.GET_UNINSTALLED_PACKAGES - | PackageManager.GET_DISABLED_COMPONENTS); + | PackageManager.GET_DISABLED_COMPONENTS); } catch (NameNotFoundException e) { + operationIterator.remove(); + mSyncStorageEngine.deleteFromPending(op.pendingOperation); + continue; } } // If app is considered idle, then skip for now and backoff @@ -2644,6 +2629,24 @@ public class SyncManager { } else { op.appIdle = false; } + if (!isOperationValidLocked(op)) { + operationIterator.remove(); + mSyncStorageEngine.deleteFromPending(op.pendingOperation); + continue; + } + // If the next run time is in the future, even given the flexible scheduling, + // return the time. + if (op.effectiveRunTime - op.flexTime > now) { + if (nextReadyToRunTime > op.effectiveRunTime) { + nextReadyToRunTime = op.effectiveRunTime; + } + if (isLoggable) { + Log.v(TAG, " Not running sync operation: Sync too far in future." + + "effective: " + op.effectiveRunTime + " flex: " + op.flexTime + + " now: " + now); + } + continue; + } // Add this sync to be run. operations.add(op); } diff --git a/services/core/java/com/android/server/display/LiveDisplayController.java b/services/core/java/com/android/server/display/LiveDisplayController.java index 9e6da2d..28f2432 100644 --- a/services/core/java/com/android/server/display/LiveDisplayController.java +++ b/services/core/java/com/android/server/display/LiveDisplayController.java @@ -42,19 +42,23 @@ import android.util.Slog; import com.android.server.LocalServices; import com.android.server.accessibility.DisplayAdjustmentUtils; +import com.android.server.pm.UserContentObserver; import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightState; import cyanogenmod.hardware.CMHardwareManager; import cyanogenmod.providers.CMSettings; +import cyanogenmod.util.ColorUtils; import java.io.PrintWriter; +import java.util.List; public class LiveDisplayController { private static final String TAG = "LiveDisplay"; + private static final String DELIMITER = "|"; private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 1; private static final int OFF_TEMPERATURE = 6500; @@ -133,13 +137,6 @@ public class LiveDisplayController { mDefaultOutdoorLux = mContext.getResources().getInteger( org.cyanogenmod.platform.internal.R.integer.config_outdoorAmbientLux); - // Counter used to determine when we should tell the user about this feature. - // If it's not used after 3 sunsets, we'll show the hint once. - mHintCounter = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.LIVE_DISPLAY_HINTED, - -3, - UserHandle.USER_CURRENT); - mUseOutdoorMode = mHardware.isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT); mOutdoorModeIsSelfManaged = mUseOutdoorMode ? @@ -186,6 +183,12 @@ public class LiveDisplayController { CMSettings.System.DISPLAY_TEMPERATURE_MODE, MODE_OFF, UserHandle.USER_CURRENT); + // Counter used to determine when we should tell the user about this feature. + // If it's not used after 3 sunsets, we'll show the hint once. + mHintCounter = CMSettings.System.getIntForUser(mContext.getContentResolver(), + CMSettings.System.LIVE_DISPLAY_HINTED, + -3, + UserHandle.USER_CURRENT); // Clear the hint forever if (mMode != MODE_OFF) { @@ -213,9 +216,33 @@ public class LiveDisplayController { } updateLiveDisplay(mCurrentLux); + updateGamma(); + } + + private void updateGamma() { + if (!mHardware.isSupported(CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION)) { + return; + } + ContentResolver contentResolver = mContext.getContentResolver(); + for (int i = 0; i < mHardware.getNumGammaControls(); i++) { + List<String> gammaValue = CMSettings.Secure.getDelimitedStringAsList( + contentResolver, DELIMITER, + CMSettings.Secure.DISPLAY_GAMMA_CALIBRATION_PREFIX + i); + if (gammaValue != null) { + mHardware.setDisplayGammaCalibration(i, stringArrayToIntArray(gammaValue)); + } + } } - private final class SettingsObserver extends ContentObserver { + private int[] stringArrayToIntArray(List<String> value) { + int[] result = new int[value.size()]; + for (int i = 0; i < value.size(); i++) { + result[i] = Integer.parseInt(value.get(i)); + } + return result; + } + + private final class SettingsObserver extends UserContentObserver { private final Uri DISPLAY_TEMPERATURE_DAY_URI = CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_DAY); private final Uri DISPLAY_TEMPERATURE_NIGHT_URI = @@ -244,14 +271,22 @@ public class LiveDisplayController { cr.registerContentObserver(DISPLAY_LOW_POWER_URI, false, this, UserHandle.USER_ALL); cr.registerContentObserver(DISPLAY_COLOR_ENHANCE_URI, false, this, UserHandle.USER_ALL); cr.registerContentObserver(DISPLAY_COLOR_ADJUSTMENT_URI, false, this, UserHandle.USER_ALL); + if (mHardware.isSupported(CMHardwareManager.FEATURE_DISPLAY_GAMMA_CALIBRATION)) { + for (int i = 0; i < mHardware.getNumGammaControls(); i++) { + Uri gammaUri = CMSettings.Secure.getUriFor( + CMSettings.Secure.DISPLAY_GAMMA_CALIBRATION_PREFIX + i); + cr.registerContentObserver(gammaUri, false, this, UserHandle.USER_ALL); + } + } + observe(); } else { cr.unregisterContentObserver(this); + unobserve(); } } @Override - public void onChange(boolean selfChange, Uri uri) { - super.onChange(selfChange, uri); + protected void update() { updateSettings(); } } @@ -293,7 +328,7 @@ public class LiveDisplayController { private synchronized void setDisplayTemperature(int temperature) { mColorTemperature = temperature; - final float[] rgb = temperatureToRGB(temperature); + final float[] rgb = ColorUtils.temperatureToRGB(temperature); if (!mLowPerformance) { rgb[0] *= mColorAdjustment[0]; @@ -431,25 +466,6 @@ public class LiveDisplayController { } /** - * Convert a color temperature value (in Kelvin) to a RGB units as floats. - * This can be used in a transform matrix or hardware gamma control. - * - * @param tempK - * @return - */ - private static float[] temperatureToRGB(int degreesK) { - int k = MathUtils.constrain(degreesK, 1000, 20000); - float a = (k % 100) / 100.0f; - int i = ((k - 1000)/ 100) * 3; - - return new float[] { interp(i, a), interp(i+1, a), interp(i+2, a) }; - } - - private static float interp(int i, float a) { - return MathUtils.lerp((float)sColorTable[i], (float)sColorTable[i+3], a); - } - - /** * Where is the sun anyway? This calculation determines day or night, and scales * the value around sunset/sunrise for a smooth transition. * @@ -563,7 +579,8 @@ public class LiveDisplayController { .setStyle(new Notification.BigTextStyle().bigText(mContext.getResources() .getString( org.cyanogenmod.platform.internal.R.string.live_display_hint))) - .setContentIntent(result); + .setContentIntent(result) + .setAutoCancel(true); NotificationManager nm = (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); @@ -630,205 +647,4 @@ public class LiveDisplayController { pw.println(" mColorEnhancement=" + (mUseColorEnhancement ? mColorEnhancement : "N/A")); pw.println(" mLowPower=" + (mUseLowPower ? mLowPower : "N/A")); } - - /** - * This table is a modified version of the original blackbody chart, found here: - * http://www.vendian.org/mncharity/dir3/blackbody/UnstableURLs/bbr_color.html - * - * Created by Ingo Thiel. - */ - private static final double[] sColorTable = new double[] { - 1.00000000, 0.18172716, 0.00000000, - 1.00000000, 0.25503671, 0.00000000, - 1.00000000, 0.30942099, 0.00000000, - 1.00000000, 0.35357379, 0.00000000, - 1.00000000, 0.39091524, 0.00000000, - 1.00000000, 0.42322816, 0.00000000, - 1.00000000, 0.45159884, 0.00000000, - 1.00000000, 0.47675916, 0.00000000, - 1.00000000, 0.49923747, 0.00000000, - 1.00000000, 0.51943421, 0.00000000, - 1.00000000, 0.54360078, 0.08679949, - 1.00000000, 0.56618736, 0.14065513, - 1.00000000, 0.58734976, 0.18362641, - 1.00000000, 0.60724493, 0.22137978, - 1.00000000, 0.62600248, 0.25591950, - 1.00000000, 0.64373109, 0.28819679, - 1.00000000, 0.66052319, 0.31873863, - 1.00000000, 0.67645822, 0.34786758, - 1.00000000, 0.69160518, 0.37579588, - 1.00000000, 0.70602449, 0.40267128, - 1.00000000, 0.71976951, 0.42860152, - 1.00000000, 0.73288760, 0.45366838, - 1.00000000, 0.74542112, 0.47793608, - 1.00000000, 0.75740814, 0.50145662, - 1.00000000, 0.76888303, 0.52427322, - 1.00000000, 0.77987699, 0.54642268, - 1.00000000, 0.79041843, 0.56793692, - 1.00000000, 0.80053332, 0.58884417, - 1.00000000, 0.81024551, 0.60916971, - 1.00000000, 0.81957693, 0.62893653, - 1.00000000, 0.82854786, 0.64816570, - 1.00000000, 0.83717703, 0.66687674, - 1.00000000, 0.84548188, 0.68508786, - 1.00000000, 0.85347859, 0.70281616, - 1.00000000, 0.86118227, 0.72007777, - 1.00000000, 0.86860704, 0.73688797, - 1.00000000, 0.87576611, 0.75326132, - 1.00000000, 0.88267187, 0.76921169, - 1.00000000, 0.88933596, 0.78475236, - 1.00000000, 0.89576933, 0.79989606, - 1.00000000, 0.90198230, 0.81465502, - 1.00000000, 0.90963069, 0.82838210, - 1.00000000, 0.91710889, 0.84190889, - 1.00000000, 0.92441842, 0.85523742, - 1.00000000, 0.93156127, 0.86836903, - 1.00000000, 0.93853986, 0.88130458, - 1.00000000, 0.94535695, 0.89404470, - 1.00000000, 0.95201559, 0.90658983, - 1.00000000, 0.95851906, 0.91894041, - 1.00000000, 0.96487079, 0.93109690, - 1.00000000, 0.97107439, 0.94305985, - 1.00000000, 0.97713351, 0.95482993, - 1.00000000, 0.98305189, 0.96640795, - 1.00000000, 0.98883326, 0.97779486, - 1.00000000, 0.99448139, 0.98899179, - 1.00000000, 1.00000000, 1.00000000, - 0.98947904, 0.99348723, 1.00000000, - 0.97940448, 0.98722715, 1.00000000, - 0.96975025, 0.98120637, 1.00000000, - 0.96049223, 0.97541240, 1.00000000, - 0.95160805, 0.96983355, 1.00000000, - 0.94303638, 0.96443333, 1.00000000, - 0.93480451, 0.95923080, 1.00000000, - 0.92689056, 0.95421394, 1.00000000, - 0.91927697, 0.94937330, 1.00000000, - 0.91194747, 0.94470005, 1.00000000, - 0.90488690, 0.94018594, 1.00000000, - 0.89808115, 0.93582323, 1.00000000, - 0.89151710, 0.93160469, 1.00000000, - 0.88518247, 0.92752354, 1.00000000, - 0.87906581, 0.92357340, 1.00000000, - 0.87315640, 0.91974827, 1.00000000, - 0.86744421, 0.91604254, 1.00000000, - 0.86191983, 0.91245088, 1.00000000, - 0.85657444, 0.90896831, 1.00000000, - 0.85139976, 0.90559011, 1.00000000, - 0.84638799, 0.90231183, 1.00000000, - 0.84153180, 0.89912926, 1.00000000, - 0.83682430, 0.89603843, 1.00000000, - 0.83225897, 0.89303558, 1.00000000, - 0.82782969, 0.89011714, 1.00000000, - 0.82353066, 0.88727974, 1.00000000, - 0.81935641, 0.88452017, 1.00000000, - 0.81530175, 0.88183541, 1.00000000, - 0.81136180, 0.87922257, 1.00000000, - 0.80753191, 0.87667891, 1.00000000, - 0.80380769, 0.87420182, 1.00000000, - 0.80018497, 0.87178882, 1.00000000, - 0.79665980, 0.86943756, 1.00000000, - 0.79322843, 0.86714579, 1.00000000, - 0.78988728, 0.86491137, 1.00000000, - 0.78663296, 0.86273225, 1.00000000, - 0.78346225, 0.86060650, 1.00000000, - 0.78037207, 0.85853224, 1.00000000, - 0.77735950, 0.85650771, 1.00000000, - 0.77442176, 0.85453121, 1.00000000, - 0.77155617, 0.85260112, 1.00000000, - 0.76876022, 0.85071588, 1.00000000, - 0.76603147, 0.84887402, 1.00000000, - 0.76336762, 0.84707411, 1.00000000, - 0.76076645, 0.84531479, 1.00000000, - 0.75822586, 0.84359476, 1.00000000, - 0.75574383, 0.84191277, 1.00000000, - 0.75331843, 0.84026762, 1.00000000, - 0.75094780, 0.83865816, 1.00000000, - 0.74863017, 0.83708329, 1.00000000, - 0.74636386, 0.83554194, 1.00000000, - 0.74414722, 0.83403311, 1.00000000, - 0.74197871, 0.83255582, 1.00000000, - 0.73985682, 0.83110912, 1.00000000, - 0.73778012, 0.82969211, 1.00000000, - 0.73574723, 0.82830393, 1.00000000, - 0.73375683, 0.82694373, 1.00000000, - 0.73180765, 0.82561071, 1.00000000, - 0.72989845, 0.82430410, 1.00000000, - 0.72802807, 0.82302316, 1.00000000, - 0.72619537, 0.82176715, 1.00000000, - 0.72439927, 0.82053539, 1.00000000, - 0.72263872, 0.81932722, 1.00000000, - 0.72091270, 0.81814197, 1.00000000, - 0.71922025, 0.81697905, 1.00000000, - 0.71756043, 0.81583783, 1.00000000, - 0.71593234, 0.81471775, 1.00000000, - 0.71433510, 0.81361825, 1.00000000, - 0.71276788, 0.81253878, 1.00000000, - 0.71122987, 0.81147883, 1.00000000, - 0.70972029, 0.81043789, 1.00000000, - 0.70823838, 0.80941546, 1.00000000, - 0.70678342, 0.80841109, 1.00000000, - 0.70535469, 0.80742432, 1.00000000, - 0.70395153, 0.80645469, 1.00000000, - 0.70257327, 0.80550180, 1.00000000, - 0.70121928, 0.80456522, 1.00000000, - 0.69988894, 0.80364455, 1.00000000, - 0.69858167, 0.80273941, 1.00000000, - 0.69729688, 0.80184943, 1.00000000, - 0.69603402, 0.80097423, 1.00000000, - 0.69479255, 0.80011347, 1.00000000, - 0.69357196, 0.79926681, 1.00000000, - 0.69237173, 0.79843391, 1.00000000, - 0.69119138, 0.79761446, 1.00000000, - 0.69003044, 0.79680814, 1.00000000, - 0.68888844, 0.79601466, 1.00000000, - 0.68776494, 0.79523371, 1.00000000, - 0.68665951, 0.79446502, 1.00000000, - 0.68557173, 0.79370830, 1.00000000, - 0.68450119, 0.79296330, 1.00000000, - 0.68344751, 0.79222975, 1.00000000, - 0.68241029, 0.79150740, 1.00000000, - 0.68138918, 0.79079600, 1.00000000, - 0.68038380, 0.79009531, 1.00000000, - 0.67939381, 0.78940511, 1.00000000, - 0.67841888, 0.78872517, 1.00000000, - 0.67745866, 0.78805526, 1.00000000, - 0.67651284, 0.78739518, 1.00000000, - 0.67558112, 0.78674472, 1.00000000, - 0.67466317, 0.78610368, 1.00000000, - 0.67375872, 0.78547186, 1.00000000, - 0.67286748, 0.78484907, 1.00000000, - 0.67198916, 0.78423512, 1.00000000, - 0.67112350, 0.78362984, 1.00000000, - 0.67027024, 0.78303305, 1.00000000, - 0.66942911, 0.78244457, 1.00000000, - 0.66859988, 0.78186425, 1.00000000, - 0.66778228, 0.78129191, 1.00000000, - 0.66697610, 0.78072740, 1.00000000, - 0.66618110, 0.78017057, 1.00000000, - 0.66539706, 0.77962127, 1.00000000, - 0.66462376, 0.77907934, 1.00000000, - 0.66386098, 0.77854465, 1.00000000, - 0.66310852, 0.77801705, 1.00000000, - 0.66236618, 0.77749642, 1.00000000, - 0.66163375, 0.77698261, 1.00000000, - 0.66091106, 0.77647551, 1.00000000, - 0.66019791, 0.77597498, 1.00000000, - 0.65949412, 0.77548090, 1.00000000, - 0.65879952, 0.77499315, 1.00000000, - 0.65811392, 0.77451161, 1.00000000, - 0.65743716, 0.77403618, 1.00000000, - 0.65676908, 0.77356673, 1.00000000, - 0.65610952, 0.77310316, 1.00000000, - 0.65545831, 0.77264537, 1.00000000, - 0.65481530, 0.77219324, 1.00000000, - 0.65418036, 0.77174669, 1.00000000, - 0.65355332, 0.77130560, 1.00000000, - 0.65293404, 0.77086988, 1.00000000, - 0.65232240, 0.77043944, 1.00000000, - 0.65171824, 0.77001419, 1.00000000, - 0.65112144, 0.76959404, 1.00000000, - 0.65053187, 0.76917889, 1.00000000, - 0.64994941, 0.76876866, 1.00000000, - 0.64937392, 0.76836326, 1.00000000 - }; } diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index b2207f3..7a28f48 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -192,6 +192,9 @@ final class LocalDisplayAdapter extends DisplayAdapter { for (int j = 0; j < colorTransforms.size(); j++) { if (colorTransforms.get(j).getColorTransform() == info.colorTransform) { existingMode = true; + if (i == activeDisplayInfo) { + activeColorTransform = colorTransforms.get(j); + } break; } } diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java index 7d1dbe1..c986e74 100644 --- a/services/core/java/com/android/server/dreams/DreamManagerService.java +++ b/services/core/java/com/android/server/dreams/DreamManagerService.java @@ -247,6 +247,9 @@ public final class DreamManagerService extends SystemService { private void setLidStateInternal(int state) { synchronized (mLock) { + if (mLidState == state) { + return; + } mLidState = state; } switch (state) { diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index 11de1a2..bdb77db 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -781,6 +781,10 @@ public class GpsLocationProvider implements LocationProviderInterface { && mAGpsDataConnectionState == AGPS_DATA_CONNECTION_OPENING) { if (mNetworkAvailable) { String apnName = info.getExtraInfo(); + // APN wasn't found in the intent, try to get it from the content provider. + if (apnName == null) { + apnName = getSelectedApn(); + } if (apnName == null) { /* Assign a dummy value in the case of C2K as otherwise we will have a runtime exception in the following call to native_agps_data_conn_open*/ diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index bf7560e..da62313 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -203,6 +203,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int VERSION_LATEST = VERSION_SWITCH_UID; @VisibleForTesting + public static final int TYPE_NONE = 0; + @VisibleForTesting public static final int TYPE_WARNING = 0x1; @VisibleForTesting public static final int TYPE_LIMIT = 0x2; @@ -247,6 +249,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6; private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7; private static final int MSG_SCREEN_ON_CHANGED = 8; + private static final int MSG_PROCESS_LOW_POWER_CHANGED = 9; private final Context mContext; private final IActivityManager mActivityManager; @@ -262,6 +265,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { private PowerManagerInternal mPowerManagerInternal; private IDeviceIdleController mDeviceIdleController; + private final ComponentName mNotificationComponent; + private int mNotificationSequenceNumber; + final Object mRulesLock = new Object(); volatile boolean mSystemReady; @@ -363,6 +369,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml")); mAppOps = context.getSystemService(AppOpsManager.class); + + final String notificationComponent = context.getString( + R.string.config_networkPolicyNotificationComponent); + mNotificationComponent = notificationComponent != null + ? ComponentName.unflattenFromString(notificationComponent) : null; } public void bindConnectivityManager(IConnectivityManager connManager) { @@ -437,13 +448,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { mPowerManagerInternal.registerLowPowerModeObserver( new PowerManagerInternal.LowPowerModeListener() { @Override - public void onLowPowerModeChanged(boolean enabled) { - synchronized (mRulesLock) { - if (mRestrictPower != enabled) { - mRestrictPower = enabled; - updateRulesForGlobalChangeLocked(true); - } - } + public void onLowPowerModeChanged(final boolean enabled) { + mHandler.removeMessages(MSG_PROCESS_LOW_POWER_CHANGED); + Message msg = Message.obtain(mHandler, MSG_PROCESS_LOW_POWER_CHANGED, enabled); + mHandler.sendMessage(msg); } }); mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled(); @@ -778,6 +786,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final ArraySet<String> beforeNotifs = new ArraySet<String>(mActiveNotifs); mActiveNotifs.clear(); + // increment the sequence number so custom components know + // this update is new + mNotificationSequenceNumber++; + boolean hasNotifications = false; + // TODO: when switching to kernel notifications, compute next future // cycle boundary to recompute notifications. @@ -794,6 +807,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final long totalBytes = getTotalBytes(policy.template, start, end); if (policy.isOverLimit(totalBytes)) { + hasNotifications = true; if (policy.lastLimitSnooze >= start) { enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes); } else { @@ -807,10 +821,18 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start && policy.limitBytes != LIMIT_DISABLED) { enqueueNotification(policy, TYPE_WARNING, totalBytes); + hasNotifications = true; } } } + // right now we don't care about restricted background notifications + // in the custom notification component, so trigger an update now + // if we didn't update anything this pass + if (!hasNotifications) { + sendNotificationToCustomComponent(null, TYPE_NONE, 0); + } + // ongoing notification when restricting background data if (mRestrictBackground) { enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND); @@ -857,6 +879,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user. */ private void notifyOverLimitLocked(NetworkTemplate template) { + if (mNotificationComponent != null) { + // It is the job of the notification component to handle UI, + // so we do nothing here + return; + } + if (!mOverLimitNotified.contains(template)) { mContext.startActivity(buildNetworkOverLimitIntent(template)); mOverLimitNotified.add(template); @@ -875,11 +903,55 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return TAG + ":" + policy.template.hashCode() + ":" + type; } + private boolean sendNotificationToCustomComponent( + NetworkPolicy policy, + int type, + long totalBytes) { + if (mNotificationComponent == null) { + return false; + } + + Intent intent = new Intent(); + intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); + intent.setComponent(mNotificationComponent); + + int notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_NONE; + switch (type) { + case TYPE_WARNING: + notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_WARNING; + break; + case TYPE_LIMIT: + notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_REACHED_LIMIT; + break; + case TYPE_LIMIT_SNOOZED: + notificationType = NetworkPolicyManager.NOTIFICATION_TYPE_USAGE_EXCEEDED_LIMIT; + break; + } + + intent.setAction(NetworkPolicyManager.ACTION_SHOW_NETWORK_POLICY_NOTIFICATION); + intent.putExtra(NetworkPolicyManager.EXTRA_NOTIFICATION_TYPE, notificationType); + intent.putExtra( + NetworkPolicyManager.EXTRA_NOTIFICATION_SEQUENCE_NUMBER, + mNotificationSequenceNumber); + + if (notificationType != NetworkPolicyManager.NOTIFICATION_TYPE_NONE) { + intent.putExtra(NetworkPolicyManager.EXTRA_NETWORK_POLICY, policy); + intent.putExtra(NetworkPolicyManager.EXTRA_BYTES_USED, totalBytes); + } + + mContext.sendBroadcast(intent); + return true; + } + /** * Show notification for combined {@link NetworkPolicy} and specific type, * like {@link #TYPE_LIMIT}. Okay to call multiple times. */ private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) { + if (sendNotificationToCustomComponent(policy, type, totalBytes)) { + return; + } + final String tag = buildNotificationTag(policy, type); final Notification.Builder builder = new Notification.Builder(mContext); builder.setOnlyAlertOnce(true); @@ -1739,6 +1811,19 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @Override + public void snoozeWarning(NetworkTemplate template) { + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + + final long token = Binder.clearCallingIdentity(); + try { + // TODO: this seems like a race condition? (along with snoozeLimit above) + performSnooze(template, TYPE_WARNING); + } finally { + Binder.restoreCallingIdentity(token); + } + } + void performSnooze(NetworkTemplate template, int type) { maybeRefreshTrustedTime(); final long currentTime = currentTimeMillis(); @@ -2137,12 +2222,23 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { uidRules.clear(); // Fully update the app idle firewall chain. + final IPackageManager ipm = AppGlobals.getPackageManager(); final List<UserInfo> users = mUserManager.getUsers(); for (int ui = users.size() - 1; ui >= 0; ui--) { UserInfo user = users.get(ui); int[] idleUids = mUsageStats.getIdleUidsForUser(user.id); for (int uid : idleUids) { if (!mPowerSaveTempWhitelistAppIds.get(UserHandle.getAppId(uid), false)) { + // quick check: if this uid doesn't have INTERNET permission, it + // doesn't have network access anyway, so it is a waste to mess + // with it here. + try { + if (ipm.checkUidPermission(Manifest.permission.INTERNET, uid) + != PackageManager.PERMISSION_GRANTED) { + continue; + } + } catch (RemoteException e) { + } uidRules.put(uid, FIREWALL_RULE_DENY); } } @@ -2227,11 +2323,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { 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, uid, userId)) { - return false; + if (packages != null) { + final int userId = UserHandle.getUserId(uid); + for (String packageName : packages) { + if (!mUsageStats.isAppIdle(packageName, uid, userId)) { + return false; + } } } return true; @@ -2430,6 +2528,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { updateScreenOn(); return true; } + case MSG_PROCESS_LOW_POWER_CHANGED: { + boolean enabled = (Boolean) msg.obj; + synchronized (mRulesLock) { + if (mRestrictPower != enabled) { + mRestrictPower = enabled; + updateRulesForGlobalChangeLocked(true); + } + } + return true; + } default: { return false; } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 8429cc8..36818b5 100755..100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -58,6 +58,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; import android.content.res.Resources; import android.database.ContentObserver; +import android.graphics.drawable.Drawable; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.AudioManagerInternal; @@ -124,6 +125,7 @@ import com.android.server.notification.ManagedServices.UserProfiles; import com.android.server.statusbar.StatusBarManagerInternal; import cyanogenmod.providers.CMSettings; +import cyanogenmod.util.ColorUtils; import libcore.io.IoUtils; @@ -248,6 +250,8 @@ public class NotificationManagerService extends SystemService { private boolean mMultipleNotificationLeds; private boolean mMultipleLedsEnabledSetting = false; + private boolean mAutoGenerateNotificationColor = true; + private boolean mScreenOnEnabled = false; private boolean mScreenOnDefault = false; @@ -287,6 +291,8 @@ public class NotificationManagerService extends SystemService { private boolean mNotificationPulseEnabled; private HashMap<String, NotificationLedValues> mNotificationPulseCustomLedValues; private Map<String, String> mPackageNameMappings; + private final Map<String, Integer> mGeneratedPackageLedColors = + new HashMap<String, Integer>(); // for checking lockscreen status private KeyguardManager mKeyguardManager; @@ -1001,6 +1007,9 @@ public class NotificationManagerService extends SystemService { resolver.registerContentObserver(CMSettings.Global.getUriFor( CMSettings.Global.ZEN_DISABLE_DUCKING_DURING_MEDIA_PLAYBACK), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(CMSettings.System.getUriFor( + CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO), false, + this, UserHandle.USER_ALL); if (mAdjustableNotificationLedBrightness) { resolver.registerContentObserver(CMSettings.System.getUriFor( CMSettings.System.NOTIFICATION_LIGHT_BRIGHTNESS_LEVEL), @@ -1025,6 +1034,11 @@ public class NotificationManagerService extends SystemService { mNotificationPulseEnabled = Settings.System.getIntForUser(resolver, Settings.System.NOTIFICATION_LIGHT_PULSE, 0, UserHandle.USER_CURRENT) != 0; + // Automatically pick a color for LED if not set + mAutoGenerateNotificationColor = CMSettings.System.getIntForUser(resolver, + CMSettings.System.NOTIFICATION_LIGHT_COLOR_AUTO, + 1, UserHandle.USER_CURRENT) != 0; + // LED default color mDefaultNotificationColor = CMSettings.System.getIntForUser(resolver, CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_COLOR, @@ -1040,6 +1054,9 @@ public class NotificationManagerService extends SystemService { CMSettings.System.NOTIFICATION_LIGHT_PULSE_DEFAULT_LED_OFF, mDefaultNotificationLedOff, UserHandle.USER_CURRENT); + // LED generated notification colors + mGeneratedPackageLedColors.clear(); + // LED custom notification colors mNotificationPulseCustomLedValues.clear(); if (CMSettings.System.getIntForUser(resolver, @@ -1219,6 +1236,7 @@ public class NotificationManagerService extends SystemService { mDisableNotificationEffects = true; } mZenModeHelper.initZenMode(); + mZenModeHelper.readAllowLightsFromSettings(); mInterruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter(); mUserProfiles.updateCache(getContext()); @@ -1578,10 +1596,11 @@ public class NotificationManagerService extends SystemService { Binder.getCallingUid(), incomingUserId, true, false, "getAppActiveNotifications", pkg); - final int N = mNotificationList.size(); - final ArrayList<StatusBarNotification> list = new ArrayList<StatusBarNotification>(N); + final ArrayList<StatusBarNotification> list + = new ArrayList<StatusBarNotification>(mNotificationList.size()); synchronized (mNotificationList) { + final int N = mNotificationList.size(); for (int i = 0; i < N; i++) { final StatusBarNotification sbn = mNotificationList.get(i).sbn; if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId) { @@ -2768,8 +2787,9 @@ public class NotificationManagerService extends SystemService { // light // release the light boolean wasShowLights = mLights.remove(record.getKey()); - final boolean aboveThresholdWithLight = aboveThreshold || isLedNotificationForcedOn(record); - if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && aboveThresholdWithLight) { + final boolean canInterruptWithLight = canInterrupt || isLedNotificationForcedOn(record) + || (!canInterrupt && mZenModeHelper.getAllowLights()); + if ((notification.flags & Notification.FLAG_SHOW_LIGHTS) != 0 && canInterruptWithLight) { mLights.add(record.getKey()); updateLightsLocked(); if (mUseAttentionLight) { @@ -3433,7 +3453,7 @@ public class NotificationManagerService extends SystemService { ledOnMS = ledValues.onMS >= 0 ? ledValues.onMS : mDefaultNotificationLedOn; ledOffMS = ledValues.offMS >= 0 ? ledValues.offMS : mDefaultNotificationLedOff; } else if ((ledno.defaults & Notification.DEFAULT_LIGHTS) != 0) { - ledARGB = mDefaultNotificationColor; + ledARGB = generateLedColorForNotification(ledNotification); ledOnMS = mDefaultNotificationLedOn; ledOffMS = mDefaultNotificationLedOff; } else { @@ -3494,6 +3514,33 @@ public class NotificationManagerService extends SystemService { return mNotificationPulseCustomLedValues.get(mapPackage(packageName)); } + private int generateLedColorForNotification(NotificationRecord ledNotification) { + if (!mAutoGenerateNotificationColor) { + return mDefaultNotificationColor; + } + final String packageName = ledNotification.sbn.getPackageName(); + final String mapping = mapPackage(packageName); + int color = mDefaultNotificationColor; + + if (mGeneratedPackageLedColors.containsKey(mapping)) { + return mGeneratedPackageLedColors.get(mapping); + } + + PackageManager pm = getContext().getPackageManager(); + Drawable icon; + try { + icon = pm.getApplicationIcon(mapping); + } catch (NameNotFoundException e) { + Slog.e(TAG, e.getMessage(), e); + return color; + } + + color = ColorUtils.generateAlertColorFromDrawable(icon); + mGeneratedPackageLedColors.put(mapping, color); + + return color; + } + private String mapPackage(String pkg) { if (!mPackageNameMappings.containsKey(pkg)) { return pkg; diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 461c3a2..468ef8d 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -53,6 +53,7 @@ import android.util.SparseArray; import com.android.internal.R; import com.android.internal.logging.MetricsLogger; import com.android.server.LocalServices; +import cyanogenmod.providers.CMSettings; import libcore.io.IoUtils; @@ -89,6 +90,7 @@ public class ZenModeHelper { private ZenModeConfig mConfig; private AudioManagerInternal mAudioManager; private boolean mEffectsSuppressed; + private boolean mAllowLights; public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) { mContext = context; @@ -378,6 +380,7 @@ public class ZenModeHelper { ZenLog.traceSetZenMode(zen, reason); mZenMode = zen; updateRingerModeAffectedStreams(); + readAllowLightsFromSettings(); setZenModeSetting(mZenMode); if (setRingerMode) { applyZenToRingerMode(); @@ -407,6 +410,24 @@ public class ZenModeHelper { return zen; } + public boolean getAllowLights() { + return mAllowLights; + } + + public void readAllowLightsFromSettings() { + switch (mZenMode) { + case Global.ZEN_MODE_NO_INTERRUPTIONS: + case Global.ZEN_MODE_ALARMS: + mAllowLights = CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.ZEN_ALLOW_LIGHTS, 1) == 1; + break; + case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: + mAllowLights = CMSettings.System.getInt(mContext.getContentResolver(), + CMSettings.System.ZEN_PRIORITY_ALLOW_LIGHTS, 1) == 1; + break; + } + } + private void applyRestrictions() { final boolean zen = mZenMode != Global.ZEN_MODE_OFF; @@ -415,13 +436,14 @@ public class ZenModeHelper { applyRestrictions(muteNotifications, USAGE_NOTIFICATION); // call restrictions - final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers - || mEffectsSuppressed; + final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers; applyRestrictions(muteCalls, USAGE_NOTIFICATION_RINGTONE); // alarm restrictions final boolean muteAlarms = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS; applyRestrictions(muteAlarms, USAGE_ALARM); + + readAllowLightsFromSettings(); } private void applyRestrictions(boolean mute, int usage) { @@ -692,6 +714,10 @@ public class ZenModeHelper { private final class SettingsObserver extends ContentObserver { private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE); + private final Uri ZEN_ALLOW_LIGHTS = CMSettings.System.getUriFor( + CMSettings.System.ZEN_ALLOW_LIGHTS); + private final Uri ZEN_PRIORITY_ALLOW_LIGHTS = CMSettings.System.getUriFor( + CMSettings.System.ZEN_PRIORITY_ALLOW_LIGHTS); public SettingsObserver(Handler handler) { super(handler); @@ -700,6 +726,10 @@ public class ZenModeHelper { public void observe() { final ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this); + resolver.registerContentObserver( + ZEN_ALLOW_LIGHTS, false /*notifyForDescendents*/, this); + resolver.registerContentObserver( + ZEN_PRIORITY_ALLOW_LIGHTS, false /*notifyForDescendents*/, this); update(null); } @@ -714,6 +744,8 @@ public class ZenModeHelper { if (DEBUG) Log.d(TAG, "Fixing zen mode setting"); setZenModeSetting(mZenMode); } + } else if (ZEN_ALLOW_LIGHTS.equals(uri) || ZEN_PRIORITY_ALLOW_LIGHTS.equals(uri)) { + readAllowLightsFromSettings(); } } } diff --git a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java index df023fd..29e9fa6 100644 --- a/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java @@ -572,6 +572,26 @@ final class DefaultPermissionGrantPolicy { grantRuntimePermissionsLPw(musicPackage, STORAGE_PERMISSIONS, userId); } + // Android Wear Home + if (mService.hasSystemFeature(PackageManager.FEATURE_WATCH)) { + Intent homeIntent = new Intent(Intent.ACTION_MAIN); + homeIntent.addCategory(Intent.CATEGORY_HOME_MAIN); + + PackageParser.Package wearHomePackage = getDefaultSystemHandlerActivityPackageLPr( + homeIntent, userId); + + if (wearHomePackage != null + && doesPackageSupportRuntimePermissions(wearHomePackage)) { + grantRuntimePermissionsLPw(wearHomePackage, CONTACTS_PERMISSIONS, false, + userId); + grantRuntimePermissionsLPw(wearHomePackage, PHONE_PERMISSIONS, true, userId); + grantRuntimePermissionsLPw(wearHomePackage, MICROPHONE_PERMISSIONS, false, + userId); + grantRuntimePermissionsLPw(wearHomePackage, LOCATION_PERMISSIONS, false, + userId); + } + } + mService.mSettings.onDefaultRuntimePermissionsGrantedLPr(userId); } } @@ -579,7 +599,10 @@ final class DefaultPermissionGrantPolicy { private void grantDefaultPermissionsToDefaultSystemDialerAppLPr( PackageParser.Package dialerPackage, int userId) { if (doesPackageSupportRuntimePermissions(dialerPackage)) { - grantRuntimePermissionsLPw(dialerPackage, PHONE_PERMISSIONS, userId); + boolean isPhonePermFixed = + mService.hasSystemFeature(PackageManager.FEATURE_WATCH); + grantRuntimePermissionsLPw( + dialerPackage, PHONE_PERMISSIONS, isPhonePermFixed, userId); grantRuntimePermissionsLPw(dialerPackage, CONTACTS_PERMISSIONS, userId); grantRuntimePermissionsLPw(dialerPackage, SMS_PERMISSIONS, userId); grantRuntimePermissionsLPw(dialerPackage, MICROPHONE_PERMISSIONS, userId); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 8abb9f0..d5c58df 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -17,7 +17,6 @@ package com.android.server.pm; -import static android.Manifest.permission.ACCESS_THEME_MANAGER; import static android.Manifest.permission.READ_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE; import static android.Manifest.permission.WRITE_MEDIA_STORAGE; @@ -92,6 +91,7 @@ import android.content.res.Configuration; import android.Manifest; +import cyanogenmod.app.CMContextConstants; import cyanogenmod.app.suggest.AppSuggestManager; import android.app.ActivityManager; @@ -156,14 +156,12 @@ import android.content.pm.ServiceInfo; import android.content.pm.Signature; import android.content.pm.UserInfo; import android.content.pm.ManifestDigest; -import android.content.pm.ThemeUtils; import android.content.pm.VerificationParams; import android.content.pm.VerifierDeviceIdentity; import android.content.pm.VerifierInfo; import android.content.res.Resources; import android.content.res.AssetManager; import android.content.res.ThemeConfig; -import android.content.res.ThemeManager; import android.hardware.display.DisplayManager; import android.net.Uri; import android.os.Debug; @@ -222,6 +220,8 @@ import android.util.Xml; import android.view.Display; import cyanogenmod.providers.CMSettings; +import cyanogenmod.themes.IThemeService; + import dalvik.system.DexFile; import dalvik.system.VMRuntime; @@ -254,6 +254,7 @@ import com.android.server.pm.Settings.DatabaseVersion; import com.android.server.pm.Settings.VersionInfo; import com.android.server.storage.DeviceStorageMonitorInternal; +import org.cyanogenmod.internal.util.ThemeUtils; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; @@ -303,8 +304,6 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** * Keep track of all those .apks everywhere. @@ -463,6 +462,9 @@ public class PackageManagerService extends IPackageManager.Stub { private static final long COMMON_RESOURCE_EXPIRATION = 3*60*1000; // 3 minutes + private static final String PROTECTED_APPS_TARGET_VALIDATION_COMPONENT = + "com.android.settings/com.android.settings.applications.ProtectedAppsActivity"; + /** * The offset in bytes to the beginning of the hashes in an idmap */ @@ -1462,7 +1464,8 @@ public class PackageManagerService extends IPackageManager.Stub { } String category = null; if(res.pkg.mIsThemeApk) { - category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; + category = cyanogenmod.content.Intent + .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; } sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, null, extras, null, null, updateUsers); @@ -8269,7 +8272,8 @@ public class PackageManagerService extends IPackageManager.Stub { boolean hasCommonResources = (hasCommonResources(pkg) && !COMMON_OVERLAY.equals(target)); PackageParser.Package targetPkg = mPackages.get(target); - String appPath = targetPkg != null ? targetPkg.baseCodePath : ""; + String appPath = targetPkg != null ? targetPkg.baseCodePath : + Environment.getRootDirectory() + "/framework/framework-res.apk"; if (mInstaller.aapt(pkg.baseCodePath, internalPath, resPath, sharedGid, pkgId, pkg.applicationInfo.targetSdkVersion, @@ -13538,7 +13542,8 @@ public class PackageManagerService extends IPackageManager.Stub { String category = null; if (info.isThemeApk) { - category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; + category = cyanogenmod.content.Intent + .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; } sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName, category, @@ -13583,7 +13588,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (removedPackage != null) { String category = null; if (isThemeApk) { - category = Intent.CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; + category = cyanogenmod.content.Intent + .CATEGORY_THEME_PACKAGE_INSTALLED_STATE_CHANGE; } sendPackageBroadcast(Intent.ACTION_PACKAGE_REMOVED, removedPackage, category, extras, null, null, removedUsers); @@ -17223,6 +17229,11 @@ public class PackageManagerService extends IPackageManager.Stub { return false; } + if (TextUtils.equals(PROTECTED_APPS_TARGET_VALIDATION_COMPONENT, + componentName.flattenToString())) { + return false; + } + PackageSetting pkgSetting; ArraySet<String> components; @@ -17698,8 +17709,11 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public int processThemeResources(String themePkgName) { mContext.enforceCallingOrSelfPermission( - Manifest.permission.ACCESS_THEME_MANAGER, null); - PackageParser.Package pkg = mPackages.get(themePkgName); + cyanogenmod.platform.Manifest.permission.ACCESS_THEME_MANAGER, null); + PackageParser.Package pkg; + synchronized (mPackages) { + pkg = mPackages.get(themePkgName); + } if (pkg == null) { Log.w(TAG, "Unable to get pkg for processing " + themePkgName); return 0; @@ -17720,11 +17734,15 @@ public class PackageManagerService extends IPackageManager.Stub { // Generate Idmaps and res tables if pkg is a theme Iterator<String> iterator = pkg.mOverlayTargets.iterator(); - while(iterator.hasNext()) { + while (iterator.hasNext()) { String target = iterator.next(); Exception failedException = null; + PackageParser.Package targetPkg; + synchronized (mPackages) { + targetPkg = mPackages.get(target); + } try { - compileResourcesAndIdmapIfNeeded(mPackages.get(target), pkg); + compileResourcesAndIdmapIfNeeded(targetPkg, pkg); } catch (IdmapException e) { failedException = e; } catch (AaptException e) { @@ -17735,7 +17753,7 @@ public class PackageManagerService extends IPackageManager.Stub { if (failedException != null) { Slog.w(TAG, "Unable to process theme " + pkg.packageName + " for " + target, - failedException); + failedException); // remove target from mOverlayTargets iterator.remove(); } @@ -17745,10 +17763,16 @@ public class PackageManagerService extends IPackageManager.Stub { } private void processThemeResourcesInThemeService(String pkgName) { - ThemeManager tm = - (ThemeManager) mContext.getSystemService(Context.THEME_SERVICE); - if (tm != null) { - tm.processThemeResources(pkgName); + IThemeService ts = IThemeService.Stub.asInterface(ServiceManager.getService( + CMContextConstants.CM_THEME_SERVICE)); + if (ts == null) { + Slog.e(TAG, "Theme service not available"); + return; + } + try { + ts.processThemeResources(pkgName); + } catch (RemoteException e) { + /* ignore */ } } diff --git a/services/core/java/com/android/server/pm/UserContentObserver.java b/services/core/java/com/android/server/pm/UserContentObserver.java new file mode 100644 index 0000000..6145c3b --- /dev/null +++ b/services/core/java/com/android/server/pm/UserContentObserver.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2016 The CyanogenMod 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.pm; + +import android.app.ActivityManagerNative; +import android.app.IUserSwitchObserver; +import android.database.ContentObserver; +import android.net.Uri; +import android.os.Handler; +import android.os.IRemoteCallback; +import android.os.RemoteException; +import android.util.Log; + +/** + * Simple extension of ContentObserver that also listens for user switch events to call update + */ +public abstract class UserContentObserver extends ContentObserver { + private static final String TAG = "UserContentObserver"; + + private Runnable mUpdateRunnable; + + private IUserSwitchObserver mUserSwitchObserver = new IUserSwitchObserver.Stub() { + @Override + public void onUserSwitching(int newUserId, IRemoteCallback reply) { + } + @Override + public void onUserSwitchComplete(int newUserId) throws RemoteException { + mHandler.post(mUpdateRunnable); + } + @Override + public void onForegroundProfileSwitch(int newProfileId) { + } + }; + + private Handler mHandler; + + /** + * Content observer that tracks user switches + * to allow clients to re-load settings for current user + */ + public UserContentObserver(Handler handler) { + super(handler); + mHandler = handler; + mUpdateRunnable = new Runnable() { + @Override + public void run() { + update(); + } + }; + } + + protected void observe() { + try { + ActivityManagerNative.getDefault().registerUserSwitchObserver(mUserSwitchObserver); + } catch (RemoteException e) { + Log.w(TAG, "Unable to register user switch observer!", e); + } + } + + protected void unobserve() { + try { + mHandler.removeCallbacks(mUpdateRunnable); + ActivityManagerNative.getDefault().unregisterUserSwitchObserver(mUserSwitchObserver); + } catch (RemoteException e) { + Log.w(TAG, "Unable to unregister user switch observer!", e); + } + } + + /** + * Called to notify of registered uri changes and user switches. + * Always invoked on the handler passed in at construction + */ + protected abstract void update(); + + @Override + public void onChange(boolean selfChange, Uri uri) { + update(); + } +} diff --git a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java index fef1e57..e6ec6a6 100644 --- a/services/core/java/com/android/server/policy/BurnInProtectionHelper.java +++ b/services/core/java/com/android/server/policy/BurnInProtectionHelper.java @@ -72,6 +72,9 @@ public class BurnInProtectionHelper implements DisplayManager.DisplayListener, /* 1 means increasing, -1 means decreasing */ private int mYOffsetDirection = 1; + private int mAppliedBurnInXOffset = 0; + private int mAppliedBurnInYOffset = 0; + private final AlarmManager mAlarmManager; private final PendingIntent mBurnInProtectionIntent; private final DisplayManagerInternal mDisplayManagerInternal; @@ -139,6 +142,8 @@ public class BurnInProtectionHelper implements DisplayManager.DisplayListener, mFirstUpdate = false; } else { adjustOffsets(); + mAppliedBurnInXOffset = mLastBurnInXOffset; + mAppliedBurnInYOffset = mLastBurnInYOffset; mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), mLastBurnInXOffset, mLastBurnInYOffset); } @@ -258,6 +263,8 @@ public class BurnInProtectionHelper implements DisplayManager.DisplayListener, @Override public void onAnimationEnd(Animator animator) { if (animator == mCenteringAnimator && !mBurnInProtectionActive) { + mAppliedBurnInXOffset = 0; + mAppliedBurnInYOffset = 0; // No matter how the animation finishes, we want to zero the offsets. mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), 0, 0); } @@ -276,7 +283,7 @@ public class BurnInProtectionHelper implements DisplayManager.DisplayListener, if (!mBurnInProtectionActive) { final float value = (Float) valueAnimator.getAnimatedValue(); mDisplayManagerInternal.setDisplayOffsets(mDisplay.getDisplayId(), - (int) (mLastBurnInXOffset * value), (int) (mLastBurnInYOffset * value)); + (int) (mAppliedBurnInXOffset * value), (int) (mAppliedBurnInYOffset * value)); } } } diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java index 8c42917..9b5f5d0 100644 --- a/services/core/java/com/android/server/policy/GlobalActions.java +++ b/services/core/java/com/android/server/policy/GlobalActions.java @@ -22,12 +22,14 @@ import com.android.internal.app.AlertController.AlertParams; import com.android.internal.telephony.TelephonyIntents; import com.android.internal.telephony.TelephonyProperties; import com.android.internal.R; +import com.android.internal.util.UserIcons; import com.android.internal.widget.LockPatternUtils; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AlertDialog; import android.app.Dialog; +import android.app.INotificationManager; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.Context; @@ -35,10 +37,17 @@ import android.content.ContentResolver; import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.ThemeUtils; import android.content.pm.UserInfo; import android.content.ServiceConnection; import android.database.ContentObserver; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.Manifest; import android.media.AudioManager; @@ -58,6 +67,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.Vibrator; import android.provider.Settings; +import android.provider.Settings.Global; import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.telephony.PhoneStateListener; @@ -84,12 +94,15 @@ import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.ListView; import android.widget.TextView; + import cyanogenmod.providers.CMSettings; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import org.cyanogenmod.internal.util.ThemeUtils; + import static com.android.internal.util.cm.PowerMenuConstants.*; /** @@ -163,6 +176,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); + // Set the initial status of airplane mode toggle + mAirplaneState = getUpdatedAirplaneToggleState(); + updatePowerMenuActions(); } @@ -612,16 +628,24 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac if (um.isUserSwitcherEnabled()) { List<UserInfo> users = um.getUsers(); UserInfo currentUser = getCurrentUser(); + final int avatarSize = mContext.getResources().getDimensionPixelSize( + com.android.internal.R.dimen.global_actions_avatar_size); for (final UserInfo user : users) { if (user.supportsSwitchTo()) { boolean isCurrentUser = currentUser == null ? user.id == 0 : (currentUser.id == user.id); - Drawable icon = user.iconPath != null ? Drawable.createFromPath(user.iconPath) - : null; + Drawable avatar = null; + Bitmap rawAvatar = um.getUserIcon(user.id); + if (rawAvatar == null) { + rawAvatar = UserIcons.convertToBitmap(UserIcons.getDefaultUserIcon( + user.isGuest() ? UserHandle.USER_NULL : user.id, /*light=*/ false)); + } + avatar = new BitmapDrawable(mContext.getResources(), + createCircularClip(rawAvatar, avatarSize, avatarSize)); + SinglePressAction switchToUser = new SinglePressAction( - com.android.internal.R.drawable.ic_lock_user, icon, - (user.name != null ? user.name : "Primary") - + (isCurrentUser ? " \u2714" : "")) { + com.android.internal.R.drawable.ic_lock_user, avatar, + (user.name != null ? user.name : "Primary")) { public void onPress() { try { ActivityManagerNative.getDefault().switchUser(user.id); @@ -638,6 +662,10 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac return false; } }; + if (isCurrentUser) { + switchToUser.setStatus(mContext.getString( + R.string.global_action_current_user)); + } items.add(switchToUser); } } @@ -721,7 +749,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac @Override public void onServiceDisconnected(ComponentName name) {} }; - if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) { + if (mContext.bindServiceAsUser( + intent, conn, Context.BIND_AUTO_CREATE, UserHandle.CURRENT)) { mScreenshotConnection = conn; mHandler.postDelayed(mScreenshotTimeout, 10000); } @@ -890,6 +919,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private final Drawable mIcon; private final int mMessageResId; private final CharSequence mMessage; + private CharSequence mStatusMessage; protected SinglePressAction(int iconResId, int messageResId) { mIconResId = iconResId; @@ -916,8 +946,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac return true; } - public String getStatus() { - return null; + public CharSequence getStatus() { + return mStatusMessage; + } + + public void setStatus(CharSequence status) { + mStatusMessage = status; } abstract public void onPress(); @@ -938,7 +972,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac TextView messageView = (TextView) v.findViewById(R.id.message); TextView statusView = (TextView) v.findViewById(R.id.status); - final String status = getStatus(); + final CharSequence status = getStatus(); if (!TextUtils.isEmpty(status)) { statusView.setText(status); } else { @@ -946,7 +980,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } if (mIcon != null) { icon.setImageDrawable(mIcon); - icon.setScaleType(ScaleType.CENTER_CROP); + icon.setScaleType(ScaleType.CENTER); } else if (mIconResId != 0) { icon.setImageDrawable(context.getDrawable(mIconResId)); } @@ -1116,9 +1150,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } } - private static class SilentModeTriStateAction implements Action, View.OnClickListener { + private final class SilentModeTriStateAction implements Action, View.OnClickListener { - private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3 }; + private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3, R.id.option4 }; private final AudioManager mAudioManager; private final Handler mHandler; @@ -1130,14 +1164,15 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mContext = context; } - private int ringerModeToIndex(int ringerMode) { - // They just happen to coincide - return ringerMode; - } - private int indexToRingerMode(int index) { - // They just happen to coincide - return index; + if (index == 2) { + if (mHasVibrator) { + return AudioManager.RINGER_MODE_VIBRATE; + } else { + return AudioManager.RINGER_MODE_NORMAL; + } + } + return AudioManager.RINGER_MODE_NORMAL; } @Override @@ -1149,9 +1184,28 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac LayoutInflater inflater) { View v = inflater.inflate(R.layout.global_actions_silent_mode, parent, false); - int selectedIndex = ringerModeToIndex(mAudioManager.getRingerMode()); - for (int i = 0; i < 3; i++) { + int ringerMode = mAudioManager.getRingerModeInternal(); + int zenMode = Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, + Global.ZEN_MODE_OFF); + int selectedIndex = 0; + if (zenMode != Global.ZEN_MODE_OFF) { + if (zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) { + selectedIndex = 0; + } else if (zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { + selectedIndex = 1; + } + } else if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { + selectedIndex = 2; + } else if (ringerMode == AudioManager.RINGER_MODE_NORMAL) { + selectedIndex = 3; + } + + for (int i = 0; i < ITEM_IDS.length; i++) { View itemView = v.findViewById(ITEM_IDS[i]); + if (!mHasVibrator && i == 2) { + itemView.setVisibility(View.GONE); + continue; + } itemView.setSelected(selectedIndex == i); // Set up click handler itemView.setTag(i); @@ -1182,7 +1236,28 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac if (!(v.getTag() instanceof Integer)) return; int index = (Integer) v.getTag(); - mAudioManager.setRingerMode(indexToRingerMode(index)); + if (index == 0 || index == 1) { + int zenMode = index == 0 + ? Global.ZEN_MODE_NO_INTERRUPTIONS + : Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; + // ZenModeHelper will revert zen mode back to the previous value if we just + // put the value into the Settings db, so use INotificationManager instead + INotificationManager noMan = INotificationManager.Stub.asInterface( + ServiceManager.getService(Context.NOTIFICATION_SERVICE)); + try { + noMan.setZenMode(zenMode, null, TAG); + } catch (RemoteException e) { + Log.e(TAG, "Unable to set zen mode", e); + } + } else { + Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF); + } + + if (index == 2 || index == 3) { + int ringerMode = indexToRingerMode(index); + mAudioManager.setRingerModeInternal(ringerMode); + } + mAdapter.notifyDataSetChanged(); mHandler.sendEmptyMessageDelayed(MESSAGE_DISMISS, DIALOG_DISMISS_DELAY); } } @@ -1274,15 +1349,17 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } }; + private ToggleAction.State getUpdatedAirplaneToggleState() { + return (Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.AIRPLANE_MODE_ON, 0) == 1) ? + ToggleAction.State.On : ToggleAction.State.Off; + } + private void onAirplaneModeChanged() { // Let the service state callbacks handle the state. if (mHasTelephony) return; - boolean airplaneModeOn = Settings.Global.getInt( - mContext.getContentResolver(), - Settings.Global.AIRPLANE_MODE_ON, - 0) == 1; - mAirplaneState = airplaneModeOn ? ToggleAction.State.On : ToggleAction.State.Off; + mAirplaneState = getUpdatedAirplaneToggleState(); mAirplaneModeOn.updateState(mAirplaneState); } @@ -1303,6 +1380,33 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } } + /** + * Generate a new bitmap (width x height pixels, ARGB_8888) with the input bitmap scaled + * to fit and clipped to an inscribed circle. + * @param input Bitmap to resize and clip + * @param width Width of output bitmap (and diameter of circle) + * @param height Height of output bitmap + * @return A shiny new bitmap for you to use + */ + private static Bitmap createCircularClip(Bitmap input, int width, int height) { + if (input == null) return null; + + final int inWidth = input.getWidth(); + final int inHeight = input.getHeight(); + final Bitmap output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + final Canvas canvas = new Canvas(output); + final Paint paint = new Paint(); + paint.setShader(new BitmapShader(input, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)); + paint.setAntiAlias(true); + final RectF srcRect = new RectF(0, 0, inWidth, inHeight); + final RectF dstRect = new RectF(0, 0, width, height); + final Matrix m = new Matrix(); + m.setRectToRect(srcRect, dstRect, Matrix.ScaleToFit.CENTER); + canvas.setMatrix(m); + canvas.drawCircle(inWidth / 2, inHeight / 2, inWidth / 2, paint); + return output; + } + private static final class GlobalActionsDialog extends Dialog implements DialogInterface { private final Context mContext; private final int mWindowTouchSlop; diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 58f26fa..9cb969c 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -83,10 +83,11 @@ import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.speech.RecognizerIntent; import android.telecom.TelecomManager; -import android.service.gesture.EdgeGestureManager; import com.android.internal.os.DeviceKeyHandler; import com.android.internal.util.cm.ActionUtils; + +import cyanogenmod.hardware.CMHardwareManager; import cyanogenmod.providers.CMSettings; import dalvik.system.DexClassLoader; import android.util.DisplayMetrics; @@ -129,8 +130,6 @@ import com.android.internal.R; import com.android.internal.policy.IKeyguardService; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.util.ScreenShapeHelper; -import com.android.internal.util.gesture.EdgeGesturePosition; -import com.android.internal.util.gesture.EdgeServiceConstants; import com.android.internal.view.RotationPolicy; import com.android.internal.widget.PointerLocationView; import com.android.server.GestureLauncherService; @@ -749,6 +748,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mHasPermanentMenuKey; private boolean mClearedBecauseOfForceShow; private boolean mTopWindowIsKeyguard; + private CMHardwareManager mCMHardware; private class PolicyHandler extends Handler { @Override @@ -899,9 +899,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { CMSettings.System.VOLBTN_MUSIC_CONTROLS), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(CMSettings.System.getUriFor( - CMSettings.System.USE_EDGE_SERVICE_FOR_GESTURES), false, this, - UserHandle.USER_ALL); - resolver.registerContentObserver(CMSettings.System.getUriFor( CMSettings.System.BACK_WAKE_SCREEN), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(CMSettings.System.getUriFor( @@ -995,67 +992,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { private SystemGesturesPointerEventListener mSystemGestures; - private EdgeGestureManager.EdgeGestureActivationListener mEdgeGestureActivationListener - = new EdgeGestureManager.EdgeGestureActivationListener() { - - @Override - public void onEdgeGestureActivation(int touchX, int touchY, - EdgeGesturePosition position, int flags) { - WindowState target = null; - - if (position == EdgeGesturePosition.TOP) { - target = mStatusBar; - } else if (position == EdgeGesturePosition.BOTTOM && mNavigationBarOnBottom) { - target = mNavigationBar; - } else if (position == EdgeGesturePosition.LEFT - && !mNavigationBarOnBottom && mNavigationBarLeftInLandscape) { - target = mNavigationBar; - } else if (position == EdgeGesturePosition.RIGHT && !mNavigationBarOnBottom) { - target = mNavigationBar; - } - - if (target != null) { - requestTransientBars(target); - dropEventsUntilLift(); - mEdgeListenerActivated = true; - } else { - restoreListenerState(); - } - } - }; - private EdgeGestureManager mEdgeGestureManager = null; - private int mLastEdgePositions = 0; - private boolean mEdgeListenerActivated = false; - private boolean mUsingEdgeGestureServiceForGestures = false; - - private void updateEdgeGestureListenerState() { - int flags = 0; - if (mUsingEdgeGestureServiceForGestures) { - flags = EdgeServiceConstants.LONG_LIVING | EdgeServiceConstants.UNRESTRICTED; - if (mStatusBar != null && !mStatusBar.isVisibleLw()) { - flags |= EdgeGesturePosition.TOP.FLAG; - } - if (mNavigationBar != null && !mNavigationBar.isVisibleLw() && !isStatusBarKeyguard()) { - if (mNavigationBarOnBottom) { - flags |= EdgeGesturePosition.BOTTOM.FLAG; - } else if (mNavigationBarLeftInLandscape) { - flags |= EdgeGesturePosition.LEFT.FLAG; - } else { - flags |= EdgeGesturePosition.RIGHT.FLAG; - } - } - } - if (mEdgeListenerActivated) { - mEdgeGestureActivationListener.restoreListenerState(); - mEdgeListenerActivated = false; - } - if (flags != mLastEdgePositions) { - mEdgeGestureManager.updateEdgeGestureActivationListener(mEdgeGestureActivationListener, - flags); - mLastEdgePositions = flags; - } - } - IStatusBarService getStatusBarService() { synchronized (mServiceAquireLock) { if (mStatusBarService == null) { @@ -1634,6 +1570,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mDreamManagerInternal = LocalServices.getService(DreamManagerInternal.class); mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); + mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); // Init display burn-in protection boolean burnInProtectionEnabled = context.getResources().getBoolean( @@ -1677,7 +1614,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mOrientationListener.setCurrentRotation(windowManager.getRotation()); } catch (RemoteException ex) { } mSettingsObserver = new SettingsObserver(mHandler); - mSettingsObserver.observe(); mShortcutManager = new ShortcutManager(context); mUiMode = context.getResources().getInteger( com.android.internal.R.integer.config_defaultUiModeType); @@ -2186,23 +2122,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateWakeGestureListenerLp(); } - final boolean useEdgeService = CMSettings.System.getIntForUser(resolver, - CMSettings.System.USE_EDGE_SERVICE_FOR_GESTURES, 0, UserHandle.USER_CURRENT) == 1; - if (useEdgeService ^ mUsingEdgeGestureServiceForGestures && mSystemReady) { - if (!mUsingEdgeGestureServiceForGestures && useEdgeService) { - mUsingEdgeGestureServiceForGestures = true; - mWindowManagerFuncs.unregisterPointerEventListener(mSystemGestures); - } else if (mUsingEdgeGestureServiceForGestures && !useEdgeService) { - mUsingEdgeGestureServiceForGestures = false; - mWindowManagerFuncs.registerPointerEventListener(mSystemGestures); - } - updateEdgeGestureListenerState(); - } - boolean devForceNavbar = CMSettings.Secure.getIntForUser(resolver, CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; if (devForceNavbar != mDevForceNavbar) { mDevForceNavbar = devForceNavbar; + if (mCMHardware.isSupported(CMHardwareManager.FEATURE_KEY_DISABLE)) { + mCMHardware.set(CMHardwareManager.FEATURE_KEY_DISABLE, mDevForceNavbar); + } } mNavigationBarLeftInLandscape = CMSettings.System.getIntForUser(resolver, @@ -3167,19 +3093,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { + " canceled=" + canceled); } - // If the boot mode is power off alarm, we should not dispatch the several physical keys - // in power off alarm UI to avoid pausing power off alarm UI. - int isPowerOffAlarmMode = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.POWER_OFF_ALARM_MODE, 0); - if (DEBUG_INPUT) { Log.d(TAG, "intercept Dispatching isPowerOffAlarmMode = " + - isPowerOffAlarmMode); } - - if (isPowerOffAlarmMode == 1 && (keyCode == KeyEvent.KEYCODE_HOME - || keyCode == KeyEvent.KEYCODE_SEARCH - || keyCode == KeyEvent.KEYCODE_MENU)) { - return -1; // ignore the physical key here - } - // If we think we might have a volume down & power key chord on the way // but we're not sure, then tell the dispatcher to wait a little while and // try again later before dispatching. @@ -4042,8 +3955,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { mNavigationBarController.adjustSystemUiVisibilityLw(mLastSystemUiFlags, visibility); mRecentsVisible = (visibility & View.RECENT_APPS_VISIBLE) > 0; - updateEdgeGestureListenerState(); - // Reset any bits in mForceClearingStatusBarVisibility that // are now clear. mResettingSystemUiFlags &= visibility; @@ -5372,7 +5283,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { // update since mAllowLockscreenWhenOn might have changed updateLockScreenTimeout(); - updateEdgeGestureListenerState(); return changes; } @@ -5661,7 +5571,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (isValidGlobalKey(keyCode) && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) { if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, + "android.policy:KEY", true); } return result; } @@ -5924,6 +5835,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { break; } + case KeyEvent.KEYCODE_SOFT_SLEEP: { + result &= ~ACTION_PASS_TO_USER; + isWakeKey = false; + if (!down) { + mPowerManagerInternal.setUserInactiveOverrideFromWindowManager(); + } + break; + } + case KeyEvent.KEYCODE_WAKEUP: { result &= ~ACTION_PASS_TO_USER; isWakeKey = true; @@ -5999,7 +5919,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY"); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY", true); } return result; @@ -6136,11 +6056,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private boolean shouldDispatchInputWhenNonInteractive() { - if (mDisplay == null || mDisplay.getState() == Display.STATE_OFF) { - return false; - } - // Send events to keyguard while the screen is on and it's showing. - if (isKeyguardShowingAndNotOccluded()) { + // Send events to keyguard while the screen is on. + if (isKeyguardShowingAndNotOccluded() && mDisplay != null + && mDisplay.getState() != Display.STATE_OFF) { return true; } @@ -6439,10 +6357,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void wakeUpFromPowerKey(long eventTime) { - wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); + wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER", true); } private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { + return wakeUp(wakeTime, wakeInTheaterMode, reason, false); + } + + private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason, + boolean withProximityCheck) { final boolean theaterModeEnabled = isTheaterModeEnabled(); if (!wakeInTheaterMode && theaterModeEnabled) { return false; @@ -6453,7 +6376,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { Settings.Global.THEATER_MODE_ON, 0); } - mPowerManager.wakeUp(wakeTime, reason); + if (withProximityCheck) { + mPowerManager.wakeUpWithProximityCheck(wakeTime, reason); + } else { + mPowerManager.wakeUp(wakeTime, reason); + } return true; } @@ -6968,8 +6895,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardDelegate = new KeyguardServiceDelegate(mContext); mKeyguardDelegate.onSystemReady(); - mEdgeGestureManager = EdgeGestureManager.getInstance(); - mEdgeGestureManager.setEdgeGestureActivationListener(mEdgeGestureActivationListener); + mCMHardware = CMHardwareManager.getInstance(mContext); + // Ensure observe happens in systemReady() since we need + // CMHardwareService to be up and running + mSettingsObserver.observe(); readCameraLensCoverState(); updateUiMode(); diff --git a/services/core/java/com/android/server/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java index 9916223..651ee22 100644 --- a/services/core/java/com/android/server/policy/WindowOrientationListener.java +++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java @@ -55,6 +55,7 @@ public abstract class WindowOrientationListener { private boolean mEnabled; private int mRate; private String mSensorType; + private boolean mUseSystemClockforRotationSensor; private Sensor mSensor; private OrientationJudge mOrientationJudge; private int mCurrentRotation = -1; @@ -90,6 +91,9 @@ public abstract class WindowOrientationListener { mSensorType = context.getResources().getString( com.android.internal.R.string.config_orientationSensorType); + mUseSystemClockforRotationSensor = context.getResources().getBoolean( + com.android.internal.R.bool.config_useSystemClockforRotationSensor); + if (!TextUtils.isEmpty(mSensorType)) { List<Sensor> sensors = mSensorManager.getSensorList(Sensor.TYPE_ALL); final int N = sensors.size(); @@ -598,7 +602,8 @@ public abstract class WindowOrientationListener { // Reset the orientation listener state if the samples are too far apart in time // or when we see values of (0, 0, 0) which indicates that we polled the // accelerometer too soon after turning it on and we don't have any data yet. - final long now = event.timestamp; + final long now = mUseSystemClockforRotationSensor + ? SystemClock.elapsedRealtimeNanos() : event.timestamp; final long then = mLastFilteredTimestampNanos; final float timeDeltaMS = (now - then) * 0.000001f; final boolean skipSample; diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 05ab6b6..1fd1fbd 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -434,6 +434,14 @@ public final class PowerManagerService extends SystemService // Use -1 to disable. private int mButtonBrightnessOverrideFromWindowManager = -1; + // The window manager has determined the user to be inactive via other means. + // Set this to false to disable. + private boolean mUserInactiveOverrideFromWindowManager; + + // The next possible user activity timeout after being explicitly told the user is inactive. + // Set to -1 when not told the user is inactive since the last period spent dozing or asleep. + private long mOverriddenTimeout = -1; + // The user activity timeout override from the window manager // to allow the current foreground activity to override the user activity timeout. // Use -1 to disable. @@ -516,6 +524,7 @@ public final class PowerManagerService extends SystemService private boolean mProximityWakeSupported; android.os.PowerManager.WakeLock mProximityWakeLock; SensorEventListener mProximityListener; + private boolean mForceNavbar; private PerformanceManagerInternal mPerf; @@ -690,6 +699,9 @@ public final class PowerManagerService extends SystemService resolver.registerContentObserver(CMSettings.Global.getUriFor( CMSettings.Global.WAKE_WHEN_PLUGGED_OR_UNPLUGGED), false, mSettingsObserver, UserHandle.USER_ALL); + resolver.registerContentObserver(CMSettings.Secure.getUriFor( + CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR), + false, mSettingsObserver, UserHandle.USER_ALL); // Go. readConfigurationLocked(); @@ -834,7 +846,8 @@ public final class PowerManagerService extends SystemService mKeyboardBrightness = CMSettings.Secure.getIntForUser(resolver, CMSettings.Secure.KEYBOARD_BRIGHTNESS, mKeyboardBrightnessSettingDefault, UserHandle.USER_CURRENT); - + mForceNavbar = CMSettings.Secure.getIntForUser(resolver, + CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; mDirty |= DIRTY_SETTINGS; } @@ -1151,6 +1164,11 @@ public final class PowerManagerService extends SystemService mNotifier.onUserActivity(event, uid); + if (mUserInactiveOverrideFromWindowManager) { + mUserInactiveOverrideFromWindowManager = false; + mOverriddenTimeout = -1; + } + if (mWakefulness == WAKEFULNESS_ASLEEP || mWakefulness == WAKEFULNESS_DOZING || (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) { @@ -1366,12 +1384,28 @@ public final class PowerManagerService extends SystemService } } + /** + * Logs the time the device would have spent awake before user activity timeout, + * had the system not been told the user was inactive. + */ + private void logSleepTimeoutRecapturedLocked() { + final long now = SystemClock.uptimeMillis(); + final long savedWakeTimeMs = mOverriddenTimeout - now; + if (savedWakeTimeMs >= 0) { + EventLog.writeEvent(EventLogTags.POWER_SOFT_SLEEP_REQUESTED, savedWakeTimeMs); + mOverriddenTimeout = -1; + } + } + private void finishWakefulnessChangeIfNeededLocked() { if (mWakefulnessChanging && mDisplayReady) { if (mWakefulness == WAKEFULNESS_DOZING && (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) { return; // wait until dream has enabled dozing } + if (mWakefulness == WAKEFULNESS_DOZING || mWakefulness == WAKEFULNESS_ASLEEP) { + logSleepTimeoutRecapturedLocked(); + } mWakefulnessChanging = false; mNotifier.onWakefulnessChangeFinished(); } @@ -1657,6 +1691,7 @@ public final class PowerManagerService extends SystemService final int sleepTimeout = getSleepTimeoutLocked(); final int screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout); final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout); + final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager; mUserActivitySummary = 0; if (mLastUserActivityTime >= mLastWakeTime) { @@ -1670,7 +1705,11 @@ public final class PowerManagerService extends SystemService buttonBrightness = mButtonBrightnessOverrideFromWindowManager; keyboardBrightness = mButtonBrightnessOverrideFromWindowManager; } else { - buttonBrightness = mButtonBrightness; + if (!mForceNavbar) { + buttonBrightness = mButtonBrightness; + } else { + buttonBrightness = 0; + } keyboardBrightness = mKeyboardBrightness; } @@ -1710,6 +1749,7 @@ public final class PowerManagerService extends SystemService } } } + if (mUserActivitySummary == 0) { if (sleepTimeout >= 0) { final long anyUserActivity = Math.max(mLastUserActivityTime, @@ -1725,6 +1765,20 @@ public final class PowerManagerService extends SystemService nextTimeout = -1; } } + + if (mUserActivitySummary != USER_ACTIVITY_SCREEN_DREAM && userInactiveOverride) { + if ((mUserActivitySummary & + (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) != 0) { + // Device is being kept awake by recent user activity + if (nextTimeout >= now && mOverriddenTimeout == -1) { + // Save when the next timeout would have occurred + mOverriddenTimeout = nextTimeout; + } + } + mUserActivitySummary = USER_ACTIVITY_SCREEN_DREAM; + nextTimeout = -1; + } + if (mUserActivitySummary != 0 && nextTimeout >= 0) { Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT); msg.setAsynchronous(true); @@ -2654,6 +2708,14 @@ public final class PowerManagerService extends SystemService } } + private void setUserInactiveOverrideFromWindowManagerInternal() { + synchronized (mLock) { + mUserInactiveOverrideFromWindowManager = true; + mDirty |= DIRTY_USER_ACTIVITY; + updatePowerStateLocked(); + } + } + private void setUserActivityTimeoutOverrideFromWindowManagerInternal(long timeoutMillis) { synchronized (mLock) { if (mUserActivityTimeoutOverrideFromWindowManager != timeoutMillis) { @@ -2843,6 +2905,8 @@ public final class PowerManagerService extends SystemService + mScreenBrightnessOverrideFromWindowManager); pw.println(" mUserActivityTimeoutOverrideFromWindowManager=" + mUserActivityTimeoutOverrideFromWindowManager); + pw.println(" mUserInactiveOverrideFromWindowManager=" + + mUserInactiveOverrideFromWindowManager); pw.println(" mTemporaryScreenBrightnessSettingOverride=" + mTemporaryScreenBrightnessSettingOverride); pw.println(" mTemporaryScreenAutoBrightnessAdjustmentSettingOverride=" @@ -3839,6 +3903,11 @@ public final class PowerManagerService extends SystemService } @Override + public void setUserInactiveOverrideFromWindowManager() { + setUserInactiveOverrideFromWindowManagerInternal(); + } + + @Override public void setUserActivityTimeoutOverrideFromWindowManager(long timeoutMillis) { setUserActivityTimeoutOverrideFromWindowManagerInternal(timeoutMillis); } diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index 9b8ea14..34b6e2b 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -26,7 +26,6 @@ import android.app.KeyguardManager; import android.app.ProgressDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.IBluetoothManager; -import android.content.pm.ThemeUtils; import android.media.AudioAttributes; import android.nfc.NfcAdapter; import android.nfc.INfcAdapter; @@ -78,6 +77,8 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.OutputStreamWriter; +import org.cyanogenmod.internal.util.ThemeUtils; + public final class ShutdownThread extends Thread { // constants private static final String TAG = "ShutdownThread"; diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java index 7c2da2d..be3e922 100644 --- a/services/core/java/com/android/server/wm/CircularDisplayMask.java +++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java @@ -56,7 +56,7 @@ class CircularDisplayMask { int screenOffset, int maskThickness) { mScreenSize = new Point(); display.getSize(mScreenSize); - if (mScreenSize.x != mScreenSize.y) { + if (mScreenSize.x != mScreenSize.y + screenOffset) { Slog.w(TAG, "Screen dimensions of displayId = " + display.getDisplayId() + "are not equal, circularMask will not be drawn."); mDimensionsUnequal = true; diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 331ddbf..2edf552 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -116,6 +116,7 @@ class DisplayContent { display.getDisplayInfo(mDisplayInfo); isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY; mService = service; + initializeDisplayBaseInfo(); } int getDisplayId() { @@ -176,6 +177,21 @@ class DisplayContent { } } + void initializeDisplayBaseInfo() { + synchronized(mDisplaySizeLock) { + // Bootstrap the default logical display from the display manager. + final DisplayInfo newDisplayInfo = + mService.mDisplayManagerInternal.getDisplayInfo(mDisplayId); + if (newDisplayInfo != null) { + mDisplayInfo.copyFrom(newDisplayInfo); + } + mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth; + mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight; + mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi; + mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight); + } + } + void getLogicalDisplayRect(Rect out) { // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked. final int orientation = mDisplayInfo.rotation; diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplaySettings.java index 01f878c..80526f2 100644 --- a/services/core/java/com/android/server/wm/DisplaySettings.java +++ b/services/core/java/com/android/server/wm/DisplaySettings.java @@ -79,17 +79,20 @@ public class DisplaySettings { } } - public void setOverscanLocked(String name, int left, int top, int right, int bottom) { + public void setOverscanLocked(String uniqueId, String name, int left, int top, int right, + int bottom) { if (left == 0 && top == 0 && right == 0 && bottom == 0) { // Right now all we are storing is overscan; if there is no overscan, // we have no need for the entry. + mEntries.remove(uniqueId); + // Legacy name might have been in used, so we need to clear it. mEntries.remove(name); return; } - Entry entry = mEntries.get(name); + Entry entry = mEntries.get(uniqueId); if (entry == null) { - entry = new Entry(name); - mEntries.put(name, entry); + entry = new Entry(uniqueId); + mEntries.put(uniqueId, entry); } entry.overscanLeft = left; entry.overscanTop = top; diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java index 480da44..7e437c7 100644 --- a/services/core/java/com/android/server/wm/TaskStack.java +++ b/services/core/java/com/android/server/wm/TaskStack.java @@ -399,7 +399,9 @@ public class TaskStack { void resetAnimationBackgroundAnimator() { mAnimationBackgroundAnimator = null; - mAnimationBackgroundSurface.hide(); + if (mAnimationBackgroundSurface != null) { + mAnimationBackgroundSurface.hide(); + } } private long getBlurBehindFadeDuration(long duration) { @@ -468,11 +470,14 @@ public class TaskStack { } boolean isDimming() { + if (mDimLayer == null) { + return false; + } return mDimLayer.isDimming(); } boolean isDimming(WindowStateAnimator winAnimator) { - return mDimWinAnimator == winAnimator && mDimLayer.isDimming(); + return mDimWinAnimator == winAnimator && isDimming(); } void startDimmingIfNeeded(WindowStateAnimator newWinAnimator) { diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 1d5f64c..dcb1e18 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -1015,7 +1015,6 @@ public class WindowManagerService extends IWindowManager.Stub // Load hardware rotation from prop mSfHwRotation = android.os.SystemProperties.getInt("ro.sf.hwrotation",0) / 90; - updateCircularDisplayMaskIfNeeded(); showEmulatorDisplayOverlayIfNeeded(); } @@ -4490,13 +4489,8 @@ public class WindowManagerService extends IWindowManager.Stub + " ShowWallpaper=" + ent.array.getBoolean( com.android.internal.R.styleable.Window_windowShowWallpaper, false)); - final boolean windowIsTranslucentDefined = ent.array.hasValue( - com.android.internal.R.styleable.Window_windowIsTranslucent); - final boolean windowIsTranslucent = ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowIsTranslucent, false); - final boolean windowSwipeToDismiss = ent.array.getBoolean( - com.android.internal.R.styleable.Window_windowSwipeToDismiss, false); - if (windowIsTranslucent || (!windowIsTranslucentDefined && windowSwipeToDismiss)) { + if (ent.array.getBoolean( + com.android.internal.R.styleable.Window_windowIsTranslucent, false)) { return; } if (ent.array.getBoolean( @@ -6003,7 +5997,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - public void updateCircularDisplayMaskIfNeeded() { + private void updateCircularDisplayMaskIfNeeded() { // we're fullscreen and not hosted in an ActivityView if (mContext.getResources().getConfiguration().isScreenRound() && mContext.getResources().getBoolean( @@ -6043,8 +6037,8 @@ public class WindowManagerService extends IWindowManager.Stub if (visible) { // TODO(multi-display): support multiple displays if (mCircularDisplayMask == null) { - int screenOffset = mContext.getResources().getDimensionPixelSize( - com.android.internal.R.dimen.circular_display_mask_offset); + int screenOffset = mContext.getResources().getInteger( + com.android.internal.R.integer.config_windowOutsetBottom); int maskThickness = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.circular_display_mask_thickness); @@ -7726,6 +7720,8 @@ public class WindowManagerService extends IWindowManager.Stub mActivityManager.updateConfiguration(null); } catch (RemoteException e) { } + + updateCircularDisplayMaskIfNeeded(); } private void displayReady(int displayId) { @@ -7733,22 +7729,7 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayContent displayContent = getDisplayContentLocked(displayId); if (displayContent != null) { mAnimator.addDisplayLocked(displayId); - synchronized(displayContent.mDisplaySizeLock) { - // Bootstrap the default logical display from the display manager. - final DisplayInfo displayInfo = displayContent.getDisplayInfo(); - DisplayInfo newDisplayInfo = mDisplayManagerInternal.getDisplayInfo(displayId); - if (newDisplayInfo != null) { - displayInfo.copyFrom(newDisplayInfo); - } - displayContent.mInitialDisplayWidth = displayInfo.logicalWidth; - displayContent.mInitialDisplayHeight = displayInfo.logicalHeight; - displayContent.mInitialDisplayDensity = displayInfo.logicalDensityDpi; - displayContent.mBaseDisplayWidth = displayContent.mInitialDisplayWidth; - displayContent.mBaseDisplayHeight = displayContent.mInitialDisplayHeight; - displayContent.mBaseDisplayDensity = displayContent.mInitialDisplayDensity; - displayContent.mBaseDisplayRect.set(0, 0, - displayContent.mBaseDisplayWidth, displayContent.mBaseDisplayHeight); - } + displayContent.initializeDisplayBaseInfo(); } } } @@ -8787,7 +8768,8 @@ public class WindowManagerService extends IWindowManager.Stub displayInfo.overscanBottom = bottom; } - mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, left, top, right, bottom); + mDisplaySettings.setOverscanLocked(displayInfo.uniqueId, displayInfo.name, left, top, + right, bottom); mDisplaySettings.writeSettingsLocked(); reconfigureDisplayLocked(displayContent); |