summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/accessibility/java/com/android/server/accessibility/DisplayAdjustmentUtils.java24
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java36
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java61
-rw-r--r--services/core/java/com/android/server/AppOpsPolicy.java7
-rw-r--r--services/core/java/com/android/server/AppOpsService.java103
-rw-r--r--services/core/java/com/android/server/BatteryService.java60
-rw-r--r--services/core/java/com/android/server/BluetoothManagerService.java17
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java20
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java6
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java9
-rw-r--r--services/core/java/com/android/server/LockSettingsService.java19
-rw-r--r--services/core/java/com/android/server/LockSettingsStorage.java13
-rw-r--r--services/core/java/com/android/server/MasterClearReceiver.java2
-rw-r--r--services/core/java/com/android/server/MountService.java10
-rw-r--r--services/core/java/com/android/server/NetPluginDelegate.java (renamed from services/core/java/com/android/server/net/NetPluginDelegate.java)24
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java138
-rw-r--r--services/core/java/com/android/server/PermissionDialog.java4
-rw-r--r--services/core/java/com/android/server/PermissionDialogReqQueue.java6
-rw-r--r--services/core/java/com/android/server/SystemConfig.java71
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java50
-rw-r--r--services/core/java/com/android/server/accounts/TokenCache.java10
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java130
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java17
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java78
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueue.java5
-rw-r--r--services/core/java/com/android/server/am/LockTaskNotify.java4
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java10
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java2
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java171
-rw-r--r--services/core/java/com/android/server/connectivity/PacManager.java36
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java4
-rw-r--r--services/core/java/com/android/server/content/ContentService.java6
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java3
-rw-r--r--services/core/java/com/android/server/content/SyncStorageEngine.java26
-rw-r--r--services/core/java/com/android/server/display/AutomaticBrightnessController.java9
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java16
-rw-r--r--services/core/java/com/android/server/display/LiveDisplayController.java650
-rw-r--r--services/core/java/com/android/server/display/WifiDisplayController.java97
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java31
-rw-r--r--services/core/java/com/android/server/lights/LightsService.java4
-rw-r--r--services/core/java/com/android/server/location/GpsLocationProvider.java2
-rw-r--r--services/core/java/com/android/server/location/GpsXtraDownloader.java21
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java8
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java19
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsCollection.java15
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsRecorder.java61
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java40
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java208
-rw-r--r--services/core/java/com/android/server/notification/RankingConfig.java5
-rw-r--r--services/core/java/com/android/server/notification/RankingHelper.java55
-rw-r--r--services/core/java/com/android/server/notification/ZenModeHelper.java37
-rw-r--r--services/core/java/com/android/server/pm/MultiTaskDealer.java141
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java653
-rwxr-xr-xservices/core/java/com/android/server/pm/Settings.java46
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java94
-rw-r--r--services/core/java/com/android/server/policy/GlobalActions.java144
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java203
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java11
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java12
-rw-r--r--services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java11
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java103
-rw-r--r--services/core/java/com/android/server/power/ShutdownThread.java18
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java2
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java58
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java43
-rw-r--r--services/java/com/android/server/SystemServer.java70
-rw-r--r--services/net/java/android/net/dhcp/DhcpPacket.java7
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java68
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java2
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java9
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;
}