diff options
author | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2016-12-12 15:03:40 +0100 |
---|---|---|
committer | Wolfgang Wiedmeyer <wolfgit@wiedmeyer.de> | 2016-12-12 15:03:40 +0100 |
commit | ae08d65dc25290d8d411ff44d7eb07f4cb74e8c6 (patch) | |
tree | 1afe8d827942011eafc2afebd0ae158b24f8b38e /services | |
parent | 90e1e6b2e9b79d444545d729561cf7fc099a8f10 (diff) | |
parent | 2df190c3a2ed1e339bb34c175fa227f90e7cbb02 (diff) | |
download | frameworks_base-ae08d65dc25290d8d411ff44d7eb07f4cb74e8c6.zip frameworks_base-ae08d65dc25290d8d411ff44d7eb07f4cb74e8c6.tar.gz frameworks_base-ae08d65dc25290d8d411ff44d7eb07f4cb74e8c6.tar.bz2 |
Merge branch 'cm-13.0' of https://github.com/CyanogenMod/android_frameworks_base into replicant-6.0
Diffstat (limited to 'services')
72 files changed, 2779 insertions, 1384 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java index 1b4182d..4e4c249 100644 --- a/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java +++ b/services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java @@ -31,7 +31,7 @@ import cyanogenmod.providers.CMSettings; /** * Utility methods for performing accessibility display adjustments. */ -public class DisplayAdjustmentUtils { +class DisplayAdjustmentUtils { private static final String LOG_TAG = DisplayAdjustmentUtils.class.getSimpleName(); /** Matrix and offset used for converting color to gray-scale. */ @@ -77,11 +77,6 @@ public class DisplayAdjustmentUtils { return true; } - if (CMSettings.Secure.getStringForUser(cr, - CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, userId) != null) { - return true; - } - return false; } @@ -97,23 +92,6 @@ public class DisplayAdjustmentUtils { colorMatrix = multiply(colorMatrix, INVERSION_MATRIX_VALUE_ONLY); } - String adj = CMSettings.Secure.getStringForUser(cr, - CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, userId); - if (adj != null) { - String[] tmp = adj.split(" "); - if (tmp.length == 16) { - float[] adjMatrix = new float[16]; - try { - for (int i = 0; i < 16; i++) { - adjMatrix[i] = Float.parseFloat(tmp[i]); - } - colorMatrix = multiply(colorMatrix, adjMatrix); - } catch (NumberFormatException e) { - Slog.e(LOG_TAG, e.getMessage(), e); - } - } - } - if (Settings.Secure.getIntForUser(cr, Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, userId) != 0) { final int daltonizerMode = Settings.Secure.getIntForUser(cr, diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 1629a37..d16c78a 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -80,7 +80,9 @@ import android.os.storage.StorageManager; import android.provider.Settings; import android.system.ErrnoException; import android.system.Os; +import android.text.TextUtils; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.AtomicFile; import android.util.EventLog; import android.util.Log; @@ -93,6 +95,7 @@ import com.android.internal.backup.IBackupTransport; import com.android.internal.backup.IObbBackupService; import com.android.server.AppWidgetBackupBridge; import com.android.server.EventLogTags; +import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.backup.PackageManagerBackupAgent.Metadata; @@ -300,6 +303,7 @@ public class BackupManagerService { volatile boolean mClearingData; // Transport bookkeeping + final ArraySet<ComponentName> mTransportWhitelist; final Intent mTransportServiceIntent = new Intent(SERVICE_ACTION_TRANSPORT_HOST); final ArrayMap<String,String> mTransportNames = new ArrayMap<String,String>(); // component name -> registration name @@ -1084,11 +1088,15 @@ public class BackupManagerService { // Set up our transport options and initialize the default transport // TODO: Don't create transports that we don't need to? - mCurrentTransport = Settings.Secure.getString(context.getContentResolver(), + SystemConfig systemConfig = SystemConfig.getInstance(); + mTransportWhitelist = systemConfig.getBackupTransportWhitelist(); + + String transport = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.BACKUP_TRANSPORT); - if ("".equals(mCurrentTransport)) { - mCurrentTransport = null; + if (TextUtils.isEmpty(transport)) { + transport = null; } + mCurrentTransport = transport; if (DEBUG) Slog.v(TAG, "Starting with transport " + mCurrentTransport); // Find all transport hosts and bind to their services @@ -1099,11 +1107,11 @@ public class BackupManagerService { } if (hosts != null) { for (int i = 0; i < hosts.size(); i++) { - final ServiceInfo transport = hosts.get(i).serviceInfo; + final ServiceInfo transportService = hosts.get(i).serviceInfo; if (MORE_DEBUG) { - Slog.v(TAG, " " + transport.packageName + "/" + transport.name); + Slog.v(TAG, " " + transportService.packageName + "/" + transportService.name); } - tryBindTransport(transport); + tryBindTransport(transportService); } } @@ -1983,7 +1991,12 @@ public class BackupManagerService { // Actually bind; presumes that we have already validated the transport service boolean bindTransport(ServiceInfo transport) { ComponentName svcName = new ComponentName(transport.packageName, transport.name); - if (MORE_DEBUG) { + if (!mTransportWhitelist.contains(svcName)) { + Slog.w(TAG, "Proposed transport " + svcName + " not whitelisted; ignoring"); + return false; + } + + if (DEBUG) { Slog.i(TAG, "Binding to transport host " + svcName); } Intent intent = new Intent(mTransportServiceIntent); @@ -2222,7 +2235,8 @@ public class BackupManagerService { synchronized(mAgentConnectLock) { mConnecting = true; mConnectedAgent = null; - if (mActivityManager.bindBackupAgent(app, mode)) { + if (mActivityManager.bindBackupAgent(app.packageName, mode, + UserHandle.USER_OWNER)) { Slog.d(TAG, "awaiting agent for " + app); // success; wait for the agent to arrive @@ -9654,6 +9668,12 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF + " (now = " + System.currentTimeMillis() + ')'); pw.println(" next scheduled: " + KeyValueBackupJob.nextScheduled()); + pw.println("Transport whitelist:"); + for (ComponentName transport : mTransportWhitelist) { + pw.print(" "); + pw.println(transport.flattenToShortString()); + } + pw.println("Available transports:"); final String[] transports = listAllTransports(); if (transports != null) { diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index 1433490..5875ca9 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -74,6 +74,8 @@ import java.util.Locale; import java.util.Random; import java.util.TimeZone; import java.util.TreeSet; +import java.util.Timer; +import java.util.TimerTask; import static android.app.AlarmManager.RTC_WAKEUP; import static android.app.AlarmManager.RTC; @@ -127,6 +129,7 @@ class AlarmManagerService extends SystemService { private final ArrayList<Integer> mTriggeredUids = new ArrayList<Integer>(); private final ArrayList<Integer> mBlockedUids = new ArrayList<Integer>(); + private static final int BLOCKED_UID_CHECK_INTERVAL = 1000; // 1 sec. long mNativeData; private long mNextWakeup; @@ -1250,16 +1253,9 @@ class AlarmManagerService extends SystemService { synchronized(mLock) { if(isBlocked) { mBlockedUids.add(new Integer(uid)); - if (checkReleaseWakeLock()) { - /* all the uids for which the alarms are triggered - * are either blocked or have called onSendFinished. - */ - if (mWakeLock.isHeld()) { - mWakeLock.release(); - if (localLOGV) - Slog.v(TAG, "AM WakeLock Released Internally in updateBlockedUids"); - } - } + Timer checkBlockedUidTimer = new Timer(); + checkBlockedUidTimer.schedule( new CheckBlockedUidTimerTask(uid), + BLOCKED_UID_CHECK_INTERVAL); } else { mBlockedUids.clear(); } @@ -1267,6 +1263,24 @@ class AlarmManagerService extends SystemService { } }; + class CheckBlockedUidTimerTask extends TimerTask { + private int mUid; + CheckBlockedUidTimerTask(int uid) { + mUid = uid; + } + @Override + public void run(){ + if (mBlockedUids.contains(mUid) && mTriggeredUids.contains(mUid)) { + if (mWakeLock.isHeld()) { + mWakeLock.release(); + if (localLOGV) + Slog.v(TAG, "AM WakeLock Released Internally!!"); + return; + } + } + return; + } + } void dumpImpl(PrintWriter pw) { synchronized (mLock) { pw.println("Current Alarm Manager state:"); @@ -1745,20 +1759,6 @@ class AlarmManagerService extends SystemService { } } - boolean checkReleaseWakeLock() { - if (mTriggeredUids.size() == 0 || mBlockedUids.size() == 0) - return false; - - int uid; - for (int i = 0; i < mTriggeredUids.size(); i++) { - uid = mTriggeredUids.get(i); - if (!mBlockedUids.contains(uid)) { - return false; - } - } - return true; - } - private void removeLocked(PendingIntent operation) { boolean didRemove = false; for (int i = mAlarmBatches.size() - 1; i >= 0; i--) { @@ -2277,12 +2277,6 @@ class AlarmManagerService extends SystemService { mInFlight.add(inflight); mBroadcastRefCount++; mTriggeredUids.add(new Integer(alarm.uid)); - if (checkReleaseWakeLock()) { - if (mWakeLock.isHeld()) { - mWakeLock.release(); - if (localLOGV) Slog.v(TAG, "AM WakeLock Released Internally deliverAlarms"); - } - } if (allowWhileIdle) { // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm. @@ -2839,13 +2833,6 @@ class AlarmManagerService extends SystemService { mBroadcastRefCount--; mTriggeredUids.remove(new Integer(uid)); - if (checkReleaseWakeLock()) { - if (mWakeLock.isHeld()) { - mWakeLock.release(); - if (localLOGV) Slog.v(TAG, "AM WakeLock Released Internally onSendFinish"); - } - } - if (mBroadcastRefCount == 0) { if (mWakeLock.isHeld()) { mWakeLock.release(); diff --git a/services/core/java/com/android/server/AppOpsPolicy.java b/services/core/java/com/android/server/AppOpsPolicy.java index 75bca05..d51983f 100644 --- a/services/core/java/com/android/server/AppOpsPolicy.java +++ b/services/core/java/com/android/server/AppOpsPolicy.java @@ -60,6 +60,11 @@ public class AppOpsPolicy { public static final int CONTROL_UNKNOWN = 2; + // Rate limiting thresholds for ask operations + public static final int RATE_LIMIT_OP_COUNT = 3; + public static final int RATE_LIMIT_OPS_TOTAL_PKG_COUNT = 4; + public static final int RATE_LIMIT_OP_DELAY_CEILING = 10; + public static int stringToControl(String show) { if ("true".equalsIgnoreCase(show)) { return CONTROL_SHOW; @@ -438,4 +443,4 @@ public class AppOpsPolicy { Slog.d(TAG, "Returning mode=" + mode); return mode; } -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java index 83a0a99..b205d24 100644 --- a/services/core/java/com/android/server/AppOpsService.java +++ b/services/core/java/com/android/server/AppOpsService.java @@ -39,8 +39,10 @@ import android.app.ActivityThread; import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.Dialog; +import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; @@ -51,6 +53,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.os.PowerManager; import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; @@ -96,6 +99,7 @@ public class AppOpsService extends IAppOpsService.Stub { final Looper mLooper; final boolean mStrictEnable; AppOpsPolicy mPolicy; + private PowerManager mPowerManager; private static final int[] PRIVACY_GUARD_OP_STATES = new int[] { AppOpsManager.OP_COARSE_LOCATION, @@ -184,6 +188,7 @@ public class AppOpsService extends IAppOpsService.Stub { final ArrayList<IBinder> clientTokens; public int allowedCount; public int ignoredCount; + public int delayedCount; public Op(int _uid, String _packageName, int _op, int _mode) { uid = _uid; @@ -317,10 +322,17 @@ public class AppOpsService extends IAppOpsService.Stub { } catch (RemoteException ignored) { } if (curUid != ops.uidState.uid) { - Slog.i(TAG, "Pruning old package " + ops.packageName - + "/" + ops.uidState + ": new uid=" + curUid); - it.remove(); - changed = true; + // Do not prune apps that are not currently present in the device + // (like SDcard ones). While booting, SDcards are not available but + // must not be purged from AppOps, because they are still present + // in the Android app database. + String pkgName = mContext.getPackageManager().getNameForUid(ops.uidState.uid); + if (curUid != -1 || pkgName == null || !pkgName.equals(ops.packageName)) { + Slog.i(TAG, "Pruning old package " + ops.packageName + + "/" + ops.uidState + ": new uid=" + curUid); + it.remove(); + changed = true; + } } } @@ -360,8 +372,45 @@ public class AppOpsService extends IAppOpsService.Stub { || mountMode == Zygote.MOUNT_EXTERNAL_WRITE; } }); + + mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_SCREEN_OFF); + mContext.registerReceiver(mIntentReceiver, filter); } + private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (action.equals(Intent.ACTION_SCREEN_OFF)) { + synchronized (this) { + for (int i = mUidStates.size() - 1; i >= 0; i--) { + UidState uidState = mUidStates.valueAt(i); + + ArrayMap<String, Ops> packages = uidState.pkgOps; + if (packages == null) { + continue; + } + + Iterator<Map.Entry<String, Ops>> it = packages.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry<String, Ops> ent = it.next(); + Ops pkgOps = ent.getValue(); + for (int j = pkgOps.size() - 1; j >= 0; j--) { + Op curOp = pkgOps.valueAt(j); + if (DEBUG) + Log.d(TAG, "Ignoring " + curOp.packageName + " request " + + curOp.op); + curOp.dialogReqQueue.ignore(); + } + } + } + } + } + } + }; + public void packageRemoved(int uid, String packageName) { synchronized (this) { UidState uidState = mUidStates.get(uid); @@ -1058,8 +1107,50 @@ public class AppOpsService extends IAppOpsService.Stub { + packageName + ")"); return switchOp.mode; } - op.noteOpCount++; - req = askOperationLocked(code, uid, packageName, switchOp); + + if (DEBUG) { + Log.d(TAG, "Package " + op.packageName + " has " + op.noteOpCount + + " requests and " + op.startOpCount + " start requests with " + + op.ignoredCount + " ignored at " + op.time + + " with a duration of " + + op.duration + " while being delayed " + op.delayedCount + + " times"); + Log.d(TAG, "Total pkops for " + ops.packageName + " " + + ops.uidState.pkgOps.size()); + } + + // First drop all request events if the device is not interactive, next + // check what the global pkg ops count for the package, + // then check op scoped count. High frequency request ops will be delayed until + // their delay count ceiling is met. This is to mitigate the overloading the + // main activity manager service handler and having watchdog kill our service. + // Google play services likes to share its uid with numerous packages to avoid + // having to grant permissions from the users perspective and thus is the worst + // example of overloading this queue -- so, to not encourage bad behavior, + // we move them to the back of the line. NOTE: these values are magic, and may need + // tuning. Ideally we'd want a ringbuffer or token bucket here to do proper rate + // limiting. + final boolean isInteractive = mPowerManager.isInteractive(); + if (isInteractive && + (ops.uidState.pkgOps.size() < AppOpsPolicy.RATE_LIMIT_OPS_TOTAL_PKG_COUNT + && op.noteOpCount < AppOpsPolicy.RATE_LIMIT_OP_COUNT + || op.delayedCount > AppOpsPolicy.RATE_LIMIT_OP_DELAY_CEILING)) { + + // Reset delayed count, most ops will never need this + if (op.delayedCount > 0) { + if (DEBUG) Log.d(TAG, "Resetting delayed count for " + op.packageName); + op.delayedCount = 0; + } + + op.noteOpCount++; + req = askOperationLocked(code, uid, packageName, switchOp); + } else { + if (isInteractive) { + op.delayedCount++; + } + op.ignoredCount++; + return AppOpsManager.MODE_IGNORED; + } } } diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index f20cfe9..97ad02c 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -58,10 +58,6 @@ import android.util.Slog; import java.io.File; import java.io.FileDescriptor; import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.BufferedInputStream; -import java.io.BufferedReader; -import java.io.FileInputStream; import java.io.IOException; import java.io.PrintWriter; @@ -165,6 +161,7 @@ public final class BatteryService extends SystemService { private boolean mAdjustableNotificationLedBrightness; private int mNotificationLedBrightnessLevel = LIGHT_BRIGHTNESS_MAXIMUM; + private boolean mUseSegmentedBatteryLed = false; private boolean mMultipleNotificationLeds; private boolean mMultipleLedsEnabled = false; @@ -1030,51 +1027,29 @@ public final class BatteryService extends SystemService { private final int mBatteryLedOff; public Led(Context context, LightsManager lights) { + NotificationManager nm = context.getSystemService(NotificationManager.class); mBatteryLight = lights.getLight(LightsManager.LIGHT_ID_BATTERY); // Does the Device support changing battery LED colors? - mMultiColorLed = context.getResources().getBoolean( - com.android.internal.R.bool.config_multiColorBatteryLed); + mMultiColorLed = nm.deviceLightsCan(NotificationManager.LIGHTS_RGB_BATTERY); // Is the notification LED brightness changeable ? - mAdjustableNotificationLedBrightness = context.getResources().getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness); + mAdjustableNotificationLedBrightness = nm.deviceLightsCan( + NotificationManager.LIGHTS_ADJUSTABLE_NOTIFICATION_BRIGHTNESS); // Does the Device have multiple LEDs ? - mMultipleNotificationLeds = context.getResources().getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds); + mMultipleNotificationLeds = nm.deviceLightsCan( + NotificationManager.LIGHTS_MULTIPLE_LED); mBatteryLedOn = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOn); mBatteryLedOff = context.getResources().getInteger( com.android.internal.R.integer.config_notificationsBatteryLedOff); - } - - private boolean isHvdcpPresent() { - File mChargerTypeFile = new File("/sys/class/power_supply/usb/type"); - FileReader fileReader; - BufferedReader br; - String type; - boolean ret = false; - - if (!mChargerTypeFile.exists()) { - // Device does not support HVDCP - return ret; - } - - try { - fileReader = new FileReader(mChargerTypeFile); - br = new BufferedReader(fileReader); - type = br.readLine(); - if (type.regionMatches(true, 0, "USB_HVDCP", 0, 9)) - ret = true; - br.close(); - fileReader.close(); - } catch (IOException e) { - Slog.e(TAG, "Failure in reading charger type", e); - } - return ret; + // Does the Device have segmented battery LED support? In this case, we send the level + // in the alpha channel of the color and let the HAL sort it out. + mUseSegmentedBatteryLed = nm.deviceLightsCan( + NotificationManager.LIGHTS_SEGMENTED_BATTERY_LIGHTS); } /** @@ -1089,6 +1064,9 @@ public final class BatteryService extends SystemService { final int level = mBatteryProps.batteryLevel; final int status = mBatteryProps.batteryStatus; + mNotificationLedBrightnessLevel = mUseSegmentedBatteryLed ? level : + LIGHT_BRIGHTNESS_MAXIMUM; + if (!mLightEnabled) { // No lights if explicitly disabled mBatteryLight.turnOff(); @@ -1114,14 +1092,8 @@ public final class BatteryService extends SystemService { // Battery is full or charging and nearly full mBatteryLight.setColor(mBatteryFullARGB); } else { - if (isHvdcpPresent()) { - // Blinking orange if HVDCP charger - mBatteryLight.setFlashing(mBatteryMediumARGB, Light.LIGHT_FLASH_TIMED, - mBatteryLedOn, mBatteryLedOn); - } else { - // Battery is charging and halfway full - mBatteryLight.setColor(mBatteryMediumARGB); - } + // Battery is charging and halfway full + mBatteryLight.setColor(mBatteryMediumARGB); } } else { // No lights if not charging and not low diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java index 5a76227..dbdffef 100644 --- a/services/core/java/com/android/server/BluetoothManagerService.java +++ b/services/core/java/com/android/server/BluetoothManagerService.java @@ -763,6 +763,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } catch (RemoteException e) { Log.e(TAG, "Unable to call onBluetoothServiceUp() on callback #" + i, e); } + Log.d(TAG, "Broadcasted onBluetoothServiceUp() to " + mCallbacks.getBroadcastItem(i)); } } finally { mCallbacks.finishBroadcast(); @@ -784,6 +785,7 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } catch (RemoteException e) { Log.e(TAG, "Unable to call onBluetoothServiceDown() on callback #" + i, e); } + Log.d(TAG, "Broadcasted onBluetoothServiceDown() to " + mCallbacks.getBroadcastItem(i)); } } finally { mCallbacks.finishBroadcast(); @@ -1145,8 +1147,13 @@ class BluetoothManagerService extends IBluetoothManager.Stub { recoverBluetoothServiceFromError(); } if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && - (newState == BluetoothAdapter.STATE_BLE_ON) && - (mBluetooth != null) && mEnable) { + (newState == BluetoothAdapter.STATE_OFF) && + (mBluetooth != null) && mEnable) { + persistBluetoothSetting(BLUETOOTH_OFF); + } + if ((prevState == BluetoothAdapter.STATE_TURNING_ON) && + (newState == BluetoothAdapter.STATE_BLE_ON) && + (mBluetooth != null) && mEnable) { recoverBluetoothServiceFromError(); } if (newState == BluetoothAdapter.STATE_ON || @@ -1646,7 +1653,11 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetooth != null) { mBluetooth = null; //Unbind - mContext.unbindService(mConnection); + try { + mContext.unbindService(mConnection); + } catch (Exception e) { + Log.e(TAG, "Unable to unbind",e); + } } mBluetoothGatt = null; } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 2a47460..1489fd8 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -159,6 +159,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; +import java.util.Random; /** * @hide @@ -646,18 +647,23 @@ public class ConnectivityService extends IConnectivityManager.Stub mTrackerHandler = new NetworkStateTrackerHandler(mHandlerThread.getLooper()); // setup our unique device name - String hostname = CMSettings.Secure.getString(context.getContentResolver(), - CMSettings.Secure.DEVICE_HOSTNAME); - if (TextUtils.isEmpty(hostname) && - TextUtils.isEmpty(SystemProperties.get("net.hostname"))) { + // either to (in order): current net.hostname + // DEVICE_HOSTNAME + // android-ANDROID_ID + // android-r-RANDOM_NUMBER + if (TextUtils.isEmpty(SystemProperties.get("net.hostname"))) { + String hostname = CMSettings.Secure.getString(context.getContentResolver(), + CMSettings.Secure.DEVICE_HOSTNAME); String id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID); - if (id != null && id.length() > 0) { + if (!TextUtils.isEmpty(hostname)) { + SystemProperties.set("net.hostname", hostname); + } else if (!TextUtils.isEmpty(id)) { String name = new String("android-").concat(id); SystemProperties.set("net.hostname", name); + } else { + SystemProperties.set("net.hostname", "android-r-" + new Random().nextInt()); } - } else { - SystemProperties.set("net.hostname", hostname); } // read our default dns server ip diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index a9f6e40..6348460 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -3029,10 +3029,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub Slog.d(TAG, "Found an input method " + p); } - } catch (XmlPullParserException e) { - Slog.w(TAG, "Unable to load input method " + compName, e); - } catch (IOException e) { - Slog.w(TAG, "Unable to load input method " + compName, e); + } catch (Exception e) { + Slog.wtf(TAG, "Unable to load input method " + compName, e); } } diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java index ebe8759..6cd8e10 100644 --- a/services/core/java/com/android/server/LocationManagerService.java +++ b/services/core/java/com/android/server/LocationManagerService.java @@ -2418,11 +2418,8 @@ public class LocationManagerService extends ILocationManager.Stub { Bundle extras = location.getExtras(); boolean isBeingScreened = false; - if (extras == null) { - extras = new Bundle(); - } - if (!extras.containsKey(mComboNlpReadyMarker)) { + if (extras == null || !extras.containsKey(mComboNlpReadyMarker)) { // see if Combo Nlp is a passive listener ArrayList<UpdateRecord> records = mRecordsByProvider.get(LocationManager.PASSIVE_PROVIDER); @@ -2431,6 +2428,10 @@ public class LocationManagerService extends ILocationManager.Stub { if (r.mReceiver.mPackageName.equals(mComboNlpPackageName)) { if (!isBeingScreened) { isBeingScreened = true; + if (extras == null) { + location.setExtras(new Bundle()); + extras = location.getExtras(); + } extras.putBoolean(mComboNlpScreenMarker, true); } // send location to Combo Nlp for screening diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index 274adf8..10b0bdd 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -263,6 +263,17 @@ public class LockSettingsService extends ILockSettings.Stub { setString("migrated_lockscreen_disabled", "true", 0); Slog.i(TAG, "Migrated lockscreen disabled flag"); } + + if (getString("migrated_pattern_size", null, 0) == null) { + final String val = getString(Secure.LOCK_PATTERN_SIZE, null, + UserHandle.USER_CURRENT); + if (val != null) { + setString(Secure.LOCK_PATTERN_SIZE, val, 0); + } + + setString("migrated_pattern_size", "true", 0); + Slog.i(TAG, "Migrated primary user pattern size"); + } } catch (RemoteException re) { Slog.e(TAG, "Unable to migrate old data", re); } @@ -459,6 +470,7 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public void setLockPattern(String pattern, String savedCredential, int userId) throws RemoteException { + checkWritePermission(userId); byte[] currentHandle = getCurrentHandle(userId); if (pattern == null) { @@ -487,6 +499,7 @@ public class LockSettingsService extends ILockSettings.Stub { @Override public void setLockPassword(String password, String savedCredential, int userId) throws RemoteException { + checkWritePermission(userId); byte[] currentHandle = getCurrentHandle(userId); if (password == null) { @@ -552,6 +565,9 @@ public class LockSettingsService extends ILockSettings.Stub { private VerifyCredentialResponse doVerifyPattern(String pattern, boolean hasChallenge, long challenge, int userId) throws RemoteException { checkPasswordReadPermission(userId); + if (TextUtils.isEmpty(pattern)) { + throw new IllegalArgumentException("Pattern can't be null or empty"); + } CredentialHash storedHash = mStorage.readPatternHash(userId); boolean shouldReEnrollBaseZero = storedHash != null && storedHash.isBaseZeroPattern; @@ -615,6 +631,9 @@ public class LockSettingsService extends ILockSettings.Stub { private VerifyCredentialResponse doVerifyPassword(String password, boolean hasChallenge, long challenge, int userId) throws RemoteException { checkPasswordReadPermission(userId); + if (TextUtils.isEmpty(password)) { + throw new IllegalArgumentException("Password can't be null or empty"); + } CredentialHash storedHash = mStorage.readPasswordHash(userId); return verifyCredential(userId, storedHash, password, hasChallenge, challenge, new CredentialUtil() { diff --git a/services/core/java/com/android/server/LockSettingsStorage.java b/services/core/java/com/android/server/LockSettingsStorage.java index 1b42dfe..7ac2e42 100644 --- a/services/core/java/com/android/server/LockSettingsStorage.java +++ b/services/core/java/com/android/server/LockSettingsStorage.java @@ -62,6 +62,7 @@ class LockSettingsStorage { private static final String LOCK_PATTERN_FILE = "gatekeeper.pattern.key"; private static final String BASE_ZERO_LOCK_PATTERN_FILE = "gatekeeper.gesture.key"; private static final String LEGACY_LOCK_PATTERN_FILE = "gesture.key"; + private static final String CM_LEGACY_LOCK_PATTERN_FILE = "cm_gesture.key"; private static final String LOCK_PASSWORD_FILE = "gatekeeper.password.key"; private static final String LEGACY_LOCK_PASSWORD_FILE = "password.key"; @@ -241,6 +242,11 @@ class LockSettingsStorage { return new CredentialHash(stored, CredentialHash.VERSION_LEGACY); } + stored = readFile(getCmLegacyLockPatternFilename(userId)); + if (stored != null && stored.length > 0) { + return new CredentialHash(stored, CredentialHash.VERSION_LEGACY); + } + return null; } @@ -253,7 +259,8 @@ class LockSettingsStorage { public boolean hasPattern(int userId) { return hasFile(getLockPatternFilename(userId)) || hasFile(getBaseZeroLockPatternFilename(userId)) || - hasFile(getLegacyLockPatternFilename(userId)); + hasFile(getLegacyLockPatternFilename(userId)) || + hasFile(getCmLegacyLockPatternFilename(userId)); } private boolean hasFile(String name) { @@ -380,6 +387,10 @@ class LockSettingsStorage { return getLockCredentialFilePathForUser(userId, LEGACY_LOCK_PATTERN_FILE); } + String getCmLegacyLockPatternFilename(int userId) { + return getLockCredentialFilePathForUser(userId, CM_LEGACY_LOCK_PATTERN_FILE); + } + @VisibleForTesting String getLegacyLockPasswordFilename(int userId) { return getLockCredentialFilePathForUser(userId, LEGACY_LOCK_PASSWORD_FILE); diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index 23556c0..3fa02ba 100644 --- a/services/core/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java @@ -57,7 +57,7 @@ public class MasterClearReceiver extends BroadcastReceiver { @Override public void run() { try { - boolean wipeMedia = intent.getBooleanExtra(EXTRA_WIPE_MEDIA, false); + boolean wipeMedia = intent.getBooleanExtra(EXTRA_WIPE_MEDIA, true); RecoverySystem.rebootWipeUserData(context, shutdown, reason, wipeMedia); Log.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 4847de3..d539201 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -1742,6 +1742,8 @@ class MountService extends IMountService.Stub Preconditions.checkNotNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); + if (rec == null) + return; rec.nickname = nickname; mCallbacks.notifyVolumeRecordChanged(rec); writeSettingsLocked(); @@ -1756,6 +1758,8 @@ class MountService extends IMountService.Stub Preconditions.checkNotNull(fsUuid); synchronized (mLock) { final VolumeRecord rec = mRecords.get(fsUuid); + if (rec == null) + return; rec.userFlags = (rec.userFlags & ~mask) | (flags & mask); mCallbacks.notifyVolumeRecordChanged(rec); writeSettingsLocked(); @@ -2388,6 +2392,12 @@ class MountService extends IMountService.Stub // to let the UI to clear itself mHandler.postDelayed(new Runnable() { public void run() { + // unmount the internal emulated volume first + try { + mConnector.execute("volume", "unmount", "emulated"); + } catch (NativeDaemonConnectorException e) { + Slog.e(TAG, "unable to shut down internal volume", e); + } try { mCryptConnector.execute("cryptfs", "restart"); } catch (NativeDaemonConnectorException e) { diff --git a/services/core/java/com/android/server/net/NetPluginDelegate.java b/services/core/java/com/android/server/NetPluginDelegate.java index 6716a6b..18365f1 100644 --- a/services/core/java/com/android/server/net/NetPluginDelegate.java +++ b/services/core/java/com/android/server/NetPluginDelegate.java @@ -27,17 +27,16 @@ *IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package com.android.server.net; +package com.android.server; import dalvik.system.PathClassLoader; -import java.lang.reflect.Constructor; - import android.util.Slog; +import android.net.Network; import android.net.NetworkStats; import android.util.Log; -class NetPluginDelegate { +public class NetPluginDelegate { private static final String TAG = "ConnectivityExtension"; private static final boolean LOGV = false; @@ -47,7 +46,7 @@ class NetPluginDelegate { private static boolean extensionFailed; - static void getTetherStats(NetworkStats uidStats, NetworkStats devStats, + public static void getTetherStats(NetworkStats uidStats, NetworkStats devStats, NetworkStats xtStats) { if (!loadTetherExtJar()) { return; @@ -60,9 +59,10 @@ class NetPluginDelegate { e.printStackTrace(); Log.w(TAG, "error in invoke method"); } + if (LOGV) Slog.v(TAG, "getTetherStats() X"); } - static void setQuota(String iface, long quota) { + public static void setQuota(String iface, long quota) { if (!loadTetherExtJar()) { return; } @@ -72,8 +72,20 @@ class NetPluginDelegate { } catch (Exception ex) { Log.w(TAG, "Error calling setQuota Method on extension jar"); } + if (LOGV) Slog.v(TAG, "setQuota(" + iface + ", " + quota + ") X"); } + public static void setUpstream(Network net) { + if (LOGV) Slog.v(TAG, "setUpstream(" + net + ") E"); + loadTetherExtJar(); + try { + tetherExtensionClass.getMethod("setUpstream", Network.class).invoke( + tetherExtensionObj, net); + } catch (Exception ex) { + Log.w(TAG, "Error calling setUpstream Method on extension jar"); + } + if (LOGV) Slog.v(TAG, "setUpstream(" + net + ") E"); + } private static boolean loadTetherExtJar() { diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index fd42b0a..f53c4ef 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -46,12 +46,16 @@ import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENAB import android.annotation.NonNull; import android.app.ActivityManagerNative; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.INetworkManagementEventObserver; import android.net.InterfaceConfiguration; import android.net.IpPrefix; import android.net.LinkAddress; +import android.net.LinkProperties; import android.net.Network; import android.net.NetworkPolicyManager; import android.net.NetworkStats; @@ -77,11 +81,13 @@ import android.telephony.DataConnectionRealTimeInfo; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.text.TextUtils; import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.SparseIntArray; +import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.app.IBatteryStats; import com.android.internal.net.NetworkStatsFactory; @@ -110,6 +116,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; +import java.util.Objects; import java.util.StringTokenizer; import java.util.concurrent.CountDownLatch; @@ -188,7 +195,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub private final Handler mFgHandler; private final Handler mDaemonHandler; private final PhoneStateListener mPhoneStateListener; - + private String mWifiInterfaceName, mDataInterfaceName; private IBatteryStats mBatteryStats; private final Thread mThread; @@ -231,6 +238,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub /** Set of states for the child firewall chains. True if the chain is active. */ @GuardedBy("mQuotaLock") final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray(); + @GuardedBy("mQuotaLock") + final Map<Integer, Boolean> mWlanBlacklist = new HashMap<Integer, Boolean>(); + @GuardedBy("mQuotaLock") + final Map<Integer, Boolean> mDataBlacklist = new HashMap<Integer, Boolean>(); private Object mIdleTimerLock = new Object(); /** Set of interfaces with active idle timers. */ @@ -258,6 +269,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners = new RemoteCallbackList<INetworkActivityListener>(); private boolean mNetworkActive; + private HashMap<Integer, Boolean> mPendingRestrictOnData = new HashMap<Integer, Boolean>(); /** * Constructs a new NetworkManagementService instance @@ -282,6 +294,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub FgThread.get().getLooper()); mThread = new Thread(mConnector, NETD_TAG); + mWifiInterfaceName = SystemProperties.get("wifi.interface"); mDaemonHandler = new Handler(FgThread.get().getLooper()); mPhoneStateListener = new PhoneStateListener(SubscriptionManager.DEFAULT_SUBSCRIPTION_ID, @@ -292,6 +305,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub if (DBG) Slog.d(TAG, "onDataConnectionRealTimeInfoChanged: " + dcRtInfo); notifyInterfaceClassActivity(ConnectivityManager.TYPE_MOBILE, dcRtInfo.getDcPowerState(), dcRtInfo.getTime(), true); + processPendingDataRestrictRequests(); } }; TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE); @@ -322,6 +336,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void systemReady() { prepareNativeDaemon(); + // Register the receiver for Zerobalance blocking/unblocking + if (mContext.getResources().getBoolean(R.bool.config_zero_balance_operator)) { + final IntentFilter restrictFilter = new IntentFilter(); + restrictFilter.addAction("org.codeaurora.restrictData"); + mContext.registerReceiver(mZeroBalanceReceiver, restrictFilter); + } if (DBG) Slog.d(TAG, "Prepared"); } @@ -1821,6 +1841,85 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + private void processPendingDataRestrictRequests() { + initDataInterface(); + if (TextUtils.isEmpty(mDataInterfaceName) || mPendingRestrictOnData.isEmpty()) { + return; + } + for (Integer key : mPendingRestrictOnData.keySet()) { + restrictAppOnData(key, mPendingRestrictOnData.get(key)); + } + mPendingRestrictOnData.clear(); + } + + @Override + public void restrictAppOnData(int uid, boolean restrict) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + // silently discard when control disabled + // TODO: eventually migrate to be always enabled + if (!mBandwidthControlEnabled) return; + + initDataInterface(); + if (TextUtils.isEmpty(mDataInterfaceName)) { + // We don't have an interface name since data is not active + // yet, so queue up the request for when it comes up alive + mPendingRestrictOnData.put(uid, restrict); + return; + } + + synchronized (mQuotaLock) { + if (!mDataBlacklist.containsKey(uid) && !restrict) { + return; + } + Boolean wasRestricted = mDataBlacklist.get(uid); + if (Objects.equals(wasRestricted, restrict)) { + return; + } + mDataBlacklist.put(uid, restrict); + } + + try { + if (restrict) { + mConnector.execute("bandwidth", "addrestrictappsondata", mDataInterfaceName, uid); + } else { + mConnector.execute("bandwidth", "removerestrictappsondata", mDataInterfaceName, uid); + } + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + + @Override + public void restrictAppOnWlan(int uid, boolean restrict) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + // silently discard when control disabled + // TODO: eventually migrate to be always enabled + if (!mBandwidthControlEnabled) return; + + synchronized (mQuotaLock) { + if (!mWlanBlacklist.containsKey(uid) && !restrict) { + return; + } + Boolean wasRestricted = mWlanBlacklist.get(uid); + if (Objects.equals(wasRestricted, restrict) || TextUtils.isEmpty(mWifiInterfaceName)) { + return; + } + mWlanBlacklist.put(uid, restrict); + } + + + try { + if (restrict) { + mConnector.execute("bandwidth", "addrestrictappsonwlan", mWifiInterfaceName, uid); + } else { + mConnector.execute("bandwidth", "removerestrictappsonwlan", mWifiInterfaceName, uid); + } + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + @Override public void setUidCleartextNetworkPolicy(int uid, int policy) { if (Binder.getCallingUid() != uid) { @@ -2573,4 +2672,41 @@ public class NetworkManagementService extends INetworkManagementService.Stub public void removeInterfaceFromLocalNetwork(String iface) { modifyInterfaceInNetwork("remove", "local", iface); } + + private void initDataInterface() { + if (!TextUtils.isEmpty(mDataInterfaceName)) { + return; + } + ConnectivityManager cm = (ConnectivityManager) mContext.getSystemService( + Context.CONNECTIVITY_SERVICE); + LinkProperties linkProperties = cm.getLinkProperties(ConnectivityManager.TYPE_MOBILE); + if (linkProperties != null) { + mDataInterfaceName = linkProperties.getInterfaceName(); + } + } + + private BroadcastReceiver mZeroBalanceReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + boolean isBlockAllData = false; + if (intent != null + && intent.getAction().equals("org.codeaurora.restrictData")) { + isBlockAllData = intent.getBooleanExtra("Restrict", false); + Log.wtf("ZeroBalance", "Intent value to block unblock data" + isBlockAllData); + } + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + // Silently discard when control disabled + // TODO: Eventually migrate to always be enabled + if (!mBandwidthControlEnabled) return; + try { + Log.wtf("ZeroBalance", "before calling connector Intent" + + "value to block unblock data" + isBlockAllData); + mConnector.execute("bandwidth", + isBlockAllData ? "blockAllData" : "unblockAllData"); + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + }; } diff --git a/services/core/java/com/android/server/PermissionDialog.java b/services/core/java/com/android/server/PermissionDialog.java index 0f337b8..fd676b5 100644 --- a/services/core/java/com/android/server/PermissionDialog.java +++ b/services/core/java/com/android/server/PermissionDialog.java @@ -102,6 +102,10 @@ public class PermissionDialog extends BasePermissionDialog { mHandler.obtainMessage(ACTION_IGNORED_TIMEOUT), DISMISS_TIMEOUT); } + public void ignore() { + mHandler.sendMessage(mHandler.obtainMessage(ACTION_IGNORED_TIMEOUT)); + } + private String getAppName(String packageName) { ApplicationInfo appInfo = null; PackageManager pm = mContext.getPackageManager(); diff --git a/services/core/java/com/android/server/PermissionDialogReqQueue.java b/services/core/java/com/android/server/PermissionDialogReqQueue.java index ee94427..5b602e3 100644 --- a/services/core/java/com/android/server/PermissionDialogReqQueue.java +++ b/services/core/java/com/android/server/PermissionDialogReqQueue.java @@ -79,4 +79,10 @@ public class PermissionDialogReqQueue { } } } + + public void ignore() { + if (mDialog != null) { + mDialog.ignore(); + } + } } diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java index 2d94370..fe69d98 100644 --- a/services/core/java/com/android/server/SystemConfig.java +++ b/services/core/java/com/android/server/SystemConfig.java @@ -16,7 +16,14 @@ package com.android.server; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; +import static android.content.pm.PackageManager.INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; + import android.app.ActivityManager; +import android.content.ComponentName; import android.content.pm.FeatureInfo; import android.content.pm.Signature; import android.os.*; @@ -98,11 +105,14 @@ public class SystemConfig { // These are the package names of apps which should be in the 'always' // URL-handling state upon factory reset. - final ArraySet<String> mLinkedApps = new ArraySet<>(); + final ArraySet<AppLink> mLinkedApps = new ArraySet<>(); final ArrayMap<Signature, ArraySet<String>> mSignatureAllowances = new ArrayMap<Signature, ArraySet<String>>(); + // These are the permitted backup transport service components + final ArraySet<ComponentName> mBackupTransportWhitelist = new ArraySet<>(); + public static SystemConfig getInstance() { synchronized (SystemConfig.class) { if (sInstance == null) { @@ -144,7 +154,7 @@ public class SystemConfig { return mFixedImeApps; } - public ArraySet<String> getLinkedApps() { + public ArraySet<AppLink> getLinkedApps() { return mLinkedApps; } @@ -152,6 +162,10 @@ public class SystemConfig { return mSignatureAllowances; } + public ArraySet<ComponentName> getBackupTransportWhitelist() { + return mBackupTransportWhitelist; + } + SystemConfig() { // Read configuration from system readPermissions(Environment.buildPath( @@ -418,11 +432,29 @@ public class SystemConfig { } else if ("app-link".equals(name)) { String pkgname = parser.getAttributeValue(null, "package"); + String state = parser.getAttributeValue(null, "state"); if (pkgname == null) { Slog.w(TAG, "<app-link> without package in " + permFile + " at " + parser.getPositionDescription()); } else { - mLinkedApps.add(pkgname); + mLinkedApps.add(makeLink(pkgname, state)); + } + XmlUtils.skipCurrentTag(parser); + } else if ("backup-transport-whitelisted-service".equals(name)) { + String serviceName = parser.getAttributeValue(null, "service"); + if (serviceName == null) { + Slog.w(TAG, "<backup-transport-whitelisted-service> without service in " + + permFile + " at " + parser.getPositionDescription()); + } else { + ComponentName cn = ComponentName.unflattenFromString(serviceName); + if (cn == null) { + Slog.w(TAG, + "<backup-transport-whitelisted-service> with invalid service name " + + serviceName + " in "+ permFile + + " at " + parser.getPositionDescription()); + } else { + mBackupTransportWhitelist.add(cn); + } } XmlUtils.skipCurrentTag(parser); @@ -446,6 +478,23 @@ public class SystemConfig { } } + private AppLink makeLink(String pkgname, String state) { + AppLink al = new AppLink(); + al.pkgname = pkgname; + if (state == null || "always".equals(state)) { // default + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS; + } else if ("always-ask".equals(state)) { + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS_ASK; + } else if ("ask".equals("state")) { + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ASK; + } else if ("never".equals("state")) { + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_NEVER; + } else { + al.state = INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED; + } + return al; + } + void readPermission(XmlPullParser parser, String name) throws IOException, XmlPullParserException { if (mPermissions.containsKey(name)) { @@ -480,4 +529,20 @@ public class SystemConfig { XmlUtils.skipCurrentTag(parser); } } + + /** Simple value class to hold an app-link entry. + * It is public because PackageManagerService needs to see it */ + public static class AppLink { + public String pkgname; + public int state; + + @Override + public int hashCode() { return pkgname.hashCode(); } + + @Override + public boolean equals(Object other) { + if (!(other instanceof AppLink)) { return false; } + return pkgname.equals(((AppLink)other).pkgname); + } + } } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 71ff6e9..c7f4d0f 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -1019,7 +1019,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (validatePhoneId(phoneId)) { mDataActivity[phoneId] = state; for (Record r : mRecords) { - if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY)) { + if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_DATA_ACTIVITY) + && idMatch(r.subId, subId, phoneId)) { try { r.callback.onDataActivity(state); } catch (RemoteException ex) { @@ -1062,7 +1063,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } boolean modified = false; if (state == TelephonyManager.DATA_CONNECTED) { - if (!mConnectedApns[phoneId].contains(apnType)) { + if (!mConnectedApns[phoneId].contains(apnType) + && !apnType.equals(PhoneConstants.APN_TYPE_IMS)) { mConnectedApns[phoneId].add(apnType); if (mDataConnectionState[phoneId] != state) { mDataConnectionState[phoneId] = state; @@ -1248,7 +1250,41 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState, DisconnectCause.NOT_VALID, - PreciseDisconnectCause.NOT_VALID); + PreciseDisconnectCause.NOT_VALID, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + } + + public void notifyPreciseCallStateForSubscriber(int subId, int ringingCallState, + int foregroundCallState, int backgroundCallState) { + if (!checkNotifyPermission("notifyPreciseCallStateForSubscriber()")) { + return; + } + synchronized (mRecords) { + int phoneId = SubscriptionManager.getPhoneId(subId); + if (validatePhoneId(phoneId)) { + mRingingCallState = ringingCallState; + mForegroundCallState = foregroundCallState; + mBackgroundCallState = backgroundCallState; + mPreciseCallState = new PreciseCallState(ringingCallState, foregroundCallState, + backgroundCallState, + DisconnectCause.NOT_VALID, + PreciseDisconnectCause.NOT_VALID); + for (Record r : mRecords) { + if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_PRECISE_CALL_STATE) + && ((r.subId == subId) || + (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID))) { + try { + r.callback.onPreciseCallStateChanged(mPreciseCallState); + } catch (RemoteException ex) { + mRemoveList.add(r.binder); + } + } + } + } + handleRemoveListLocked(); + } + broadcastPreciseCallStateChanged(ringingCallState, foregroundCallState, backgroundCallState, + DisconnectCause.NOT_VALID, + PreciseDisconnectCause.NOT_VALID, subId); } public void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause) { @@ -1270,7 +1306,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { handleRemoveListLocked(); } broadcastPreciseCallStateChanged(mRingingCallState, mForegroundCallState, - mBackgroundCallState, disconnectCause, preciseDisconnectCause); + mBackgroundCallState, disconnectCause, preciseDisconnectCause, + SubscriptionManager.INVALID_SUBSCRIPTION_ID); } public void notifyPreciseDataConnectionFailed(String reason, String apnType, @@ -1510,13 +1547,16 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } private void broadcastPreciseCallStateChanged(int ringingCallState, int foregroundCallState, - int backgroundCallState, int disconnectCause, int preciseDisconnectCause) { + int backgroundCallState, int disconnectCause, int preciseDisconnectCause, int subId) { Intent intent = new Intent(TelephonyManager.ACTION_PRECISE_CALL_STATE_CHANGED); intent.putExtra(TelephonyManager.EXTRA_RINGING_CALL_STATE, ringingCallState); intent.putExtra(TelephonyManager.EXTRA_FOREGROUND_CALL_STATE, foregroundCallState); intent.putExtra(TelephonyManager.EXTRA_BACKGROUND_CALL_STATE, backgroundCallState); intent.putExtra(TelephonyManager.EXTRA_DISCONNECT_CAUSE, disconnectCause); intent.putExtra(TelephonyManager.EXTRA_PRECISE_DISCONNECT_CAUSE, preciseDisconnectCause); + if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); + } mContext.sendBroadcastAsUser(intent, UserHandle.ALL, android.Manifest.permission.READ_PRECISE_PHONE_STATE); } diff --git a/services/core/java/com/android/server/accounts/TokenCache.java b/services/core/java/com/android/server/accounts/TokenCache.java index be91f98..81c6b0e 100644 --- a/services/core/java/com/android/server/accounts/TokenCache.java +++ b/services/core/java/com/android/server/accounts/TokenCache.java @@ -125,7 +125,7 @@ import java.util.Objects; * This is recursive, but it won't spiral out of control because LruCache is * thread safe and the Evictor can only be removed once. */ - Evictor evictor = mTokenEvictors.remove(oldVal.token); + Evictor evictor = mTokenEvictors.remove(new Pair<>(k.account.type, oldVal.token)); if (evictor != null) { evictor.evict(); } @@ -133,13 +133,15 @@ import java.util.Objects; } public void putToken(Key k, Value v) { - // Prepare for removal by token string. - Evictor tokenEvictor = mTokenEvictors.get(v.token); + // Prepare for removal by pair of account type and token string. + Pair<String, String> pair = new Pair<>(k.account.type, v.token); + + Evictor tokenEvictor = mTokenEvictors.get(pair); if (tokenEvictor == null) { tokenEvictor = new Evictor(); } tokenEvictor.add(k); - mTokenEvictors.put(new Pair<>(k.account.type, v.token), tokenEvictor); + mTokenEvictors.put(pair, tokenEvictor); // Prepare for removal by associated account. Evictor accountEvictor = mAccountEvictors.get(k.account); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index def4c59..30f35af 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -44,6 +44,7 @@ import android.app.ApplicationThreadNative; import android.app.BroadcastOptions; import android.app.IActivityContainer; import android.app.IActivityContainerCallback; +import android.app.IActivityManager; import android.app.IAppTask; import android.app.ITaskStackListener; import android.app.ProfilerInfo; @@ -218,6 +219,7 @@ import android.os.UpdateLock; import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; +import android.telecom.TelecomManager; import android.text.format.DateUtils; import android.text.format.Time; import android.util.AtomicFile; @@ -264,6 +266,9 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; + +import cyanogenmod.power.PerformanceManagerInternal; + import java.util.Date; import java.text.SimpleDateFormat; @@ -1094,6 +1099,8 @@ public final class ActivityManagerService extends ActivityManagerNative */ private IVoiceInteractionSession mRunningVoice; + PerformanceManagerInternal mPerf; + /** * For some direct access we need to power manager. */ @@ -2200,6 +2207,7 @@ public final class ActivityManagerService extends ActivityManagerNative try { Intent protectedAppIntent = new Intent(); + protectedAppIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); protectedAppIntent.setComponent( new ComponentName("com.android.settings", "com.android.settings.applications.ProtectedAppsActivity")); @@ -2232,6 +2240,8 @@ public final class ActivityManagerService extends ActivityManagerNative .build(); try { int[] outId = new int[1]; + inm.cancelNotificationWithTag("android", null, + R.string.notify_package_component_protected_title, msg.arg1); inm.enqueueNotificationWithTag("android", "android", null, R.string.notify_package_component_protected_title, notification, outId, mCurrentUserId); @@ -3010,7 +3020,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (!app.killed) { Slog.wtfStack(TAG, "Removing process that hasn't been killed: " + app); Process.killProcessQuiet(app.pid); - killProcessGroup(app.info.uid, app.pid); + killProcessGroup(app.uid, app.pid); } if (lrui <= mLruProcessActivityStart) { mLruProcessActivityStart--; @@ -3385,7 +3395,7 @@ public final class ActivityManagerService extends ActivityManagerNative // clean it up now. if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_PROCESSES, "App died: " + app); checkTime(startTime, "startProcess: bad proc running, killing"); - killProcessGroup(app.info.uid, app.pid); + killProcessGroup(app.uid, app.pid); handleAppDiedLocked(app, true, true); checkTime(startTime, "startProcess: done killing old proc"); } @@ -3440,6 +3450,17 @@ public final class ActivityManagerService extends ActivityManagerNative null /* entryPoint */, null /* entryPointArgs */); } + void launchBoost(int pid, String packageName) { + if (mPerf == null) { + mPerf = LocalServices.getService(PerformanceManagerInternal.class); + if (mPerf == null) { + Slog.e(TAG, "PerformanceManager not ready!"); + return; + } + } + mPerf.launchBoost(pid, packageName); + } + private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { long startTime = SystemClock.elapsedRealtime(); @@ -3602,6 +3623,9 @@ public final class ActivityManagerService extends ActivityManagerNative checkTime(startTime, "startProcess: building log message"); StringBuilder buf = mStringBuilder; buf.setLength(0); + if (hostingType.equals("activity")) { + launchBoost(startResult.pid, app.processName); + } buf.append("Start proc "); buf.append(startResult.pid); buf.append(':'); @@ -3626,6 +3650,18 @@ public final class ActivityManagerService extends ActivityManagerNative app.killed = false; app.killedByAm = false; checkTime(startTime, "startProcess: starting to update pids map"); + ProcessRecord oldApp; + synchronized (mPidsSelfLocked) { + oldApp = mPidsSelfLocked.get(startResult.pid); + } + // If there is already an app occupying that pid that hasn't been cleaned up + if (oldApp != null && !app.isolated) { + // Clean up anything relating to this pid first + Slog.w(TAG, "Reusing pid " + startResult.pid + + " while app is still mapped to it"); + cleanUpApplicationRecordLocked(oldApp, false, false, -1, + true /*replacingPid*/); + } synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(startResult.pid, app); if (isActivityProcess) { @@ -4780,7 +4816,8 @@ public final class ActivityManagerService extends ActivityManagerNative private final void handleAppDiedLocked(ProcessRecord app, boolean restarting, boolean allowRestart) { int pid = app.pid; - boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1); + boolean kept = cleanUpApplicationRecordLocked(app, restarting, allowRestart, -1, + false /*replacingPid*/); if (!kept && !restarting) { removeLruProcessLocked(app); if (pid > 0) { @@ -4921,7 +4958,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (!fromBinderDied) { Process.killProcessQuiet(pid); } - killProcessGroup(app.info.uid, pid); + killProcessGroup(app.uid, pid); app.killed = true; } @@ -6535,12 +6572,14 @@ public final class ActivityManagerService extends ActivityManagerNative } @Override - public void showBootMessage(final CharSequence msg, final boolean always) { + public void updateBootProgress(final int stage, final ApplicationInfo optimizedApp, + final int currentAppPos, final int totalAppCount, final boolean always) { if (Binder.getCallingUid() != Process.myUid()) { // These days only the core system can call this, so apps can't get in // the way of what we show about running them. } - mWindowManager.showBootMessage(msg, always); + mWindowManager.updateBootProgress(stage, optimizedApp, + currentAppPos, totalAppCount, always); } @Override @@ -9047,6 +9086,27 @@ public final class ActivityManagerService extends ActivityManagerNative } } + private void cleanupProtectedComponentTasksLocked() { + for (int i = mRecentTasks.size() - 1; i >= 0; i--) { + TaskRecord tr = mRecentTasks.get(i); + + for (int j = tr.mActivities.size() - 1; j >= 0; j--) { + ActivityRecord r = tr.mActivities.get(j); + ComponentName cn = r.realActivity; + + try { + boolean isProtected = AppGlobals.getPackageManager() + .isComponentProtected(null, -1, cn, getCurrentUserIdLocked()); + if (isProtected) { + removeTaskByIdLocked(tr.taskId, false); + } + } catch (RemoteException re) { + + } + } + } + } + /** * Removes the task with the specified task id. * @@ -9453,6 +9513,10 @@ public final class ActivityManagerService extends ActivityManagerNative mStackSupervisor.setLockTaskModeLocked(null, ActivityManager.LOCK_TASK_MODE_NONE, "stopLockTask", true); } + TelecomManager tm = (TelecomManager) mContext.getSystemService(Context.TELECOM_SERVICE); + if (tm != null) { + tm.showInCallScreen(false); + } } finally { Binder.restoreCallingIdentity(ident); } @@ -11937,8 +12001,8 @@ public final class ActivityManagerService extends ActivityManagerNative intent.setComponent(comp); doneReceivers.add(comp); lastRi = curRi; - CharSequence label = ai.loadLabel(mContext.getPackageManager()); - showBootMessage(mContext.getString(R.string.android_preparing_apk, label), false); + updateBootProgress(IActivityManager.BOOT_STAGE_PREPARING_APPS, + ai.applicationInfo, 0, 0, false); } Slog.i(TAG, "Pre-boot of " + intent.getComponent().toShortString() + " for user " + users[curUser]); @@ -12046,6 +12110,7 @@ public final class ActivityManagerService extends ActivityManagerNative mRecentTasks.clear(); mRecentTasks.addAll(mTaskPersister.restoreTasksLocked()); + cleanupProtectedComponentTasksLocked(); mRecentTasks.cleanupLocked(UserHandle.USER_ALL); mTaskPersister.startPersisting(); @@ -12060,9 +12125,8 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (ActivityManagerService.this) { mDidUpdate = true; } - showBootMessage(mContext.getText( - R.string.android_upgrading_complete), - false); + updateBootProgress(IActivityManager.BOOT_STAGE_COMPLETE, + null, 0, 0, false); writeLastDonePreBootReceivers(doneReceivers); systemReady(goingCallback); } @@ -12552,6 +12616,7 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (sb) { bufferWasEmpty = sb.length() == 0; appendDropBoxProcessHeaders(process, processName, sb); + sb.append("CM Version: ").append(cyanogenmod.os.Build.CYANOGENMOD_VERSION).append("\n"); sb.append("Build: ").append(Build.FINGERPRINT).append("\n"); sb.append("System-App: ").append(isSystemApp).append("\n"); sb.append("Uptime-Millis: ").append(info.violationUptimeMillis).append("\n"); @@ -12821,6 +12886,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (subject != null) { sb.append("Subject: ").append(subject).append("\n"); } + sb.append("CM Version: ").append(cyanogenmod.os.Build.CYANOGENMOD_VERSION).append("\n"); sb.append("Build: ").append(Build.FINGERPRINT).append("\n"); if (Debug.isDebuggerConnected()) { sb.append("Debugger: Connected\n"); @@ -15850,7 +15916,8 @@ public final class ActivityManagerService extends ActivityManagerNative * app that was passed in must remain on the process lists. */ private final boolean cleanUpApplicationRecordLocked(ProcessRecord app, - boolean restarting, boolean allowRestart, int index) { + boolean restarting, boolean allowRestart, int index, boolean replacingPid) { + Slog.d(TAG, "cleanUpApplicationRecord -- " + app.pid); if (index >= 0) { removeLruProcessLocked(app); ProcessList.remove(app.pid); @@ -15980,7 +16047,9 @@ public final class ActivityManagerService extends ActivityManagerNative if (!app.persistent || app.isolated) { if (DEBUG_PROCESSES || DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Removing non-persistent process during cleanup: " + app); - removeProcessNameLocked(app.processName, app.uid); + if (!replacingPid) { + removeProcessNameLocked(app.processName, app.uid); + } if (mHeavyWeightProcess == app) { mHandler.sendMessage(mHandler.obtainMessage(CANCEL_HEAVY_NOTIFICATION_MSG, mHeavyWeightProcess.userId, 0)); @@ -16387,11 +16456,22 @@ public final class ActivityManagerService extends ActivityManagerNative // Cause the target app to be launched if necessary and its backup agent // instantiated. The backup agent will invoke backupAgentCreated() on the // activity manager to announce its creation. - public boolean bindBackupAgent(ApplicationInfo app, int backupMode) { - if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, - "bindBackupAgent: app=" + app + " mode=" + backupMode); + public boolean bindBackupAgent(String packageName, int backupMode, int userId) { + if (DEBUG_BACKUP) Slog.v(TAG, "bindBackupAgent: app=" + packageName + " mode=" + backupMode); enforceCallingPermission("android.permission.CONFIRM_FULL_BACKUP", "bindBackupAgent"); + IPackageManager pm = AppGlobals.getPackageManager(); + ApplicationInfo app = null; + try { + app = pm.getApplicationInfo(packageName, 0, userId); + } catch (RemoteException e) { + // can't happen; package manager is process-local + } + if (app == null) { + Slog.w(TAG, "Unable to bind backup agent for " + packageName); + return false; + } + synchronized(this) { // !!! TODO: currently no check here that we're already bound BatteryStatsImpl.Uid.Pkg.Serv ss = null; @@ -16916,7 +16996,8 @@ public final class ActivityManagerService extends ActivityManagerNative } else if (callerApp == null || !callerApp.persistent) { try { if (AppGlobals.getPackageManager().isProtectedBroadcast( - intent.getAction())) { + intent.getAction()) && !AppGlobals.getPackageManager() + .isProtectedBroadcastAllowed(intent.getAction(), callingUid)) { String msg = "Permission Denial: not allowed to send broadcast " + intent.getAction() + " from pid=" + callingPid + ", uid=" + callingUid; @@ -17087,6 +17168,14 @@ public final class ActivityManagerService extends ActivityManagerNative ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO); mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy)); break; + case cyanogenmod.content.Intent.ACTION_PROTECTED_CHANGED: + final boolean state = + intent.getBooleanExtra( + cyanogenmod.content.Intent.EXTRA_PROTECTED_STATE, false); + if (state == PackageManager.COMPONENT_PROTECTED_STATUS) { + cleanupProtectedComponentTasksLocked(); + } + break; } } @@ -17753,6 +17842,11 @@ public final class ActivityManagerService extends ActivityManagerNative !values.themeConfig.equals(mConfiguration.themeConfig)); } + if ((changes & ActivityInfo.CONFIG_THEME_FONT) != 0) { + // Notify zygote that themes need a refresh + SystemProperties.set(PROP_REFRESH_THEME, "1"); + } + mConfigurationSeq++; if (mConfigurationSeq <= 0) { mConfigurationSeq = 1; @@ -19923,7 +20017,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Ignore exceptions. } } - cleanUpApplicationRecordLocked(app, false, true, -1); + cleanUpApplicationRecordLocked(app, false, true, -1, false /*replacingPid*/); mRemovedProcesses.remove(i); if (app.persistent) { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index f439966..f676db9 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1701,10 +1701,10 @@ final class ActivityStack { if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); // Some activities may want to alter the system power management - if (mStackSupervisor.mPerf != null) { - mStackSupervisor.mPerf.activityResumed(next.intent); + if (mStackSupervisor.mService.mPerf != null) { + mStackSupervisor.mService.mPerf.activityResumed(next.intent); } - + // If we are currently pausing an activity, then don't do anything // until that is done. if (!mStackSupervisor.allPausedActivitiesComplete()) { @@ -1838,8 +1838,8 @@ final class ActivityStack { ? AppTransition.TRANSIT_ACTIVITY_CLOSE : AppTransition.TRANSIT_TASK_CLOSE, false); if (prev.task != next.task) { - if (mStackSupervisor.mPerf != null) { - mStackSupervisor.mPerf.cpuBoost(2000 * 1000); + if (mStackSupervisor.mService.mPerf != null) { + mStackSupervisor.mService.mPerf.cpuBoost(2000 * 1000); } } } @@ -1858,8 +1858,8 @@ final class ActivityStack { ? AppTransition.TRANSIT_TASK_OPEN_BEHIND : AppTransition.TRANSIT_TASK_OPEN, false); if (prev.task != next.task) { - if (mStackSupervisor.mPerf != null) { - mStackSupervisor.mPerf.cpuBoost(2000 * 1000); + if (mStackSupervisor.mService.mPerf != null) { + mStackSupervisor.mService.mPerf.cpuBoost(2000 * 1000); } } } @@ -4230,7 +4230,8 @@ final class ActivityStack { if (focusedStack && topTask) { // Give the latest time to ensure foreground task can be sorted // at the first, because lastActiveTime of creating task is 0. - ci.lastActiveTime = System.currentTimeMillis(); + // Only do this if the clock didn't run backwards, though. + ci.lastActiveTime = Math.max(ci.lastActiveTime, System.currentTimeMillis()); topTask = false; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index cf49e15..bde32e7 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -118,8 +118,6 @@ import com.android.server.LocalServices; import com.android.server.am.ActivityStack.ActivityState; import com.android.server.wm.WindowManagerService; -import cyanogenmod.power.PerformanceManagerInternal; - import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; @@ -276,8 +274,6 @@ public final class ActivityStackSupervisor implements DisplayListener { PowerManager mPm; - PerformanceManagerInternal mPerf; - /** * Is the privacy guard currently enabled? Shared between ActivityStacks */ @@ -354,17 +350,6 @@ public final class ActivityStackSupervisor implements DisplayListener { mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper()); } - private void launchBoost() { - if (mPerf == null) { - mPerf = LocalServices.getService(PerformanceManagerInternal.class); - } - if (mPerf == null) { - Slog.e(TAG, "PerformanceManager not ready!"); - } else { - mPerf.launchBoost(); - } - } - /** * At the time when the constructor runs, the power manager has not yet been * initialized. So we initialize our wakelocks afterwards. @@ -972,10 +957,26 @@ public final class ActivityStackSupervisor implements DisplayListener { return ActivityManager.START_CANCELED; } + if (intent.getAction() != null && !isProvisioned()) { + switch (intent.getAction()) { + case Intent.ACTION_SEARCH: + case Intent.ACTION_WEB_SEARCH: + case Intent.ACTION_PROCESS_TEXT: + case Intent.ACTION_ASSIST: + case Intent.ACTION_VOICE_ASSIST: + Slog.w(TAG, "not starting assist intent while not provisioned"); + return ActivityManager.START_NOT_CURRENT_USER_ACTIVITY; + } + } try { //TODO: This needs to be a flushed out API in the future. - if (intent.getComponent() != null && AppGlobals.getPackageManager() - .isComponentProtected(callingPackage, intent.getComponent(), userId)) { + boolean isProtected = intent.getComponent() != null + && AppGlobals.getPackageManager() + .isComponentProtected(callingPackage, callingUid, + intent.getComponent(), userId) && + (intent.getFlags()&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0; + + if (isProtected) { Message msg = mService.mHandler.obtainMessage( ActivityManagerService.POST_COMPONENT_PROTECTED_MSG); //Store start flags, userid @@ -988,6 +989,7 @@ public final class ActivityStackSupervisor implements DisplayListener { } catch (RemoteException e) { e.printStackTrace(); } + final int realCallingPid = Binder.getCallingPid(); final int realCallingUid = Binder.getCallingUid(); int callingPid; @@ -1468,8 +1470,6 @@ public final class ActivityStackSupervisor implements DisplayListener { Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) : (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY : container.mActivityDisplay.mDisplayId))); - /* Acquire perf lock during new app launch */ - launchBoost(); } ActivityRecord sourceRecord = null; @@ -1886,6 +1886,29 @@ public final class ActivityStackSupervisor implements DisplayListener { inTask = null; } + try { + //TODO: This needs to be a flushed out API in the future. + boolean isProtected = intent.getComponent() != null + && AppGlobals.getPackageManager() + .isComponentProtected(sourceRecord == null ? "android" : + sourceRecord.launchedFromPackage, r.launchedFromUid, + intent.getComponent(), r.userId) && + (intent.getFlags()&Intent.FLAG_GRANT_READ_URI_PERMISSION) == 0; + + if (isProtected && r.state == INITIALIZING) { + Message msg = mService.mHandler.obtainMessage( + ActivityManagerService.POST_COMPONENT_PROTECTED_MSG); + //Store start flags, userid + intent.setFlags(startFlags); + intent.putExtra("com.android.settings.PROTECTED_APPS_USER_ID", r.userId); + msg.obj = intent; + mService.mHandler.sendMessage(msg); + return ActivityManager.START_NOT_CURRENT_USER_ACTIVITY; + } + } catch (RemoteException e) { + e.printStackTrace(); + } + final boolean launchSingleTop = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP; final boolean launchSingleInstance = r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE; final boolean launchSingleTask = r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK; @@ -2822,7 +2845,7 @@ public final class ActivityStackSupervisor implements DisplayListener { ActivityRecord top = task.stack.topRunningActivityLocked(null); /* App is launching from recent apps and it's a new process */ if(top != null && top.state == ActivityState.DESTROYED) { - launchBoost(); + mService.launchBoost(-1, top.packageName); } if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) { @@ -3107,15 +3130,15 @@ public final class ActivityStackSupervisor implements DisplayListener { final ActivityRecord ar = stack.findTaskLocked(r); if (ar != null) { if (ar.state == ActivityState.DESTROYED) { - launchBoost(); + mService.launchBoost(-1, r.packageName); } return ar; } } } - if (DEBUG_TASKS) Slog.d(TAG_TASKS, "No task found"); - launchBoost(); + mService.launchBoost(-1, r.packageName); + if (DEBUG_TASKS) Slog.d(TAG_TASKS, "No task found"); return null; } @@ -3924,7 +3947,9 @@ public final class ActivityStackSupervisor implements DisplayListener { } void showLockTaskToast() { - mLockTaskNotify.showToast(mLockTaskModeState); + if (mLockTaskNotify != null) { + mLockTaskNotify.showToast(mLockTaskModeState); + } } void showLockTaskEscapeMessageLocked(TaskRecord task) { @@ -4663,4 +4688,9 @@ public final class ActivityStackSupervisor implements DisplayListener { return onLeanbackOnly; } + + private boolean isProvisioned() { + return Settings.Global.getInt(mService.mContext.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 0) == 1; + } } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 589a4b8..e7fec19 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -297,6 +297,11 @@ public final class BroadcastQueue { boolean didSomething = false; final BroadcastRecord br = mPendingBroadcast; if (br != null && br.curApp.pid == app.pid) { + if (br.curApp != app) { + Slog.e(TAG, "App mismatch when sending pending broadcast to " + + app.processName + ", intended target is " + br.curApp.processName); + return false; + } try { mPendingBroadcast = null; processCurBroadcastLocked(br, app); diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java index 055e33e..a5d37f0 100644 --- a/services/core/java/com/android/server/am/LockTaskNotify.java +++ b/services/core/java/com/android/server/am/LockTaskNotify.java @@ -51,8 +51,8 @@ public class LockTaskNotify { private boolean hasNavigationBar() { 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; + || CMSettings.Global.getIntForUser(mContext.getContentResolver(), + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; } public void showToast(int lockTaskModeState) { diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java index 9c9a421..4def2fb 100644 --- a/services/core/java/com/android/server/am/ProcessList.java +++ b/services/core/java/com/android/server/am/ProcessList.java @@ -260,8 +260,8 @@ final class ProcessList { int maxSize = 1280*800; // 1024000 230400 870400 .264 float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize); if (false) { - Slog.i("XXXXXX", "scaleMem=" + scaleMem); - Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + Slog.i(TAG, "scaleMem=" + scaleMem); + Slog.i(TAG, "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight); } @@ -273,7 +273,7 @@ final class ProcessList { int minfree_abs = Resources.getSystem().getInteger( com.android.internal.R.integer.config_lowMemoryKillerMinFreeKbytesAbsolute); if (false) { - Slog.i("XXXXXX", "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs); + Slog.i(TAG, "minfree_adj=" + minfree_adj + " minfree_abs=" + minfree_abs); } // We've now baked in the increase to the basic oom values above, since @@ -286,12 +286,12 @@ final class ProcessList { int low = mOomMinFreeLow[i]; int high = mOomMinFreeHigh[i]; if (is64bit) { - Slog.i("XXXXXX", "choosing minFree values for 64 Bit"); + Slog.i(TAG, "choosing minFree values for 64 Bit"); // Increase the high min-free levels for cached processes for 64-bit if (i == 4) high = (high*3)/2; else if (i == 5) high = (high*7)/4; } else { - Slog.i("XXXXXX", "choosing minFree values for 32 Bit"); + Slog.i(TAG, "choosing minFree values for 32 Bit"); low = mOomMinFreeLow32Bit[i]; high = mOomMinFreeHigh32Bit[i]; } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index 33f1a1c..30f2c3e 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -578,7 +578,7 @@ final class ProcessRecord { } EventLog.writeEvent(EventLogTags.AM_KILL, userId, pid, processName, setAdj, reason); Process.killProcessQuiet(pid); - Process.killProcessGroup(info.uid, pid); + Process.killProcessGroup(uid, pid); if (!persistent) { killed = true; killedByAm = true; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 92643ba..fe3df61 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -911,59 +911,63 @@ public class AudioService extends IAudioService.Stub { * @hide */ public void addMediaPlayerAndUpdateRemoteController (String packageName) { - Log.v(TAG, "addMediaPlayerAndUpdateRemoteController: size of existing list: " + - mMediaPlayers.size()); - boolean playerToAdd = true; - if (mMediaPlayers.size() > 0) { - final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator(); - while (rccIterator.hasNext()) { - final MediaPlayerInfo player = rccIterator.next(); - if (packageName.equals(player.getPackageName())) { - Log.e(TAG, "Player entry present, no need to add"); - playerToAdd = false; - player.setFocus(true); - } else { - Log.e(TAG, "Player: " + player.getPackageName()+ "Lost Focus"); - player.setFocus(false); + synchronized(mMediaPlayers) { + Log.v(TAG, "addMediaPlayerAndUpdateRemoteController: size of existing list: " + + mMediaPlayers.size()); + boolean playerToAdd = true; + if (mMediaPlayers.size() > 0) { + final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator(); + while (rccIterator.hasNext()) { + final MediaPlayerInfo player = rccIterator.next(); + if (packageName.equals(player.getPackageName())) { + Log.e(TAG, "Player entry present, no need to add"); + playerToAdd = false; + player.setFocus(true); + } else { + Log.e(TAG, "Player: " + player.getPackageName()+ "Lost Focus"); + player.setFocus(false); + } } } + if (playerToAdd) { + Log.e(TAG, "Adding Player: " + packageName + " to available player list"); + mMediaPlayers.add(new MediaPlayerInfo(packageName, true)); + } + Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); + intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName); + intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, true); + intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true); + sendBroadcastToAll(intent); + Log.v(TAG, "updating focussed RCC change to RCD: CallingPackageName:" + + packageName); } - if (playerToAdd) { - Log.e(TAG, "Adding Player: " + packageName + " to available player list"); - mMediaPlayers.add(new MediaPlayerInfo(packageName, true)); - } - Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName); - intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, true); - intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true); - sendBroadcastToAll(intent); - Log.v(TAG, "updating focussed RCC change to RCD: CallingPackageName:" - + packageName); } /** * @hide */ public void updateRemoteControllerOnExistingMediaPlayers() { - Log.v(TAG, "updateRemoteControllerOnExistingMediaPlayers: size of Player list: " + + synchronized(mMediaPlayers) { + Log.v(TAG, "updateRemoteControllerOnExistingMediaPlayers: size of Player list: " + mMediaPlayers.size()); - if (mMediaPlayers.size() > 0) { - Log.v(TAG, "Inform RemoteController regarding existing RCC entry"); - final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator(); - while (rccIterator.hasNext()) { - final MediaPlayerInfo player = rccIterator.next(); - Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, - player.getPackageName()); - intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, - player.isFocussed()); - intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true); - sendBroadcastToAll(intent); - Log.v(TAG, "updating RCC change: CallingPackageName:" + - player.getPackageName()); + if (mMediaPlayers.size() > 0) { + Log.v(TAG, "Inform RemoteController regarding existing RCC entry"); + final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator(); + while (rccIterator.hasNext()) { + final MediaPlayerInfo player = rccIterator.next(); + Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); + intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, + player.getPackageName()); + intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, + player.isFocussed()); + intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, true); + sendBroadcastToAll(intent); + Log.v(TAG, "updating RCC change: CallingPackageName:" + + player.getPackageName()); + } + } else { + Log.e(TAG, "No RCC entry present to update"); } - } else { - Log.e(TAG, "No RCC entry present to update"); } } @@ -971,34 +975,36 @@ public class AudioService extends IAudioService.Stub { * @hide */ public void removeMediaPlayerAndUpdateRemoteController (String packageName) { - Log.v(TAG, "removeMediaPlayerAndUpdateRemoteController: size of existing list: " + - mMediaPlayers.size()); - boolean playerToRemove = false; - int index = -1; - if (mMediaPlayers.size() > 0) { - final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator(); - while (rccIterator.hasNext()) { - index++; - final MediaPlayerInfo player = rccIterator.next(); - if (packageName.equals(player.getPackageName())) { - Log.v(TAG, "Player entry present remove and update RemoteController"); - playerToRemove = true; - break; - } else { - Log.v(TAG, "Player entry for " + player.getPackageName()+ " is not present"); + synchronized(mMediaPlayers) { + Log.v(TAG, "removeMediaPlayerAndUpdateRemoteController: size of existing list: " + + mMediaPlayers.size()); + boolean playerToRemove = false; + int index = -1; + if (mMediaPlayers.size() > 0) { + final Iterator<MediaPlayerInfo> rccIterator = mMediaPlayers.iterator(); + while (rccIterator.hasNext()) { + index++; + final MediaPlayerInfo player = rccIterator.next(); + if (packageName.equals(player.getPackageName())) { + Log.v(TAG, "Player entry present remove and update RemoteController"); + playerToRemove = true; + break; + } else { + Log.v(TAG, "Player entry for " + player.getPackageName()+ " is not present"); + } } } + if (playerToRemove) { + Log.e(TAG, "Removing Player: " + packageName + " from index" + index); + mMediaPlayers.remove(index); + } + Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); + intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName); + intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, false); + intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, false); + sendBroadcastToAll(intent); + Log.v(TAG, "Updated List size: " + mMediaPlayers.size()); } - if (playerToRemove) { - Log.e(TAG, "Removing Player: " + packageName + " from index" + index); - mMediaPlayers.remove(index); - } - Intent intent = new Intent(AudioManager.RCC_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_CALLING_PACKAGE_NAME, packageName); - intent.putExtra(AudioManager.EXTRA_FOCUS_CHANGED_VALUE, false); - intent.putExtra(AudioManager.EXTRA_AVAILABLITY_CHANGED_VALUE, false); - sendBroadcastToAll(intent); - Log.v(TAG, "Updated List size: " + mMediaPlayers.size()); } private void checkAllAliasStreamVolumes() { @@ -4003,8 +4009,29 @@ public class AudioService extends IAudioService.Stub { int index; if (mIsMuted) { index = 0; - } else if (((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) - || ((device & mFullVolumeDevices) != 0)) { + } else if ((device & AudioSystem.DEVICE_OUT_ALL_A2DP) != 0 && mAvrcpAbsVolSupported) { + /* Special handling for Bluetooth Absolute Volume scenario + * If we send full audio gain, some accessories are too loud even at its lowest + * volume. We are not able to enumerate all such accessories, so here is the + * workaround from phone side. + * For the lowest volume steps 1 and 2, restrict audio gain to 50% and 75%. + * For volume step 0, set audio gain to 0 as some accessories won't mute on their end. + */ + int i = (getIndex(device) + 5)/10; + if (i == 0) { + // 0% for volume 0 + index = 0; + } else if (i == 1) { + // 50% for volume 1 + index = (int)(mIndexMax * 0.5) /10; + } else if (i == 2) { + // 75% for volume 2 + index = (int)(mIndexMax * 0.75) /10; + } else { + // otherwise, full gain + index = (mIndexMax + 5)/10; + } + } else if ((device & mFullVolumeDevices) != 0) { index = (mIndexMax + 5)/10; } else { index = (getIndex(device) + 5)/10; @@ -4628,7 +4655,11 @@ public class AudioService extends IAudioService.Stub { break; case MSG_PLAY_SOUND_EFFECT: - onPlaySoundEffect(msg.arg1, msg.arg2); + if (isStreamMute(AudioSystem.STREAM_SYSTEM)) { + Log.d(TAG, "Stream muted, skip playback"); + } else { + onPlaySoundEffect(msg.arg1, msg.arg2); + } break; case MSG_BTA2DP_DOCK_TIMEOUT: diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java index 7d1da01..58c76ec 100644 --- a/services/core/java/com/android/server/connectivity/PacManager.java +++ b/services/core/java/com/android/server/connectivity/PacManager.java @@ -27,6 +27,7 @@ import android.content.ServiceConnection; import android.net.ProxyInfo; import android.net.Uri; import android.os.Handler; +import android.os.HandlerThread; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -39,10 +40,10 @@ import com.android.internal.annotations.GuardedBy; import com.android.net.IProxyCallback; import com.android.net.IProxyPortListener; import com.android.net.IProxyService; -import com.android.server.IoThread; import libcore.io.Streams; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.net.URL; import java.net.URLConnection; @@ -66,6 +67,7 @@ public class PacManager { private static final int DELAY_1 = 0; private static final int DELAY_4 = 3; private static final int DELAY_LONG = 4; + private static final long MAX_PAC_SIZE = 20 * 1000 * 1000; /** Keep these values up-to-date with ProxyService.java */ public static final String KEY_PROXY = "keyProxy"; @@ -123,15 +125,21 @@ public class PacManager { } }; + private final HandlerThread mNetThread = new HandlerThread("android.pacmanager", + android.os.Process.THREAD_PRIORITY_DEFAULT); + private final Handler mNetThreadHandler; + class PacRefreshIntentReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { - IoThread.getHandler().post(mPacDownloader); + mNetThreadHandler.post(mPacDownloader); } } public PacManager(Context context, Handler handler, int proxyMessage) { mContext = context; mLastPort = -1; + mNetThread.start(); + mNetThreadHandler = new Handler(mNetThread.getLooper()); mPacRefreshIntent = PendingIntent.getBroadcast( context, 0, new Intent(ACTION_PAC_REFRESH), 0); @@ -199,7 +207,25 @@ public class PacManager { private static String get(Uri pacUri) throws IOException { URL url = new URL(pacUri.toString()); URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY); - return new String(Streams.readFully(urlConnection.getInputStream())); + long contentLength = -1; + try { + contentLength = Long.parseLong(urlConnection.getHeaderField("Content-Length")); + } catch (NumberFormatException e) { + // Ignore + } + if (contentLength > MAX_PAC_SIZE) { + throw new IOException("PAC too big: " + contentLength + " bytes"); + } + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int count; + while ((count = urlConnection.getInputStream().read(buffer)) != -1) { + bytes.write(buffer, 0, count); + if (bytes.size() > MAX_PAC_SIZE) { + throw new IOException("PAC too big"); + } + } + return bytes.toString(); } private int getNextDelay(int currentDelay) { @@ -267,7 +293,7 @@ public class PacManager { intent.setClassName(PAC_PACKAGE, PAC_SERVICE); if ((mProxyConnection != null) && (mConnection != null)) { // Already bound no need to bind again, just download the new file. - IoThread.getHandler().post(mPacDownloader); + mNetThreadHandler.post(mPacDownloader); return; } mConnection = new ServiceConnection() { @@ -297,7 +323,7 @@ public class PacManager { } catch (RemoteException e) { Log.e(TAG, "Unable to reach ProxyService - PAC will not be started", e); } - IoThread.getHandler().post(mPacDownloader); + mNetThreadHandler.post(mPacDownloader); } } } diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java index 3472db2..60d6772 100644 --- a/services/core/java/com/android/server/connectivity/Tethering.java +++ b/services/core/java/com/android/server/connectivity/Tethering.java @@ -59,6 +59,7 @@ import com.android.internal.util.IState; import com.android.internal.util.State; import com.android.internal.util.StateMachine; import com.android.server.IoThread; +import com.android.server.NetPluginDelegate; import com.android.server.net.BaseNetworkObserver; import java.io.FileDescriptor; @@ -1595,6 +1596,8 @@ public class Tethering extends BaseNetworkObserver { sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); } } else { + Network network = getConnectivityManager().getNetworkForType(upType); + NetPluginDelegate.setUpstream(network); LinkProperties linkProperties = getConnectivityManager().getLinkProperties(upType); if (linkProperties != null) { @@ -1629,7 +1632,6 @@ public class Tethering extends BaseNetworkObserver { } } try { - Network network = getConnectivityManager().getNetworkForType(upType); if (network == null) { Log.e(TAG, "No Network for upstream type " + upType + "!"); } diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index b766894..f581a7f 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -815,9 +815,13 @@ public final class ContentService extends IContentService.Stub { mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_STATS, "no permission to read the sync stats"); + final boolean canAccessAccounts = + mContext.checkCallingOrSelfPermission(Manifest.permission.GET_ACCOUNTS) + == PackageManager.PERMISSION_GRANTED; long identityToken = clearCallingIdentity(); try { - return getSyncManager().getSyncStorageEngine().getCurrentSyncsCopy(userId); + return getSyncManager().getSyncStorageEngine() + .getCurrentSyncsCopy(userId, canAccessAccounts); } finally { restoreCallingIdentity(identityToken); } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index ef086da..53c36ff 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -2435,10 +2435,9 @@ public class SyncManager { final long shiftedLastPollTimeAbsolute = (0 < lastPollTimeAbsolute - mSyncRandomOffsetMillis) ? (lastPollTimeAbsolute - mSyncRandomOffsetMillis) : 0; - long remainingMillis - = periodInMillis - (shiftedNowAbsolute % periodInMillis); long timeSinceLastRunMillis = (nowAbsolute - lastPollTimeAbsolute); + long remainingMillis = periodInMillis - timeSinceLastRunMillis; // Schedule this periodic sync to run early if it's close enough to its next // runtime, and far enough from its last run time. // If we are early, there will still be time remaining in this period. diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java index cca0c16..96a7bb4 100644 --- a/services/core/java/com/android/server/content/SyncStorageEngine.java +++ b/services/core/java/com/android/server/content/SyncStorageEngine.java @@ -45,6 +45,7 @@ import android.util.Pair; import android.util.SparseArray; import android.util.ArrayMap; import android.util.Xml; +import android.util.EventLog; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; @@ -1458,15 +1459,23 @@ public class SyncStorageEngine extends Handler { } /** - * @return a copy of the current syncs data structure. Will not return - * null. + * @param userId Id of user to return current sync info. + * @param canAccessAccounts Determines whether to redact Account information from the result. + * @return a copy of the current syncs data structure. Will not return null. */ - public List<SyncInfo> getCurrentSyncsCopy(int userId) { + public List<SyncInfo> getCurrentSyncsCopy(int userId, boolean canAccessAccounts) { synchronized (mAuthorities) { final List<SyncInfo> syncs = getCurrentSyncsLocked(userId); final List<SyncInfo> syncsCopy = new ArrayList<SyncInfo>(); for (SyncInfo sync : syncs) { - syncsCopy.add(new SyncInfo(sync)); + SyncInfo copy; + if (!canAccessAccounts) { + copy = SyncInfo.createAccountRedacted( + sync.authorityId, sync.authority, sync.startTime); + } else { + copy = new SyncInfo(sync); + } + syncsCopy.add(copy); } return syncsCopy; } @@ -1892,8 +1901,13 @@ public class SyncStorageEngine extends Handler { if ("authority".equals(tagName)) { authority = parseAuthority(parser, version); periodicSync = null; - if (authority.ident > highestAuthorityId) { - highestAuthorityId = authority.ident; + if (authority != null) { + if (authority.ident > highestAuthorityId) { + highestAuthorityId = authority.ident; + } + } else { + EventLog.writeEvent(0x534e4554, "26513719", -1, + "Malformed authority"); } } else if (XML_TAG_LISTEN_FOR_TICKLES.equals(tagName)) { parseListenForTickles(parser); diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 1925ed3..eca6a2e 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -194,9 +194,6 @@ class AutomaticBrightnessController { private int mBrightnessAdjustmentSampleOldBrightness; private float mBrightnessAdjustmentSampleOldGamma; - // Night mode color temperature adjustments - private final LiveDisplayController mLiveDisplay; - // Period of time in which to consider light samples in milliseconds. private int mAmbientLightHorizon; @@ -212,7 +209,7 @@ class AutomaticBrightnessController { int lightSensorRate, long brighteningLightDebounceConfig, long brighteningLightFastDebounceConfig, long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, - int ambientLightHorizon, LiveDisplayController ldc) { + int ambientLightHorizon) { mContext = context; mCallbacks = callbacks; mTwilight = LocalServices.getService(TwilightManager.class); @@ -227,7 +224,6 @@ class AutomaticBrightnessController { mBrighteningLightFastDebounceConfig = brighteningLightFastDebounceConfig; mDarkeningLightDebounceConfig = darkeningLightDebounceConfig; mResetAmbientLuxAfterWarmUpConfig = resetAmbientLuxAfterWarmUpConfig; - mLiveDisplay = ldc; mAmbientLightHorizon = ambientLightHorizon; mWeightingIntercept = ambientLightHorizon; @@ -503,9 +499,6 @@ class AutomaticBrightnessController { } } - // Update LiveDisplay with the current lux - mLiveDisplay.updateLiveDisplay(mAmbientLux); - if (USE_TWILIGHT_ADJUSTMENT) { TwilightState state = mTwilight.getCurrentState(); if (state != null && state.isNight()) { diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java index e8a857b..6a6570b 100644 --- a/services/core/java/com/android/server/display/DisplayManagerService.java +++ b/services/core/java/com/android/server/display/DisplayManagerService.java @@ -287,8 +287,6 @@ public final class DisplayManagerService extends SystemService { mOnlyCore = onlyCore; } - mDisplayPowerController.systemReady(); - mHandler.sendEmptyMessage(MSG_REGISTER_ADDITIONAL_DISPLAY_ADAPTERS); } diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index ae596cb..25e59d5 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -251,9 +251,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call // The controller for the automatic brightness level. private AutomaticBrightnessController mAutomaticBrightnessController; - // The controller for LiveDisplay - private final LiveDisplayController mLiveDisplayController; - // Animators. private ObjectAnimator mColorFadeOnAnimator; private ObjectAnimator mColorFadeOffAnimator; @@ -275,8 +272,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mBlanker = blanker; mContext = context; - mLiveDisplayController = new LiveDisplayController(context, handler.getLooper()); - final Resources resources = context.getResources(); final int screenBrightnessSettingMinimum = clampAbsoluteBrightness(resources.getInteger( com.android.internal.R.integer.config_screenBrightnessSettingMinimum)); @@ -363,7 +358,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mScreenBrightnessRangeMaximum, dozeScaleFactor, lightSensorRate, brighteningLightDebounce, brighteningLightFastDebounce, darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp, - ambientLightHorizon, mLiveDisplayController); + ambientLightHorizon); } } @@ -716,9 +711,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } } - // Update LiveDisplay now - mLiveDisplayController.updateLiveDisplay(); - // Determine whether the display is ready for use in the newly requested state. // Note that we do not wait for the brightness ramp animation to complete before // reporting the display is ready because we only need to ensure the screen is in the @@ -1157,8 +1149,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call if (mAutomaticBrightnessController != null) { mAutomaticBrightnessController.dump(pw); } - - mLiveDisplayController.dump(pw); } private static String proximityToString(int state) { @@ -1220,10 +1210,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON); } - void systemReady() { - mLiveDisplayController.systemReady(); - } - private final class DisplayControllerHandler extends Handler { public DisplayControllerHandler(Looper looper) { super(looper, null, true /*async*/); diff --git a/services/core/java/com/android/server/display/LiveDisplayController.java b/services/core/java/com/android/server/display/LiveDisplayController.java deleted file mode 100644 index 28f2432..0000000 --- a/services/core/java/com/android/server/display/LiveDisplayController.java +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (C) 2015 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.display; - -import android.animation.ValueAnimator; -import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.app.Notification; -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.IBinder; -import android.os.Looper; -import android.os.Message; -import android.os.Parcel; -import android.os.PowerManagerInternal; -import android.os.RemoteException; -import android.os.ServiceManager; -import android.os.UserHandle; -import android.provider.Settings; -import android.text.TextUtils; -import android.text.format.DateUtils; -import android.util.MathUtils; -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; - - public static final int MODE_OFF = 0; - public static final int MODE_NIGHT = 1; - public static final int MODE_AUTO = 2; - public static final int MODE_OUTDOOR = 3; - public static final int MODE_DAY = 4; - - private int mColorTemperature = OFF_TEMPERATURE; - private float mCurrentLux = 0.0f; - - private int mHintCounter; - private int mMode; - - private boolean mOutdoorMode; - private boolean mColorEnhancement; - private boolean mLowPower; - - private final Context mContext; - private final Handler mHandler; - - private CMHardwareManager mHardware; - - private int mDayTemperature; - private int mNightTemperature; - - private boolean mUseOutdoorMode; - private boolean mUseColorEnhancement; - private boolean mUseLowPower; - - private boolean mOutdoorModeIsSelfManaged; - - private final float[] mColorAdjustment = new float[] { 1.0f, 1.0f, 1.0f }; - private final float[] mRGB = new float[] { 0.0f, 0.0f, 0.0f }; - - private TwilightManager mTwilightManager; - private boolean mSunset = false; - - private SettingsObserver mObserver; - - private ValueAnimator mAnimator; - - private int mDefaultDayTemperature; - private int mDefaultNightTemperature; - private int mDefaultOutdoorLux; - - private boolean mInitialized = false; - - private static final int MSG_UPDATE_LIVE_DISPLAY = 1; - - // Display postprocessing can have power impact. Disable it if powersave mode is on. - private boolean mLowPerformance = false; - private PowerManagerInternal.LowPowerModeListener mLowPowerModeListener = - new PowerManagerInternal.LowPowerModeListener() { - @Override - public void onLowPowerModeChanged(boolean enabled) { - mLowPerformance = enabled; - updateLiveDisplay(mCurrentLux); - } - }; - - LiveDisplayController(Context context, Looper looper) { - mContext = context; - mHandler = new LiveDisplayHandler(looper); - } - - void systemReady() { - mHardware = CMHardwareManager.getInstance(mContext); - - mDefaultDayTemperature = mContext.getResources().getInteger( - org.cyanogenmod.platform.internal.R.integer.config_dayColorTemperature); - mDefaultNightTemperature = mContext.getResources().getInteger( - org.cyanogenmod.platform.internal.R.integer.config_nightColorTemperature); - mDefaultOutdoorLux = mContext.getResources().getInteger( - org.cyanogenmod.platform.internal.R.integer.config_outdoorAmbientLux); - - mUseOutdoorMode = - mHardware.isSupported(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT); - mOutdoorModeIsSelfManaged = mUseOutdoorMode ? - mHardware.isSunlightEnhancementSelfManaged() : false; - - mUseLowPower = - mHardware.isSupported(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT); - if (mUseLowPower) { - mLowPower = mHardware.get(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT); - } - - mUseColorEnhancement = - mHardware.isSupported(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT); - if (mUseColorEnhancement) { - mColorEnhancement = - mHardware.get(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT); - } - - updateSettings(); - - mObserver = new SettingsObserver(); - mObserver.register(true); - - PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class); - pmi.registerLowPowerModeObserver(mLowPowerModeListener); - mLowPerformance = pmi.getLowPowerModeEnabled(); - - mTwilightManager = LocalServices.getService(TwilightManager.class); - mTwilightManager.registerListener(mTwilightListener, mHandler); - - mInitialized = true; - } - - private void updateSettings() { - mDayTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_DAY, - mDefaultDayTemperature, - UserHandle.USER_CURRENT); - mNightTemperature = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_TEMPERATURE_NIGHT, - mDefaultNightTemperature, - UserHandle.USER_CURRENT); - mMode = CMSettings.System.getIntForUser(mContext.getContentResolver(), - 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) { - saveUserHint(1); - } - - // Manual color adjustment will be set as a space separated string of float values - String colorAdjustmentTemp = CMSettings.System.getStringForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_COLOR_ADJUSTMENT, - UserHandle.USER_CURRENT); - String[] colorAdjustment = colorAdjustmentTemp == null ? - null : colorAdjustmentTemp.split(" "); - if (colorAdjustment == null || colorAdjustment.length != 3) { - colorAdjustment = new String[] { "1.0", "1.0", "1.0" }; - } - try { - mColorAdjustment[0] = Float.parseFloat(colorAdjustment[0]); - mColorAdjustment[1] = Float.parseFloat(colorAdjustment[1]); - mColorAdjustment[2] = Float.parseFloat(colorAdjustment[2]); - } catch (NumberFormatException e) { - Slog.e(TAG, e.getMessage(), e); - mColorAdjustment[0] = 1.0f; - mColorAdjustment[1] = 1.0f; - mColorAdjustment[2] = 1.0f; - } - - 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 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 = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_NIGHT); - private final Uri DISPLAY_TEMPERATURE_MODE_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_TEMPERATURE_MODE); - private final Uri DISPLAY_AUTO_OUTDOOR_MODE_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE); - private final Uri DISPLAY_LOW_POWER_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_LOW_POWER); - private final Uri DISPLAY_COLOR_ENHANCE_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_COLOR_ENHANCE); - private final Uri DISPLAY_COLOR_ADJUSTMENT_URI = - CMSettings.System.getUriFor(CMSettings.System.DISPLAY_COLOR_ADJUSTMENT); - public SettingsObserver() { - super(mHandler); - } - - public void register(boolean register) { - final ContentResolver cr = mContext.getContentResolver(); - if (register) { - cr.registerContentObserver(DISPLAY_TEMPERATURE_DAY_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_TEMPERATURE_NIGHT_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_TEMPERATURE_MODE_URI, false, this, UserHandle.USER_ALL); - cr.registerContentObserver(DISPLAY_AUTO_OUTDOOR_MODE_URI, false, this, UserHandle.USER_ALL); - 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 - protected void update() { - updateSettings(); - } - } - - public void updateLiveDisplay() { - updateLiveDisplay(mCurrentLux); - } - - synchronized void updateLiveDisplay(float lux) { - mCurrentLux = lux; - mHandler.removeMessages(MSG_UPDATE_LIVE_DISPLAY); - mHandler.sendEmptyMessage(MSG_UPDATE_LIVE_DISPLAY); - } - - private synchronized void updateColorTemperature(TwilightState twilight) { - int temperature = mDayTemperature; - if (mMode == MODE_OFF || mLowPerformance) { - temperature = OFF_TEMPERATURE; - } else if (mMode == MODE_NIGHT) { - temperature = mNightTemperature; - } else if (mMode == MODE_AUTO) { - temperature = getTwilightK(twilight); - } - - if (mAnimator != null) { - mAnimator.cancel(); - } - mAnimator = ValueAnimator.ofInt(mColorTemperature, temperature); - mAnimator.setDuration(Math.abs(mColorTemperature - temperature) / 2); - mAnimator.addUpdateListener(new AnimatorUpdateListener() { - @Override - public void onAnimationUpdate(ValueAnimator animation) { - setDisplayTemperature((Integer)animation.getAnimatedValue()); - } - }); - mAnimator.start(); - } - - private synchronized void setDisplayTemperature(int temperature) { - mColorTemperature = temperature; - - final float[] rgb = ColorUtils.temperatureToRGB(temperature); - - if (!mLowPerformance) { - rgb[0] *= mColorAdjustment[0]; - rgb[1] *= mColorAdjustment[1]; - rgb[2] *= mColorAdjustment[2]; - } - - if (rgb[0] == mRGB[0] && rgb[1] == mRGB[1] && rgb[2] == mRGB[2]) { - // no changes - return; - } - - System.arraycopy(rgb, 0, mRGB, 0, 3); - - Slog.d(TAG, "Adjust display temperature to " + temperature + - "K [r=" + rgb[0] + " g=" + rgb[1] + " b=" + rgb[2] + "]"); - - if (mHardware.isSupported(CMHardwareManager.FEATURE_DISPLAY_COLOR_CALIBRATION)) { - // Clear this out in case of an upgrade - CMSettings.Secure.putStringForUser(mContext.getContentResolver(), - CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, - null, - UserHandle.USER_CURRENT); - - int max = mHardware.getDisplayColorCalibrationMax(); - mHardware.setDisplayColorCalibration(new int[] { - (int) Math.ceil(rgb[0] * max), - (int) Math.ceil(rgb[1] * max), - (int) Math.ceil(rgb[2] * max) - }); - screenRefresh(); - } else { - String colorMatrixStr = null; - if (rgb[0] != 1.0f || rgb[1] != 1.0f || rgb[2] != 1.0f) { - final Float[] colorMatrix = new Float[] { - rgb[0], 0.0f, 0.0f, 0.0f, - 0.0f, rgb[1], 0.0f, 0.0f, - 0.0f, 0.0f, rgb[2], 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f }; - colorMatrixStr = TextUtils.join(" ", colorMatrix); - } - - // For GPU color transform, go thru DisplayAdjustmentUtils in - // order to coexist with accessibility settings - CMSettings.Secure.putStringForUser(mContext.getContentResolver(), - CMSettings.Secure.LIVE_DISPLAY_COLOR_MATRIX, - colorMatrixStr, - UserHandle.USER_CURRENT); - - DisplayAdjustmentUtils.applyAdjustments(mContext, UserHandle.USER_CURRENT); - } - } - - /** - * Outdoor mode is optionally enabled when ambient lux > 10000 and it's daytime - * Melt faces! - * - * TODO: Use the camera or RGB sensor to determine if it's really sunlight - */ - private synchronized void updateOutdoorMode(TwilightState twilight) { - if (!mUseOutdoorMode) { - return; - } - - boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_AUTO_OUTDOOR_MODE, - 1, - UserHandle.USER_CURRENT) == 1; - - boolean enabled; - if (mOutdoorModeIsSelfManaged) { - enabled = value; - } else { - enabled = !mLowPerformance && - ((mMode == MODE_OUTDOOR) || - (value && mMode == MODE_AUTO && - twilight != null && !twilight.isNight() && - mCurrentLux > mDefaultOutdoorLux)); - } - - if (enabled == mOutdoorMode) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_SUNLIGHT_ENHANCEMENT, enabled); - mOutdoorMode = enabled; - } - - /** - * Color enhancement is optional, but can look bad with night mode - */ - private synchronized void updateColorEnhancement(TwilightState twilight) { - if (!mUseColorEnhancement) { - return; - } - - boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_COLOR_ENHANCE, - 1, - UserHandle.USER_CURRENT) == 1; - - boolean enabled = !mLowPerformance && value && - !(mMode == MODE_NIGHT || - (mMode == MODE_AUTO && twilight != null && twilight.isNight())); - - if (enabled == mColorEnhancement) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_COLOR_ENHANCEMENT, enabled); - mColorEnhancement = enabled; - } - - /** - * Adaptive backlight / low power mode. Turn it off when under very bright light. - */ - private synchronized void updateLowPowerMode() { - if (!mUseLowPower) { - return; - } - - boolean value = CMSettings.System.getIntForUser(mContext.getContentResolver(), - CMSettings.System.DISPLAY_LOW_POWER, - 1, - UserHandle.USER_CURRENT) == 1; - - boolean enabled = value && (mCurrentLux < mDefaultOutdoorLux); - - if (enabled == mLowPower) { - return; - } - - mHardware.set(CMHardwareManager.FEATURE_ADAPTIVE_BACKLIGHT, enabled); - mLowPower = enabled; - } - - /** - * Where is the sun anyway? This calculation determines day or night, and scales - * the value around sunset/sunrise for a smooth transition. - * - * @param now - * @param sunset - * @param sunrise - * @return float between 0 and 1 - */ - private static float adj(long now, long sunset, long sunrise) { - if (sunset < 0 || sunrise < 0 - || now < sunset || now > sunrise) { - return 1.0f; - } - - if (now < sunset + TWILIGHT_ADJUSTMENT_TIME) { - return MathUtils.lerp(1.0f, 0.0f, - (float)(now - sunset) / TWILIGHT_ADJUSTMENT_TIME); - } - - if (now > sunrise - TWILIGHT_ADJUSTMENT_TIME) { - return MathUtils.lerp(1.0f, 0.0f, - (float)(sunrise - now) / TWILIGHT_ADJUSTMENT_TIME); - } - - return 0.0f; - } - - /** - * Determine the color temperature we should use for the display based on - * the position of the sun. - * - * @param state - * @return color temperature in Kelvin - */ - private int getTwilightK(TwilightState state) { - float adjustment = 1.0f; - - if (state != null) { - final long now = System.currentTimeMillis(); - adjustment = adj(now, state.getYesterdaySunset(), state.getTodaySunrise()) * - adj(now, state.getTodaySunset(), state.getTomorrowSunrise()); - } - - return (int)MathUtils.lerp(mNightTemperature, mDayTemperature, adjustment); - } - - /** - * Tell SurfaceFlinger to repaint the screen. This is called after updating - * hardware registers for display calibration to have an immediate effect. - */ - private static void screenRefresh() { - try { - final IBinder flinger = ServiceManager.getService("SurfaceFlinger"); - if (flinger != null) { - final Parcel data = Parcel.obtain(); - data.writeInterfaceToken("android.ui.ISurfaceComposer"); - flinger.transact(1004, data, null, 0); - data.recycle(); - } - } catch (RemoteException ex) { - Slog.e(TAG, "Failed to refresh screen", ex); - } - } - - private void saveUserHint(int value) { - if (mHintCounter == value) { - return; - } - CMSettings.System.putIntForUser(mContext.getContentResolver(), - CMSettings.System.LIVE_DISPLAY_HINTED, - value, - UserHandle.USER_CURRENT); - mHintCounter = value; - } - - /** - * Show a friendly notification to the user about the potential benefits of decreasing - * blue light at night. Do this only once if the feature has not been used after - * three sunsets. It would be great to enable this by default, but we don't want - * the change of screen color to be considered a "bug" by a user who doesn't - * understand what's happening. - * - * @param state - */ - private void updateUserHint(TwilightState state) { - // check if we should send the hint only once after sunset - if (state == null || mHintCounter == 1) { - return; - } - boolean transition = state.isNight() && !mSunset; - mSunset = state.isNight(); - if (!transition) { - return; - } - - if (mHintCounter <= 0) { - mHintCounter++; - saveUserHint(mHintCounter); - } - if (mHintCounter == 0) { - //show the notification and don't come back here - final Intent intent = new Intent("android.settings.LIVEDISPLAY_SETTINGS"); - PendingIntent result = PendingIntent.getActivity( - mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); - Notification.Builder builder = new Notification.Builder(mContext) - .setContentTitle(mContext.getResources().getString( - org.cyanogenmod.platform.internal.R.string.live_display_title)) - .setContentText(mContext.getResources().getString( - org.cyanogenmod.platform.internal.R.string.live_display_hint)) - .setSmallIcon(org.cyanogenmod.platform.internal.R.drawable.ic_livedisplay_notif) - .setStyle(new Notification.BigTextStyle().bigText(mContext.getResources() - .getString( - org.cyanogenmod.platform.internal.R.string.live_display_hint))) - .setContentIntent(result) - .setAutoCancel(true); - - NotificationManager nm = - (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE); - nm.notifyAsUser(null, 1, builder.build(), UserHandle.CURRENT); - - saveUserHint(1); - } - } - - private final TwilightListener mTwilightListener = new TwilightListener() { - @Override - public void onTwilightStateChanged() { - updateLiveDisplay(mCurrentLux); - } - }; - - private final class LiveDisplayHandler extends Handler { - public LiveDisplayHandler(Looper looper) { - super(looper, null, true /*async*/); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case MSG_UPDATE_LIVE_DISPLAY: - if (!mInitialized) { - break; - } - TwilightState twilight = mTwilightManager.getCurrentState(); - - updateColorTemperature(twilight); - updateOutdoorMode(twilight); - updateColorEnhancement(twilight); - updateLowPowerMode(); - updateUserHint(twilight); - - boolean transition = mMode == MODE_AUTO && - mColorTemperature != mDayTemperature && - mColorTemperature != mNightTemperature; - if (transition) { - // fire again in a minute - sendEmptyMessageDelayed(MSG_UPDATE_LIVE_DISPLAY, - DateUtils.MINUTE_IN_MILLIS); - } - break; - } - } - } - - public void dump(PrintWriter pw) { - pw.println(); - pw.println("LiveDisplay Controller Configuration:"); - pw.println(" mDayTemperature=" + mDayTemperature); - pw.println(" mNightTemperature=" + mNightTemperature); - pw.println(); - pw.println("LiveDisplay Controller State:"); - pw.println(" mMode=" + (mLowPerformance ? "disabled in powersave mode" : mMode)); - pw.println(" mSunset=" + mSunset); - pw.println(" mColorTemperature=" + mColorTemperature); - pw.println(" mColorAdjustment=[r: " + mColorAdjustment[0] + " g:" + mColorAdjustment[1] + - " b:" + mColorAdjustment[2] + "]"); - pw.println(" mRGB=[r:" + mRGB[0] + " g:" + mRGB[1] + " b:" + mRGB[2] + "]"); - pw.println(" mOutdoorMode=" + (mUseOutdoorMode ? mOutdoorMode : "N/A")); - pw.println(" mColorEnhancement=" + (mUseColorEnhancement ? mColorEnhancement : "N/A")); - pw.println(" mLowPower=" + (mUseLowPower ? mLowPower : "N/A")); - } -} diff --git a/services/core/java/com/android/server/display/WifiDisplayController.java b/services/core/java/com/android/server/display/WifiDisplayController.java index 239f8cd..eaeca01 100644 --- a/services/core/java/com/android/server/display/WifiDisplayController.java +++ b/services/core/java/com/android/server/display/WifiDisplayController.java @@ -78,6 +78,9 @@ final class WifiDisplayController implements DumpUtils.Dump { private static final int RTSP_TIMEOUT_SECONDS = 30; private static final int RTSP_TIMEOUT_SECONDS_CERT_MODE = 120; + // time given for RTSP teardown sequence to complete. + private static final int RTSP_TEARDOWN_TIMEOUT = 3; + // We repeatedly issue calls to discover peers every so often for a few reasons. // 1. The initial request may fail and need to retried. // 2. Discovery will self-abort after any group is initiated, which may not necessarily @@ -151,6 +154,12 @@ final class WifiDisplayController implements DumpUtils.Dump { // True if RTSP has connected. private boolean mRemoteDisplayConnected; + // Waiting for displayDisconnected from ERD. + private boolean mRemoteDisplayTearingDown; + + // Timed out waiting for RTSP teardown to complete. + private boolean mRemoteDisplayRtspTeardownTimedOut; + // The information we have most recently told WifiDisplayAdapter about. private WifiDisplay mAdvertisedDisplay; private Surface mAdvertisedDisplaySurface; @@ -363,7 +372,15 @@ final class WifiDisplayController implements DumpUtils.Dump { } private void updateScanState() { - if (mScanRequested && mWfdEnabled && mDesiredDevice == null) { + + if (true == mRemoteDisplayTearingDown) { + // when rtsp teardown sequence is completed or timed out, this + // function will be called again. + Slog.i(TAG, "updateScanState no-op as rtsp teardown sequence is in progress"); + return; + } + + if (mScanRequested && mWfdEnabled && (mDesiredDevice == null)) { if (!mDiscoverPeersInProgress) { Slog.i(TAG, "Starting Wifi display scan."); mDiscoverPeersInProgress = true; @@ -570,7 +587,7 @@ final class WifiDisplayController implements DumpUtils.Dump { // Step 1. Before we try to connect to a new device, tell the system we // have disconnected from the old one. if ((mRemoteDisplay != null || mExtRemoteDisplay != null) && - mConnectedDevice != mDesiredDevice) { + mConnectedDevice != mDesiredDevice && false == mRemoteDisplayTearingDown) { Slog.i(TAG, "Stopped listening for RTSP connection on " + mRemoteDisplayInterface + " from Wifi display: " + mConnectedDevice.deviceName); @@ -581,16 +598,25 @@ final class WifiDisplayController implements DumpUtils.Dump { ExtendedRemoteDisplayHelper.dispose(mExtRemoteDisplay); } - mExtRemoteDisplay = null; - mRemoteDisplay = null; - mRemoteDisplayInterface = null; - mRemoteDisplayConnected = false; mHandler.removeCallbacks(mRtspTimeout); + mRemoteDisplayTearingDown = true; - mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED); - unadvertiseDisplay(); + // Use extended timeout value for certification, as some tests require user inputs + int rtspTimeout = mWifiDisplayCertMode ? + RTSP_TIMEOUT_SECONDS_CERT_MODE : RTSP_TIMEOUT_SECONDS; + + Slog.i(TAG, "Starting wait for rtsp teardown sequence for " + + rtspTimeout + " secs"); - // continue to next step + mHandler.postDelayed(mRtspTimeout, rtspTimeout * 1000); + + return; + } + + if (true == mRemoteDisplayTearingDown && false == mRemoteDisplayRtspTeardownTimedOut) { + // Need to wait for ERD to notify that p2p connection is no longer needed. + Slog.i(TAG, "updateConnection - return as rtsp teardown sequence in progress"); + return; } // Step 2. Before we try to connect to a new device, disconnect from the old one. @@ -630,6 +656,11 @@ final class WifiDisplayController implements DumpUtils.Dump { return; // wait for asynchronous callback } + if (true == mRemoteDisplayTearingDown) { + Slog.i(TAG, "rtsp teardown sequence in progress"); + return; + } + // Step 3. Before we try to connect to a new device, stop trying to connect // to the old one. if (mCancelingDevice != null) { @@ -771,10 +802,11 @@ final class WifiDisplayController implements DumpUtils.Dump { @Override public void onDisplayDisconnected() { + Slog.i(TAG, "onDisplayDisconnected called"); if (mConnectedDevice == oldDevice) { Slog.i(TAG, "Closed RTSP connection with Wifi display: " + mConnectedDevice.deviceName); - mHandler.removeCallbacks(mRtspTimeout); + FinishRtspTeardown(); disconnect(); } } @@ -907,6 +939,21 @@ final class WifiDisplayController implements DumpUtils.Dump { } } + private void FinishRtspTeardown() + { + Slog.i(TAG, "Wait for rtsp teardown sequence completed"); + mRemoteDisplayTearingDown = false; + + mExtRemoteDisplay = null; // callbacks no longer needed + mRemoteDisplay = null; + mRemoteDisplayInterface = null; + mRemoteDisplayConnected = false; + mHandler.removeCallbacks(mRtspTimeout); + + mWifiP2pManager.setMiracastMode(WifiP2pManager.MIRACAST_DISABLED); + unadvertiseDisplay(); + } + private final Runnable mDiscoverPeers = new Runnable() { @Override public void run() { @@ -929,13 +976,31 @@ final class WifiDisplayController implements DumpUtils.Dump { private final Runnable mRtspTimeout = new Runnable() { @Override public void run() { + Slog.i(TAG, "mRtspTimeout triggerred"); if (mConnectedDevice != null - && (mRemoteDisplay != null || mExtRemoteDisplay != null) - && !mRemoteDisplayConnected) { - Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after " - + RTSP_TIMEOUT_SECONDS + " seconds: " - + mConnectedDevice.deviceName); - handleConnectionFailure(true); + && (mRemoteDisplay != null || mExtRemoteDisplay != null)) { + if (true == mRemoteDisplayTearingDown) { + // rtsp teardown sequence timed out + Slog.i(TAG, "Timed out waiting for RTSP teardown sequence after " + + RTSP_TEARDOWN_TIMEOUT + " seconds: " + + mConnectedDevice.deviceName); + mRemoteDisplayRtspTeardownTimedOut = true; + + // this should close P2P + disconnect(); + + FinishRtspTeardown(); + + // Ok to resume wifi-scans + updateConnection(); + } else if (!mRemoteDisplayConnected) { + Slog.i(TAG, "Timed out waiting for Wifi display RTSP connection after " + + RTSP_TIMEOUT_SECONDS + " seconds: " + + mConnectedDevice.deviceName); + handleConnectionFailure(true); + } else { + Slog.i(TAG, "Timed out. no-op"); + } } } }; diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 6612218..e5ab37f 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -127,6 +127,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private IFingerprintDaemon mDaemon; private final PowerManager mPowerManager; private final AlarmManager mAlarmManager; + private int mCurrentUserId = UserHandle.USER_NULL; private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() { @Override @@ -340,7 +341,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe return; } stopPendingOperations(true); - mEnrollClient = new ClientMonitor(token, receiver, groupId, restricted, token.toString()); + mEnrollClient = new ClientMonitor(token, receiver, mCurrentUserId, groupId, restricted, + token.toString()); final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC); try { final int result = daemon.enroll(cryptoToken, groupId, timeout); @@ -428,7 +430,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe return; } stopPendingOperations(true); - mAuthClient = new ClientMonitor(token, receiver, groupId, restricted, opPackageName); + mAuthClient = new ClientMonitor(token, receiver, mCurrentUserId, groupId, restricted, + opPackageName); if (inLockoutMode()) { Slog.v(TAG, "In lockout mode; disallowing authentication"); if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) { @@ -485,7 +488,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe } stopPendingOperations(true); - mRemoveClient = new ClientMonitor(token, receiver, userId, restricted, token.toString()); + mRemoveClient = new ClientMonitor(token, receiver, mCurrentUserId, userId, restricted, + token.toString()); // The fingerprint template ids will be removed when we get confirmation from the HAL try { final int result = daemon.remove(fingerId, userId); @@ -623,15 +627,17 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private class ClientMonitor implements IBinder.DeathRecipient { IBinder token; IFingerprintServiceReceiver receiver; - int userId; + int userId; // userId of the caller + int currentUserId; // current user id when this was created boolean restricted; // True if client does not have MANAGE_FINGERPRINT permission String owner; - public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId, - boolean restricted, String owner) { + public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, + int currentUserId, int userId, boolean restricted, String owner) { this.token = token; this.receiver = receiver; this.userId = userId; + this.currentUserId = currentUserId; this.restricted = restricted; this.owner = owner; // name of the client that owns this - for debugging try { @@ -720,9 +726,9 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe Slog.v(TAG, "onAuthenticated(owner=" + mAuthClient.owner + ", id=" + fpId + ", gp=" + groupId + ")"); } - Fingerprint fp = !restricted ? - new Fingerprint("" /* TODO */, groupId, fpId, mHalDeviceId) : null; - receiver.onAuthenticationSucceeded(mHalDeviceId, fp); + Fingerprint fp = !restricted ? new Fingerprint("" /* TODO */, groupId, fpId, + mHalDeviceId) : null; + receiver.onAuthenticationSucceeded(mHalDeviceId, fp, currentUserId); } } catch (RemoteException e) { Slog.w(TAG, "Failed to notify Authenticated:", e); @@ -1147,6 +1153,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe Slog.e(TAG, "Failed to setActiveGroup():", e); } } + mCurrentUserId = userId; } private void listenForUserSwitches() { @@ -1157,6 +1164,12 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe public void onUserSwitching(int newUserId, IRemoteCallback reply) { mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */) .sendToTarget(); + if (reply != null) { + try { + reply.sendResult(null); + } catch (RemoteException e) { + } + } } @Override public void onUserSwitchComplete(int newUserId) throws RemoteException { diff --git a/services/core/java/com/android/server/lights/LightsService.java b/services/core/java/com/android/server/lights/LightsService.java index 16dde26..d4762bd 100644 --- a/services/core/java/com/android/server/lights/LightsService.java +++ b/services/core/java/com/android/server/lights/LightsService.java @@ -113,9 +113,10 @@ public class LightsService extends SystemService { private void setLightLocked(int color, int mode, int onMS, int offMS, int brightnessMode) { if (mModesUpdate || color != mColor || mode != mMode || onMS != mOnMS || - offMS != mOffMS) { + offMS != mOffMS || mReset) { if (DEBUG) Slog.v(TAG, "setLight #" + mId + ": color=#" + Integer.toHexString(color)); + mReset = false; mColor = color; mMode = mode; mOnMS = onMS; @@ -141,6 +142,7 @@ public class LightsService extends SystemService { private boolean mFlashing; private boolean mModesUpdate; private boolean mMultipleLeds; + private boolean mReset = true; } public LightsService(Context context) { diff --git a/services/core/java/com/android/server/location/GpsLocationProvider.java b/services/core/java/com/android/server/location/GpsLocationProvider.java index bdb77db..833c340 100644 --- a/services/core/java/com/android/server/location/GpsLocationProvider.java +++ b/services/core/java/com/android/server/location/GpsLocationProvider.java @@ -1118,7 +1118,7 @@ public class GpsLocationProvider implements LocationProviderInterface { } if (DEBUG) Log.d(TAG, "setRequest " + mProviderRequest); - if (mProviderRequest.reportLocation && !mDisableGps) { + if (mProviderRequest.reportLocation && !mDisableGps && isEnabled()) { // update client uids updateClientUids(mWorkSource); diff --git a/services/core/java/com/android/server/location/GpsXtraDownloader.java b/services/core/java/com/android/server/location/GpsXtraDownloader.java index 3585049..6310361 100644 --- a/services/core/java/com/android/server/location/GpsXtraDownloader.java +++ b/services/core/java/com/android/server/location/GpsXtraDownloader.java @@ -21,8 +21,11 @@ import android.util.Log; import java.net.HttpURLConnection; import java.net.URL; -import libcore.io.Streams; +import libcore.io.IoUtils; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; import java.io.IOException; import java.util.Properties; import java.util.Random; @@ -36,6 +39,7 @@ public class GpsXtraDownloader { private static final String TAG = "GpsXtraDownloader"; private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private static final long MAXIMUM_CONTENT_LENGTH_BYTES = 1000000; // 1MB. private static final String DEFAULT_USER_AGENT = "Android"; private final String[] mXtraServers; @@ -121,7 +125,19 @@ public class GpsXtraDownloader { return null; } - return Streams.readFully(connection.getInputStream()); + try (InputStream in = connection.getInputStream()) { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int count; + while ((count = in.read(buffer)) != -1) { + bytes.write(buffer, 0, count); + if (bytes.size() > MAXIMUM_CONTENT_LENGTH_BYTES) { + if (DEBUG) Log.d(TAG, "XTRA file too large"); + return null; + } + } + return bytes.toByteArray(); + } } catch (IOException ioe) { if (DEBUG) Log.d(TAG, "Error downloading gps XTRA: ", ioe); } finally { @@ -133,3 +149,4 @@ public class GpsXtraDownloader { } } + diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 7028fa6..22f9f72 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -47,6 +47,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.os.PowerManager; +import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.ServiceManager; @@ -760,6 +761,13 @@ public class MediaSessionService extends SystemService implements Monitor { + "setup is in progress."); return; } + if (isGlobalPriorityActive() && uid != Process.SYSTEM_UID) { + // Prevent dispatching key event through reflection while the global priority + // session is active. + Slog.i(TAG, "Only the system can dispatch media key event " + + "to the global priority session."); + return; + } synchronized (mLock) { // If we don't have a media button receiver to fall back on diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index da62313..4c847a2 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -45,6 +45,9 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY; import static android.net.NetworkPolicyManager.POLICY_ALLOW_BACKGROUND_BATTERY_SAVE; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_DATA; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_WLAN; +import static android.net.NetworkPolicyManager.POLICY_REJECT_ON_WLAN_BACKGROUND; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; @@ -105,6 +108,7 @@ import android.net.INetworkPolicyListener; import android.net.INetworkPolicyManager; import android.net.INetworkStatsService; import android.net.LinkProperties; +import android.net.NetworkCapabilities; import android.net.NetworkIdentity; import android.net.NetworkInfo; import android.net.NetworkPolicy; @@ -159,6 +163,7 @@ import com.android.internal.util.IndentingPrintWriter; import com.android.server.DeviceIdleController; import com.android.server.EventLogTags; import com.android.server.LocalServices; +import com.android.server.NetPluginDelegate; import com.google.android.collect.Lists; import org.xmlpull.v1.XmlPullParser; @@ -1205,7 +1210,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final ArrayList<Pair<String, NetworkIdentity>> connIdents = new ArrayList<>(states.length); final ArraySet<String> connIfaces = new ArraySet<String>(states.length); for (NetworkState state : states) { - if (state.networkInfo.isConnected()) { + if (state.networkInfo.isConnected() && (state.networkCapabilities == null + || !state.networkCapabilities.hasTransport( + NetworkCapabilities.TRANSPORT_CELLULAR) + || state.networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_INTERNET))) { final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); final String baseIface = state.linkProperties.getInterfaceName(); @@ -2397,6 +2406,14 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { uidRules = RULE_REJECT_ALL; } + try { + mNetworkManager.restrictAppOnWlan(uid, (uidPolicy & POLICY_REJECT_ON_WLAN) != 0 || + (((uidPolicy & POLICY_REJECT_ON_WLAN_BACKGROUND) != 0) && !uidForeground)); + mNetworkManager.restrictAppOnData(uid, (uidPolicy & POLICY_REJECT_ON_DATA) != 0); + } catch (RemoteException e) { + // ignored; service lives in system_server + } + final int oldRules = mUidRules.get(uid); if (uidRules == RULE_ALLOW_ALL) { mUidRules.delete(uid); diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java index 15b68c7..0176ec4 100644 --- a/services/core/java/com/android/server/net/NetworkStatsCollection.java +++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java @@ -491,6 +491,21 @@ public class NetworkStatsCollection implements FileRotator.Reader { } } + /** + * Replace data usage history for each matching identity in the template with empty values + */ + public void resetDataUsage(NetworkTemplate template) { + final ArrayList<Key> knownKeys = Lists.newArrayList(); + knownKeys.addAll(mStats.keySet()); + + for (Key key : knownKeys) { + if (templateMatches(template, key.ident)) { + mStats.put(key, new NetworkStatsHistory(mBucketDuration, 10)); + mDirty = true; + } + } + } + private void noteRecordedHistory(long startMillis, long endMillis, long totalBytes) { if (startMillis < mStartMillis) mStartMillis = startMillis; if (endMillis > mEndMillis) mEndMillis = endMillis; diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java index 6490865..3201981 100644 --- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java +++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java @@ -290,6 +290,31 @@ public class NetworkStatsRecorder { } /** + * Reset data usage for all matching identities in {@link FileRotator} history, + */ + public void resetDataUsageLocked(NetworkTemplate template) { + try { + // Reset all persisted data to empty values + mRotator.rewriteAll(new ResetDataUsageRewriter(mBucketDuration, template)); + } catch (IOException e) { + Log.wtf(TAG, "problem resetting data stats " + e); + recoverFromWtf(); + } catch (OutOfMemoryError e) { + Log.wtf(TAG, "problem resetting data stats " + e); + recoverFromWtf(); + } + + // Reset any pending stats + mPending.resetDataUsage(template); + mSinceBoot.resetDataUsage(template); + + final NetworkStatsCollection complete = mComplete != null ? mComplete.get() : null; + if (complete != null) { + complete.resetDataUsage(template); + } + } + + /** * Rewriter that will combine current {@link NetworkStatsCollection} values * with anything read from disk, and write combined set to disk. Clears the * original {@link NetworkStatsCollection} when finished writing. @@ -359,6 +384,42 @@ public class NetworkStatsRecorder { } } + /** + * Rewriter that will remove any {@link NetworkStatsHistory} attributed to + * identities in input template, replacing it with empty values. + */ + public static class ResetDataUsageRewriter implements FileRotator.Rewriter { + private final NetworkStatsCollection mTemp; + private NetworkTemplate mTemplate; + + public ResetDataUsageRewriter(long bucketDuration, NetworkTemplate template) { + mTemp = new NetworkStatsCollection(bucketDuration); + mTemplate = template; + } + + @Override + public void reset() { + mTemp.reset(); + } + + @Override + public void read(InputStream in) throws IOException { + mTemp.read(in); + mTemp.clearDirty(); + mTemp.resetDataUsage(mTemplate); + } + + @Override + public boolean shouldWrite() { + return mTemp.isDirty(); + } + + @Override + public void write(OutputStream out) throws IOException { + mTemp.write(new DataOutputStream(out)); + } + } + public void importLegacyNetworkLocked(File file) throws IOException { // legacy file still exists; start empty to avoid double importing mRotator.deleteAll(); diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index acd05f7..baaf055 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -81,6 +81,7 @@ import android.net.INetworkManagementEventObserver; import android.net.INetworkStatsService; import android.net.INetworkStatsSession; import android.net.LinkProperties; +import android.net.NetworkCapabilities; import android.net.NetworkIdentity; import android.net.NetworkInfo; import android.net.NetworkState; @@ -123,6 +124,7 @@ import com.android.internal.util.FileRotator; import com.android.internal.util.IndentingPrintWriter; import com.android.server.EventLogTags; import com.android.server.LocalServices; +import com.android.server.NetPluginDelegate; import com.android.server.connectivity.Tethering; import java.io.File; @@ -628,6 +630,26 @@ public class NetworkStatsService extends INetworkStatsService.Stub { return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields); } + /** + * Reset entire data usage history for all the uids in the template and update global + * data stats + */ + @Override + public void resetDataUsageHistoryForAllUid(NetworkTemplate template) { + mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); + + synchronized (mStatsLock) { + mWakeLock.acquire(); + try { + resetDataUsageLocked(template); + } catch (Exception e) { + // ignored; service lives in system_server + } finally { + mWakeLock.release(); + } + } + } + @Override public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); @@ -920,7 +942,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final ArraySet<String> mobileIfaces = new ArraySet<>(); for (NetworkState state : states) { - if (state.networkInfo.isConnected()) { + if (state.networkInfo.isConnected() && (state.networkCapabilities == null + || !state.networkCapabilities.hasTransport( + NetworkCapabilities.TRANSPORT_CELLULAR) + || state.networkCapabilities.hasCapability( + NetworkCapabilities.NET_CAPABILITY_INTERNET))) { final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType()); final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state); @@ -1148,6 +1174,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { removeUidsLocked(uids); } + /** + * Reset data usage history for all uids, uid tags, and global transfer data for the input template + */ + private void resetDataUsageLocked(NetworkTemplate template) { + // Perform one last poll before removing + performPollLocked(FLAG_PERSIST_ALL); + + mUidRecorder.resetDataUsageLocked(template); + mUidTagRecorder.resetDataUsageLocked(template); + mXtRecorder.resetDataUsageLocked(template); + } + @Override protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) { mContext.enforceCallingOrSelfPermission(DUMP, TAG); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 36818b5..422aee2 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -24,7 +24,6 @@ import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.END_TAG; import static org.xmlpull.v1.XmlPullParser.START_TAG; -import android.annotation.Nullable; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.AppGlobals; @@ -64,9 +63,6 @@ import android.media.AudioManager; import android.media.AudioManagerInternal; import android.media.AudioSystem; import android.media.IRingtonePlayer; -import android.media.session.MediaController; -import android.media.session.MediaSessionManager; -import android.media.session.PlaybackState; import android.net.Uri; import android.os.Binder; import android.os.Build; @@ -80,6 +76,7 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteException; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -104,6 +101,7 @@ import android.util.Log; import android.util.LruCache; import android.util.Slog; import android.util.SparseIntArray; +import android.util.TimeUtils; import android.util.Xml; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -124,6 +122,8 @@ import com.android.server.notification.ManagedServices.ManagedServiceInfo; import com.android.server.notification.ManagedServices.UserProfiles; import com.android.server.statusbar.StatusBarManagerInternal; +import cyanogenmod.media.AudioSessionInfo; +import cyanogenmod.media.CMAudioManager; import cyanogenmod.providers.CMSettings; import cyanogenmod.util.ColorUtils; @@ -304,6 +304,7 @@ public class NotificationManagerService extends SystemService { new ArrayMap<String, NotificationRecord>(); final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>(); final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>(); + final ArrayMap<String, Long> mLastSoundTimestamps = new ArrayMap<>(); final PolicyAccess mPolicyAccess = new PolicyAccess(); // The last key in this list owns the hardware. @@ -339,6 +340,8 @@ public class NotificationManagerService extends SystemService { private boolean mDisableDuckingWhileMedia; private boolean mActiveMedia; + private boolean mMultiColorNotificationLed; + private static final int MY_UID = Process.myUid(); private static final int MY_PID = Process.myPid(); private static final int REASON_DELEGATE_CLICK = 1; @@ -1094,15 +1097,39 @@ public class NotificationManagerService extends SystemService { } } + private BroadcastReceiver mMediaSessionReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + updateForActiveSessions(); + } + }; + + private void updateForActiveSessions() { + CMAudioManager manager = CMAudioManager.getInstance(getContext()); + List<AudioSessionInfo> sessions = manager.listAudioSessions(AudioManager.STREAM_MUSIC); + mActiveMedia = false; + for (AudioSessionInfo sessionInfo : sessions) { + if (sessionInfo.getSessionId() > 0) { + mActiveMedia = true; + break; + } + } + } + private void updateDisableDucking() { if (!mSystemReady) { return; } - final MediaSessionManager mediaSessionManager = (MediaSessionManager) getContext() - .getSystemService(Context.MEDIA_SESSION_SERVICE); - mediaSessionManager.removeOnActiveSessionsChangedListener(mSessionListener); + try { + getContext().unregisterReceiver(mMediaSessionReceiver); + } catch (IllegalArgumentException e) { + // Never registered + } if (mDisableDuckingWhileMedia) { - mediaSessionManager.addOnActiveSessionsChangedListener(mSessionListener, null); + updateForActiveSessions(); + IntentFilter intentFilter = new IntentFilter(CMAudioManager + .ACTION_AUDIO_SESSIONS_CHANGED); + getContext().registerReceiver(mMediaSessionReceiver, intentFilter); } } @@ -1200,6 +1227,8 @@ public class NotificationManagerService extends SystemService { mDefaultNotificationLedOff = resources.getInteger( R.integer.config_defaultNotificationLedOff); + mMultiColorNotificationLed = deviceLightsCan(NotificationManager.LIGHTS_RGB_NOTIFICATION); + mNotificationPulseCustomLedValues = new HashMap<String, NotificationLedValues>(); mPackageNameMappings = new HashMap<String, String>(); @@ -1220,10 +1249,10 @@ public class NotificationManagerService extends SystemService { VIBRATE_PATTERN_MAXLEN, DEFAULT_VIBRATE_PATTERN); - mAdjustableNotificationLedBrightness = resources.getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness); - mMultipleNotificationLeds = resources.getBoolean( - org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds); + mAdjustableNotificationLedBrightness = deviceLightsCan( + NotificationManager.LIGHTS_ADJUSTABLE_NOTIFICATION_BRIGHTNESS); + mMultipleNotificationLeds = deviceLightsCan( + NotificationManager.LIGHTS_MULTIPLE_LED); mUseAttentionLight = resources.getBoolean(R.bool.config_useAttentionLight); @@ -1237,6 +1266,7 @@ public class NotificationManagerService extends SystemService { } mZenModeHelper.initZenMode(); mZenModeHelper.readAllowLightsFromSettings(); + mZenModeHelper.readVibrationModeFromSettings(); mInterruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter(); mUserProfiles.updateCache(getContext()); @@ -1365,6 +1395,47 @@ public class NotificationManagerService extends SystemService { scheduleInterruptionFilterChanged(interruptionFilter); } + private int deviceLightsCapabilities() { + Resources resources = getContext().getResources(); + int capabilities = SystemProperties.getInt("sys.lights.capabilities", 0); + + if (capabilities == 0) { + int[] deviceCaps = resources.getIntArray( + com.android.internal.R.array.config_deviceLightCapabilities); + for (int cap : deviceCaps) { + capabilities |= 1<<cap; + } + } + + /* Legacy format */ + if (capabilities == 0) { + if (resources.getBoolean(com.android.internal.R.bool.config_multiColorNotificationLed)) { + capabilities |= 1<<NotificationManager.LIGHTS_RGB_NOTIFICATION; + } + if (resources.getBoolean(com.android.internal.R.bool.config_multiColorBatteryLed)) { + capabilities |= 1<<NotificationManager.LIGHTS_RGB_BATTERY; + } + if (resources.getBoolean(com.android.internal.R.bool.config_ledCanPulse)) { + capabilities |= 1<<NotificationManager.LIGHTS_LED_PULSE; + } + if (resources.getBoolean(org.cyanogenmod.platform.internal.R.bool.config_multipleNotificationLeds)) { + capabilities |= 1<<NotificationManager.LIGHTS_MULTIPLE_LED; + } + if (resources.getBoolean(org.cyanogenmod.platform.internal.R.bool.config_useSegmentedBatteryLed)) { + capabilities |= 1<<NotificationManager.LIGHTS_SEGMENTED_BATTERY_LIGHTS; + } + if (resources.getBoolean(org.cyanogenmod.platform.internal.R.bool.config_adjustableNotificationLedBrightness)) { + capabilities |= 1<<NotificationManager.LIGHTS_ADJUSTABLE_NOTIFICATION_BRIGHTNESS; + } + } + return capabilities; + } + + /** @hide */ + public boolean deviceLightsCan(int lightCapability) { + return ( (deviceLightsCapabilities() & 1<<lightCapability) != 0 ); + } + private final IBinder mService = new INotificationManager.Stub() { // Toasts // ============================================================================ @@ -1553,6 +1624,33 @@ public class NotificationManagerService extends SystemService { return mRankingHelper.getPackageVisibilityOverride(pkg, uid); } + @Override + public void setShowNotificationForPackageOnKeyguard( + String pkg, int uid, int status) { + checkCallerIsSystem(); + mRankingHelper.setShowNotificationForPackageOnKeyguard(pkg, uid, status); + savePolicyFile(); + } + + @Override + public int getShowNotificationForPackageOnKeyguard(String pkg, int uid) { + enforceSystemOrSystemUI("INotificationManager.getShowNotificationForPackageOnKeyguard"); + return mRankingHelper.getShowNotificationForPackageOnKeyguard(pkg, uid); + } + + @Override + public void setPackageNotificationSoundTimeout(String pkg, int uid, long timeout) { + checkCallerIsSystem(); + mRankingHelper.setPackageNotificationSoundTimeout(pkg, uid, timeout); + savePolicyFile(); + } + + @Override + public long getPackageNotificationSoundTimeout(String pkg, int uid) { + checkCallerIsSystem(); + return mRankingHelper.getPackageNotificationSoundTimeout(pkg, uid); + } + /** * System-only API for getting a list of current (i.e. not cleared) notifications. * @@ -1950,6 +2048,7 @@ public class NotificationManagerService extends SystemService { } private void enforcePolicyAccess(String pkg, String method) { + checkCallerIsSameApp(pkg); if (!checkPolicyAccess(pkg)) { Slog.w(TAG, "Notification policy access denied calling " + method); throw new SecurityException("Notification policy access denied"); @@ -1989,7 +2088,7 @@ public class NotificationManagerService extends SystemService { } @Override - public boolean matchesCallFilter(Bundle extras) { + public boolean[] matchesCallFilter(Bundle extras) { enforceSystemOrSystemUI("INotificationManager.matchesCallFilter"); return mZenModeHelper.matchesCallFilter( UserHandle.getCallingUserHandle(), @@ -2102,6 +2201,10 @@ public class NotificationManagerService extends SystemService { Binder.restoreCallingIdentity(identity); } } + + public boolean deviceLightsCan(int lightCapability) { + return ( (deviceLightsCapabilities() & 1<<lightCapability) != 0 ); + } }; private String disableNotificationEffects(NotificationRecord record) { @@ -2274,6 +2377,14 @@ public class NotificationManagerService extends SystemService { } catch (NameNotFoundException e) { // pass } + + long now = SystemClock.elapsedRealtime(); + pw.println("\n Last notification sound timestamps:"); + for (Map.Entry<String, Long> entry: mLastSoundTimestamps.entrySet()) { + pw.print(" " + entry.getKey() + " -> "); + TimeUtils.formatDuration(entry.getValue(), now, pw); + pw.println(" ago"); + } } } @@ -2626,21 +2737,6 @@ public class NotificationManagerService extends SystemService { return false; } - private MediaSessionManager.OnActiveSessionsChangedListener mSessionListener = - new MediaSessionManager.OnActiveSessionsChangedListener() { - @Override - public void onActiveSessionsChanged(@Nullable List<MediaController> controllers) { - for (MediaController activeSession : controllers) { - PlaybackState playbackState = activeSession.getPlaybackState(); - if (playbackState != null && playbackState.getState() == PlaybackState.STATE_PLAYING) { - mActiveMedia = true; - return; - } - } - mActiveMedia = false; - } - }; - private void buzzBeepBlinkLocked(NotificationRecord record) { boolean buzz = false; boolean beep = false; @@ -2671,21 +2767,29 @@ public class NotificationManagerService extends SystemService { ZenLog.traceDisableEffects(record, disableEffects); } - if ((disableEffects == null) + boolean readyForBeepOrBuzz = disableEffects == null && (!(record.isUpdate && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 )) && (record.getUserId() == UserHandle.USER_ALL || record.getUserId() == currentUser || mUserProfiles.isCurrentProfile(record.getUserId())) - && canInterrupt + && !isInSoundTimeoutPeriod(record) && mSystemReady - && mAudioManager != null) { + && mAudioManager != null; + + boolean canBeep = readyForBeepOrBuzz && canInterrupt; + boolean canBuzz = readyForBeepOrBuzz && + (canInterrupt || (aboveThreshold && mZenModeHelper.allowVibrationForNotifications())); + boolean hasValidSound = false; + + if (canBeep || canBuzz) { if (DBG) Slog.v(TAG, "Interrupting!"); sendAccessibilityEvent(notification, record.sbn.getPackageName()); + } - // sound - + // sound + if (canBeep) { // should we use the default notification sound? (indicated either by // DEFAULT_SOUND or because notification.sound is pointing at // Settings.System.NOTIFICATION_SOUND) @@ -2695,7 +2799,6 @@ public class NotificationManagerService extends SystemService { .equals(notification.sound); Uri soundUri = null; - boolean hasValidSound = false; if (useDefaultSound) { soundUri = Settings.System.DEFAULT_NOTIFICATION_URI; @@ -2736,15 +2839,17 @@ public class NotificationManagerService extends SystemService { } } } + } + - // vibrate + // vibrate + if (canBuzz) { // Does the notification want to specify its own vibration? final boolean hasCustomVibrate = notification.vibrate != null; // new in 4.2: if there was supposed to be a sound and we're in vibrate // mode, and no other vibration is specified, we fall back to vibration - final boolean convertSoundToVibration = - !hasCustomVibrate + final boolean convertSoundToVibration = !hasCustomVibrate && hasValidSound && (mAudioManager.getRingerModeInternal() == AudioManager.RINGER_MODE_VIBRATE); @@ -2799,6 +2904,10 @@ public class NotificationManagerService extends SystemService { } else if (wasShowLights) { updateLightsLocked(); } + if (buzz || beep) { + mLastSoundTimestamps.put(generateLastSoundTimeoutKey(record), + SystemClock.elapsedRealtime()); + } if (buzz || beep || blink) { EventLogTags.writeNotificationAlert(record.getKey(), buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0); @@ -2806,6 +2915,24 @@ public class NotificationManagerService extends SystemService { } } + private boolean isInSoundTimeoutPeriod(NotificationRecord record) { + long timeoutMillis = mRankingHelper.getPackageNotificationSoundTimeout( + record.sbn.getPackageName(), record.sbn.getUid()); + if (timeoutMillis == 0) { + return false; + } + + Long value = mLastSoundTimestamps.get(generateLastSoundTimeoutKey(record)); + if (value == null) { + return false; + } + return SystemClock.elapsedRealtime() - value < timeoutMillis; + } + + private String generateLastSoundTimeoutKey(NotificationRecord record) { + return record.sbn.getPackageName() + "|" + record.sbn.getUid(); + } + private static AudioAttributes audioAttributesForNotification(Notification n) { if (n.audioAttributes != null && !Notification.AUDIO_ATTRIBUTES_DEFAULT.equals(n.audioAttributes)) { @@ -3518,6 +3645,9 @@ public class NotificationManagerService extends SystemService { if (!mAutoGenerateNotificationColor) { return mDefaultNotificationColor; } + if (!mMultiColorNotificationLed) { + return mDefaultNotificationColor; + } final String packageName = ledNotification.sbn.getPackageName(); final String mapping = mapPackage(packageName); int color = mDefaultNotificationColor; @@ -3600,6 +3730,10 @@ public class NotificationManagerService extends SystemService { if (isCallerSystem()) { return; } + checkCallerIsSameApp(pkg); + } + + private static void checkCallerIsSameApp(String pkg) { final int uid = Binder.getCallingUid(); try { ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo( diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java index 803db10..320cf75 100644 --- a/services/core/java/com/android/server/notification/RankingConfig.java +++ b/services/core/java/com/android/server/notification/RankingConfig.java @@ -27,4 +27,9 @@ public interface RankingConfig { int getPackageVisibilityOverride(String packageName, int uid); void setPackageVisibilityOverride(String packageName, int uid, int visibility); + + void setShowNotificationForPackageOnKeyguard(String packageName, int uid, int status); + + int getShowNotificationForPackageOnKeyguard(String packageName, int uid); + } diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index a089518..233eb0a 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -51,6 +51,8 @@ public class RankingHelper implements RankingConfig { private static final String ATT_PRIORITY = "priority"; private static final String ATT_PEEKABLE = "peekable"; private static final String ATT_VISIBILITY = "visibility"; + private static final String ATT_KEYGUARD = "keyguard"; + private static final String ATT_SOUND_TIMEOUT = "sound-timeout"; private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT; private static final boolean DEFAULT_PEEKABLE = true; @@ -143,6 +145,9 @@ public class RankingHelper implements RankingConfig { int priority = safeInt(parser, ATT_PRIORITY, DEFAULT_PRIORITY); boolean peekable = safeBool(parser, ATT_PEEKABLE, DEFAULT_PEEKABLE); int vis = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); + int keyguard = safeInt(parser, ATT_KEYGUARD, + Notification.SHOW_ALL_NOTI_ON_KEYGUARD); + long soundTimeout = safeInt(parser, ATT_SOUND_TIMEOUT, 0); String name = parser.getAttributeValue(null, ATT_NAME); if (!TextUtils.isEmpty(name)) { @@ -172,6 +177,12 @@ public class RankingHelper implements RankingConfig { if (vis != DEFAULT_VISIBILITY) { r.visibility = vis; } + if (keyguard != Notification.SHOW_ALL_NOTI_ON_KEYGUARD) { + r.keyguard = keyguard; + } + if (soundTimeout != 0) { + r.notificationSoundTimeout = soundTimeout; + } } } } @@ -200,8 +211,10 @@ public class RankingHelper implements RankingConfig { for (int i = N - 1; i >= 0; i--) { final Record r = mRecords.valueAt(i); if (r.priority == DEFAULT_PRIORITY && r.peekable == DEFAULT_PEEKABLE - && r.visibility == DEFAULT_VISIBILITY) { - mRecords.remove(i); + && r.visibility == DEFAULT_VISIBILITY + && r.keyguard == Notification.SHOW_ALL_NOTI_ON_KEYGUARD + && r.notificationSoundTimeout == 0) { + mRecords.removeAt(i); } } } @@ -227,6 +240,12 @@ public class RankingHelper implements RankingConfig { if (r.visibility != DEFAULT_VISIBILITY) { out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility)); } + if (r.keyguard != Notification.SHOW_ALL_NOTI_ON_KEYGUARD) { + out.attribute(null, ATT_KEYGUARD, Integer.toBinaryString(r.keyguard)); + } + if (r.notificationSoundTimeout != 0) { + out.attribute(null, ATT_SOUND_TIMEOUT, Long.toString(r.notificationSoundTimeout)); + } if (!forBackup) { out.attribute(null, ATT_UID, Integer.toString(r.uid)); } @@ -377,6 +396,36 @@ public class RankingHelper implements RankingConfig { updateConfig(); } + @Override + public int getShowNotificationForPackageOnKeyguard(String packageName, int uid) { + final Record r = mRecords.get(recordKey(packageName, uid)); + return r != null ? r.keyguard : Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + } + + @Override + public void setShowNotificationForPackageOnKeyguard( + String packageName, int uid, int keyguard) { + if (keyguard == getShowNotificationForPackageOnKeyguard(packageName, uid)) { + return; + } + getOrCreateRecord(packageName, uid).keyguard = keyguard; + removeDefaultRecords(); + updateConfig(); + } + + public long getPackageNotificationSoundTimeout(String packageName, int uid) { + final Record r = mRecords.get(recordKey(packageName, uid)); + return r != null ? r.notificationSoundTimeout : 0; + } + + public void setPackageNotificationSoundTimeout(String packageName, int uid, long timeout) { + if (timeout == getPackageNotificationSoundTimeout(packageName, uid)) { + return; + } + getOrCreateRecord(packageName, uid).notificationSoundTimeout = timeout; + removeDefaultRecords(); + } + public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) { if (filter == null) { final int N = mSignalExtractors.length; @@ -459,6 +508,8 @@ public class RankingHelper implements RankingConfig { int priority = DEFAULT_PRIORITY; boolean peekable = DEFAULT_PEEKABLE; int visibility = DEFAULT_VISIBILITY; + int keyguard = Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + long notificationSoundTimeout = 0; } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 468ef8d..54eac06 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -91,6 +91,7 @@ public class ZenModeHelper { private AudioManagerInternal mAudioManager; private boolean mEffectsSuppressed; private boolean mAllowLights; + private int mVibrationMode; public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) { mContext = context; @@ -117,10 +118,12 @@ public class ZenModeHelper { return TAG; } - public boolean matchesCallFilter(UserHandle userHandle, Bundle extras, + public boolean[] matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) { - return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle, extras, - validator, contactsTimeoutMs, timeoutAffinity); + boolean matches = ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, + userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity); + boolean matchesForVibration = matches || allowVibrationForCalls(); + return new boolean[] { matches, matchesForVibration }; } public boolean isCall(NotificationRecord record) { @@ -238,6 +241,8 @@ public class ZenModeHelper { pw.print(prefix); pw.print("mUser="); pw.println(mUser); dump(pw, prefix, "mConfig", mConfig); pw.print(prefix); pw.print("mEffectsSuppressed="); pw.println(mEffectsSuppressed); + pw.print(prefix); pw.print("mAllowLights="); pw.println(mAllowLights); + pw.print(prefix); pw.print("mVibrationMode="); pw.println(mVibrationMode); mFiltering.dump(pw, prefix); mConditions.dump(pw, prefix); } @@ -381,6 +386,7 @@ public class ZenModeHelper { mZenMode = zen; updateRingerModeAffectedStreams(); readAllowLightsFromSettings(); + readVibrationModeFromSettings(); setZenModeSetting(mZenMode); if (setRingerMode) { applyZenToRingerMode(); @@ -428,6 +434,21 @@ public class ZenModeHelper { } } + public boolean allowVibrationForCalls() { + return mVibrationMode > 0; + } + + public boolean allowVibrationForNotifications() { + return mVibrationMode > 1; + } + + public void readVibrationModeFromSettings() { + final ContentResolver cr = mContext.getContentResolver(); + mVibrationMode = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS + ? CMSettings.System.getInt(cr, CMSettings.System.ZEN_PRIORITY_VIBRATION_MODE, 0) + : 0; + } + private void applyRestrictions() { final boolean zen = mZenMode != Global.ZEN_MODE_OFF; @@ -715,9 +736,11 @@ 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); + CMSettings.System.ZEN_ALLOW_LIGHTS); private final Uri ZEN_PRIORITY_ALLOW_LIGHTS = CMSettings.System.getUriFor( - CMSettings.System.ZEN_PRIORITY_ALLOW_LIGHTS); + CMSettings.System.ZEN_PRIORITY_ALLOW_LIGHTS); + private final Uri ZEN_PRIORITY_VIBRATION_MODE = CMSettings.System.getUriFor( + CMSettings.System.ZEN_PRIORITY_VIBRATION_MODE); public SettingsObserver(Handler handler) { super(handler); @@ -730,6 +753,8 @@ public class ZenModeHelper { ZEN_ALLOW_LIGHTS, false /*notifyForDescendents*/, this); resolver.registerContentObserver( ZEN_PRIORITY_ALLOW_LIGHTS, false /*notifyForDescendents*/, this); + resolver.registerContentObserver( + ZEN_PRIORITY_VIBRATION_MODE, false /*notifyForDescendents*/, this); update(null); } @@ -746,6 +771,8 @@ public class ZenModeHelper { } } else if (ZEN_ALLOW_LIGHTS.equals(uri) || ZEN_PRIORITY_ALLOW_LIGHTS.equals(uri)) { readAllowLightsFromSettings(); + } else if (ZEN_PRIORITY_VIBRATION_MODE.equals(uri)) { + readVibrationModeFromSettings(); } } } diff --git a/services/core/java/com/android/server/pm/MultiTaskDealer.java b/services/core/java/com/android/server/pm/MultiTaskDealer.java new file mode 100644 index 0000000..9b8d46e --- /dev/null +++ b/services/core/java/com/android/server/pm/MultiTaskDealer.java @@ -0,0 +1,141 @@ +/* +* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of The Linux Foundation nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED +* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT +* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS +* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package com.android.server.pm; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.locks.ReentrantLock; + +import android.util.Log; + +public class MultiTaskDealer { + + public static final String TAG = "MultiTaskDealer"; + public static final String PACKAGEMANAGER_SCANER = "packagescan"; + private static final boolean DEBUG_TASK = false; + + private static HashMap<String, WeakReference<MultiTaskDealer>> map = new HashMap<String, WeakReference<MultiTaskDealer>>(); + + public static MultiTaskDealer getDealer(String name) { + WeakReference<MultiTaskDealer> ref = map.get(name); + MultiTaskDealer dealer = ref!=null?ref.get():null; + return dealer; + } + + public static MultiTaskDealer startDealer(String name,int taskCount) { + MultiTaskDealer dealer = getDealer(name); + if(dealer==null) { + dealer = new MultiTaskDealer(name,taskCount); + WeakReference<MultiTaskDealer> ref = new WeakReference<MultiTaskDealer>(dealer); + map.put(name,ref); + } + return dealer; + } + + public void startLock() { + mLock.lock(); + } + + public void endLock() { + mLock.unlock(); + } + + private ThreadPoolExecutor mExecutor; + private int mTaskCount = 0; + private boolean mNeedNotifyEnd = false; + private Object mObjWaitAll = new Object(); + private ReentrantLock mLock = new ReentrantLock(); + + public MultiTaskDealer(String name,int taskCount) { + final String taskName = name; + ThreadFactory factory = new ThreadFactory() + { + private final AtomicInteger mCount = new AtomicInteger(1); + + public Thread newThread(final Runnable r) { + if (DEBUG_TASK) Log.d(TAG, "create a new thread:" + taskName); + return new Thread(r, taskName + "-" + mCount.getAndIncrement()); + } + }; + mExecutor = new ThreadPoolExecutor(taskCount, taskCount, 5, TimeUnit.SECONDS, + new LinkedBlockingQueue<Runnable>(), factory){ + protected void afterExecute(Runnable r, Throwable t) { + if(t!=null) { + t.printStackTrace(); + } + MultiTaskDealer.this.TaskCompleteNotify(r); + if (DEBUG_TASK) Log.d(TAG, "end task"); + super.afterExecute(r,t); + } + protected void beforeExecute(Thread t, Runnable r) { + if (DEBUG_TASK) Log.d(TAG, "start task"); + super.beforeExecute(t,r); + } + }; + } + + public void addTask(Runnable task) { + synchronized (mObjWaitAll) { + mTaskCount+=1; + } + mExecutor.execute(task); + if (DEBUG_TASK) Log.d(TAG, "addTask"); + } + + private void TaskCompleteNotify(Runnable task) { + synchronized (mObjWaitAll) { + mTaskCount-=1; + if(mTaskCount<=0 && mNeedNotifyEnd) { + if (DEBUG_TASK) Log.d(TAG, "complete notify"); + mObjWaitAll.notify(); + } + } + } + + public void waitAll() { + if (DEBUG_TASK) Log.d(TAG, "start wait all"); + synchronized (mObjWaitAll) { + if(mTaskCount>0) { + mNeedNotifyEnd = true; + try { + mObjWaitAll.wait(); + } catch (Exception e) { + } + mNeedNotifyEnd = false; + } + if (DEBUG_TASK) Log.d(TAG, "wait finish"); + return; + } + } +} diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index f73cb0a..fa11ff8 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -57,6 +57,8 @@ final class PackageDexOptimizer { private final PowerManager.WakeLock mDexoptWakeLock; private volatile boolean mSystemReady; + private Object mDeferredDexOptSync = new Object(); + PackageDexOptimizer(PackageManagerService packageManagerService) { this.mPackageManagerService = packageManagerService; PowerManager powerManager = (PowerManager)packageManagerService.mContext.getSystemService( @@ -150,7 +152,9 @@ final class PackageDexOptimizer { // We're deciding to defer a needed dexopt. Don't bother dexopting for other // paths and instruction sets. We'll deal with them all together when we process // our list of deferred dexopts. - addPackageForDeferredDexopt(pkg); + synchronized (mDeferredDexOptSync) { + addPackageForDeferredDexopt(pkg); + } return DEX_OPT_DEFERRED; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index d5c58df..920a850 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -1,4 +1,7 @@ /* + * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * Not a Contribution. + * * Copyright (C) 2006 The Android Open Source Project * This code has been modified. Portions copyright (C) 2010, T-Mobile USA, Inc. * @@ -248,6 +251,7 @@ import com.android.server.IntentResolver; import com.android.server.LocalServices; import com.android.server.ServiceThread; import com.android.server.SystemConfig; +import com.android.server.SystemConfig.AppLink; import com.android.server.Watchdog; import com.android.server.pm.PermissionsState.PermissionState; import com.android.server.pm.Settings.DatabaseVersion; @@ -333,6 +337,7 @@ public class PackageManagerService extends IPackageManager.Stub { private static final boolean DEBUG_PACKAGE_SCANNING = false; private static final boolean DEBUG_VERIFY = false; private static final boolean DEBUG_DEXOPT = false; + private static final boolean DEBUG_FILTERS = false; private static final boolean DEBUG_ABI_SELECTION = false; private static final boolean DEBUG_PREBUNDLED_SCAN = false; private static final boolean DEBUG_PROTECTED = false; @@ -616,7 +621,7 @@ public class PackageManagerService extends IPackageManager.Stub { final ArraySet<String> mTransferedPackages = new ArraySet<String>(); // Broadcast actions that are only available to the system. - final ArraySet<String> mProtectedBroadcasts = new ArraySet<String>(); + final ArrayMap<String, String> mProtectedBroadcasts = new ArrayMap<>(); /** List of packages waiting for verification. */ final SparseArray<PackageVerificationState> mPendingVerification @@ -1491,6 +1496,17 @@ public class PackageManagerService extends IPackageManager.Stub { // if this was a theme, send it off to the theme service for processing if(res.pkg.mIsThemeApk || res.pkg.mIsLegacyIconPackApk) { processThemeResourcesInThemeService(res.pkg.packageName); + } else if (mOverlays.containsKey(res.pkg.packageName)) { + + // if this was an app and is themed send themes that theme it + // for processing + ArrayMap<String, PackageParser.Package> themes = + mOverlays.get(res.pkg.packageName); + + for (PackageParser.Package themePkg : themes.values()) { + processThemeResourcesInThemeService(themePkg.packageName); + } + } if (res.removedInfo.args != null) { // Remove the replaced package's older resources safely now @@ -1962,9 +1978,9 @@ public class PackageManagerService extends IPackageManager.Stub { mAvailableFeatures = systemConfig.getAvailableFeatures(); mSignatureAllowances = systemConfig.getSignatureAllowances(); - synchronized (mInstallLock) { +// synchronized (mInstallLock) { // writer - synchronized (mPackages) { +// synchronized (mPackages) { mHandlerThread = new ServiceThread(TAG, Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/); mHandlerThread.start(); @@ -2488,8 +2504,8 @@ public class PackageManagerService extends IPackageManager.Stub { mIntentFilterVerifier = new IntentVerifierProxy(mContext, mIntentFilterVerifierComponent); - } // synchronized (mPackages) - } // synchronized (mInstallLock) + //} // synchronized (mPackages) + //} // synchronized (mInstallLock) // Now after opening every single application zip, make sure they // are all flushed. Not really needed, but keeps things nice and @@ -2626,10 +2642,11 @@ public class PackageManagerService extends IPackageManager.Stub { } SystemConfig systemConfig = SystemConfig.getInstance(); - ArraySet<String> packages = systemConfig.getLinkedApps(); + ArraySet<AppLink> links = systemConfig.getLinkedApps(); ArraySet<String> domains = new ArraySet<String>(); - for (String packageName : packages) { + for (AppLink link : links) { + String packageName = link.pkgname; PackageParser.Package pkg = mPackages.get(packageName); if (pkg != null) { if (!pkg.isSystemApp()) { @@ -2654,11 +2671,11 @@ public class PackageManagerService extends IPackageManager.Stub { // state w.r.t. the formal app-linkage "no verification attempted" state; // and then 'always' in the per-user state actually used for intent resolution. final IntentFilterVerificationInfo ivi; - ivi = mSettings.createIntentFilterVerificationIfNeededLPw(packageName, - new ArrayList<String>(domains)); + ivi = mSettings.createIntentFilterVerificationIfNeededLPw( + packageName, new ArrayList<String>(domains)); ivi.setStatus(INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED); - mSettings.updateIntentFilterVerificationStatusLPw(packageName, - INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_ALWAYS, userId); + mSettings.updateIntentFilterVerificationStatusLPw( + packageName, link.state, userId); } else { Slog.w(TAG, "Sysconfig <app-link> package '" + packageName + "' does not handle web links"); @@ -4028,7 +4045,19 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean isProtectedBroadcast(String actionName) { synchronized (mPackages) { - return mProtectedBroadcasts.contains(actionName); + return mProtectedBroadcasts.containsKey(actionName); + } + } + + @Override + public boolean isProtectedBroadcastAllowed(String actionName, int callingUid) { + synchronized (mPackages) { + if (mProtectedBroadcasts.containsKey(actionName)) { + final int result = checkUidPermission(mProtectedBroadcasts.get(actionName), + callingUid); + return result == PackageManager.PERMISSION_GRANTED; + } + return false; } } @@ -4701,10 +4730,14 @@ public class PackageManagerService extends IPackageManager.Stub { } private boolean shouldIncludeResolveActivity(Intent intent) { - synchronized(mPackages) { - AppSuggestManager suggest = AppSuggestManager.getInstance(mContext); - return mResolverReplaced && (suggest != null) ? suggest.handles(intent) : false; + // Don't call into AppSuggestManager before it comes up later in the SystemServer init! + if (!mSystemReady || mOnlyCore) { + return false; } + + AppSuggestManager suggest = AppSuggestManager.getInstance(mContext); + return mResolverReplaced && (suggest.getService() != null) ? + suggest.handles(intent) : false; } @Override @@ -5797,7 +5830,7 @@ public class PackageManagerService extends IPackageManager.Stub { } private void scanDirLI(File dir, int parseFlags, int scanFlags, long currentTime, - UserHandle user) { + final UserHandle user) { final File[] files = dir.listFiles(); if (ArrayUtils.isEmpty(files)) { Log.d(TAG, "No files in app dir " + dir); @@ -5809,8 +5842,8 @@ public class PackageManagerService extends IPackageManager.Stub { + " flags=0x" + Integer.toHexString(parseFlags)); } - int prebundledUserId = user == null ? UserHandle.USER_OWNER : user.getIdentifier(); - boolean isPrebundled = (parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0; + final int prebundledUserId = user == null ? UserHandle.USER_OWNER : user.getIdentifier(); + final boolean isPrebundled = (parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0; if (isPrebundled) { synchronized (mPackages) { if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, "Reading prebundled packages for user " @@ -5819,6 +5852,13 @@ public class PackageManagerService extends IPackageManager.Stub { } } + Log.d(TAG, "start scanDirLI:"+dir); + // use multi thread to speed up scanning + int iMultitaskNum = SystemProperties.getInt("persist.pm.multitask", 6); + Log.d(TAG, "max thread:" + iMultitaskNum); + final MultiTaskDealer dealer = (iMultitaskNum > 1) ? MultiTaskDealer.startDealer( + MultiTaskDealer.PACKAGEMANAGER_SCANER, iMultitaskNum) : null; + for (File file : files) { final boolean isPackage = (isApkFile(file) || file.isDirectory()) && !PackageInstallerService.isStageName(file.getName()); @@ -5826,43 +5866,64 @@ public class PackageManagerService extends IPackageManager.Stub { // Ignore entries which are not packages continue; } - try { - scanPackageLI(file, parseFlags | PackageParser.PARSE_MUST_BE_APK, - scanFlags, currentTime, user); - if (isPrebundled) { - final PackageParser.Package pkg; + + final File ref_file = file; + final int ref_parseFlags = parseFlags; + final int ref_scanFlags = scanFlags; + final long ref_currentTime = currentTime; + + Runnable scanTask = new Runnable() { + public void run() { + try { - pkg = new PackageParser().parsePackage(file, parseFlags); - } catch (PackageParserException e) { - throw PackageManagerException.from(e); - } - synchronized (mPackages) { - if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, - "Marking prebundled packages for user " + prebundledUserId); - mSettings.markPrebundledPackageInstalledLPr(prebundledUserId, - pkg.packageName); - // do this for every other user - for (UserInfo userInfo : sUserManager.getUsers(true)) { - if (userInfo.id == prebundledUserId) continue; - mSettings.markPrebundledPackageInstalledLPr(userInfo.id, + scanPackageLI(ref_file, ref_parseFlags | PackageParser.PARSE_MUST_BE_APK, + ref_scanFlags, ref_currentTime, user); + if (isPrebundled) { + final PackageParser.Package pkg; + try { + pkg = new PackageParser().parsePackage(ref_file, ref_parseFlags); + } catch (PackageParserException e) { + throw PackageManagerException.from(e); + } + if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, + "Marking prebundled package " + pkg.packageName + + " for user " + prebundledUserId); + mSettings.markPrebundledPackageInstalledLPr(prebundledUserId, pkg.packageName); + // do this for every other user + for (UserInfo userInfo : sUserManager.getUsers(true)) { + if (userInfo.id == prebundledUserId) continue; + if (DEBUG_PREBUNDLED_SCAN) Log.d(TAG, + "Marking for secondary user " + userInfo.id); + mSettings.markPrebundledPackageInstalledLPr(userInfo.id, + pkg.packageName); + } + } + } catch (PackageManagerException e) { + Slog.w(TAG, "Failed to parse " + ref_file + ": " + e.getMessage()); + + // Delete invalid userdata apps + if ((ref_parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && + e.error == PackageManager.INSTALL_FAILED_INVALID_APK) { + logCriticalInfo(Log.WARN, "Deleting invalid package at " + ref_file); + if (ref_file.isDirectory()) { + mInstaller.rmPackageDir(ref_file.getAbsolutePath()); + } else { + ref_file.delete(); + } } } } - } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to parse " + file + ": " + e.getMessage()); + }; - // Delete invalid userdata apps - if ((parseFlags & PackageParser.PARSE_IS_SYSTEM) == 0 && - e.error == PackageManager.INSTALL_FAILED_INVALID_APK) { - logCriticalInfo(Log.WARN, "Deleting invalid package at " + file); - if (file.isDirectory()) { - mInstaller.rmPackageDir(file.getAbsolutePath()); - } else { - file.delete(); - } - } - } + if (dealer != null) + dealer.addTask(scanTask); + else + scanTask.run(); + } + + if (dealer != null) { + dealer.waitAll(); } if (isPrebundled) { @@ -5872,6 +5933,8 @@ public class PackageManagerService extends IPackageManager.Stub { mSettings.writePrebundledPackagesLPr(prebundledUserId); } } + + Log.d(TAG, "end scanDirLI:"+dir); } private static File getSettingsProblemFile() { @@ -5885,7 +5948,7 @@ public class PackageManagerService extends IPackageManager.Stub { logCriticalInfo(priority, msg); } - static void logCriticalInfo(int priority, String msg) { + static synchronized void logCriticalInfo(int priority, String msg) { Slog.println(priority, TAG, msg); EventLogTags.writePmCriticalInfo(msg); try { @@ -5975,15 +6038,17 @@ public class PackageManagerService extends IPackageManager.Stub { if ((parseFlags & PackageParser.PARSE_IS_PREBUNDLED_DIR) != 0) { synchronized (mPackages) { PackageSetting existingSettings = mSettings.peekPackageLPr(pkg.packageName); - if (mSettings.wasPrebundledPackageInstalledLPr(user.getIdentifier() - , pkg.packageName) && existingSettings == null) { - // The prebundled app was installed at some point in time, but now it is - // gone. Assume that the user uninstalled it intentionally: do not reinstall. + + if (!mSettings.shouldPrebundledPackageBeInstalledForUserLPr(existingSettings, + user.getIdentifier(), pkg.packageName)) { + // The prebundled app was installed at some point for the owner and isn't + // currently installed for the owner, dont install it for a new user + // OR the prebundled app was installed for the user at some point and isn't + // current installed for the user, so skip reinstalling it throw new PackageManagerException(INSTALL_FAILED_UNINSTALLED_PREBUNDLE, "skip reinstall for " + pkg.packageName); - } else if (existingSettings == null && - !mSettings.shouldPrebundledPackageBeInstalled(mContext.getResources(), - pkg.packageName, mCustomResources)) { + } else if (!mSettings.shouldPrebundledPackageBeInstalledForRegion( + mContext.getResources(), pkg.packageName, mCustomResources)) { // The prebundled app is not needed for the default mobile country code, // skip installing it throw new PackageManagerException(INSTALL_FAILED_REGION_LOCKED_PREBUNDLE, @@ -6299,9 +6364,8 @@ public class PackageManagerService extends IPackageManager.Stub { if (doTrim) { if (!isFirstBoot()) { try { - ActivityManagerNative.getDefault().showBootMessage( - mContext.getResources().getString( - R.string.android_upgrading_fstrim), true); + ActivityManagerNative.getDefault().updateBootProgress( + IActivityManager.BOOT_STAGE_FSTRIM, null, 0, 0, true); } catch (RemoteException e) { } } @@ -6428,9 +6492,9 @@ public class PackageManagerService extends IPackageManager.Stub { Log.i(TAG, "Optimizing app " + curr + " of " + total + ": " + pkg.packageName); } try { - ActivityManagerNative.getDefault().showBootMessage( - mContext.getResources().getString(R.string.android_upgrading_apk, - curr, total), true); + ActivityManagerNative.getDefault().updateBootProgress( + IActivityManager.BOOT_STAGE_PREPARING_APPS, + pkg.applicationInfo, curr, total, true); } catch (RemoteException e) { } PackageParser.Package p = pkg; @@ -7458,6 +7522,25 @@ public class PackageManagerService extends IPackageManager.Stub { KeySetManagerService ksms = mSettings.mKeySetManagerService; ksms.assertScannedPackageValid(pkg); + // Get the current theme config. We do this outside the lock + // since ActivityManager might be waiting on us already + // and a deadlock would result. + final boolean isBootScan = (scanFlags & SCAN_BOOTING) != 0; + ThemeConfig config = mBootThemeConfig; + if (!isBootScan) { + final IActivityManager am = ActivityManagerNative.getDefault(); + try { + if (am != null) { + config = am.getConfiguration().themeConfig; + } else { + Log.w(TAG, "ActivityManager getDefault() " + + "returned null, cannot compile app's theme"); + } + } catch(RemoteException e) { + Log.w(TAG, "Failed to get the theme config from ActivityManager"); + } + } + // writer synchronized (mPackages) { // We don't expect installation to fail beyond this point @@ -7799,32 +7882,36 @@ public class PackageManagerService extends IPackageManager.Stub { if (pkg.protectedBroadcasts != null) { N = pkg.protectedBroadcasts.size(); for (i=0; i<N; i++) { - mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i)); + mProtectedBroadcasts.put(pkg.protectedBroadcasts.keyAt(i), + pkg.protectedBroadcasts.valueAt(i)); } } pkgSetting.setTimeStamp(scanFileTime); - final boolean isBootScan = (scanFlags & SCAN_BOOTING) != 0; // Generate resources & idmaps if pkg is NOT a theme // We must compile resources here because during the initial boot process we may get // here before a default theme has had a chance to compile its resources + // During app installation we only compile applied theme here (rest will be compiled + // in background) if (pkg.mOverlayTargets.isEmpty() && mOverlays.containsKey(pkg.packageName)) { ArrayMap<String, PackageParser.Package> themes = mOverlays.get(pkg.packageName); - for(PackageParser.Package themePkg : themes.values()) { - if (!isBootScan || (mBootThemeConfig != null && - (themePkg.packageName.equals(mBootThemeConfig.getOverlayPkgName()) || + + if (config != null) { + for(PackageParser.Package themePkg : themes.values()) { + if (themePkg.packageName.equals(config.getOverlayPkgName()) || themePkg.packageName.equals( - mBootThemeConfig.getOverlayPkgNameForApp(pkg.packageName))))) { - try { - compileResourcesAndIdmapIfNeeded(pkg, themePkg); - } catch (Exception e) { - // Do not stop a pkg installation just because of one bad theme - // Also we don't break here because we should try to compile other - // themes - Slog.w(TAG, "Unable to compile " + themePkg.packageName - + " for target " + pkg.packageName, e); - themePkg.mOverlayTargets.remove(pkg.packageName); + config.getOverlayPkgNameForApp(pkg.packageName))) { + try { + compileResourcesAndIdmapIfNeeded(pkg, themePkg); + } catch (Exception e) { + // Do not stop a pkg installation just because of one bad theme + // Also we don't break here because we should try to compile other + // themes + Slog.w(TAG, "Unable to compile " + themePkg.packageName + + " for target " + pkg.packageName, e); + themePkg.mOverlayTargets.remove(pkg.packageName); + } } } } @@ -7858,10 +7945,22 @@ public class PackageManagerService extends IPackageManager.Stub { } if (failedException != null) { - Slog.w(TAG, "Unable to process theme " + pkgName + " for " + target, - failedException); - // remove target from mOverlayTargets - iterator.remove(); + if (failedException instanceof AaptException && + ((AaptException) failedException).isCommon) { + Slog.e(TAG, "Unable to process common resources for " + pkgName + + ", uninstalling theme.", failedException); + uninstallThemeForAllApps(pkg); + deletePackageLI(pkg.packageName, null, true, null, null, 0, null, + false); + throw new PackageManagerException( + PackageManager.INSTALL_FAILED_THEME_AAPT_ERROR, + "Unable to process theme " + pkgName, failedException); + } else { + Slog.w(TAG, "Unable to process theme " + pkgName + " for " + target, + failedException); + // remove target from mOverlayTargets + iterator.remove(); + } } } } @@ -8234,8 +8333,15 @@ public class PackageManagerService extends IPackageManager.Stub { } public class AaptException extends Exception { + boolean isCommon; + public AaptException(String message) { + this(message, false); + } + + public AaptException(String message, boolean isCommon) { super(message); + this.isCommon = isCommon; } } @@ -8261,16 +8367,19 @@ public class PackageManagerService extends IPackageManager.Stub { String internalPath = APK_PATH_TO_OVERLAY + target + File.separator; String resPath = ThemeUtils.getTargetCacheDir(target, pkg); final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); + final boolean isCommonResources = COMMON_OVERLAY.equals(target); int pkgId; if ("android".equals(target)) { pkgId = Resources.THEME_FRAMEWORK_PKG_ID; - } else if (COMMON_OVERLAY.equals(target)) { + } else if ("cyanogenmod.platform".equals(target)) { + pkgId = Resources.THEME_CM_PKG_ID; + } else if (isCommonResources) { pkgId = Resources.THEME_COMMON_PKG_ID; } else { pkgId = Resources.THEME_APP_PKG_ID; } - boolean hasCommonResources = (hasCommonResources(pkg) && !COMMON_OVERLAY.equals(target)); + boolean hasCommonResources = (hasCommonResources(pkg) && !isCommonResources); PackageParser.Package targetPkg = mPackages.get(target); String appPath = targetPkg != null ? targetPkg.baseCodePath : Environment.getRootDirectory() + "/framework/framework-res.apk"; @@ -8280,7 +8389,7 @@ public class PackageManagerService extends IPackageManager.Stub { appPath, hasCommonResources ? ThemeUtils.getTargetCacheDir(COMMON_OVERLAY, pkg) + File.separator + "resources.apk" : "") != 0) { - throw new AaptException("Failed to run aapt"); + throw new AaptException("Failed to run aapt", isCommonResources); } } @@ -9384,12 +9493,15 @@ public class PackageManagerService extends IPackageManager.Stub { mFlags = flags; List<ResolveInfo> list = super.queryIntent(intent, resolvedType, (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0, userId); - // Remove protected Application components + // Remove protected Application components if they're explicitly queried for. + // Implicit intent queries will be gated when the returned component is acted upon. int callingUid = Binder.getCallingUid(); String[] pkgs = getPackagesForUid(callingUid); List<String> packages = (pkgs != null) ? Arrays.asList(pkgs) : Collections.EMPTY_LIST; - if (callingUid != Process.SYSTEM_UID && - (getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM) == 0) { + final boolean isNotSystem = callingUid != Process.SYSTEM_UID && + (getFlagsForUid(callingUid) & ApplicationInfo.FLAG_SYSTEM) == 0; + + if (isNotSystem && intent.getComponent() != null) { Iterator<ResolveInfo> itr = list.iterator(); while (itr.hasNext()) { ActivityInfo activityInfo = itr.next().activityInfo; @@ -9427,6 +9539,255 @@ public class PackageManagerService extends IPackageManager.Stub { return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId); } + /** + * Finds a privileged activity that matches the specified activity names. + */ + private PackageParser.Activity findMatchingActivity( + List<PackageParser.Activity> activityList, ActivityInfo activityInfo) { + for (PackageParser.Activity sysActivity : activityList) { + if (sysActivity.info.name.equals(activityInfo.name)) { + return sysActivity; + } + if (sysActivity.info.name.equals(activityInfo.targetActivity)) { + return sysActivity; + } + if (sysActivity.info.targetActivity != null) { + if (sysActivity.info.targetActivity.equals(activityInfo.name)) { + return sysActivity; + } + if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) { + return sysActivity; + } + } + } + return null; + } + + public class IterGenerator<E> { + public Iterator<E> generate(ActivityIntentInfo info) { + return null; + } + } + + public class ActionIterGenerator extends IterGenerator<String> { + @Override + public Iterator<String> generate(ActivityIntentInfo info) { + return info.actionsIterator(); + } + } + + public class CategoriesIterGenerator extends IterGenerator<String> { + @Override + public Iterator<String> generate(ActivityIntentInfo info) { + return info.categoriesIterator(); + } + } + + public class SchemesIterGenerator extends IterGenerator<String> { + @Override + public Iterator<String> generate(ActivityIntentInfo info) { + return info.schemesIterator(); + } + } + + public class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> { + @Override + public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) { + return info.authoritiesIterator(); + } + } + + /** + * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE + * MODIFIED. Do not pass in a list that should not be changed. + */ + private <T> void getIntentListSubset(List<ActivityIntentInfo> intentList, + IterGenerator<T> generator, Iterator<T> searchIterator) { + // loop through the set of actions; every one must be found in the intent filter + while (searchIterator.hasNext()) { + // we must have at least one filter in the list to consider a match + if (intentList.size() == 0) { + break; + } + + final T searchAction = searchIterator.next(); + + // loop through the set of intent filters + final Iterator<ActivityIntentInfo> intentIter = intentList.iterator(); + while (intentIter.hasNext()) { + final ActivityIntentInfo intentInfo = intentIter.next(); + boolean selectionFound = false; + + // loop through the intent filter's selection criteria; at least one + // of them must match the searched criteria + final Iterator<T> intentSelectionIter = generator.generate(intentInfo); + while (intentSelectionIter != null && intentSelectionIter.hasNext()) { + final T intentSelection = intentSelectionIter.next(); + if (intentSelection != null && intentSelection.equals(searchAction)) { + selectionFound = true; + break; + } + } + + // the selection criteria wasn't found in this filter's set; this filter + // is not a potential match + if (!selectionFound) { + intentIter.remove(); + } + } + } + } + + /** + * Adjusts the priority of the given intent filter according to policy. + * <p> + * <ul> + * <li>The priority for unbundled updates to system applications is capped to the + * priority defined on the system partition</li> + * </ul> + */ + private void adjustPriority( + List<PackageParser.Activity> systemActivities, ActivityIntentInfo intent) { + // nothing to do; priority is fine as-is + if (intent.getPriority() <= 0) { + return; + } + + final ActivityInfo activityInfo = intent.activity.info; + final ApplicationInfo applicationInfo = activityInfo.applicationInfo; + + final boolean systemApp = applicationInfo.isSystemApp(); + if (!systemApp) { + // non-system applications can never define a priority >0 + Slog.w(TAG, "Non-system app; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + intent.setPriority(0); + return; + } + + if (systemActivities == null) { + // the system package is not disabled; we're parsing the system partition + // apps on the system image get whatever priority they request + return; + } + + // system app unbundled update ... try to find the same activity + final PackageParser.Activity foundActivity = + findMatchingActivity(systemActivities, activityInfo); + if (foundActivity == null) { + // this is a new activity; it cannot obtain >0 priority + if (DEBUG_FILTERS) { + Slog.i(TAG, "New activity; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + + // found activity, now check for filter equivalence + + // a shallow copy is enough; we modify the list, not its contents + final List<ActivityIntentInfo> intentListCopy = + new ArrayList<>(foundActivity.intents); + final List<ActivityIntentInfo> foundFilters = findFilters(intent); + + // find matching action subsets + final Iterator<String> actionsIterator = intent.actionsIterator(); + if (actionsIterator != null) { + getIntentListSubset( + intentListCopy, new ActionIterGenerator(), actionsIterator); + if (intentListCopy.size() == 0) { + // no more intents to match; we're not equivalent + if (DEBUG_FILTERS) { + Slog.i(TAG, "Mismatched action; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + } + + // find matching category subsets + final Iterator<String> categoriesIterator = intent.categoriesIterator(); + if (categoriesIterator != null) { + getIntentListSubset(intentListCopy, new CategoriesIterGenerator(), + categoriesIterator); + if (intentListCopy.size() == 0) { + // no more intents to match; we're not equivalent + if (DEBUG_FILTERS) { + Slog.i(TAG, "Mismatched category; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + } + + // find matching schemes subsets + final Iterator<String> schemesIterator = intent.schemesIterator(); + if (schemesIterator != null) { + getIntentListSubset(intentListCopy, new SchemesIterGenerator(), + schemesIterator); + if (intentListCopy.size() == 0) { + // no more intents to match; we're not equivalent + if (DEBUG_FILTERS) { + Slog.i(TAG, "Mismatched scheme; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + } + + // find matching authorities subsets + final Iterator<IntentFilter.AuthorityEntry> + authoritiesIterator = intent.authoritiesIterator(); + if (authoritiesIterator != null) { + getIntentListSubset(intentListCopy, + new AuthoritiesIterGenerator(), + authoritiesIterator); + if (intentListCopy.size() == 0) { + // no more intents to match; we're not equivalent + if (DEBUG_FILTERS) { + Slog.i(TAG, "Mismatched authority; cap priority to 0;" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(0); + return; + } + } + + // we found matching filter(s); app gets the max priority of all intents + int cappedPriority = 0; + for (int i = intentListCopy.size() - 1; i >= 0; --i) { + cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority()); + } + if (intent.getPriority() > cappedPriority) { + if (DEBUG_FILTERS) { + Slog.i(TAG, "Found matching filter(s);" + + " cap priority to " + cappedPriority + ";" + + " package: " + applicationInfo.packageName + + " activity: " + intent.activity.className + + " origPrio: " + intent.getPriority()); + } + intent.setPriority(cappedPriority); + return; + } + // all this for nothing; the requested priority was <= what was on the system + } + public final void addActivity(PackageParser.Activity a, String type) { final boolean systemApp = a.info.applicationInfo.isSystemApp(); mActivities.put(a.getComponentName(), a); @@ -9439,10 +9800,12 @@ public class PackageManagerService extends IPackageManager.Stub { final int NI = a.intents.size(); for (int j=0; j<NI; j++) { PackageParser.ActivityIntentInfo intent = a.intents.get(j); - if (!systemApp && intent.getPriority() > 0 && "activity".equals(type)) { - intent.setPriority(0); - Log.w(TAG, "Package " + a.info.applicationInfo.packageName + " has activity " - + a.className + " with priority > 0, forcing to 0"); + if ("activity".equals(type)) { + final PackageSetting ps = + mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName); + final List<PackageParser.Activity> systemActivities = + ps != null && ps.pkg != null ? ps.pkg.activities : null; + adjustPriority(systemActivities, intent); } if (DEBUG_SHOW_INFO) { Log.v(TAG, " IntentFilter:"); @@ -9596,18 +9959,6 @@ public class PackageManagerService extends IPackageManager.Stub { out.println(); } -// List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) { -// final Iterator<ResolveInfo> i = resolveInfoList.iterator(); -// final List<ResolveInfo> retList = Lists.newArrayList(); -// while (i.hasNext()) { -// final ResolveInfo resolveInfo = i.next(); -// if (isEnabledLP(resolveInfo.activityInfo)) { -// retList.add(resolveInfo); -// } -// } -// return retList; -// } - // Keys are String (activity class name), values are Activity. private final ArrayMap<ComponentName, PackageParser.Activity> mActivities = new ArrayMap<ComponentName, PackageParser.Activity>(); @@ -10175,10 +10526,10 @@ public class PackageManagerService extends IPackageManager.Stub { void startCleaningPackages() { // reader + if (!isExternalMediaAvailable()) { + return; + } synchronized (mPackages) { - if (!isExternalMediaAvailable()) { - return; - } if (mSettings.mPackagesToBeCleaned.isEmpty()) { return; } @@ -11154,7 +11505,7 @@ public class PackageManagerService extends IPackageManager.Stub { final IPackageInstallObserver2 observer; int installFlags; final String installerPackageName; - final String volumeUuid; + String volumeUuid; final VerificationParams verificationParams; private InstallArgs mArgs; private int mRet; @@ -11359,6 +11710,28 @@ public class PackageManagerService extends IPackageManager.Stub { } } + // Check whether we're replacing an existing package that's + // installed on adopted storage. If yes, override the new + // package location to match. + if (move == null && (installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { + synchronized (mPackages) { + PackageParser.Package pkg = mPackages.get(pkgLite.packageName); + if (pkg != null && isExternalAdopted(pkg)) { + // Check whether anything will actually change + // so that we log only when a fixup was needed + if (!((installFlags & PackageManager.INSTALL_INTERNAL) != 0 + && (installFlags & PackageManager.INSTALL_EXTERNAL) == 0 + && Objects.equals(volumeUuid, pkg.volumeUuid))) { + installFlags |= PackageManager.INSTALL_INTERNAL; + installFlags &= ~PackageManager.INSTALL_EXTERNAL; + volumeUuid = pkg.volumeUuid; + Slog.w(TAG, "Replacing package on adopted storage, updating " + +"new package destination to volumeUuid "+volumeUuid); + } + } + } + } + final InstallArgs args = createInstallArgs(this); mArgs = args; @@ -11667,8 +12040,6 @@ public class PackageManagerService extends IPackageManager.Stub { * Called after the source arguments are copied. This is used mostly for * MoveParams when it needs to read the source file to put it in the * destination. - * - * @return */ int doPostCopy(int uid) { return PackageManager.INSTALL_SUCCEEDED; @@ -13312,6 +13683,14 @@ public class PackageManagerService extends IPackageManager.Stub { return (info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0; } + // Package is assumed to be on adopted storage if: + // FLAG_EXTERNAL_STORAGE is set + // volumeUuid is neither private internal (null) nor primary physical + private static boolean isExternalAdopted(PackageParser.Package pkg) { + return isExternal(pkg) && !TextUtils.isEmpty(pkg.volumeUuid) + && !Objects.equals(pkg.volumeUuid, StorageManager.UUID_PRIMARY_PHYSICAL); + } + private static boolean isSystemApp(PackageParser.Package pkg) { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } @@ -17205,10 +17584,12 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public boolean isComponentProtected(String callingPackage, + public boolean isComponentProtected(String callingPackage, int callingUid, ComponentName componentName, int userId) { if (DEBUG_PROTECTED) Log.d(TAG, "Checking if component is protected " - + componentName.flattenToShortString() + " from calling package " + callingPackage); + + componentName.flattenToShortString() + " from calling package " + callingPackage + + " and callinguid " + callingUid); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "set protected"); //Allow managers full access @@ -17229,8 +17610,24 @@ public class PackageManagerService extends IPackageManager.Stub { return false; } + //If this component is launched from a validation component, allow it. if (TextUtils.equals(PROTECTED_APPS_TARGET_VALIDATION_COMPONENT, - componentName.flattenToString())) { + componentName.flattenToString()) && callingUid == Process.SYSTEM_UID) { + return false; + } + + //If this component is launched from the system or a uid of a protected component, allow it. + boolean fromProtectedComponentUid = false; + for (String protectedComponentManager : protectedComponentManagers) { + int packageUid = getPackageUid(protectedComponentManager, userId); + if (packageUid != -1 && callingUid == packageUid) { + fromProtectedComponentUid = true; + } + } + + if (TextUtils.equals(callingPackage, "android") && callingUid == Process.SYSTEM_UID + || callingPackage == null && fromProtectedComponentUid) { + if (DEBUG_PROTECTED) Log.d(TAG, "Calling package is android or manager, allow"); return false; } @@ -17240,14 +17637,8 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { pkgSetting = mSettings.mPackages.get(packageName); - if (pkgSetting == null) { - if (className == null) { - throw new IllegalArgumentException( - "Unknown package: " + packageName); - } - throw new IllegalArgumentException( - "Unknown component: " + packageName - + "/" + className); + if (pkgSetting == null || className == null) { + return false; } // Get all the protected components components = pkgSetting.getProtectedComponents(userId); @@ -17752,10 +18143,20 @@ public class PackageManagerService extends IPackageManager.Stub { } if (failedException != null) { - Slog.w(TAG, "Unable to process theme " + pkg.packageName + " for " + target, - failedException); - // remove target from mOverlayTargets - iterator.remove(); + if (failedException instanceof AaptException && + ((AaptException) failedException).isCommon) { + Slog.e(TAG, "Unable to process common resources for " + pkg.packageName + + ", uninstalling theme.", failedException); + uninstallThemeForAllApps(pkg); + deletePackageX(pkg.packageName, getCallingUid(), + PackageManager.DELETE_ALL_USERS); + return PackageManager.INSTALL_FAILED_THEME_AAPT_ERROR; + } else { + Slog.w(TAG, "Unable to process theme " + pkg.packageName + " for " + target, + failedException); + // remove target from mOverlayTargets + iterator.remove(); + } } } @@ -17812,6 +18213,8 @@ public class PackageManagerService extends IPackageManager.Stub { for (String themePkgName : themesToProcess) { processThemeResources(themePkgName); } + + updateIconMapping(themeConfig.getIconPackPkgName()); } private void createAndSetCustomResources() { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 7b95106..38478c2 100755 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -338,7 +338,7 @@ final class Settings { // Packages that have been uninstalled and still need their external // storage data deleted. final ArrayList<PackageCleanItem> mPackagesToBeCleaned = new ArrayList<PackageCleanItem>(); - + // Packages that have been renamed since they were first installed. // Keys are the new names of the packages, values are the original // names. The packages appear everwhere else under their original @@ -2459,11 +2459,16 @@ final class Settings { private void readPrebundledPackagesForUserFromFileLPr(int userId, File file) { BufferedReader reader = null; try { + HashSet<String> ppkg = mPrebundledPackages.get(userId); + if (ppkg == null) { + Slog.e(PackageManagerService.TAG, "Unable to get packages for user " + userId); + return; + } reader = new BufferedReader(new FileReader(file)); String packageName = reader.readLine(); while (packageName != null) { if (!TextUtils.isEmpty(packageName)) { - mPrebundledPackages.get(userId).add(packageName); + ppkg.add(packageName); } packageName = reader.readLine(); } @@ -2519,7 +2524,7 @@ final class Settings { return mPrebundledPackages.get(userId).contains(packageName); } - boolean shouldPrebundledPackageBeInstalled(Resources res, String packageName, + boolean shouldPrebundledPackageBeInstalledForRegion(Resources res, String packageName, Resources configuredResources) { // Default fallback on lack of bad package if (TextUtils.isEmpty(packageName)) { @@ -2552,6 +2557,37 @@ final class Settings { return !ArrayUtils.contains(prebundledArray, packageName); } + boolean shouldPrebundledPackageBeInstalledForUserLPr(PackageSetting existingSettings, + int userIdentifier, String packageName) { + + // Check if package installed for the user + final boolean isInstalledForUser = (existingSettings != null + && existingSettings.getInstalled(userIdentifier)); + + // Check if package installed for the owner + final boolean isInstalledForOwner = (existingSettings != null + && existingSettings.getInstalled(UserHandle.USER_OWNER)); + + // Check if the user is the owner + final boolean isOwner = userIdentifier == UserHandle.USER_OWNER; + + // If the given user is not the owner, and the prebundle was installed for the owner + // but is no longer installed, and isn't currently installed for the user, + // skip installing it. + if (!isOwner && wasPrebundledPackageInstalledLPr(UserHandle.USER_OWNER, packageName) + && !isInstalledForOwner && !isInstalledForUser) { + return false; + } + + // If the given package was installed for the user and isn't currently, skip reinstalling it + if (wasPrebundledPackageInstalledLPr(userIdentifier, packageName) && + !isInstalledForUser) { + return false; + } + + return true; + } + void writeDisabledSysPackageLPr(XmlSerializer serializer, final PackageSetting pkg) throws java.io.IOException { serializer.startTag(null, "updated-package"); @@ -3751,7 +3787,7 @@ final class Settings { } String tagName = parser.getName(); - // Legacy + // Legacy if (tagName.equals(TAG_DISABLED_COMPONENTS)) { readDisabledComponentsLPw(packageSetting, parser, 0); } else if (tagName.equals(TAG_ENABLED_COMPONENTS)) { @@ -4029,7 +4065,7 @@ final class Settings { private String compToString(ArraySet<String> cmp) { return cmp != null ? Arrays.toString(cmp.toArray()) : "[]"; } - + boolean isEnabledLPr(ComponentInfo componentInfo, int flags, int userId) { if ((flags&PackageManager.GET_DISABLED_COMPONENTS) != 0) { return true; diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 06c3682..583d764 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -125,6 +125,11 @@ public class UserManagerService extends IUserManager.Stub { private static final String RESTRICTIONS_FILE_PREFIX = "res_"; private static final String XML_SUFFIX = ".xml"; + private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION = + UserInfo.FLAG_MANAGED_PROFILE + | UserInfo.FLAG_RESTRICTED + | UserInfo.FLAG_GUEST; + private static final int MIN_USER_ID = 10; private static final int USER_VERSION = 5; @@ -262,11 +267,22 @@ public class UserManagerService extends IUserManager.Stub { Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions"); } } + UserInfo currentGuestUser = null; + synchronized (mPackagesLock) { + currentGuestUser = findCurrentGuestUserLocked(); + } + if (currentGuestUser != null && !hasUserRestriction( + UserManager.DISALLOW_CONFIG_WIFI, currentGuestUser.id)) { + // If a guest user currently exists, apply the DISALLOW_CONFIG_WIFI option + // to it, in case this guest was created in a previous version where this + // user restriction was not a default guest restriction. + setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, currentGuestUser.id); + } } @Override public List<UserInfo> getUsers(boolean excludeDying) { - checkManageUsersPermission("query users"); + checkManageOrCreateUsersPermission("query users"); synchronized (mPackagesLock) { ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size()); for (int i = 0; i < mUsers.size(); i++) { @@ -285,7 +301,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public List<UserInfo> getProfiles(int userId, boolean enabledOnly) { if (userId != UserHandle.getCallingUserId()) { - checkManageUsersPermission("getting profiles related to user " + userId); + checkManageOrCreateUsersPermission("getting profiles related to user " + userId); } final long ident = Binder.clearCallingIdentity(); try { @@ -377,7 +393,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo getUserInfo(int userId) { - checkManageUsersPermission("query user"); + checkManageOrCreateUsersPermission("query user"); synchronized (mPackagesLock) { return getUserInfoLocked(userId); } @@ -509,6 +525,7 @@ public class UserManagerService extends IUserManager.Stub { if (mGuestRestrictions.isEmpty()) { mGuestRestrictions.putBoolean(UserManager.DISALLOW_OUTGOING_CALLS, true); mGuestRestrictions.putBoolean(UserManager.DISALLOW_SMS, true); + mGuestRestrictions.putBoolean(UserManager.DISALLOW_CONFIG_WIFI, true); } } @@ -664,6 +681,71 @@ public class UserManagerService extends IUserManager.Stub { } } + /** + * Enforces that only the system UID or root's UID or apps that have the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} + * can make certain calls to the UserManager. + * + * @param message used as message if SecurityException is thrown + * @throws SecurityException if the caller is not system or root + * @see #hasManageOrCreateUsersPermission() + */ + private static final void checkManageOrCreateUsersPermission(String message) { + if (!hasManageOrCreateUsersPermission()) { + throw new SecurityException( + "You either need MANAGE_USERS or CREATE_USERS permission to: " + message); + } + } + + /** + * Similar to {@link #checkManageOrCreateUsersPermission(String)} but when the caller is tries + * to create user/profiles other than what is allowed for + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} permission, then it will only + * allow callers with {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} permission. + */ + private static final void checkManageOrCreateUsersPermission(int creationFlags) { + if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) { + if (!hasManageOrCreateUsersPermission()) { + throw new SecurityException("You either need MANAGE_USERS or CREATE_USERS " + + "permission to create an user with flags: " + creationFlags); + } + } else if (!hasManageUsersPermission()) { + throw new SecurityException("You need MANAGE_USERS permission to create an user " + + " with flags: " + creationFlags); + } + } + + /** + * @return whether the calling UID is system UID or root's UID or the calling app has the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}. + */ + private static final boolean hasManageUsersPermission() { + final int callingUid = Binder.getCallingUid(); + return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) + || callingUid == Process.ROOT_UID + || ActivityManager.checkComponentPermission( + android.Manifest.permission.MANAGE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; + } + + /** + * @return whether the calling UID is system UID or root's UID or the calling app has the + * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or + * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}. + */ + private static final boolean hasManageOrCreateUsersPermission() { + final int callingUid = Binder.getCallingUid(); + return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) + || callingUid == Process.ROOT_UID + || ActivityManager.checkComponentPermission( + android.Manifest.permission.MANAGE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED + || ActivityManager.checkComponentPermission( + android.Manifest.permission.CREATE_USERS, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED; + } + private static void checkSystemOrRoot(String message) { final int uid = Binder.getCallingUid(); if (uid != Process.SYSTEM_UID && uid != 0) { @@ -1215,7 +1297,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo createProfileForUser(String name, int flags, int userId) { - checkManageUsersPermission("Only the system can create users"); + checkManageOrCreateUsersPermission(flags); if (userId != UserHandle.USER_OWNER) { Slog.w(LOG_TAG, "Only user owner can have profiles"); return null; @@ -1225,7 +1307,7 @@ public class UserManagerService extends IUserManager.Stub { @Override public UserInfo createUser(String name, int flags) { - checkManageUsersPermission("Only the system can create users"); + checkManageOrCreateUsersPermission(flags); return createUserInternal(name, flags, UserHandle.USER_NULL); } @@ -1390,7 +1472,7 @@ public class UserManagerService extends IUserManager.Stub { * @param userHandle the user's id */ public boolean removeUser(int userHandle) { - checkManageUsersPermission("Only the system can remove users"); + checkManageOrCreateUsersPermission("Only the system can remove users"); if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean( UserManager.DISALLOW_REMOVE_USER, false)) { Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled."); diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java index 9b5f5d0..96e1c70 100644 --- a/services/core/java/com/android/server/policy/GlobalActions.java +++ b/services/core/java/com/android/server/policy/GlobalActions.java @@ -49,7 +49,6 @@ 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; import android.net.ConnectivityManager; import android.os.Build; @@ -72,6 +71,8 @@ import android.service.dreams.DreamService; import android.service.dreams.IDreamManager; import android.telephony.PhoneStateListener; import android.telephony.ServiceState; +import android.telephony.SubscriptionInfo; +import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; import android.util.ArraySet; @@ -98,8 +99,8 @@ import android.widget.TextView; import cyanogenmod.providers.CMSettings; import java.util.ArrayList; +import java.util.BitSet; import java.util.List; -import java.util.UUID; import org.cyanogenmod.internal.util.ThemeUtils; @@ -141,6 +142,9 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac // Power menu customizations String mActions; + private BitSet mAirplaneModeBits; + private final List<PhoneStateListener> mPhoneStateListeners = new ArrayList<>(); + /** * @param context everything needs a context :( */ @@ -164,9 +168,15 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mHasTelephony = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); // get notified of phone state changes - TelephonyManager telephonyManager = - (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); - telephonyManager.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE); + SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener( + new SubscriptionManager.OnSubscriptionsChangedListener() { + @Override + public void onSubscriptionsChanged() { + super.onSubscriptionsChanged(); + setupAirplaneModeListeners(); + } + }); + setupAirplaneModeListeners(); mContext.getContentResolver().registerContentObserver( Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON), true, mAirplaneModeObserver); @@ -176,10 +186,59 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac mShowSilentToggle = SHOW_SILENT_TOGGLE && !mContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); + updatePowerMenuActions(); + } + + /** + * Since there are two ways of handling airplane mode (with telephony, we depend on the internal + * device telephony state), and MSIM devices do not report phone state for missing SIMs, we + * need to dynamically setup listeners based on subscription changes. + * + * So if there is _any_ active SIM in the device, we can depend on the phone state, + * otherwise fall back to {@link Settings.Global#AIRPLANE_MODE_ON}. + */ + private void setupAirplaneModeListeners() { + TelephonyManager telephonyManager = + (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); + + for (PhoneStateListener listener : mPhoneStateListeners) { + telephonyManager.listen(listener, PhoneStateListener.LISTEN_NONE); + } + mPhoneStateListeners.clear(); + + final List<SubscriptionInfo> subInfoList = SubscriptionManager.from(mContext) + .getActiveSubscriptionInfoList(); + if (subInfoList != null) { + mHasTelephony = true; + mAirplaneModeBits = new BitSet(subInfoList.size()); + for (int i = 0; i < subInfoList.size(); i++) { + final int finalI = i; + PhoneStateListener subListener = new PhoneStateListener(subInfoList.get(finalI) + .getSubscriptionId()) { + @Override + public void onServiceStateChanged(ServiceState serviceState) { + final boolean inAirplaneMode = serviceState.getState() + == ServiceState.STATE_POWER_OFF; + mAirplaneModeBits.set(finalI, inAirplaneMode); + + // we're in airplane mode if _any_ of the subscriptions say we are + mAirplaneState = mAirplaneModeBits.cardinality() > 0 + ? ToggleAction.State.On : ToggleAction.State.Off; + + mAirplaneModeOn.updateState(mAirplaneState); + if (mAdapter != null) { + mAdapter.notifyDataSetChanged(); + } + } + }; + mPhoneStateListeners.add(subListener); + telephonyManager.listen(subListener, PhoneStateListener.LISTEN_SERVICE_STATE); + } + } else { + mHasTelephony = false; + } // Set the initial status of airplane mode toggle mAirplaneState = getUpdatedAirplaneToggleState(); - - updatePowerMenuActions(); } /** @@ -189,14 +248,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac public void showDialog(boolean keyguardShowing, boolean isDeviceProvisioned) { mKeyguardShowing = keyguardShowing; mDeviceProvisioned = isDeviceProvisioned; - if (mDialog != null && mUiContext == null) { + if (mDialog != null) { mDialog.dismiss(); mDialog = null; - mDialog = createDialog(); // Show delayed, so that the dismiss of the previous dialog completes mHandler.sendEmptyMessage(MESSAGE_SHOW); } else { - mDialog = createDialog(); handleShow(); } } @@ -215,6 +272,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private void handleShow() { awakenIfNecessary(); + mDialog = createDialog(); prepareDialog(); // If we only have 1 item and it's a simple press action, just do this action. @@ -234,7 +292,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private Context getUiContext() { if (mUiContext == null) { mUiContext = ThemeUtils.createUiContext(mContext); - mUiContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); + mUiContext.setTheme(com.android.internal.R.style.Theme_Power_Dialog); } return mUiContext != null ? mUiContext : mContext; } @@ -358,7 +416,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac params.mOnClickListener = this; params.mForceInverseBackground = true; - GlobalActionsDialog dialog = new GlobalActionsDialog(getUiContext(), params); + GlobalActionsDialog dialog = new GlobalActionsDialog(/** system context **/ mContext, + /** themed context **/ getUiContext(), params); dialog.setCanceledOnTouchOutside(false); // Handled by the custom class. dialog.getListView().setItemsCanFocus(true); @@ -1153,6 +1212,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private final class SilentModeTriStateAction implements Action, View.OnClickListener { private final int[] ITEM_IDS = { R.id.option1, R.id.option2, R.id.option3, R.id.option4 }; + private final int[] ITEM_INDEX_TO_ZEN_MODE = { + Global.ZEN_MODE_NO_INTERRUPTIONS, + Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS, + Global.ZEN_MODE_OFF, + Global.ZEN_MODE_OFF + }; private final AudioManager mAudioManager; private final Handler mHandler; @@ -1236,21 +1301,15 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac if (!(v.getTag() instanceof Integer)) return; int index = (Integer) v.getTag(); - 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); + int zenMode = ITEM_INDEX_TO_ZEN_MODE[index]; + // 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); } if (index == 2 || index == 3) { @@ -1297,17 +1356,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac } }; - PhoneStateListener mPhoneStateListener = new PhoneStateListener() { - @Override - public void onServiceStateChanged(ServiceState serviceState) { - if (!mHasTelephony) return; - final boolean inAirplaneMode = serviceState.getState() == ServiceState.STATE_POWER_OFF; - mAirplaneState = inAirplaneMode ? ToggleAction.State.On : ToggleAction.State.Off; - mAirplaneModeOn.updateState(mAirplaneState); - mAdapter.notifyDataSetChanged(); - } - }; - private BroadcastReceiver mRingerModeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -1409,6 +1457,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private static final class GlobalActionsDialog extends Dialog implements DialogInterface { private final Context mContext; + private Context mSystemContext = null; private final int mWindowTouchSlop; private final AlertController mAlert; private final MyAdapter mAdapter; @@ -1418,7 +1467,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac private boolean mIntercepted; private boolean mCancelOnUp; - public GlobalActionsDialog(Context context, AlertParams params) { + private GlobalActionsDialog(Context context, AlertParams params) { super(context, getDialogTheme(context)); mContext = getContext(); mAlert = new AlertController(mContext, this, getWindow()); @@ -1427,6 +1476,19 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac params.apply(mAlert); } + /** + * Utilized for a working global actions dialog for both accessibility services (which + * require a system context) and + * @param systemContext Base context (should be from system process) + * @param themedContext Themed context (created from system ui) + * @param params + */ + public GlobalActionsDialog(Context systemContext, Context themedContext, + AlertParams params) { + this(themedContext, params); + mSystemContext = systemContext; + } + private static int getDialogTheme(Context context) { TypedValue outValue = new TypedValue(); context.getTheme().resolveAttribute(com.android.internal.R.attr.alertDialogTheme, @@ -1440,8 +1502,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac // of dismissing the dialog on touch outside. This is because the dialog // is dismissed on the first down while the global gesture is a long press // with two fingers anywhere on the screen. - if (EnableAccessibilityController.canEnableAccessibilityViaGesture(mContext)) { - mEnableAccessibilityController = new EnableAccessibilityController(mContext, + if (EnableAccessibilityController.canEnableAccessibilityViaGesture(mSystemContext)) { + mEnableAccessibilityController = new EnableAccessibilityController(mSystemContext, new Runnable() { @Override public void run() { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 9cb969c..6339007 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -22,7 +22,6 @@ import android.app.ActivityManagerInternal.SleepToken; import android.app.ActivityManagerNative; import android.app.AppOpsManager; import android.app.IUiModeManager; -import android.app.ProgressDialog; import android.app.SearchManager; import android.app.StatusBarManager; import android.app.UiModeManager; @@ -36,6 +35,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.res.CompatibilityInfo; @@ -137,6 +137,8 @@ import com.android.server.LocalServices; import com.android.server.policy.keyguard.KeyguardServiceDelegate; import com.android.server.policy.keyguard.KeyguardServiceDelegate.DrawnListener; +import org.cyanogenmod.internal.BootDexoptDialog; + import java.io.File; import java.io.FileReader; import java.io.IOException; @@ -152,6 +154,7 @@ import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED; import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT; import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED; import static android.view.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED; +import static org.cyanogenmod.platform.internal.Manifest.permission.THIRD_PARTY_KEYGUARD; /** * WindowManagerPolicy implementation for the Android phone UI. This @@ -273,6 +276,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { // app shows again. If that doesn't happen for 30s we drop the gesture. private static final long PANIC_GESTURE_EXPIRATION = 30000; + private static final String DEPRECATED_THIRD_PARTY_KEYGUARD_PERMISSION = + "android.permission.THIRD_PARTY_KEYGUARD"; + /** * Keyguard stuff */ @@ -489,7 +495,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { // During wakeup by volume keys, we still need to capture subsequent events // until the key is released. This is required since the beep sound is produced // post keypressed. - boolean mVolumeWakeTriggered; + boolean mVolumeDownWakeTriggered; + boolean mVolumeUpWakeTriggered; + boolean mVolumeMuteWakeTriggered; int mPointerLocationMode = 0; // guarded by mLock @@ -749,6 +757,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mClearedBecauseOfForceShow; private boolean mTopWindowIsKeyguard; private CMHardwareManager mCMHardware; + private boolean mShowKeyguardOnLeftSwipe; private class PolicyHandler extends Handler { @Override @@ -892,8 +901,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.System.getUriFor( Settings.System.ACCELEROMETER_ROTATION_ANGLES), false, this, UserHandle.USER_ALL); - resolver.registerContentObserver(CMSettings.Secure.getUriFor( - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR), false, this, + resolver.registerContentObserver(CMSettings.Global.getUriFor( + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR), false, this, UserHandle.USER_ALL); resolver.registerContentObserver(CMSettings.System.getUriFor( CMSettings.System.VOLBTN_MUSIC_CONTROLS), false, this, @@ -1434,8 +1443,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } boolean isUserSetupComplete() { - return Settings.Secure.getIntForUser(mContext.getContentResolver(), - Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0; + return CMSettings.Secure.getIntForUser(mContext.getContentResolver(), + CMSettings.Secure.CM_SETUP_WIZARD_COMPLETED, 0, UserHandle.USER_CURRENT) != 0; } private void handleShortPressOnHome() { @@ -1758,6 +1767,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { mNavigationBarLeftInLandscape) { requestTransientBars(mNavigationBar); } + if (mShowKeyguardOnLeftSwipe && isKeyguardShowingOrOccluded() + && mKeyguardDelegate.isKeyguardPanelFocused()) { + // Show keyguard + mKeyguardDelegate.showKeyguard(); + } } @Override public void onFling(int duration) { @@ -2122,8 +2136,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { updateWakeGestureListenerLp(); } - boolean devForceNavbar = CMSettings.Secure.getIntForUser(resolver, - CMSettings.Secure.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; + boolean devForceNavbar = CMSettings.Global.getIntForUser(resolver, + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; if (devForceNavbar != mDevForceNavbar) { mDevForceNavbar = devForceNavbar; if (mCMHardware.isSupported(CMHardwareManager.FEATURE_KEY_DISABLE)) { @@ -2299,8 +2313,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { outAppOp[0] = AppOpsManager.OP_SYSTEM_ALERT_WINDOW; break; case TYPE_KEYGUARD_PANEL: - permission = - org.cyanogenmod.platform.internal.Manifest.permission.THIRD_PARTY_KEYGUARD; + permission = THIRD_PARTY_KEYGUARD; break; default: permission = android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; @@ -2335,6 +2348,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { return WindowManagerGlobal.ADD_OKAY; } } + } else if (permission == THIRD_PARTY_KEYGUARD) { + // check if caller has the old permission and if so allow adding window + if (mContext.checkCallingOrSelfPermission( + DEPRECATED_THIRD_PARTY_KEYGUARD_PERMISSION) + == PackageManager.PERMISSION_GRANTED) { + return WindowManagerGlobal.ADD_OKAY; + } + // fall through to the normal check below } if (mContext.checkCallingOrSelfPermission(permission) @@ -2426,6 +2447,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { attrs.subtreeSystemUiVisibility |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; } + + if ((attrs.privateFlags & (WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS | + WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY)) != 0) { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.PREVENT_SYSTEM_KEYS, + "No permission to prevent system key"); + } } void readLidState() { @@ -2669,6 +2696,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return mWinShowWhenLocked; } + @Override + public WindowState getWinKeyguardPanelLw() { + return mKeyguardPanel; + } + /** {@inheritDoc} */ @Override public View addStartingWindow(IBinder appToken, String packageName, int theme, @@ -2864,9 +2896,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { "PhoneWindowManager"); break; case TYPE_KEYGUARD_PANEL: - mContext.enforceCallingOrSelfPermission( - org.cyanogenmod.platform.internal.Manifest.permission.THIRD_PARTY_KEYGUARD, - "PhoneWindowManager"); + // check deprecated perm first and if not granted enforce the new permission name + if (mContext.checkCallingOrSelfPermission( + DEPRECATED_THIRD_PARTY_KEYGUARD_PERMISSION) + != PackageManager.PERMISSION_GRANTED) { + mContext.enforceCallingOrSelfPermission(THIRD_PARTY_KEYGUARD, + "PhoneWindowManager"); + } if (mKeyguardPanel != null) { return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON; } @@ -3130,6 +3166,12 @@ public class PhoneWindowManager implements WindowManagerPolicy { // timeout. if (keyCode == KeyEvent.KEYCODE_HOME) { + if (mTopFullscreenOpaqueWindowState != null && + (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags + & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS) != 0 + && mScreenOnFully) { + return 0; + } // If we have released the home key, and didn't do anything else // while it was pressed, then it is time to go home! if (!down) { @@ -3230,6 +3272,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { return 0; } + if (mTopFullscreenOpaqueWindowState != null && + (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags + & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS) != 0 + && mScreenOnFully) { + return 0; + } + if (down) { if (mPressOnMenuBehavior == KEY_ACTION_APP_SWITCH || mLongPressOnMenuBehavior == KEY_ACTION_APP_SWITCH) { @@ -3295,6 +3344,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { } return 0; } else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) { + if (mTopFullscreenOpaqueWindowState != null && + (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags + & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS) != 0 + && mScreenOnFully) { + return 0; + } + if (!keyguardOn) { if (down) { if (mPressOnAppSwitchBehavior == KEY_ACTION_APP_SWITCH @@ -5007,7 +5063,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { mForceStatusBarTransparent = true; } - } + } else if (attrs.type == TYPE_KEYGUARD_PANEL) { + if (mKeyguardDelegate.isKeyguardPanelFocused()) { + attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + attrs.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } else { + attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; + attrs.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; + } + } boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW && attrs.type < FIRST_SYSTEM_WINDOW; @@ -5510,6 +5574,36 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private void setVolumeWakeTriggered(final int keyCode, boolean triggered) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_DOWN: + mVolumeDownWakeTriggered = triggered; + break; + case KeyEvent.KEYCODE_VOLUME_UP: + mVolumeUpWakeTriggered = triggered; + break; + case KeyEvent.KEYCODE_VOLUME_MUTE: + mVolumeMuteWakeTriggered = triggered; + break; + default: + Log.w(TAG, "setVolumeWakeTriggered: unexpected keyCode=" + keyCode); + } + } + + private boolean getVolumeWakeTriggered(final int keyCode) { + switch (keyCode) { + case KeyEvent.KEYCODE_VOLUME_DOWN: + return mVolumeDownWakeTriggered; + case KeyEvent.KEYCODE_VOLUME_UP: + return mVolumeUpWakeTriggered; + case KeyEvent.KEYCODE_VOLUME_MUTE: + return mVolumeMuteWakeTriggered; + default: + Log.w(TAG, "getVolumeWakeTriggered: unexpected keyCode=" + keyCode); + return false; + } + } + /** {@inheritDoc} */ @Override public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) { @@ -5605,11 +5699,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Eat all down & up keys when using volume wake. // This disables volume control, music control, and "beep" on key up. if (isWakeKey && mVolumeWakeScreen) { - mVolumeWakeTriggered = true; + setVolumeWakeTriggered(keyCode, true); break; - } else if (mVolumeWakeTriggered && !down) { + } else if (getVolumeWakeTriggered(keyCode) && !down) { result &= ~ACTION_PASS_TO_USER; - mVolumeWakeTriggered = false; + setVolumeWakeTriggered(keyCode, false); break; } @@ -5807,7 +5901,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_POWER: { if (mTopFullscreenOpaqueWindowState != null && (mTopFullscreenOpaqueWindowState.getAttrs().privateFlags - & WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY) != 0 + & (WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_SYSTEM_KEYS | + WindowManager.LayoutParams.PRIVATE_FLAG_PREVENT_POWER_KEY)) != 0 && mScreenOnFully) { return result; } @@ -5919,7 +6014,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } if (isWakeKey) { - wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY", true); + wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY", + event.getKeyCode() == KeyEvent.KEYCODE_WAKEUP /* check prox only on wake key*/); } return result; @@ -6357,7 +6453,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } private void wakeUpFromPowerKey(long eventTime) { - wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER", true); + wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey, "android.policy:POWER"); } private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, String reason) { @@ -6954,68 +7050,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { screenTurnedOn(); } - ProgressDialog mBootMsgDialog = null; + BootDexoptDialog mBootMsgDialog = null; /** {@inheritDoc} */ @Override - public void showBootMessage(final CharSequence msg, final boolean always) { + public void updateBootProgress(final int stage, final ApplicationInfo optimizedApp, + final int currentAppPos, final int totalAppCount) { mHandler.post(new Runnable() { @Override public void run() { if (mBootMsgDialog == null) { - int theme; - if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WATCH)) { - theme = com.android.internal.R.style.Theme_Micro_Dialog_Alert; - } else if (mContext.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_TELEVISION)) { - theme = com.android.internal.R.style.Theme_Leanback_Dialog_Alert; - } else { - theme = 0; - } - - mBootMsgDialog = new ProgressDialog(mContext, theme) { - // This dialog will consume all events coming in to - // it, to avoid it trying to do things too early in boot. - @Override public boolean dispatchKeyEvent(KeyEvent event) { - return true; - } - @Override public boolean dispatchKeyShortcutEvent(KeyEvent event) { - return true; - } - @Override public boolean dispatchTouchEvent(MotionEvent ev) { - return true; - } - @Override public boolean dispatchTrackballEvent(MotionEvent ev) { - return true; - } - @Override public boolean dispatchGenericMotionEvent(MotionEvent ev) { - return true; - } - @Override public boolean dispatchPopulateAccessibilityEvent( - AccessibilityEvent event) { - return true; - } - }; - if (mContext.getPackageManager().isUpgrade()) { - mBootMsgDialog.setTitle(R.string.android_upgrading_title); - } else { - mBootMsgDialog.setTitle(R.string.android_start_title); - } - mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); - mBootMsgDialog.setIndeterminate(true); - mBootMsgDialog.getWindow().setType( - WindowManager.LayoutParams.TYPE_BOOT_PROGRESS); - mBootMsgDialog.getWindow().addFlags( - WindowManager.LayoutParams.FLAG_DIM_BEHIND - | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); - mBootMsgDialog.getWindow().setDimAmount(1); - WindowManager.LayoutParams lp = mBootMsgDialog.getWindow().getAttributes(); - lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; - mBootMsgDialog.getWindow().setAttributes(lp); - mBootMsgDialog.setCancelable(false); - mBootMsgDialog.show(); - } - mBootMsgDialog.setMessage(msg); + mBootMsgDialog = BootDexoptDialog.create(mContext); + } + mBootMsgDialog.setProgress(stage, optimizedApp, currentAppPos, totalAppCount); } }); } @@ -7932,4 +7978,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { mKeyguardDelegate.dump(prefix, pw); } } + + @Override + public void setLiveLockscreenEdgeDetector(boolean enable) { + mShowKeyguardOnLeftSwipe = enable; + } } diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index cb09dd4..a223d05 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -431,4 +431,15 @@ public class KeyguardServiceDelegate { mKeyguardService.dump(prefix, pw); } } + + public void showKeyguard() { + mKeyguardService.showKeyguard(); + } + + public boolean isKeyguardPanelFocused() { + if (mKeyguardService != null) { + return mKeyguardService.isKeyguardPanelFocused(); + } + return false; + } } diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java index 429b188..31c7a04 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java @@ -245,4 +245,16 @@ public class KeyguardServiceWrapper implements IKeyguardService { public void dump(String prefix, PrintWriter pw) { mKeyguardStateMonitor.dump(prefix, pw); } + + public void showKeyguard() { + try { + mService.showKeyguard(); + } catch (RemoteException e) { + Slog.w(TAG, "Remote Exception", e); + } + } + + public boolean isKeyguardPanelFocused() { + return mKeyguardStateMonitor.isKeyguardPanelFocused(); + } }
\ No newline at end of file diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java index 30cff03..09f9087 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java @@ -43,6 +43,7 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { private volatile boolean mIsShowing = true; private volatile boolean mSimSecure = true; private volatile boolean mInputRestricted = true; + private volatile boolean mKeyguardPanelFocused = false; private int mCurrentUserId; @@ -70,6 +71,10 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { return mInputRestricted; } + public boolean isKeyguardPanelFocused() { + return mKeyguardPanelFocused; + } + @Override // Binder interface public void onShowingStateChanged(boolean showing) { mIsShowing = showing; @@ -80,6 +85,11 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { mSimSecure = simSecure; } + @Override // Binder interface + public void onKeyguardPanelFocusChanged(boolean focused) { + mKeyguardPanelFocused = focused; + } + public synchronized void setCurrentUser(int userId) { mCurrentUserId = userId; } @@ -100,5 +110,6 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { pw.println(prefix + "mSimSecure=" + mSimSecure); pw.println(prefix + "mInputRestricted=" + mInputRestricted); pw.println(prefix + "mCurrentUserId=" + mCurrentUserId); + pw.println(prefix + "mKeyguardPanelFocused=" + mKeyguardPanelFocused); } }
\ No newline at end of file diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 1fd1fbd..a197c6e 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -17,14 +17,18 @@ package com.android.server.power; import android.app.ActivityManager; +import android.os.IDeviceIdleController; +import android.os.ServiceManager; import android.util.SparseIntArray; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IBatteryStats; import com.android.internal.os.BackgroundThread; +import com.android.internal.util.ArrayUtils; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.ServiceThread; +import com.android.server.SystemConfig; import com.android.server.SystemService; import com.android.server.am.BatteryStatsService; import com.android.server.lights.Light; @@ -108,6 +112,8 @@ public final class PowerManagerService extends SystemService private static final int MSG_SANDMAN = 2; // Message: Sent when the screen brightness boost expires. private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3; + // Message: Sent when the sandman fails to acknowledge the dream state change. + private static final int MSG_SANDMAN_TIMEOUT = 4; private static final int MSG_WAKE_UP = 5; @@ -135,6 +141,8 @@ public final class PowerManagerService extends SystemService private static final int DIRTY_DOCK_STATE = 1 << 10; // Dirty bit: brightness boost changed private static final int DIRTY_SCREEN_BRIGHTNESS_BOOST = 1 << 11; + // Dirty bit: sandman state changed + private static final int DIRTY_SANDMAN_STATE = 1 << 12; // Summarizes the state of all active wakelocks. private static final int WAKE_LOCK_CPU = 1 << 0; @@ -179,6 +187,9 @@ public final class PowerManagerService extends SystemService // Max time (microseconds) to allow a CPU boost for private static final int MAX_CPU_BOOST_TIME = 5000000; + // Max time (milliseconds) to wait for the sandman to acknowledge dream state changes + private static final int SANDMAN_RESPONSE_TIMEOUT = 2 * 1000; + private final Context mContext; private final ServiceThread mHandlerThread; private final PowerManagerHandler mHandler; @@ -278,6 +289,13 @@ public final class PowerManagerService extends SystemService // True if the display suspend blocker has been acquired. private boolean mHoldingDisplaySuspendBlocker; + // The suspend blocker used to keep the CPU alive when dreams are requesting to be + // started. + private final SuspendBlocker mDreamSuspendBlocker; + + // True if the dream suspend blocker has been acquired. + private boolean mHoldingDreamSuspendBlocker; + // True if systemReady() has been called. private boolean mSystemReady; @@ -539,6 +557,7 @@ public final class PowerManagerService extends SystemService synchronized (mLock) { mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.WakeLocks"); mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display"); + mDreamSuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Dreams"); mDisplaySuspendBlocker.acquire(); mHoldingDisplaySuspendBlocker = true; mHalAutoSuspendModeEnabled = false; @@ -699,8 +718,8 @@ 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), + resolver.registerContentObserver(CMSettings.Global.getUriFor( + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR), false, mSettingsObserver, UserHandle.USER_ALL); // Go. @@ -846,8 +865,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; + mForceNavbar = CMSettings.Global.getIntForUser(resolver, + CMSettings.Global.DEV_FORCE_SHOW_NAVBAR, 0, UserHandle.USER_CURRENT) == 1; mDirty |= DIRTY_SETTINGS; } @@ -1923,15 +1942,16 @@ public final class PowerManagerService extends SystemService | DIRTY_PROXIMITY_POSITIVE | DIRTY_BATTERY_STATE)) != 0 || displayBecameReady) { if (mDisplayReady) { - scheduleSandmanLocked(); + scheduleSandmanLocked(false); } } } - private void scheduleSandmanLocked() { + private void scheduleSandmanLocked(boolean fromDreamService) { if (!mSandmanScheduled) { mSandmanScheduled = true; Message msg = mHandler.obtainMessage(MSG_SANDMAN); + msg.arg1 = fromDreamService ? 1 : 0; msg.setAsynchronous(true); mHandler.sendMessage(msg); } @@ -1944,7 +1964,7 @@ public final class PowerManagerService extends SystemService * the dream and we don't want to hold our lock while doing so. There is a risk that * the device will wake or go to sleep in the meantime so we have to handle that case. */ - private void handleSandman() { // runs on handler thread + private void handleSandman(boolean fromDreamService) { // runs on handler thread // Handle preconditions. final boolean startDreaming; final int wakefulness; @@ -1957,6 +1977,30 @@ public final class PowerManagerService extends SystemService } else { startDreaming = false; } + // We hold the display suspend blocker as long as mSandmanSummoned is true + // That guarantees this code to be run before the system enters suspend. However, + // once we exit this lock, we are no longer guaranteed to stay awake. Hold a wake + // lock that is released once the dream service has acknowledged the request + // to start. + if (mDreamManager != null) { + if (startDreaming) { + if (!mHoldingDreamSuspendBlocker) { + mDreamSuspendBlocker.acquire(); + mHoldingDreamSuspendBlocker = true; + Message msg = mHandler.obtainMessage(MSG_SANDMAN_TIMEOUT); + msg.setAsynchronous(true); + mHandler.sendMessageDelayed(msg, SANDMAN_RESPONSE_TIMEOUT); + mDirty |= DIRTY_SANDMAN_STATE; + updatePowerStateLocked(); + } + } else if (fromDreamService) { + mHandler.removeMessages(MSG_SANDMAN_TIMEOUT); + if (mHoldingDreamSuspendBlocker) { + mDreamSuspendBlocker.release(); + mHoldingDreamSuspendBlocker = false; + } + } + } } // Start dreaming if needed. @@ -2386,6 +2430,11 @@ public final class PowerManagerService extends SystemService if (mScreenBrightnessBoostInProgress) { return true; } + + if (mSandmanSummoned) { + return true; + } + // Let the system suspend if the screen is off or dozing. return false; } @@ -2981,7 +3030,7 @@ public final class PowerManagerService extends SystemService @Override public void onReceive(Context context, Intent intent) { synchronized (mLock) { - scheduleSandmanLocked(); + scheduleSandmanLocked(true); } } } @@ -3038,7 +3087,8 @@ public final class PowerManagerService extends SystemService handleUserActivityTimeout(); break; case MSG_SANDMAN: - handleSandman(); + boolean fromDreamService = msg.arg1 == 1; + handleSandman(fromDreamService); break; case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT: handleScreenBrightnessBoostTimeout(); @@ -3047,6 +3097,10 @@ public final class PowerManagerService extends SystemService cleanupProximity(); ((Runnable) msg.obj).run(); break; + case MSG_SANDMAN_TIMEOUT: + Slog.w(TAG, "Sandman unresponsive, releasing suspend blocker"); + handleSandman(true); + break; } } } @@ -3287,6 +3341,29 @@ public final class PowerManagerService extends SystemService final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); + + try { + if (mAppOps != null && + mAppOps.checkOperation(AppOpsManager.OP_WAKE_LOCK, uid, packageName) + != AppOpsManager.MODE_ALLOWED) { + + // If this app is whitelisted as "allow-in-power-save" then always allow! + // Current impl only looks at system-loaded ones, if we want to also include + // user apps which have been manually set, we would use IDeviceIdleController + if (!SystemConfig.getInstance().getAllowInPowerSave().contains(packageName)) { + Slog.d(TAG, "acquireWakeLock: ignoring request from " + packageName); + // For (ignore) accounting purposes + mAppOps.noteOperation(AppOpsManager.OP_WAKE_LOCK, uid, packageName); + // silent return + return; + } else { + Slog.d(TAG, "wake lock requested to be ignored but " + packageName + + " is marked to opt-out of all power save restrictions."); + } + } + } catch (RemoteException ignored) { + } + final long ident = Binder.clearCallingIdentity(); try { acquireWakeLockInternal(lock, flags, tag, packageName, ws, historyTag, uid, pid); @@ -3841,10 +3918,10 @@ public final class PowerManagerService extends SystemService else { mBlockedUids.clear(); } - } - if(changed){ - mDirty |= DIRTY_WAKE_LOCKS; - updatePowerStateLocked(); + if(changed){ + mDirty |= DIRTY_WAKE_LOCKS; + updatePowerStateLocked(); + } } } } diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java index 34b6e2b..36a9ca2 100644 --- a/services/core/java/com/android/server/power/ShutdownThread.java +++ b/services/core/java/com/android/server/power/ShutdownThread.java @@ -630,6 +630,16 @@ public final class ShutdownThread extends Thread { } }; + final String cryptoStatus = SystemProperties.get("ro.crypto.state", "unsupported"); + final boolean isEncrypted = "encrypted".equalsIgnoreCase(cryptoStatus); + + if (mRebootUpdate && isEncrypted) { + sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null); + + // If it's to reboot to install update, invoke uncrypt via init service. + uncrypt(); + } + Log.i(TAG, "Shutting down MountService"); // Set initial variables and time out time. @@ -665,12 +675,6 @@ public final class ShutdownThread extends Thread { } } } - if (mRebootUpdate) { - sInstance.setRebootProgress(MOUNT_SERVICE_STOP_PERCENT, null); - - // If it's to reboot to install update, invoke uncrypt via init service. - uncrypt(); - } rebootOrShutdown(mContext, mReboot, mRebootReason); } @@ -1002,7 +1006,7 @@ public final class ShutdownThread extends Thread { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEVISION)) { uiContext.setTheme(com.android.internal.R.style.Theme_Leanback_Dialog_Alert); } else { - uiContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); + uiContext.setTheme(com.android.internal.R.style.Theme_Power_Dialog); } } return uiContext != null ? uiContext : context; diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java index e9ace29..0e51953 100644 --- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java +++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java @@ -249,7 +249,7 @@ public class StatusBarManagerService extends IStatusBarService.Stub { */ @Override public void disable2(int what, IBinder token, String pkg) { - disableForUser(what, token, pkg, mCurrentUserId); + disable2ForUser(what, token, pkg, mCurrentUserId); } /** diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 5de1837..362e959 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -30,6 +30,8 @@ import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENT import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING; import android.content.Context; +import android.database.ContentObserver; +import android.os.Handler; import android.os.RemoteException; import android.util.Slog; import android.util.SparseArray; @@ -44,6 +46,8 @@ import android.view.Choreographer; import com.android.server.wm.WindowManagerService.LayoutFields; +import cyanogenmod.providers.CMSettings; + import java.io.PrintWriter; import java.util.ArrayList; @@ -98,7 +102,7 @@ public class WindowAnimator { /** Use one animation for all entering activities after keyguard is dismissed. */ Animation mPostKeyguardExitAnimation; - private final boolean mBlurUiEnabled; + private boolean mKeyguardBlurEnabled; // forceHiding states. static final int KEYGUARD_NOT_SHOWN = 0; @@ -120,9 +124,14 @@ public class WindowAnimator { mContext = service.mContext; mPolicy = service.mPolicy; - mBlurUiEnabled = mContext.getResources().getBoolean( + boolean blurUiEnabled = mContext.getResources().getBoolean( com.android.internal.R.bool.config_ui_blur_enabled); + if (blurUiEnabled) { + SettingsObserver observer = new SettingsObserver(new Handler()); + observer.observe(mContext); + } + mAnimationFrameCallback = new Choreographer.FrameCallback() { public void doFrame(long frameTimeNs) { synchronized (mService.mWindowMap) { @@ -211,7 +220,9 @@ public class WindowAnimator { // Show SHOW_WHEN_LOCKED windows that turn on the screen allowWhenLocked |= (win.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0 && win.mTurnOnScreen; // Show windows that use TYPE_STATUS_BAR_SUB_PANEL when locked - allowWhenLocked |= win.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD_PANEL; + allowWhenLocked |= win.mAttrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD_PANEL && + winShowWhenLocked == null; + if (appShowWhenLocked != null) { allowWhenLocked |= appShowWhenLocked == win.mAppToken @@ -223,7 +234,14 @@ public class WindowAnimator { // Only hide windows if the keyguard is active and not animating away. boolean keyguardOn = mPolicy.isKeyguardShowingOrOccluded() - && (mForceHiding != KEYGUARD_ANIMATING_OUT && !mBlurUiEnabled); + && mForceHiding != KEYGUARD_ANIMATING_OUT; + + final WindowState winKeyguardPanel = (WindowState) mPolicy.getWinKeyguardPanelLw(); + // If a keyguard panel is currently being shown, we should + // continue to hide the windows as if blur is disabled. + if (winKeyguardPanel == null) { + keyguardOn &= !mKeyguardBlurEnabled; + } return keyguardOn && !allowWhenLocked && (win.getDisplayId() == Display.DEFAULT_DISPLAY); } @@ -232,7 +250,7 @@ public class WindowAnimator { final WindowList windows = mService.getWindowListLocked(displayId); - if (mKeyguardGoingAway && !mBlurUiEnabled) { + if (mKeyguardGoingAway && !mKeyguardBlurEnabled) { for (int i = windows.size() - 1; i >= 0; i--) { WindowState win = windows.get(i); if (!mPolicy.isKeyguardHostWindow(win.mAttrs)) { @@ -247,7 +265,7 @@ public class WindowAnimator { // Create a new animation to delay until keyguard is gone on its own. winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f); winAnimator.mAnimation.setDuration( - mBlurUiEnabled ? 0 : KEYGUARD_ANIM_TIMEOUT_MS); + mKeyguardBlurEnabled ? 0 : KEYGUARD_ANIM_TIMEOUT_MS); winAnimator.mAnimationIsEntrance = false; winAnimator.mAnimationStartTime = -1; winAnimator.mKeyguardGoingAwayAnimation = true; @@ -337,7 +355,7 @@ public class WindowAnimator { if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) { mForceHiding = KEYGUARD_ANIMATING_OUT; } else { - mForceHiding = win.isDrawnLw() && !mBlurUiEnabled ? + mForceHiding = win.isDrawnLw() && !mKeyguardBlurEnabled ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN; } } @@ -890,4 +908,30 @@ public class WindowAnimator { private class DisplayContentsAnimator { ScreenRotationAnimation mScreenRotationAnimation = null; } + + private class SettingsObserver extends ContentObserver { + public SettingsObserver(Handler handler) { + super(handler); + } + + public void observe(Context context) { + context.getContentResolver().registerContentObserver( + CMSettings.Secure.getUriFor(CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED), + false, + this); + + onChange(true); + } + + public void unobserve(Context context) { + context.getContentResolver().unregisterContentObserver(this); + } + + @Override + public void onChange(boolean selfChange) { + // default to being enabled since we are here because the blur config was set to true + mKeyguardBlurEnabled = CMSettings.Secure.getInt(mContext.getContentResolver(), + CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED, 1) == 1; + } + } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index dcb1e18..3d79757 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -29,6 +29,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.CompatibilityInfo; import android.content.res.Configuration; @@ -65,6 +66,7 @@ import android.os.SystemProperties; import android.os.SystemService; import android.os.Trace; import android.os.UserHandle; +import android.os.UserManager; import android.os.WorkSource; import android.provider.Settings; import android.util.ArraySet; @@ -128,6 +130,8 @@ import com.android.server.UiThread; import com.android.server.Watchdog; import com.android.server.am.BatteryStatsService; import com.android.server.input.InputManagerService; +import com.android.server.lights.Light; +import com.android.server.lights.LightsManager; import com.android.server.policy.PhoneWindowManager; import com.android.server.power.ShutdownThread; @@ -3162,7 +3166,9 @@ public class WindowManagerService extends IWindowManager.Stub } if (attrs != null) { + Binder.restoreCallingIdentity(origId); mPolicy.adjustWindowParamsLw(attrs); + origId = Binder.clearCallingIdentity(); } // if they don't have the permission, mask out the status bar bits @@ -5928,6 +5934,17 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.enableScreenAfterBoot(); + // clear any intrusive lighting which may still be on from the + // crypto landing ui + LightsManager lm = LocalServices.getService(LightsManager.class); + Light batteryLight = lm.getLight(LightsManager.LIGHT_ID_BATTERY); + Light notifLight = lm.getLight(LightsManager.LIGHT_ID_NOTIFICATIONS); + if (batteryLight != null) { + batteryLight.turnOff(); + } + if (notifLight != null) { + notifLight.turnOff(); + } // Make sure the last requested orientation has been applied. updateRotationUnchecked(false, false); } @@ -5944,13 +5961,18 @@ public class WindowManagerService extends IWindowManager.Stub return true; } - public void showBootMessage(final CharSequence msg, final boolean always) { + public void updateBootProgress(final int stage, final ApplicationInfo optimizedApp, + final int currentAppPos, final int totalAppCount, final boolean always) { boolean first = false; synchronized(mWindowMap) { if (DEBUG_BOOT) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); - Slog.i(TAG, "showBootMessage: msg=" + msg + " always=" + always + Slog.i(TAG, "updateBootProgress: stage=" + stage + + " optimizedApp=" + optimizedApp + + " currentAppPos=" + currentAppPos + + " totalAppCount=" + totalAppCount + + " always=" + always + " mAllowBootMessages=" + mAllowBootMessages + " mShowingBootMessages=" + mShowingBootMessages + " mSystemBooted=" + mSystemBooted, here); @@ -5968,7 +5990,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } mShowingBootMessages = true; - mPolicy.showBootMessage(msg, always); + mPolicy.updateBootProgress(stage, optimizedApp, currentAppPos, totalAppCount); } if (first) { performEnableScreen(); @@ -7666,6 +7688,12 @@ public class WindowManagerService extends IWindowManager.Stub + " milliseconds before attempting to detect safe mode."); } + UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + if (um != null && um.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT)) { + mSafeMode = false; + return false; + } + int menuState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_MENU); int sState = mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_ANY, KeyEvent.KEYCODE_S); @@ -10166,6 +10194,7 @@ public class WindowManagerService extends IWindowManager.Stub } } + winAnimator.computeShownFrameLocked(); winAnimator.setSurfaceBoundariesLocked(recoveringMemory); } @@ -11951,6 +11980,14 @@ public class WindowManagerService extends IWindowManager.Stub return mWindowMap; } + @Override + public void setLiveLockscreenEdgeDetector(boolean enable) { + if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.STATUS_BAR) + == PackageManager.PERMISSION_GRANTED) { + mPolicy.setLiveLockscreenEdgeDetector(enable); + } + } + private final class LocalService extends WindowManagerInternal { @Override public void requestTraversalFromDisplayManager() { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 5169607..d19f8ac 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -18,6 +18,7 @@ package com.android.server; import android.app.ActivityManagerNative; import android.app.ActivityThread; +import android.app.IActivityManager; import android.app.IAlarmManager; import android.app.INotificationManager; import android.app.usage.UsageStatsManagerInternal; @@ -99,6 +100,9 @@ import cyanogenmod.providers.CMSettings; import dalvik.system.VMRuntime; import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.Locale; import java.util.Timer; import java.util.TimerTask; @@ -326,7 +330,7 @@ public final class SystemServer { private void createSystemContext() { ActivityThread activityThread = ActivityThread.systemMain(); mSystemContext = activityThread.getSystemContext(); - mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); + mSystemContext.setTheme(com.android.internal.R.style.Theme_Power_Dialog); } /** @@ -455,8 +459,9 @@ public final class SystemServer { boolean disableNetwork = SystemProperties.getBoolean("config.disable_network", false); boolean disableNetworkTime = SystemProperties.getBoolean("config.disable_networktime", false); boolean isEmulator = SystemProperties.get("ro.kernel.qemu").equals("1"); - String[] externalServices = context.getResources().getStringArray( - org.cyanogenmod.platform.internal.R.array.config_externalCMServices); + String externalServer = context.getResources().getString( + org.cyanogenmod.platform.internal.R.string.config_externalSystemServer); + boolean disableAtlas = SystemProperties.getBoolean("config.disable_atlas", false); try { Slog.i(TAG, "Reading configuration..."); @@ -616,10 +621,8 @@ public final class SystemServer { } try { - ActivityManagerNative.getDefault().showBootMessage( - context.getResources().getText( - com.android.internal.R.string.android_upgrading_starting_apps), - false); + ActivityManagerNative.getDefault().updateBootProgress( + IActivityManager.BOOT_STAGE_STARTING_APPS, null, 0, 0, false); } catch (RemoteException e) { } @@ -957,7 +960,7 @@ public final class SystemServer { mSystemServiceManager.startService(DreamManagerService.class); } - if (!disableNonCoreServices) { + if (!disableNonCoreServices && !disableAtlas) { try { Slog.i(TAG, "Assets Atlas Service"); atlas = new AssetAtlasService(context); @@ -1052,13 +1055,22 @@ public final class SystemServer { // MMS service broker mmsService = mSystemServiceManager.startService(MmsServiceBroker.class); - for (String service : externalServices) { - try { - Slog.i(TAG, service); - mSystemServiceManager.startService(service); - } catch (Throwable e) { - reportWtf("starting " + service , e); - } + final Class<?> serverClazz; + try { + serverClazz = Class.forName(externalServer); + final Constructor<?> constructor = serverClazz.getDeclaredConstructor(Context.class); + constructor.setAccessible(true); + final Object baseObject = constructor.newInstance(mSystemContext); + final Method method = baseObject.getClass().getDeclaredMethod("run"); + method.setAccessible(true); + method.invoke(baseObject); + } catch (ClassNotFoundException + | IllegalAccessException + | InvocationTargetException + | InstantiationException + | NoSuchMethodException e) { + Slog.wtf(TAG, "Unable to start " + externalServer); + Slog.wtf(TAG, e); } // It is now time to start up the app processes... @@ -1177,15 +1189,6 @@ public final class SystemServer { Slog.i(TAG, "WebViewFactory preparation"); WebViewFactory.prepareWebViewInSystemServer(); - // Start Nfc before SystemUi to ensure NfcTile and other apps gets a - // valid NfcAdapter from NfcManager - try { - startNfcService(context); - } catch (Throwable e) { - // Don't crash. Nfc is an optional service. Just annotate that isn't ready - Slog.e(TAG, "Nfc service didn't start. Nfc will not be available.", e); - } - try { startSystemUi(context); } catch (Throwable e) { @@ -1304,23 +1307,4 @@ public final class SystemServer { //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.OWNER); } - - static final void startNfcService(Context context) { - IPackageManager pm = ActivityThread.getPackageManager(); - if (pm == null) { - Slog.w(TAG, "Cannot get package manager, assuming no NFC feature"); - return; - } - try { - if (pm.hasSystemFeature(PackageManager.FEATURE_NFC)) { - Intent intent = new Intent(); - intent.setComponent(new ComponentName("com.android.nfc", - "com.android.nfc.NfcBootstrapService")); - context.startServiceAsUser(intent, UserHandle.OWNER); - } - } catch (RemoteException e) { - Slog.w(TAG, "Package manager query failed, assuming no NFC feature", e); - return; - } - } } diff --git a/services/net/java/android/net/dhcp/DhcpPacket.java b/services/net/java/android/net/dhcp/DhcpPacket.java index 8927bfa..f97df83 100644 --- a/services/net/java/android/net/dhcp/DhcpPacket.java +++ b/services/net/java/android/net/dhcp/DhcpPacket.java @@ -602,7 +602,12 @@ abstract class DhcpPacket { protected void addCommonClientTlvs(ByteBuffer buf) { addTlv(buf, DHCP_MAX_MESSAGE_SIZE, (short) MAX_LENGTH); addTlv(buf, DHCP_VENDOR_CLASS_ID, "android-dhcp-" + Build.VERSION.RELEASE); - addTlv(buf, DHCP_HOST_NAME, SystemProperties.get("net.hostname")); + + /* the default 'android-dhcp' is there to make sure the hostname is + * never empty, because the DHCP standard forbids it (RFC2132, section + * 3.14) and certain DHCP forwarders and servers ignore such malformed + * requests */ + addTlv(buf, DHCP_HOST_NAME, SystemProperties.get("net.hostname", "android-dhcp")); } /** diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 9c44c7a..aa8b37f 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -27,6 +27,7 @@ import android.content.res.AssetManager; import android.content.res.Configuration; import android.content.res.Resources; import android.os.SystemProperties; +import android.os.UserHandle; import android.test.AndroidTestCase; import android.test.mock.MockContext; import android.text.TextUtils; @@ -365,7 +366,7 @@ public class PackageManagerSettingsTests extends AndroidTestCase { }; Mockito.when(resources.getStringArray(R.array.config_restrict_to_region_locked_devices)) .thenReturn(regionRestrictedPackages); - assertFalse(settings.shouldPrebundledPackageBeInstalled(resources, + assertFalse(settings.shouldPrebundledPackageBeInstalledForRegion(resources, expectedPackageNeededForRegion, resources)); } @@ -384,7 +385,70 @@ public class PackageManagerSettingsTests extends AndroidTestCase { Mockito.when(resources.getStringArray(R.array.config_restrict_to_region_locked_devices)) .thenReturn(regionLockedPackages); - assertTrue(settings.shouldPrebundledPackageBeInstalled(resources, + assertTrue(settings.shouldPrebundledPackageBeInstalledForRegion(resources, expectedPackageNeededForRegion, resources)); } + + // Shamelessly kanged from KeySetManagerServiceTest + public PackageSetting generateFakePackageSetting(String name) { + return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"), + new File(mContext.getCacheDir(), "fakeResPath"), "", "", "", + "", 1, 0, 0); + } + + // Checks if a package that was installed and currently isn't installed for the owner + // is accepted for a secondary user + public void testPrebundledSecondaryUserAccept() { + Settings settings = new Settings(getContext().getFilesDir()); + String expectedPackageToBeInstalled = "org.cyanogenmod.secondaryuser.package"; + + PackageSetting packageSetting = + generateFakePackageSetting(expectedPackageToBeInstalled); + + int userOwner = UserHandle.USER_OWNER; + int userSecondary = 1000; + + // Return true that the package was installed for the owner at some point + settings.markPrebundledPackageInstalledLPr(userOwner, expectedPackageToBeInstalled); + assertTrue(settings.wasPrebundledPackageInstalledLPr(userOwner, + expectedPackageToBeInstalled)); + + // Return false that the package was installed for the secondary user at some point + // DON'T MARK PREBUNDLED PACKAGE INSTALLED + + // Return false that the package is currently not installed for the owner + packageSetting.setInstalled(false, userOwner); + assertFalse(packageSetting.getInstalled(userOwner)); + + // Return false that the package is currently not installed for the secondary user + packageSetting.setInstalled(false, userSecondary); + assertFalse(packageSetting.getInstalled(userSecondary)); + + assertFalse(settings.shouldPrebundledPackageBeInstalledForUserLPr(packageSetting, + userSecondary, expectedPackageToBeInstalled)); + } + + // Checks if a package that was installed for a secondary user and currently isn't installed + // for the user is accepted to be reinstalled + public void testPrebundledSecondaryUserReinstallAccept() { + Settings settings = new Settings(getContext().getFilesDir()); + String expectedPackageToBeInstalled = "org.cyanogenmod.secondaryuser.package"; + + PackageSetting packageSetting = + generateFakePackageSetting(expectedPackageToBeInstalled); + + int userSecondary = 1000; + + // Return true that the package was installed for the secondary user at some point + settings.markPrebundledPackageInstalledLPr(userSecondary, expectedPackageToBeInstalled); + assertTrue(settings.wasPrebundledPackageInstalledLPr(userSecondary, + expectedPackageToBeInstalled)); + + // Return false that the package is currently not installed for the secondary user + packageSetting.setInstalled(false, userSecondary); + assertFalse(packageSetting.getInstalled(userSecondary)); + + assertFalse(settings.shouldPrebundledPackageBeInstalledForUserLPr(packageSetting, + userSecondary, expectedPackageToBeInstalled)); + } } diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index b275c2f..583bac2 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -219,7 +219,7 @@ public class UsageStatsService extends SystemService implements Context.DISPLAY_SERVICE); mPowerManager = getContext().getSystemService(PowerManager.class); - mDisplayManager.registerDisplayListener(mDisplayListener, mHandler); + mDisplayManager.registerDisplayListener(mDisplayListener, null); synchronized (this) { updateDisplayLocked(); } diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 3fecfb6..2886ce6 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -580,7 +580,13 @@ public class UsbDeviceManager { if (mConfigured && enteringAccessoryMode) { // successfully entered accessory mode - + if (mCurrentAccessory != null) { + Slog.w(TAG, "USB accessory re-attached, detach was not announced!"); + if (mBootCompleted) { + getCurrentSettings().accessoryDetached(mCurrentAccessory); + } + mCurrentAccessory = null; + } if (mAccessoryStrings != null) { mCurrentAccessory = new UsbAccessory(mAccessoryStrings); Slog.d(TAG, "entering USB accessory mode: " + mCurrentAccessory); @@ -895,6 +901,7 @@ public class UsbDeviceManager { private String getDefaultFunctions() { String func = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, UsbManager.USB_FUNCTION_NONE); + func = UsbManager.removeFunction(func, "charging"); if (UsbManager.USB_FUNCTION_NONE.equals(func)) { func = UsbManager.USB_FUNCTION_MTP; } |