summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/Android.mk1
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java256
-rw-r--r--services/backup/java/com/android/server/backup/Trampoline.java4
-rw-r--r--services/core/java/com/android/server/EventLogTags.logtags1
-rw-r--r--services/core/java/com/android/server/PersistentDataBlockService.java8
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java67
-rw-r--r--services/core/java/com/android/server/am/ActivityStack.java20
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java60
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java189
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java65
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java8
-rw-r--r--services/core/java/com/android/server/fingerprint/FingerprintService.java210
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java14
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java4
-rw-r--r--services/core/java/com/android/server/hdmi/RequestArcAction.java12
-rw-r--r--services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java6
-rw-r--r--services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java1
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java59
-rw-r--r--services/core/java/com/android/server/job/controllers/StateController.java6
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java14
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java14
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsCollection.java56
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java84
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java181
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java7
-rw-r--r--services/core/java/com/android/server/pm/PermissionsState.java10
-rw-r--r--services/core/java/com/android/server/pm/SettingBase.java21
-rw-r--r--services/core/java/com/android/server/pm/Settings.java228
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java1
-rw-r--r--services/core/java/com/android/server/power/DeviceIdleController.java (renamed from services/core/java/com/android/server/DeviceIdleController.java)83
-rw-r--r--services/core/java/com/android/server/power/Notifier.java38
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java48
-rw-r--r--services/core/java/com/android/server/trust/TrustAgentWrapper.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java17
-rw-r--r--services/core/jni/com_android_server_UsbMidiDevice.cpp11
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java111
-rw-r--r--services/java/com/android/server/SystemServer.java67
-rw-r--r--services/midi/Android.mk12
-rw-r--r--services/midi/java/com/android/server/midi/MidiService.java (renamed from services/core/java/com/android/server/MidiService.java)57
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java8
-rw-r--r--services/usb/java/com/android/server/usb/UsbAlsaManager.java13
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java24
-rw-r--r--services/usb/java/com/android/server/usb/UsbMidiDevice.java18
44 files changed, 1532 insertions, 593 deletions
diff --git a/services/Android.mk b/services/Android.mk
index 8777085..1918db5 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -24,6 +24,7 @@ services := \
appwidget \
backup \
devicepolicy \
+ midi \
net \
print \
restrictions \
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 31f9e22..45b0fb2 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -29,6 +29,7 @@ import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupTransport;
import android.app.backup.FullBackup;
+import android.app.backup.FullBackupDataOutput;
import android.app.backup.RestoreDescription;
import android.app.backup.RestoreSet;
import android.app.backup.IBackupManager;
@@ -134,6 +135,7 @@ import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.TreeMap;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.Deflater;
@@ -369,7 +371,7 @@ public class BackupManagerService {
// we're now good to go, so start the backup alarms
if (MORE_DEBUG) Slog.d(TAG, "Now provisioned, so starting backups");
KeyValueBackupJob.schedule(mContext);
- scheduleNextFullBackupJob();
+ scheduleNextFullBackupJob(0);
}
}
}
@@ -726,7 +728,7 @@ public class BackupManagerService {
{
try {
BackupRestoreTask task = (BackupRestoreTask) msg.obj;
- task.operationComplete();
+ task.operationComplete(msg.arg1);
} catch (ClassCastException e) {
Slog.e(TAG, "Invalid completion in flight, obj=" + msg.obj);
}
@@ -1784,7 +1786,7 @@ public class BackupManagerService {
PackageInfo app = mPackageManager.getPackageInfo(packageName, 0);
if (appGetsFullBackup(app) && appIsEligibleForBackup(app.applicationInfo)) {
enqueueFullBackup(packageName, now);
- scheduleNextFullBackupJob();
+ scheduleNextFullBackupJob(0);
}
// Transport maintenance: rebind to known existing transports that have
@@ -2224,7 +2226,7 @@ public class BackupManagerService {
void execute();
// An operation that wanted a callback has completed
- void operationComplete();
+ void operationComplete(int result);
// An operation that wanted a callback has timed out
void handleTimeout();
@@ -2792,7 +2794,7 @@ public class BackupManagerService {
}
@Override
- public void operationComplete() {
+ public void operationComplete(int unusedResult) {
// The agent reported back to us!
if (mBackupData == null) {
@@ -3128,8 +3130,23 @@ public class BackupManagerService {
// Core logic for performing one package's full backup, gathering the tarball from the
// application and emitting it to the designated OutputStream.
+
+ // Callout from the engine to an interested participant that might need to communicate
+ // with the agent prior to asking it to move data
+ interface FullBackupPreflight {
+ /**
+ * Perform the preflight operation necessary for the given package.
+ * @param pkg The name of the package being proposed for full-data backup
+ * @param agent Live BackupAgent binding to the target app's agent
+ * @return BackupTransport.TRANSPORT_OK to proceed with the backup operation,
+ * or one of the other BackupTransport.* error codes as appropriate
+ */
+ int preflightFullBackup(PackageInfo pkg, IBackupAgent agent);
+ };
+
class FullBackupEngine {
OutputStream mOutput;
+ FullBackupPreflight mPreflightHook;
IFullBackupRestoreObserver mObserver;
File mFilesDir;
File mManifestFile;
@@ -3160,8 +3177,7 @@ public class BackupManagerService {
@Override
public void run() {
try {
- BackupDataOutput output = new BackupDataOutput(
- mPipe.getFileDescriptor());
+ FullBackupDataOutput output = new FullBackupDataOutput(mPipe);
if (mWriteManifest) {
final boolean writeWidgetData = mWidgetData != null;
@@ -3204,15 +3220,16 @@ public class BackupManagerService {
}
}
- FullBackupEngine(OutputStream output, String packageName, boolean alsoApks) {
+ FullBackupEngine(OutputStream output, String packageName, FullBackupPreflight preflightHook,
+ boolean alsoApks) {
mOutput = output;
+ mPreflightHook = preflightHook;
mIncludeApks = alsoApks;
mFilesDir = new File("/data/system");
mManifestFile = new File(mFilesDir, BACKUP_MANIFEST_FILENAME);
mMetadataFile = new File(mFilesDir, BACKUP_METADATA_FILENAME);
}
-
public int backupOnePackage(PackageInfo pkg) throws RemoteException {
int result = BackupTransport.TRANSPORT_OK;
Slog.d(TAG, "Binding to full backup agent : " + pkg.packageName);
@@ -3222,42 +3239,52 @@ public class BackupManagerService {
if (agent != null) {
ParcelFileDescriptor[] pipes = null;
try {
- pipes = ParcelFileDescriptor.createPipe();
-
- ApplicationInfo app = pkg.applicationInfo;
- final boolean isSharedStorage = pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
- final boolean sendApk = mIncludeApks
- && !isSharedStorage
- && ((app.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) == 0)
- && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
+ // Call the preflight hook, if any
+ if (mPreflightHook != null) {
+ result = mPreflightHook.preflightFullBackup(pkg, agent);
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "preflight returned " + result);
+ }
+ }
+
+ // If we're still good to go after preflighting, start moving data
+ if (result == BackupTransport.TRANSPORT_OK) {
+ pipes = ParcelFileDescriptor.createPipe();
+
+ ApplicationInfo app = pkg.applicationInfo;
+ final boolean isSharedStorage = pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
+ final boolean sendApk = mIncludeApks
+ && !isSharedStorage
+ && ((app.privateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) == 0)
+ && ((app.flags & ApplicationInfo.FLAG_SYSTEM) == 0 ||
(app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0);
- byte[] widgetBlob = AppWidgetBackupBridge.getWidgetState(pkg.packageName,
- UserHandle.USER_OWNER);
+ byte[] widgetBlob = AppWidgetBackupBridge.getWidgetState(pkg.packageName,
+ UserHandle.USER_OWNER);
- final int token = generateToken();
- FullBackupRunner runner = new FullBackupRunner(pkg, agent, pipes[1],
- token, sendApk, !isSharedStorage, widgetBlob);
- pipes[1].close(); // the runner has dup'd it
- pipes[1] = null;
- Thread t = new Thread(runner, "app-data-runner");
- t.start();
+ final int token = generateToken();
+ FullBackupRunner runner = new FullBackupRunner(pkg, agent, pipes[1],
+ token, sendApk, !isSharedStorage, widgetBlob);
+ pipes[1].close(); // the runner has dup'd it
+ pipes[1] = null;
+ Thread t = new Thread(runner, "app-data-runner");
+ t.start();
- // Now pull data from the app and stuff it into the output
- try {
- routeSocketDataToOutput(pipes[0], mOutput);
- } catch (IOException e) {
- Slog.i(TAG, "Caught exception reading from agent", e);
- result = BackupTransport.AGENT_ERROR;
- }
+ // Now pull data from the app and stuff it into the output
+ try {
+ routeSocketDataToOutput(pipes[0], mOutput);
+ } catch (IOException e) {
+ Slog.i(TAG, "Caught exception reading from agent", e);
+ result = BackupTransport.AGENT_ERROR;
+ }
- if (!waitUntilOperationComplete(token)) {
- Slog.e(TAG, "Full backup failed on package " + pkg.packageName);
- result = BackupTransport.AGENT_ERROR;
- } else {
- if (DEBUG) Slog.d(TAG, "Full package backup success: " + pkg.packageName);
+ if (!waitUntilOperationComplete(token)) {
+ Slog.e(TAG, "Full backup failed on package " + pkg.packageName);
+ result = BackupTransport.AGENT_ERROR;
+ } else {
+ if (DEBUG) Slog.d(TAG, "Full package backup success: " + pkg.packageName);
+ }
}
-
} catch (IOException e) {
Slog.e(TAG, "Error backing up " + pkg.packageName, e);
result = BackupTransport.AGENT_ERROR;
@@ -3282,7 +3309,7 @@ public class BackupManagerService {
return result;
}
- private void writeApkToBackup(PackageInfo pkg, BackupDataOutput output) {
+ private void writeApkToBackup(PackageInfo pkg, FullBackupDataOutput output) {
// Forward-locked apps, system-bundled .apks, etc are filtered out before we get here
// TODO: handle backing up split APKs
final String appSourceDir = pkg.applicationInfo.getBaseCodePath();
@@ -3781,7 +3808,7 @@ public class BackupManagerService {
final boolean isSharedStorage =
pkg.packageName.equals(SHARED_BACKUP_AGENT_PACKAGE);
- mBackupEngine = new FullBackupEngine(out, pkg.packageName, mIncludeApks);
+ mBackupEngine = new FullBackupEngine(out, pkg.packageName, null, mIncludeApks);
sendOnBackupPackage(isSharedStorage ? "Shared storage" : pkg.packageName);
mBackupEngine.backupOnePackage(pkg);
@@ -3828,13 +3855,13 @@ public class BackupManagerService {
static final String TAG = "PFTBT";
ArrayList<PackageInfo> mPackages;
boolean mUpdateSchedule;
- AtomicBoolean mLatch;
+ CountDownLatch mLatch;
AtomicBoolean mKeepRunning; // signal from job scheduler
FullBackupJob mJob; // if a scheduled job needs to be finished afterwards
PerformFullTransportBackupTask(IFullBackupRestoreObserver observer,
String[] whichPackages, boolean updateSchedule,
- FullBackupJob runningJob, AtomicBoolean latch) {
+ FullBackupJob runningJob, CountDownLatch latch) {
super(observer);
mUpdateSchedule = updateSchedule;
mLatch = latch;
@@ -3892,6 +3919,7 @@ public class BackupManagerService {
ParcelFileDescriptor[] transportPipes = null;
PackageInfo currentPackage;
+ long backoff = 0;
try {
if (!mEnabled || !mProvisioned) {
@@ -3944,10 +3972,10 @@ public class BackupManagerService {
// Now set up the backup engine / data source end of things
enginePipes = ParcelFileDescriptor.createPipe();
- AtomicBoolean runnerLatch = new AtomicBoolean(false);
+ CountDownLatch runnerLatch = new CountDownLatch(1);
SinglePackageBackupRunner backupRunner =
new SinglePackageBackupRunner(enginePipes[1], currentPackage,
- runnerLatch);
+ transport, runnerLatch);
// The runner dup'd the pipe half, so we close it here
enginePipes[1].close();
enginePipes[1] = null;
@@ -3972,6 +4000,9 @@ public class BackupManagerService {
break;
}
nRead = in.read(buffer);
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "in.read(buffer) from app: " + nRead);
+ }
if (nRead > 0) {
out.write(buffer, 0, nRead);
result = transport.sendBackupData(nRead);
@@ -4003,6 +4034,14 @@ public class BackupManagerService {
Slog.e(TAG, "Error " + result
+ " backing up " + currentPackage.packageName);
}
+
+ // Also ask the transport how long it wants us to wait before
+ // moving on to the next package, if any.
+ backoff = transport.requestFullBackupTime();
+ if (DEBUG_SCHEDULING) {
+ Slog.i(TAG, "Transport suggested backoff=" + backoff);
+ }
+
}
// Roll this package to the end of the backup queue if we're
@@ -4055,15 +4094,12 @@ public class BackupManagerService {
mRunningFullBackupTask = null;
}
- synchronized (mLatch) {
- mLatch.set(true);
- mLatch.notifyAll();
- }
+ mLatch.countDown();
// Now that we're actually done with schedule-driven work, reschedule
// the next pass based on the new queue state.
if (mUpdateSchedule) {
- scheduleNextFullBackupJob();
+ scheduleNextFullBackupJob(backoff);
}
}
}
@@ -4094,15 +4130,79 @@ public class BackupManagerService {
// Run the backup and pipe it back to the given socket -- expects to run on
// a standalone thread. The runner owns this half of the pipe, and closes
// it to indicate EOD to the other end.
+ class SinglePackageBackupPreflight implements BackupRestoreTask, FullBackupPreflight {
+ final AtomicInteger mResult = new AtomicInteger();
+ final CountDownLatch mLatch = new CountDownLatch(1);
+ final IBackupTransport mTransport;
+
+ public SinglePackageBackupPreflight(IBackupTransport transport) {
+ mTransport = transport;
+ }
+
+ @Override
+ public int preflightFullBackup(PackageInfo pkg, IBackupAgent agent) {
+ int result;
+ try {
+ final int token = generateToken();
+ prepareOperationTimeout(token, TIMEOUT_FULL_BACKUP_INTERVAL, this);
+ addBackupTrace("preflighting");
+ if (MORE_DEBUG) {
+ Slog.d(TAG, "Preflighting full payload of " + pkg.packageName);
+ }
+ agent.doMeasureFullBackup(token, mBackupManagerBinder);
+
+ // now wait to get our result back
+ mLatch.await();
+ int totalSize = mResult.get();
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "Got preflight response; size=" + totalSize);
+ }
+
+ result = mTransport.checkFullBackupSize(totalSize);
+ } catch (Exception e) {
+ Slog.w(TAG, "Exception preflighting " + pkg.packageName + ": " + e.getMessage());
+ result = BackupTransport.AGENT_ERROR;
+ }
+ return result;
+ }
+
+ @Override
+ public void execute() {
+ // Unused in this case
+ }
+
+ @Override
+ public void operationComplete(int result) {
+ // got the callback, and our preflightFullBackup() method is waiting for the result
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "Preflight op complete, result=" + result);
+ }
+ mResult.set(result);
+ mLatch.countDown();
+ }
+
+ @Override
+ public void handleTimeout() {
+ if (MORE_DEBUG) {
+ Slog.i(TAG, "Preflight timeout; failing");
+ }
+ mResult.set(BackupTransport.AGENT_ERROR);
+ mLatch.countDown();
+ }
+
+ }
+
class SinglePackageBackupRunner implements Runnable {
final ParcelFileDescriptor mOutput;
final PackageInfo mTarget;
- final AtomicBoolean mLatch;
+ final FullBackupPreflight mPreflight;
+ final CountDownLatch mLatch;
SinglePackageBackupRunner(ParcelFileDescriptor output, PackageInfo target,
- AtomicBoolean latch) throws IOException {
+ IBackupTransport transport, CountDownLatch latch) throws IOException {
mOutput = ParcelFileDescriptor.dup(output.getFileDescriptor());
mTarget = target;
+ mPreflight = new SinglePackageBackupPreflight(transport);
mLatch = latch;
}
@@ -4110,15 +4210,13 @@ public class BackupManagerService {
public void run() {
try {
FileOutputStream out = new FileOutputStream(mOutput.getFileDescriptor());
- FullBackupEngine engine = new FullBackupEngine(out, mTarget.packageName, false);
+ FullBackupEngine engine = new FullBackupEngine(out, mTarget.packageName,
+ mPreflight, false);
engine.backupOnePackage(mTarget);
} catch (Exception e) {
Slog.e(TAG, "Exception during full package backup of " + mTarget);
} finally {
- synchronized (mLatch) {
- mLatch.set(true);
- mLatch.notifyAll();
- }
+ mLatch.countDown();
try {
mOutput.close();
} catch (IOException e) {
@@ -4126,7 +4224,6 @@ public class BackupManagerService {
}
}
}
-
}
}
@@ -4135,16 +4232,17 @@ public class BackupManagerService {
/**
* Schedule a job to tell us when it's a good time to run a full backup
*/
- void scheduleNextFullBackupJob() {
+ void scheduleNextFullBackupJob(long transportMinLatency) {
synchronized (mQueueLock) {
if (mFullBackupQueue.size() > 0) {
// schedule the next job at the point in the future when the least-recently
// backed up app comes due for backup again; or immediately if it's already
// due.
- long upcomingLastBackup = mFullBackupQueue.get(0).lastBackup;
- long timeSinceLast = System.currentTimeMillis() - upcomingLastBackup;
- final long latency = (timeSinceLast < MIN_FULL_BACKUP_INTERVAL)
+ final long upcomingLastBackup = mFullBackupQueue.get(0).lastBackup;
+ final long timeSinceLast = System.currentTimeMillis() - upcomingLastBackup;
+ final long appLatency = (timeSinceLast < MIN_FULL_BACKUP_INTERVAL)
? (MIN_FULL_BACKUP_INTERVAL - timeSinceLast) : 0;
+ final long latency = Math.min(transportMinLatency, appLatency);
Runnable r = new Runnable() {
@Override public void run() {
FullBackupJob.schedule(mContext, latency);
@@ -4258,7 +4356,7 @@ public class BackupManagerService {
// Okay, the top thing is runnable now. Pop it off and get going.
mFullBackupQueue.remove(0);
- AtomicBoolean latch = new AtomicBoolean(false);
+ CountDownLatch latch = new CountDownLatch(1);
String[] pkg = new String[] {entry.packageName};
mRunningFullBackupTask = new PerformFullTransportBackupTask(null, pkg, true,
scheduledJob, latch);
@@ -7895,7 +7993,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
}
@Override
- public void operationComplete() {
+ public void operationComplete(int unusedResult) {
if (MORE_DEBUG) {
Slog.i(TAG, "operationComplete() during restore: target="
+ mCurrentPackage.packageName
@@ -8395,17 +8493,25 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
Slog.d(TAG, "fullTransportBackup()");
}
- AtomicBoolean latch = new AtomicBoolean(false);
+ CountDownLatch latch = new CountDownLatch(1);
PerformFullTransportBackupTask task =
new PerformFullTransportBackupTask(null, pkgNames, false, null, latch);
(new Thread(task, "full-transport-master")).start();
- synchronized (latch) {
+ do {
try {
- while (latch.get() == false) {
- latch.wait();
- }
- } catch (InterruptedException e) {}
+ latch.await();
+ break;
+ } catch (InterruptedException e) {
+ // Just go back to waiting for the latch to indicate completion
+ }
+ } while (true);
+
+ // We just ran a backup on these packages, so kick them to the end of the queue
+ final long now = System.currentTimeMillis();
+ for (String pkg : pkgNames) {
+ enqueueFullBackup(pkg, now);
}
+
if (DEBUG) {
Slog.d(TAG, "Done with full transport backup.");
}
@@ -8575,7 +8681,7 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
if (enable && !wasEnabled && mProvisioned) {
// if we've just been enabled, start scheduling backup passes
KeyValueBackupJob.schedule(mContext);
- scheduleNextFullBackupJob();
+ scheduleNextFullBackupJob(0);
} else if (!enable) {
// No longer enabled, so stop running backups
if (DEBUG) Slog.i(TAG, "Opting out of backup");
@@ -8948,8 +9054,10 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// Note that a currently-active backup agent has notified us that it has
// completed the given outstanding asynchronous backup/restore operation.
- public void opComplete(int token) {
- if (MORE_DEBUG) Slog.v(TAG, "opComplete: " + Integer.toHexString(token));
+ public void opComplete(int token, long result) {
+ if (MORE_DEBUG) {
+ Slog.v(TAG, "opComplete: " + Integer.toHexString(token) + " result=" + result);
+ }
Operation op = null;
synchronized (mCurrentOpLock) {
op = mCurrentOperations.get(token);
@@ -8962,6 +9070,8 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF
// The completion callback, if any, is invoked on the handler
if (op != null && op.callback != null) {
Message msg = mBackupHandler.obtainMessage(MSG_OP_COMPLETE, op.callback);
+ // NB: this cannot distinguish between results > 2 gig
+ msg.arg1 = (result > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int) result;
mBackupHandler.sendMessage(msg);
}
}
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index 2e84fbe..99bbdae 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -309,10 +309,10 @@ public class Trampoline extends IBackupManager.Stub {
}
@Override
- public void opComplete(int token) throws RemoteException {
+ public void opComplete(int token, long result) throws RemoteException {
BackupManagerService svc = mService;
if (svc != null) {
- svc.opComplete(token);
+ svc.opComplete(token, result);
}
}
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 983d83a..694e851 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -221,3 +221,4 @@ option java_package com.android.server
# AudioService.java
# ---------------------------
40000 volume_changed (stream|1), (prev_level|1), (level|1), (max_level|1), (caller|3)
+40001 stream_devices_changed (stream|1), (prev_devices|1), (devices|1)
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index 97d16c0..b36f515 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -70,6 +70,7 @@ public class PersistentDataBlockService extends SystemService {
// Limit to 100k as blocks larger than this might cause strain on Binder.
private static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
public static final int DIGEST_SIZE_BYTES = 32;
+ private static final String OEM_UNLOCK_PROP = "sys.oem_unlock_allowed";
private final Context mContext;
private final String mDataBlockFile;
@@ -108,11 +109,14 @@ public class PersistentDataBlockService extends SystemService {
}
private void formatIfOemUnlockEnabled() {
- if (doGetOemUnlockEnabled()) {
+ boolean enabled = doGetOemUnlockEnabled();
+ if (enabled) {
synchronized (mLock) {
formatPartitionLocked(true);
}
}
+
+ SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
}
private void enforceOemUnlockPermission() {
@@ -132,7 +136,6 @@ public class PersistentDataBlockService extends SystemService {
throw new SecurityException("Only the Owner is allowed to change OEM unlock state");
}
}
-
private int getTotalDataSizeLocked(DataInputStream inputStream) throws IOException {
// skip over checksum
inputStream.skipBytes(DIGEST_SIZE_BYTES);
@@ -290,6 +293,7 @@ public class PersistentDataBlockService extends SystemService {
Slog.e(TAG, "unable to access persistent partition", e);
return;
} finally {
+ SystemProperties.set(OEM_UNLOCK_PROP, enabled ? "1" : "0");
IoUtils.closeQuietly(outputStream);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 626b442..b5e1de9 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2188,7 +2188,7 @@ public final class ActivityManagerService extends ActivityManagerNative
systemDir.mkdirs();
mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
mBatteryStatsService.getActiveStatistics().readLocked();
- mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
+ mBatteryStatsService.scheduleWriteToDisk();
mOnBattery = DEBUG_POWER ? true
: mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
@@ -2432,7 +2432,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (mLastWriteTime < (now-BATTERY_STATS_TIME)) {
mLastWriteTime = now;
- mBatteryStatsService.getActiveStatistics().writeAsyncLocked();
+ mBatteryStatsService.scheduleWriteToDisk();
}
}
}
@@ -3046,12 +3046,12 @@ public final class ActivityManagerService extends ActivityManagerNative
int[] permGids = null;
try {
checkTime(startTime, "startProcess: getting gids from package manager");
- final PackageManager pm = mContext.getPackageManager();
- permGids = pm.getPackageGids(app.info.packageName);
+ permGids = AppGlobals.getPackageManager().getPackageGids(app.info.packageName,
+ app.userId);
if (Environment.isExternalStorageEmulated()) {
checkTime(startTime, "startProcess: checking external storage perm");
- if (pm.checkPermission(
+ if (mContext.getPackageManager().checkPermission(
android.Manifest.permission.ACCESS_ALL_EXTERNAL_STORAGE,
app.info.packageName) == PERMISSION_GRANTED) {
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER_ALL;
@@ -3059,7 +3059,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mountExternal = Zygote.MOUNT_EXTERNAL_MULTIUSER;
}
}
- } catch (PackageManager.NameNotFoundException e) {
+ } catch (RemoteException e) {
Slog.w(TAG, "Unable to retrieve gids", e);
}
@@ -6326,31 +6326,38 @@ public final class ActivityManagerService extends ActivityManagerNative
}
try {
PendingIntentRecord res = (PendingIntentRecord)pendingResult;
- Intent intent = res.key.requestIntent;
- if (intent != null) {
- if (res.lastTag != null && res.lastTagPrefix == prefix && (res.lastTagPrefix == null
- || res.lastTagPrefix.equals(prefix))) {
- return res.lastTag;
- }
- res.lastTagPrefix = prefix;
- StringBuilder sb = new StringBuilder(128);
- if (prefix != null) {
- sb.append(prefix);
- }
- if (intent.getAction() != null) {
- sb.append(intent.getAction());
- } else if (intent.getComponent() != null) {
- intent.getComponent().appendShortString(sb);
- } else {
- sb.append("?");
- }
- return res.lastTag = sb.toString();
+ synchronized (this) {
+ return getTagForIntentSenderLocked(res, prefix);
}
} catch (ClassCastException e) {
}
return null;
}
+ String getTagForIntentSenderLocked(PendingIntentRecord res, String prefix) {
+ final Intent intent = res.key.requestIntent;
+ if (intent != null) {
+ if (res.lastTag != null && res.lastTagPrefix == prefix && (res.lastTagPrefix == null
+ || res.lastTagPrefix.equals(prefix))) {
+ return res.lastTag;
+ }
+ res.lastTagPrefix = prefix;
+ final StringBuilder sb = new StringBuilder(128);
+ if (prefix != null) {
+ sb.append(prefix);
+ }
+ if (intent.getAction() != null) {
+ sb.append(intent.getAction());
+ } else if (intent.getComponent() != null) {
+ intent.getComponent().appendShortString(sb);
+ } else {
+ sb.append("?");
+ }
+ return res.lastTag = sb.toString();
+ }
+ return null;
+ }
+
@Override
public void setProcessLimit(int max) {
enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
@@ -10479,17 +10486,21 @@ public final class ActivityManagerService extends ActivityManagerNative
if (!(sender instanceof PendingIntentRecord)) {
return;
}
- BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+ final PendingIntentRecord rec = (PendingIntentRecord)sender;
+ final String tag;
+ synchronized (this) {
+ tag = getTagForIntentSenderLocked(rec, "*walarm*:");
+ }
+ final BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
synchronized (stats) {
if (mBatteryStatsService.isOnBattery()) {
mBatteryStatsService.enforceCallingPermission();
- PendingIntentRecord rec = (PendingIntentRecord)sender;
int MY_UID = Binder.getCallingUid();
int uid = rec.uid == MY_UID ? Process.SYSTEM_UID : rec.uid;
BatteryStatsImpl.Uid.Pkg pkg =
stats.getPackageStatsLocked(sourceUid >= 0 ? sourceUid : uid,
sourcePkg != null ? sourcePkg : rec.key.packageName);
- pkg.incWakeupsLocked();
+ pkg.noteWakeupAlarmLocked(tag);
}
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b102a07..0eb914b 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -1018,6 +1018,10 @@ final class ActivityStack {
if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
prev = null;
}
+ // It is possible the activity was freezing the screen before it was paused.
+ // In that case go ahead and remove the freeze this activity has on the screen
+ // since it is no longer visible.
+ prev.stopFreezingScreenLocked(true /*force*/);
mPausingActivity = null;
}
@@ -1112,7 +1116,7 @@ final class ActivityStack {
}
}
- private void setVisibile(ActivityRecord r, boolean visible) {
+ private void setVisible(ActivityRecord r, boolean visible) {
r.visible = visible;
mWindowManager.setAppVisibility(r.appToken, visible);
final ArrayList<ActivityContainer> containers = r.mChildContainers;
@@ -1297,7 +1301,7 @@ final class ActivityStack {
if (!r.visible || r.mLaunchTaskBehind) {
if (DEBUG_VISBILITY) Slog.v(
TAG, "Starting and making visible: " + r);
- setVisibile(r, true);
+ setVisible(r, true);
}
if (r != starting) {
mStackSupervisor.startSpecificActivityLocked(r, false, false);
@@ -1329,7 +1333,7 @@ final class ActivityStack {
r.updateOptionsLocked(r.returningOptions);
mUndrawnActivitiesBelowTopTranslucent.add(r);
}
- setVisibile(r, true);
+ setVisible(r, true);
r.sleeping = false;
r.app.pendingUiClean = true;
r.app.thread.scheduleWindowVisibility(r.appToken, true);
@@ -1364,7 +1368,7 @@ final class ActivityStack {
if (r.visible) {
if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
try {
- setVisibile(r, false);
+ setVisible(r, false);
switch (r.state) {
case STOPPING:
case STOPPED:
@@ -3896,8 +3900,7 @@ final class ActivityStack {
return true;
}
- private boolean relaunchActivityLocked(ActivityRecord r,
- int changes, boolean andResume) {
+ private boolean relaunchActivityLocked(ActivityRecord r, int changes, boolean andResume) {
List<ResultInfo> results = null;
List<ReferrerIntent> newIntents = null;
if (andResume) {
@@ -3916,9 +3919,8 @@ final class ActivityStack {
mStackSupervisor.removeChildActivityContainers(r);
try {
- if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
- (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
- + r);
+ if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Moving to " +
+ (andResume ? "RESUMED" : "PAUSED") + " Relaunching " + r);
r.forceNewConfig = false;
r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, changes,
!andResume, new Configuration(mService.mConfiguration),
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index e9e6496..f874244 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -129,7 +129,7 @@ public final class ActivityStackSupervisor implements DisplayListener {
static final boolean DEBUG_RELEASE = DEBUG || false;
static final boolean DEBUG_SAVED_STATE = DEBUG || false;
static final boolean DEBUG_SCREENSHOTS = DEBUG || false;
- static final boolean DEBUG_STATES = DEBUG || false;
+ static final boolean DEBUG_STATES = DEBUG || true;
static final boolean DEBUG_VISIBLE_BEHIND = DEBUG || false;
public static final int HOME_STACK_ID = 0;
@@ -273,8 +273,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
* until the task exits or #stopLockTaskMode() is called. */
TaskRecord mLockTaskModeTask;
/** Store the current lock task mode. Possible values:
- * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActicityManager#LOCK_TASK_MODE_LOCKED},
- * {@link ActicityManager#LOCK_TASK_MODE_PINNED}
+ * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActivityManager#LOCK_TASK_MODE_LOCKED},
+ * {@link ActivityManager#LOCK_TASK_MODE_PINNED}
*/
private int mLockTaskModeState;
/**
@@ -1132,12 +1132,13 @@ public final class ActivityStackSupervisor implements DisplayListener {
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
- r.startFreezingScreenLocked(app, 0);
- if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
- mWindowManager.setAppVisibility(r.appToken, true);
+ if (andResume) {
+ r.startFreezingScreenLocked(app, 0);
+ mWindowManager.setAppVisibility(r.appToken, true);
- // schedule launch ticks to collect information about slow apps.
- r.startLaunchTickingLocked();
+ // schedule launch ticks to collect information about slow apps.
+ r.startLaunchTickingLocked();
+ }
// Have the window manager re-evaluate the orientation of
// the screen based on the new activity order. Note that
@@ -1195,34 +1196,37 @@ public final class ActivityStackSupervisor implements DisplayListener {
r.forceNewConfig = false;
mService.showAskCompatModeDialogLocked(r);
r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
- String profileFile = null;
- ParcelFileDescriptor profileFd = null;
+ ProfilerInfo profilerInfo = null;
if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
if (mService.mProfileProc == null || mService.mProfileProc == app) {
mService.mProfileProc = app;
- profileFile = mService.mProfileFile;
- profileFd = mService.mProfileFd;
- }
- }
- app.hasShownUi = true;
- app.pendingUiClean = true;
- if (profileFd != null) {
- try {
- profileFd = profileFd.dup();
- } catch (IOException e) {
- if (profileFd != null) {
- try {
- profileFd.close();
- } catch (IOException o) {
+ final String profileFile = mService.mProfileFile;
+ if (profileFile != null) {
+ ParcelFileDescriptor profileFd = mService.mProfileFd;
+ if (profileFd != null) {
+ try {
+ profileFd = profileFd.dup();
+ } catch (IOException e) {
+ if (profileFd != null) {
+ try {
+ profileFd.close();
+ } catch (IOException o) {
+ }
+ profileFd = null;
+ }
+ }
}
- profileFd = null;
+
+ profilerInfo = new ProfilerInfo(profileFile, profileFd,
+ mService.mSamplingInterval, mService.mAutoStopProfiler);
}
}
}
- ProfilerInfo profilerInfo = profileFile != null
- ? new ProfilerInfo(profileFile, profileFd, mService.mSamplingInterval,
- mService.mAutoStopProfiler) : null;
+ if (andResume) {
+ app.hasShownUi = true;
+ app.pendingUiClean = true;
+ }
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 197b51d..c8db3be 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -16,20 +16,26 @@
package com.android.server.am;
+import android.bluetooth.BluetoothActivityEnergyInfo;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
+import android.net.wifi.IWifiManager;
+import android.net.wifi.WifiActivityEnergyInfo;
import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFileDescriptor;
import android.os.PowerManagerInternal;
import android.os.Process;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -38,10 +44,12 @@ import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsHelper;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.PowerProfile;
+import com.android.server.FgThread;
import com.android.server.LocalServices;
import java.io.File;
@@ -59,15 +67,52 @@ public final class BatteryStatsService extends IBatteryStats.Stub
static final String TAG = "BatteryStatsService";
static IBatteryStats sService;
-
final BatteryStatsImpl mStats;
+ final BatteryStatsHandler mHandler;
Context mContext;
private boolean mBluetoothPendingStats;
private BluetoothHeadset mBluetoothHeadset;
PowerManagerInternal mPowerManagerInternal;
+ class BatteryStatsHandler extends Handler implements BatteryStatsImpl.ExternalStatsSync {
+ public static final int MSG_SYNC_EXTERNAL_STATS = 1;
+ public static final int MSG_WRITE_TO_DISK = 2;
+
+ public BatteryStatsHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_SYNC_EXTERNAL_STATS:
+ updateExternalStats();
+ break;
+
+ case MSG_WRITE_TO_DISK:
+ updateExternalStats();
+ synchronized (mStats) {
+ mStats.writeAsyncLocked();
+ }
+ break;
+ }
+ }
+
+ @Override
+ public void scheduleSync() {
+ if (!hasMessages(MSG_SYNC_EXTERNAL_STATS)) {
+ sendEmptyMessage(MSG_SYNC_EXTERNAL_STATS);
+ }
+ }
+ }
+
BatteryStatsService(File systemDir, Handler handler) {
- mStats = new BatteryStatsImpl(systemDir, handler);
+ // Our handler here will be accessing the disk, use a different thread than
+ // what the ActivityManagerService gave us (no I/O on that one!).
+ mHandler = new BatteryStatsHandler(FgThread.getHandler().getLooper());
+
+ // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
+ mStats = new BatteryStatsImpl(systemDir, handler, mHandler);
}
public void publish(Context context) {
@@ -92,6 +137,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void shutdown() {
Slog.w("BatteryStats", "Writing battery stats before shutdown...");
+
+ updateExternalStats();
synchronized (mStats) {
mStats.shutdownLocked();
}
@@ -122,6 +169,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return mStats;
}
+ /**
+ * Schedules a write to disk to occur. This will cause the BatteryStatsImpl
+ * object to update with the latest info, then write to disk.
+ */
+ public void scheduleWriteToDisk() {
+ mHandler.sendEmptyMessage(BatteryStatsHandler.MSG_WRITE_TO_DISK);
+ }
+
// These are for direct use by the activity manager...
void addIsolatedUid(int isolatedUid, int appUid) {
@@ -174,7 +229,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
- mStats.writeToParcel(out, 0);
+ updateExternalStats();
+ synchronized (mStats) {
+ mStats.writeToParcel(out, 0);
+ }
byte[] data = out.marshall();
out.recycle();
return data;
@@ -186,7 +244,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub
//Slog.i("foo", "SENDING BATTERY INFO:");
//mStats.dumpLocked(new LogPrinter(Log.INFO, "foo", Log.LOG_ID_SYSTEM));
Parcel out = Parcel.obtain();
- mStats.writeToParcel(out, 0);
+ updateExternalStats();
+ synchronized (mStats) {
+ mStats.writeToParcel(out, 0);
+ }
byte[] data = out.marshall();
out.recycle();
try {
@@ -663,6 +724,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ @Override
public void noteWifiMulticastDisabledFromSource(WorkSource ws) {
enforceCallingPermission();
synchronized (mStats) {
@@ -671,10 +733,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
@Override
- public void noteNetworkInterfaceType(String iface, int type) {
+ public void noteNetworkInterfaceType(String iface, int networkType) {
enforceCallingPermission();
synchronized (mStats) {
- mStats.noteNetworkInterfaceTypeLocked(iface, type);
+ mStats.noteNetworkInterfaceTypeLocked(iface, networkType);
}
}
@@ -715,7 +777,22 @@ public final class BatteryStatsService extends IBatteryStats.Stub
public void setBatteryState(int status, int health, int plugType, int level,
int temp, int volt) {
enforceCallingPermission();
- mStats.setBatteryState(status, health, plugType, level, temp, volt);
+ synchronized (mStats) {
+ final boolean onBattery = plugType == BatteryStatsImpl.BATTERY_PLUGGED_NONE;
+ if (mStats.isOnBattery() == onBattery) {
+ // The battery state has not changed, so we don't need to sync external
+ // stats immediately.
+ mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
+ return;
+ }
+ }
+
+ // Sync external stats first as the battery has changed states. If we don't sync
+ // immediately here, we may not collect the relevant data later.
+ updateExternalStats();
+ synchronized (mStats) {
+ mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt);
+ }
}
public long getAwakeTimeBattery() {
@@ -772,12 +849,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
private void dumpHelp(PrintWriter pw) {
pw.println("Battery stats (batterystats) dump options:");
- pw.println(" [--checkin] [--history] [--history-start] [--unplugged] [--charged] [-c]");
+ pw.println(" [--checkin] [--history] [--history-start] [--charged] [-c]");
pw.println(" [--daily] [--reset] [--write] [--new-daily] [--read-daily] [-h] [<package.name>]");
pw.println(" --checkin: format output for a checkin report.");
pw.println(" --history: show only history data.");
pw.println(" --history-start <num>: show only history data starting at given time offset.");
- pw.println(" --unplugged: only output data since last unplugged.");
pw.println(" --charged: only output data since last charged.");
pw.println(" --daily: only output full daily data.");
pw.println(" --reset: reset the stats, clearing all current data.");
@@ -818,6 +894,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return i;
}
+
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
@@ -856,8 +933,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub
} else if ("-c".equals(arg)) {
useCheckinFormat = true;
flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
- } else if ("--unplugged".equals(arg)) {
- flags |= BatteryStats.DUMP_UNPLUGGED_ONLY;
} else if ("--charged".equals(arg)) {
flags |= BatteryStats.DUMP_CHARGED_ONLY;
} else if ("--daily".equals(arg)) {
@@ -868,7 +943,9 @@ public final class BatteryStatsService extends IBatteryStats.Stub
pw.println("Battery stats reset.");
noOutput = true;
}
+ updateExternalStats();
} else if ("--write".equals(arg)) {
+ updateExternalStats();
synchronized (mStats) {
mStats.writeSyncLocked();
pw.println("Battery stats written.");
@@ -931,13 +1008,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
if (reqUid >= 0) {
// By default, if the caller is only interested in a specific package, then
// we only dump the aggregated data since charged.
- if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_UNPLUGGED_ONLY
- |BatteryStats.DUMP_CHARGED_ONLY)) == 0) {
+ if ((flags&(BatteryStats.DUMP_HISTORY_ONLY|BatteryStats.DUMP_CHARGED_ONLY)) == 0) {
flags |= BatteryStats.DUMP_CHARGED_ONLY;
// Also if they are doing -c, we don't want history.
flags &= ~BatteryStats.DUMP_INCLUDE_HISTORY;
}
}
+
+ // Fetch data from external sources and update the BatteryStatsImpl object with them.
+ updateExternalStats();
+
if (useCheckinFormat) {
List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
if (isRealCheckin) {
@@ -952,7 +1032,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
in.unmarshall(raw, 0, raw.length);
in.setDataPosition(0);
BatteryStatsImpl checkinStats = new BatteryStatsImpl(
- null, mStats.mHandler);
+ null, mStats.mHandler, null);
checkinStats.readSummaryFromParcel(in);
in.recycle();
checkinStats.dumpCheckinLocked(mContext, pw, apps, flags,
@@ -982,4 +1062,85 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
}
+
+ // Objects for extracting data from external sources.
+ private final Object mExternalStatsLock = new Object();
+
+ @GuardedBy("mExternalStatsLock")
+ private IWifiManager mWifiManager;
+
+ // WiFi keeps an accumulated total of stats, unlike Bluetooth.
+ // Keep the last WiFi stats so we can compute a delta.
+ @GuardedBy("mExternalStatsLock")
+ private WifiActivityEnergyInfo mLastInfo = new WifiActivityEnergyInfo(0, 0, 0, 0, 0, 0);
+
+ @GuardedBy("mExternalStatsLock")
+ private WifiActivityEnergyInfo pullWifiEnergyInfoLocked() {
+ if (mWifiManager == null) {
+ mWifiManager = IWifiManager.Stub.asInterface(
+ ServiceManager.getService(Context.WIFI_SERVICE));
+ if (mWifiManager == null) {
+ return null;
+ }
+ }
+
+ try {
+ // We read the data even if we are not on battery. This is so that we keep the
+ // correct delta from when we should start reading (aka when we are on battery).
+ WifiActivityEnergyInfo info = mWifiManager.reportActivityInfo();
+ if (info != null && info.isValid()) {
+ // We will modify the last info object to be the delta, and store the new
+ // WifiActivityEnergyInfo object as our last one.
+ final WifiActivityEnergyInfo result = mLastInfo;
+ result.mTimestamp = info.getTimeStamp();
+ result.mStackState = info.getStackState();
+ result.mControllerTxTimeMs =
+ info.getControllerTxTimeMillis()- mLastInfo.mControllerTxTimeMs;
+ result.mControllerRxTimeMs =
+ info.getControllerRxTimeMillis() - mLastInfo.mControllerRxTimeMs;
+ result.mControllerIdleTimeMs =
+ info.getControllerIdleTimeMillis() - mLastInfo.mControllerIdleTimeMs;
+ result.mControllerEnergyUsed =
+ info.getControllerEnergyUsed() - mLastInfo.mControllerEnergyUsed;
+ mLastInfo = info;
+ return result;
+ }
+ } catch (RemoteException e) {
+ // Nothing to report, WiFi is dead.
+ }
+ return null;
+ }
+
+ @GuardedBy("mExternalStatsLock")
+ private BluetoothActivityEnergyInfo pullBluetoothEnergyInfoLocked() {
+ BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
+ if (adapter != null) {
+ BluetoothActivityEnergyInfo info = adapter.getControllerActivityEnergyInfo(
+ BluetoothAdapter.ACTIVITY_ENERGY_INFO_REFRESHED);
+ if (info != null && info.isValid()) {
+ return info;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Fetches data from external sources (WiFi controller, bluetooth chipset) and updates
+ * batterystats with that information.
+ *
+ * We first grab a lock specific to this method, then once all the data has been collected,
+ * we grab the mStats lock and update the data.
+ */
+ void updateExternalStats() {
+ synchronized (mExternalStatsLock) {
+ final WifiActivityEnergyInfo wifiEnergyInfo = pullWifiEnergyInfoLocked();
+ final BluetoothActivityEnergyInfo bluetoothEnergyInfo = pullBluetoothEnergyInfoLocked();
+ synchronized (mStats) {
+ mStats.updateKernelWakelocksLocked();
+ mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime());
+ mStats.updateWifiStateLocked(wifiEnergyInfo);
+ mStats.updateBluetoothStateLocked(bluetoothEnergyInfo);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 65b2ae2..1eddc8e 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -234,9 +234,6 @@ public class AudioService extends IAudioService.Stub {
private final Object mSoundEffectsLock = new Object();
private static final int NUM_SOUNDPOOL_CHANNELS = 4;
- // Maximum volume adjust steps allowed in a single batch call.
- private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4;
-
/* Sound effect file names */
private static final String SOUND_EFFECTS_PATH = "/media/audio/ui/";
private static final List<String> SOUND_EFFECT_FILES = new ArrayList<String>();
@@ -988,6 +985,7 @@ public class AudioService extends IAudioService.Stub {
} else {
streamType = getActiveStreamType(suggestedStreamType);
}
+ ensureValidStreamType(streamType);
final int resolvedStream = mStreamVolumeAlias[streamType];
// Play sounds on STREAM_RING only.
@@ -1421,6 +1419,8 @@ public class AudioService extends IAudioService.Stub {
private void sendVolumeUpdate(int streamType, int oldIndex, int index, int flags) {
if (!isPlatformVoice() && (streamType == AudioSystem.STREAM_RING)) {
streamType = AudioSystem.STREAM_NOTIFICATION;
+ } else {
+ streamType = mStreamVolumeAlias[streamType];
}
if (streamType == AudioSystem.STREAM_MUSIC) {
@@ -3131,12 +3131,6 @@ public class AudioService extends IAudioService.Stub {
}
}
- private void ensureValidSteps(int steps) {
- if (Math.abs(steps) > MAX_BATCH_VOLUME_ADJUST_STEPS) {
- throw new IllegalArgumentException("Bad volume adjust steps " + steps);
- }
- }
-
private void ensureValidStreamType(int streamType) {
if (streamType < 0 || streamType >= mStreamStates.length) {
throw new IllegalArgumentException("Bad stream type " + streamType);
@@ -3305,7 +3299,7 @@ public class AudioService extends IAudioService.Stub {
}
private int getDeviceForStream(int stream) {
- int device = AudioSystem.getDevicesForStream(stream);
+ int device = getDevicesForStream(stream);
if ((device & (device - 1)) != 0) {
// Multiple device selection is either:
// - speaker + one other device: give priority to speaker in this case.
@@ -3328,6 +3322,27 @@ public class AudioService extends IAudioService.Stub {
return device;
}
+ private int getDevicesForStream(int stream) {
+ return getDevicesForStream(stream, true /*checkOthers*/);
+ }
+
+ private int getDevicesForStream(int stream, boolean checkOthers) {
+ ensureValidStreamType(stream);
+ synchronized (VolumeStreamState.class) {
+ return mStreamStates[stream].observeDevicesForStream_syncVSS(checkOthers);
+ }
+ }
+
+ private void observeDevicesForStreams(int skipStream) {
+ synchronized (VolumeStreamState.class) {
+ for (int stream = 0; stream < mStreamStates.length; stream++) {
+ if (stream != skipStream) {
+ mStreamStates[stream].observeDevicesForStream_syncVSS(false /*checkOthers*/);
+ }
+ }
+ }
+ }
+
/*
* A class just for packaging up a set of connection parameters.
*/
@@ -3406,9 +3421,11 @@ public class AudioService extends IAudioService.Stub {
private boolean mIsMuted;
private String mVolumeIndexSettingName;
+ private int mObservedDevices;
private final SparseIntArray mIndexMap = new SparseIntArray(8);
private final Intent mVolumeChanged;
+ private final Intent mStreamDevicesChanged;
private VolumeStreamState(String settingName, int streamType) {
@@ -3422,6 +3439,29 @@ public class AudioService extends IAudioService.Stub {
readSettings();
mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
mVolumeChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+ mStreamDevicesChanged = new Intent(AudioManager.STREAM_DEVICES_CHANGED_ACTION);
+ mStreamDevicesChanged.putExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, mStreamType);
+ }
+
+ public int observeDevicesForStream_syncVSS(boolean checkOthers) {
+ final int devices = AudioSystem.getDevicesForStream(mStreamType);
+ if (devices == mObservedDevices) {
+ return devices;
+ }
+ final int prevDevices = mObservedDevices;
+ mObservedDevices = devices;
+ if (checkOthers) {
+ // one stream's devices have changed, check the others
+ observeDevicesForStreams(mStreamType);
+ }
+ // log base stream changes to the event log
+ if (mStreamVolumeAlias[mStreamType] == mStreamType) {
+ EventLogTags.writeStreamDevicesChanged(mStreamType, prevDevices, devices);
+ }
+ sendBroadcastToAll(mStreamDevicesChanged
+ .putExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, prevDevices)
+ .putExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, devices));
+ return devices;
}
public String getSettingNameForDevice(int device) {
@@ -3716,7 +3756,7 @@ public class AudioService extends IAudioService.Stub {
}
pw.println();
pw.print(" Devices: ");
- final int devices = AudioSystem.getDevicesForStream(mStreamType);
+ final int devices = getDevicesForStream(mStreamType);
int device, i = 0, n = 0;
// iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive
// (the default device is not returned by getDevicesForStream)
@@ -4250,6 +4290,7 @@ public class AudioService extends IAudioService.Stub {
}
}
mRoutesObservers.finishBroadcast();
+ observeDevicesForStreams(-1);
break;
}
@@ -5348,7 +5389,7 @@ public class AudioService extends IAudioService.Stub {
on ? AudioSystem.FORCE_HDMI_SYSTEM_AUDIO_ENFORCED :
AudioSystem.FORCE_NONE);
}
- device = AudioSystem.getDevicesForStream(AudioSystem.STREAM_MUSIC);
+ device = getDevicesForStream(AudioSystem.STREAM_MUSIC);
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 7f47678..0b430ea 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -1021,6 +1021,14 @@ public class Vpn {
public synchronized LegacyVpnInfo getLegacyVpnInfo() {
// Check if the caller is authorized.
enforceControlPermission();
+ return getLegacyVpnInfoPrivileged();
+ }
+
+ /**
+ * Return the information of the current ongoing legacy VPN.
+ * Callers are responsible for checking permissions if needed.
+ */
+ public synchronized LegacyVpnInfo getLegacyVpnInfoPrivileged() {
if (mLegacyVpnRunner == null) return null;
final LegacyVpnInfo info = new LegacyVpnInfo();
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java
index b398f41..ab56b34 100644
--- a/services/core/java/com/android/server/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java
@@ -16,6 +16,7 @@
package com.android.server.fingerprint;
+import android.content.ContentResolver;
import android.content.Context;
import android.os.Handler;
import android.os.IBinder;
@@ -29,12 +30,16 @@ import android.util.Slog;
import com.android.server.SystemService;
import android.service.fingerprint.FingerprintUtils;
+import android.service.fingerprint.Fingerprint;
import android.service.fingerprint.IFingerprintService;
import android.service.fingerprint.IFingerprintServiceReceiver;
+
import static android.Manifest.permission.MANAGE_FINGERPRINT;
import static android.Manifest.permission.USE_FINGERPRINT;
import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
/**
* A service to manage multiple clients that want to access the fingerprint HAL API.
@@ -50,11 +55,14 @@ public class FingerprintService extends SystemService {
private static final int MSG_NOTIFY = 10;
+ private static final int ENROLLMENT_TIMEOUT_MS = 60 * 1000; // 1 minute
+
Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_NOTIFY:
- handleNotify(msg.arg1, msg.arg2, (Integer) msg.obj);
+ FpHalMsg m = (FpHalMsg) msg.obj;
+ handleNotify(m.type, m.arg1, m.arg2, m.arg3);
break;
default:
@@ -66,7 +74,7 @@ public class FingerprintService extends SystemService {
private int mHalDeviceId;
private static final int STATE_IDLE = 0;
- private static final int STATE_LISTENING = 1;
+ private static final int STATE_AUTHENTICATING = 1;
private static final int STATE_ENROLLING = 2;
private static final int STATE_REMOVING = 3;
private static final long MS_PER_SEC = 1000;
@@ -76,7 +84,10 @@ public class FingerprintService extends SystemService {
int state;
int userId;
public TokenWatcher tokenWatcher;
- IBinder getToken() { return tokenWatcher.getToken(); }
+
+ IBinder getToken() {
+ return tokenWatcher.getToken();
+ }
}
private class TokenWatcher implements IBinder.DeathRecipient {
@@ -86,7 +97,10 @@ public class FingerprintService extends SystemService {
this.token = new WeakReference<IBinder>(token);
}
- IBinder getToken() { return token.get(); }
+ IBinder getToken() {
+ return token.get();
+ }
+
public void binderDied() {
mClients.remove(token);
this.token = null;
@@ -112,21 +126,42 @@ public class FingerprintService extends SystemService {
// TODO: Move these into separate process
// JNI methods to communicate from FingerprintManagerService to HAL
- static native int nativeEnroll(int timeout);
+ static native int nativeEnroll(int timeout, int groupId);
+
+ static native int nativeAuthenticate(long sessionId, int groupId);
+
static native int nativeEnrollCancel();
- static native int nativeRemove(int fingerprintId);
+
+ static native int nativeRemove(int fingerId, int groupId);
+
static native int nativeOpenHal();
+
static native int nativeCloseHal();
+
static native void nativeInit(MessageQueue queue, FingerprintService service);
+ static final class FpHalMsg {
+ int type; // Type of the message. One of the constants in fingerprint.h
+ int arg1; // optional arguments
+ int arg2;
+ int arg3;
+
+ FpHalMsg(int type, int arg1, int arg2, int arg3) {
+ this.type = type;
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ this.arg3 = arg3;
+ }
+ }
+
// JNI methods for communicating from HAL to clients
- void notify(int msg, int arg1, int arg2) {
- mHandler.obtainMessage(MSG_NOTIFY, msg, arg1, arg2).sendToTarget();
+ void notify(int type, int arg1, int arg2, int arg3) {
+ mHandler.obtainMessage(MSG_NOTIFY, new FpHalMsg(type, arg1, arg2, arg3)).sendToTarget();
}
- void handleNotify(int msg, int arg1, int arg2) {
- Slog.v(TAG, "handleNotify(msg=" + msg + ", arg1=" + arg1 + ", arg2=" + arg2 + ")"
- + ", " + mClients.size() + " clients");
+ void handleNotify(int type, int arg1, int arg2, int arg3) {
+ Slog.v(TAG, "handleNotify(type=" + type + ", arg1=" + arg1 + ", arg2=" + arg2 + ")" + ", "
+ + mClients.size() + " clients");
for (int i = 0; i < mClients.size(); i++) {
if (DEBUG) Slog.v(TAG, "Client[" + i + "] binder token: " + mClients.keyAt(i));
ClientData clientData = mClients.valueAt(i);
@@ -134,21 +169,20 @@ public class FingerprintService extends SystemService {
if (DEBUG) Slog.v(TAG, "clientData is invalid!!");
continue;
}
- switch (msg) {
+ ContentResolver contentResolver = mContext.getContentResolver();
+ switch (type) {
case FingerprintManager.FINGERPRINT_ERROR: {
- final int error = arg1;
try {
- clientData.receiver.onError(error);
+ clientData.receiver.onError(mHalDeviceId, arg1 /* error */);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
mClients.remove(mClients.keyAt(i));
}
}
- break;
+ break;
case FingerprintManager.FINGERPRINT_ACQUIRED: {
- final int acquireInfo = arg1;
try {
- clientData.receiver.onAcquired(acquireInfo);
+ clientData.receiver.onAcquired(mHalDeviceId, arg1 /* acquireInfo */);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
mClients.remove(mClients.keyAt(i));
@@ -156,9 +190,9 @@ public class FingerprintService extends SystemService {
break;
}
case FingerprintManager.FINGERPRINT_PROCESSED: {
- final int fingerId = arg1;
try {
- clientData.receiver.onProcessed(fingerId);
+ clientData.receiver
+ .onProcessed(mHalDeviceId, arg1 /* fingerId */, arg2 /* groupId */);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
mClients.remove(mClients.keyAt(i));
@@ -167,11 +201,13 @@ public class FingerprintService extends SystemService {
}
case FingerprintManager.FINGERPRINT_TEMPLATE_ENROLLING: {
final int fingerId = arg1;
- final int remaining = arg2;
+ final int groupId = arg2;
+ final int remaining = arg3;
if (clientData.state == STATE_ENROLLING) {
// Only send enroll updates to clients that are actually enrolling
try {
- clientData.receiver.onEnrollResult(fingerId, remaining);
+ clientData.receiver.onEnrollResult(mHalDeviceId, fingerId, groupId,
+ remaining);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
mClients.remove(mClients.keyAt(i));
@@ -179,8 +215,8 @@ public class FingerprintService extends SystemService {
// Update the database with new finger id.
// TODO: move to client code (Settings)
if (remaining == 0) {
- FingerprintUtils.addFingerprintIdForUser(fingerId,
- mContext.getContentResolver(), clientData.userId);
+ FingerprintUtils.addFingerprintIdForUser(contentResolver, fingerId,
+ clientData.userId);
clientData.state = STATE_IDLE; // Nothing left to do
}
} else {
@@ -191,30 +227,50 @@ public class FingerprintService extends SystemService {
}
case FingerprintManager.FINGERPRINT_TEMPLATE_REMOVED: {
int fingerId = arg1;
- if (fingerId == 0) throw new IllegalStateException("Got illegal id from HAL");
- FingerprintUtils.removeFingerprintIdForUser(fingerId,
- mContext.getContentResolver(), clientData.userId);
+ int groupId = arg2;
+ if (fingerId == 0) {
+ throw new IllegalStateException("Got illegal id from HAL");
+ }
+ FingerprintUtils.removeFingerprintIdForUser(fingerId, contentResolver,
+ clientData.userId);
if (clientData.receiver != null) {
try {
- clientData.receiver.onRemoved(fingerId);
+ clientData.receiver.onRemoved(mHalDeviceId, fingerId, groupId);
} catch (RemoteException e) {
Slog.e(TAG, "can't send message to client. Did it die?", e);
mClients.remove(mClients.keyAt(i));
}
}
- clientData.state = STATE_LISTENING;
+ clientData.state = STATE_IDLE;
}
- break;
+ break;
}
}
}
- void startEnroll(IBinder token, long timeout, int userId) {
+ void startEnroll(IBinder token, int groupId, int flags) {
ClientData clientData = mClients.get(token);
if (clientData != null) {
- if (clientData.userId != userId) throw new IllegalStateException("Bad user");
+ if (clientData.userId != groupId) {
+ throw new IllegalStateException("Bad user");
+ }
clientData.state = STATE_ENROLLING;
- nativeEnroll((int) (timeout / MS_PER_SEC));
+ final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
+ nativeEnroll(timeout, groupId);
+ } else {
+ Slog.w(TAG, "enroll(): No listener registered");
+ }
+ }
+
+ void startAuthenticate(IBinder token, long sessionId, int groupId, int flags) {
+ ClientData clientData = mClients.get(token);
+ if (clientData != null) {
+ if (clientData.userId != groupId) {
+ throw new IllegalStateException("Bad user");
+ }
+ clientData.state = STATE_AUTHENTICATING;
+ final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
+ nativeAuthenticate(sessionId, groupId);
} else {
Slog.w(TAG, "enroll(): No listener registered");
}
@@ -224,7 +280,7 @@ public class FingerprintService extends SystemService {
ClientData clientData = mClients.get(token);
if (clientData != null) {
if (clientData.userId != userId) throw new IllegalStateException("Bad user");
- clientData.state = STATE_LISTENING;
+ clientData.state = STATE_IDLE;
nativeEnrollCancel();
} else {
Slog.w(TAG, "enrollCancel(): No listener registered");
@@ -238,7 +294,7 @@ public class FingerprintService extends SystemService {
if (clientData.userId != userId) throw new IllegalStateException("Bad user");
clientData.state = STATE_REMOVING;
// The fingerprint id will be removed when we get confirmation from the HAL
- int result = nativeRemove(fingerId);
+ int result = nativeRemove(fingerId, userId);
if (result != 0) {
Slog.w(TAG, "Error removing fingerprint with id = " + fingerId);
}
@@ -251,7 +307,7 @@ public class FingerprintService extends SystemService {
if (DEBUG) Slog.v(TAG, "startListening(" + receiver + ")");
if (mClients.get(token) == null) {
ClientData clientData = new ClientData();
- clientData.state = STATE_LISTENING;
+ clientData.state = STATE_IDLE;
clientData.receiver = receiver;
clientData.userId = userId;
clientData.tokenWatcher = new TokenWatcher(token);
@@ -266,7 +322,7 @@ public class FingerprintService extends SystemService {
}
}
- void removeListener(IBinder token, int userId) {
+ void removeListener(IBinder token, IFingerprintServiceReceiver receiver) {
if (DEBUG) Slog.v(TAG, "stopListening(" + token + ")");
ClientData clientData = mClients.get(token);
if (clientData != null) {
@@ -278,61 +334,91 @@ public class FingerprintService extends SystemService {
mClients.remove(token);
}
+ public List<Fingerprint> getEnrolledFingerprints(int groupId) {
+ ContentResolver resolver = mContext.getContentResolver();
+ int[] ids = FingerprintUtils.getFingerprintIdsForUser(resolver, groupId);
+ List<Fingerprint> result = new ArrayList<Fingerprint>();
+ for (int i = 0; i < ids.length; i++) {
+ // TODO: persist names in Settings
+ CharSequence name = "Finger" + ids[i];
+ final int group = 0; // TODO
+ final int fingerId = ids[i];
+ final long deviceId = 0; // TODO
+ Fingerprint item = new Fingerprint(name, 0, ids[i], 0);
+ result.add(item);
+ }
+ return result;
+ }
+
void checkPermission(String permission) {
- getContext().enforceCallingOrSelfPermission(permission, "Must have "
- + permission + " permission.");
+ getContext().enforceCallingOrSelfPermission(permission,
+ "Must have " + permission + " permission.");
}
private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
- @Override // Binder call
- public void enroll(IBinder token, long timeout, int userId) {
+ @Override
+ // Binder call
+ public void enroll(IBinder token, int groupId, int flags) {
checkPermission(MANAGE_FINGERPRINT);
- startEnroll(token, timeout, userId);
+ startEnroll(token, groupId, flags);
}
- @Override // Binder call
- public void enrollCancel(IBinder token,int userId) {
- checkPermission(MANAGE_FINGERPRINT);
- startEnrollCancel(token, userId);
+ @Override
+ // Binder call
+ public void authenticate(IBinder token, long sessionId, int groupId, int flags) {
+ checkPermission(USE_FINGERPRINT);
+ startAuthenticate(token, sessionId, groupId, flags);
}
- @Override // Binder call
- public void remove(IBinder token, int fingerprintId, int userId) {
+ @Override
+ // Binder call
+ public void remove(IBinder token, int fingerId, int groupId) {
checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
- startRemove(token, fingerprintId, userId);
+ startRemove(token, fingerId, groupId);
}
- @Override // Binder call
- public void startListening(IBinder token, IFingerprintServiceReceiver receiver, int userId)
- {
+ @Override
+ // Binder call
+ public void addListener(IBinder token, IFingerprintServiceReceiver receiver, int userId) {
checkPermission(USE_FINGERPRINT);
- addListener(token, receiver, userId);
+ FingerprintService.this.addListener(token, receiver, userId);
}
- @Override // Binder call
- public void stopListening(IBinder token, int userId) {
+ @Override
+ // Binder call
+ public void removeListener(IBinder token, IFingerprintServiceReceiver receiver) {
checkPermission(USE_FINGERPRINT);
- removeListener(token, userId);
+ FingerprintService.this.removeListener(token, receiver);
}
- @Override // Binder call
- public boolean isHardwareDetected() {
+ @Override
+ // Binder call
+ public boolean isHardwareDetected(long deviceId) {
checkPermission(USE_FINGERPRINT);
- return mHalDeviceId != 0;
+ return mHalDeviceId != 0; // TODO
}
@Override
- public void rename(int fpId, String name) {
+ // Binder call
+ public void rename(int fingerId, int groupId, String name) {
checkPermission(MANAGE_FINGERPRINT);
+ Slog.w(TAG, "rename id=" + fingerId + ",gid=" + groupId + ",name=" + name);
// TODO
}
+
+ @Override
+ // Binder call
+ public List<Fingerprint> getEnrolledFingerprints(int groupId) {
+ checkPermission(USE_FINGERPRINT);
+ return FingerprintService.this.getEnrolledFingerprints(groupId);
+ }
}
@Override
public void onStart() {
- publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
- mHalDeviceId = nativeOpenHal();
- if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
+ publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
+ mHalDeviceId = nativeOpenHal();
+ if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
index 70fa441..89ffe45 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDevicePlayback.java
@@ -192,6 +192,13 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
}
}
+ @ServiceThreadOnly
+ protected boolean handleUserControlPressed(HdmiCecMessage message) {
+ assertRunOnServiceThread();
+ wakeUpIfActiveSource();
+ return super.handleUserControlPressed(message);
+ }
+
@Override
@ServiceThreadOnly
protected boolean handleSetStreamPath(HdmiCecMessage message) {
@@ -229,7 +236,12 @@ final class HdmiCecLocalDevicePlayback extends HdmiCecLocalDevice {
}
private void wakeUpIfActiveSource() {
- if (mIsActiveSource && mService.isPowerStandbyOrTransient()) {
+ if (!mIsActiveSource) {
+ return;
+ }
+ // Wake up the device if the power is in standby mode, or its screen is off -
+ // which can happen if the device is holding a partial lock.
+ if (mService.isPowerStandbyOrTransient() || !mService.getPowerManager().isScreenOn()) {
mService.wakeUp();
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 7c93e56..d5cb5e3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -251,7 +251,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
int targetAddress = targetDevice.getLogicalAddress();
ActiveSource active = getActiveSource();
- if (active.isValid() && targetAddress == active.logicalAddress) {
+ if (targetDevice.getDevicePowerStatus() == HdmiControlManager.POWER_STATUS_ON
+ && active.isValid()
+ && targetAddress == active.logicalAddress) {
invokeCallback(callback, HdmiControlManager.RESULT_SUCCESS);
return;
}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index cbbf91b..75a79cb 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -58,14 +58,16 @@ abstract class RequestArcAction extends HdmiCecFeatureAction {
// received without <Request ARC Initiation> or <Request ARC Termination>.
case Constants.MESSAGE_FEATURE_ABORT:
int originalOpcode = cmd.getParams()[0] & 0xFF;
- if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_INITIATION
- || originalOpcode == Constants.MESSAGE_REQUEST_ARC_TERMINATION) {
+ if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_TERMINATION) {
disableArcTransmission();
finish();
return true;
- } else {
- return false;
+ } else if (originalOpcode == Constants.MESSAGE_REQUEST_ARC_INITIATION) {
+ tv().setArcStatus(false);
+ finish();
+ return true;
}
+ return false;
}
return false;
}
@@ -82,7 +84,7 @@ abstract class RequestArcAction extends HdmiCecFeatureAction {
if (mState != state || state != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
return;
}
- HdmiLogger.debug("[T]RequestArcAction.");
+ HdmiLogger.debug("[T] RequestArcAction.");
disableArcTransmission();
finish();
}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
index d9e1f24..f69f975 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcInitiationAction.java
@@ -35,6 +35,7 @@ final class RequestArcInitiationAction extends RequestArcAction {
@Override
boolean start() {
+ // Seq #38
mState = STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE;
addTimer(mState, HdmiConfig.TIMEOUT_MS);
@@ -44,9 +45,8 @@ final class RequestArcInitiationAction extends RequestArcAction {
@Override
public void onSendCompleted(int error) {
if (error != Constants.SEND_RESULT_SUCCESS) {
- // If failed to send <Request ARC Initiation>, start "Disabled"
- // ARC transmission action.
- disableArcTransmission();
+ // Turn off ARC status if <Request ARC Initiation> fails.
+ tv().setArcStatus(false);
finish();
}
}
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index bffa854..d200d35 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -52,6 +52,7 @@ final class SetArcTransmissionStateAction extends HdmiCecFeatureAction {
@Override
boolean start() {
+ // Seq #37.
if (mEnabled) {
// Enable ARC status immediately after sending <Report Arc Initiated>.
// If AVR responds with <Feature Abort>, disable ARC status again.
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index fe1260d..d79b5fd 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -41,6 +41,7 @@ import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
@@ -109,21 +110,22 @@ public class JobSchedulerService extends com.android.server.SystemService
* Track Services that have currently active or pending jobs. The index is provided by
* {@link JobStatus#getServiceToken()}
*/
- final List<JobServiceContext> mActiveServices = new ArrayList<JobServiceContext>();
+ final List<JobServiceContext> mActiveServices = new ArrayList<>();
/** List of controllers that will notify this service of updates to jobs. */
List<StateController> mControllers;
/**
* Queue of pending jobs. The JobServiceContext class will receive jobs from this list
* when ready to execute them.
*/
- final ArrayList<JobStatus> mPendingJobs = new ArrayList<JobStatus>();
+ final ArrayList<JobStatus> mPendingJobs = new ArrayList<>();
- final ArrayList<Integer> mStartedUsers = new ArrayList();
+ final ArrayList<Integer> mStartedUsers = new ArrayList<>();
final JobHandler mHandler;
final JobSchedulerStub mJobSchedulerStub;
IBatteryStats mBatteryStats;
+ PowerManager mPowerManager;
/**
* Set to true once we are allowed to run third party apps.
@@ -131,6 +133,11 @@ public class JobSchedulerService extends com.android.server.SystemService
boolean mReadyToRock;
/**
+ * True when in device idle mode, so we don't want to schedule any jobs.
+ */
+ boolean mDeviceIdleMode;
+
+ /**
* Cleans up outstanding jobs when a package is removed. Even if it's being replaced later we
* still clean up. On reinstall the package will have a new uid.
*/
@@ -154,6 +161,8 @@ public class JobSchedulerService extends com.android.server.SystemService
Slog.d(TAG, "Removing jobs for user: " + userId);
}
cancelJobsForUser(userId);
+ } else if (PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
+ updateIdleMode(mPowerManager != null ? mPowerManager.isDeviceIdleMode() : false);
}
}
};
@@ -199,7 +208,7 @@ public class JobSchedulerService extends com.android.server.SystemService
return outList;
}
- private void cancelJobsForUser(int userHandle) {
+ void cancelJobsForUser(int userHandle) {
List<JobStatus> jobsForUser;
synchronized (mJobs) {
jobsForUser = mJobs.getJobsByUser(userHandle);
@@ -257,6 +266,40 @@ public class JobSchedulerService extends com.android.server.SystemService
}
}
+ void updateIdleMode(boolean enabled) {
+ boolean changed = false;
+ boolean rocking;
+ synchronized (mJobs) {
+ if (mDeviceIdleMode != enabled) {
+ changed = true;
+ }
+ rocking = mReadyToRock;
+ }
+ if (changed) {
+ if (rocking) {
+ for (int i=0; i<mControllers.size(); i++) {
+ mControllers.get(i).deviceIdleModeChanged(enabled);
+ }
+ }
+ synchronized (mJobs) {
+ mDeviceIdleMode = enabled;
+ if (enabled) {
+ // When becoming idle, make sure no jobs are actively running.
+ for (int i=0; i<mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
+ final JobStatus executing = jsc.getRunningJob();
+ if (executing != null) {
+ jsc.cancelExecutingJob();
+ }
+ }
+ } else {
+ // When coming out of idle, allow thing to start back up.
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
+ }
+ }
+ }
+ }
+
/**
* Initializes the system service.
* <p>
@@ -294,8 +337,10 @@ public class JobSchedulerService extends com.android.server.SystemService
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
+ userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
+ mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE);
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mJobs) {
// Let's go!
@@ -313,6 +358,7 @@ public class JobSchedulerService extends com.android.server.SystemService
for (int i=0; i<jobs.size(); i++) {
JobStatus job = jobs.valueAt(i);
for (int controller=0; controller<mControllers.size(); controller++) {
+ mControllers.get(controller).deviceIdleModeChanged(mDeviceIdleMode);
mControllers.get(controller).maybeStartTrackingJob(job);
}
}
@@ -667,6 +713,10 @@ public class JobSchedulerService extends com.android.server.SystemService
*/
private void maybeRunPendingJobsH() {
synchronized (mJobs) {
+ if (mDeviceIdleMode) {
+ // If device is idle, we will not schedule jobs to run.
+ return;
+ }
Iterator<JobStatus> it = mPendingJobs.iterator();
if (DEBUG) {
Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
@@ -878,6 +928,7 @@ public class JobSchedulerService extends com.android.server.SystemService
}
pw.println();
pw.print("mReadyToRock="); pw.println(mReadyToRock);
+ pw.print("mDeviceIdleMode="); pw.println(mDeviceIdleMode);
}
pw.println();
}
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 7d76fc0..efd1928 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -31,12 +31,17 @@ public abstract class StateController {
protected static final boolean DEBUG = false;
protected Context mContext;
protected StateChangedListener mStateChangedListener;
+ protected boolean mDeviceIdleMode;
public StateController(StateChangedListener stateChangedListener, Context context) {
mStateChangedListener = stateChangedListener;
mContext = context;
}
+ public void deviceIdleModeChanged(boolean enabled) {
+ mDeviceIdleMode = enabled;
+ }
+
/**
* Implement the logic here to decide whether a job should be tracked by this controller.
* This logic is put here so the JobManger can be completely agnostic of Controller logic.
@@ -50,5 +55,4 @@ public abstract class StateController {
public abstract void maybeStopTrackingJob(JobStatus jobStatus);
public abstract void dumpControllerState(PrintWriter pw);
-
}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index b5036db..09d0501 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -40,6 +40,7 @@ import android.media.session.MediaSession;
import android.media.session.ParcelableVolumeInfo;
import android.media.session.PlaybackState;
import android.media.AudioAttributes;
+import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.DeadObjectException;
@@ -887,6 +888,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
}
+ public void playFromUri(Uri uri, Bundle extras) {
+ try {
+ mCb.onPlayFromUri(uri, extras);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Remote failure in playFromUri.", e);
+ }
+ }
+
public void skipToTrack(long id) {
try {
mCb.onSkipToTrack(id);
@@ -1103,6 +1112,11 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
@Override
+ public void playFromUri(Uri uri, Bundle extras) throws RemoteException {
+ mSessionCb.playFromUri(uri, extras);
+ }
+
+ @Override
public void skipToQueueItem(long id) {
mSessionCb.skipToTrack(id);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 8d46775..5de7d42 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -71,7 +71,9 @@ import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UP
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
+import android.Manifest;
import android.app.ActivityManager;
+import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.INotificationManager;
import android.app.IProcessObserver;
@@ -83,6 +85,7 @@ 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;
import android.content.pm.UserInfo;
import android.content.res.Resources;
@@ -2021,6 +2024,17 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
void updateRulesForUidLocked(int uid) {
if (!isUidValidForRules(uid)) return;
+ // quick check: if this uid doesn't have INTERNET permission, it doesn't have
+ // network access anyway, so it is a waste to mess with it here.
+ final IPackageManager ipm = AppGlobals.getPackageManager();
+ try {
+ if (ipm.checkUidPermission(Manifest.permission.INTERNET, uid)
+ != PackageManager.PERMISSION_GRANTED) {
+ return;
+ }
+ } catch (RemoteException e) {
+ }
+
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final boolean uidForeground = isUidForegroundLocked(uid);
diff --git a/services/core/java/com/android/server/net/NetworkStatsCollection.java b/services/core/java/com/android/server/net/NetworkStatsCollection.java
index 20f5f97..a415a84 100644
--- a/services/core/java/com/android/server/net/NetworkStatsCollection.java
+++ b/services/core/java/com/android/server/net/NetworkStatsCollection.java
@@ -22,21 +22,28 @@ import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_REMOVED;
+import static android.net.TrafficStats.UID_TETHERING;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
+import android.net.ConnectivityManager;
import android.net.NetworkIdentity;
import android.net.NetworkStats;
import android.net.NetworkStatsHistory;
import android.net.NetworkTemplate;
import android.net.TrafficStats;
+import android.os.Binder;
+import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.AtomicFile;
+import android.util.IntArray;
import libcore.io.IoUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
+
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
@@ -129,6 +136,23 @@ public class NetworkStatsCollection implements FileRotator.Reader {
return mStartMillis == Long.MAX_VALUE && mEndMillis == Long.MIN_VALUE;
}
+ public int[] getRelevantUids() {
+ final int callerUid = Binder.getCallingUid();
+ IntArray uids = new IntArray();
+ for (int i = 0; i < mStats.size(); i++) {
+ final Key key = mStats.keyAt(i);
+ if (isAccessibleToUser(key.uid, callerUid)) {
+ int j = uids.binarySearch(key.uid);
+
+ if (j < 0) {
+ j = ~j;
+ uids.add(j, key.uid);
+ }
+ }
+ }
+ return uids.toArray();
+ }
+
/**
* Combine all {@link NetworkStatsHistory} in this collection which match
* the requested parameters.
@@ -144,12 +168,21 @@ public class NetworkStatsCollection implements FileRotator.Reader {
*/
public NetworkStatsHistory getHistory(
NetworkTemplate template, int uid, int set, int tag, int fields, long start, long end) {
+ final int callerUid = Binder.getCallingUid();
+ if (!isAccessibleToUser(uid, callerUid)) {
+ throw new SecurityException("Network stats history of uid " + uid
+ + " is forbidden for caller " + callerUid);
+ }
+
final NetworkStatsHistory combined = new NetworkStatsHistory(
- mBucketDuration, estimateBuckets(), fields);
+ mBucketDuration, start == end ? 1 : estimateBuckets(), fields);
+
+ // shortcut when we know stats will be empty
+ if (start == end) return combined;
+
for (int i = 0; i < mStats.size(); i++) {
final Key key = mStats.keyAt(i);
- final boolean setMatches = set == SET_ALL || key.set == set;
- if (key.uid == uid && setMatches && key.tag == tag
+ if (key.uid == uid && NetworkStats.setMatches(set, key.set) && key.tag == tag
&& templateMatches(template, key.ident)) {
final NetworkStatsHistory value = mStats.valueAt(i);
combined.recordHistory(value, start, end);
@@ -166,15 +199,17 @@ public class NetworkStatsCollection implements FileRotator.Reader {
final long now = System.currentTimeMillis();
final NetworkStats stats = new NetworkStats(end - start, 24);
- final NetworkStats.Entry entry = new NetworkStats.Entry();
- NetworkStatsHistory.Entry historyEntry = null;
-
// shortcut when we know stats will be empty
if (start == end) return stats;
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+ NetworkStatsHistory.Entry historyEntry = null;
+
+ final int callerUid = Binder.getCallingUid();
for (int i = 0; i < mStats.size(); i++) {
final Key key = mStats.keyAt(i);
- if (templateMatches(template, key.ident)) {
+ if (templateMatches(template, key.ident) && isAccessibleToUser(key.uid, callerUid)
+ && key.set < NetworkStats.SET_DEBUG_START) {
final NetworkStatsHistory value = mStats.valueAt(i);
historyEntry = value.getValues(start, end, now, historyEntry);
@@ -507,6 +542,7 @@ public class NetworkStatsCollection implements FileRotator.Reader {
final NetworkStatsHistory value = mStats.valueAt(i);
if (!templateMatches(groupTemplate, key.ident)) continue;
+ if (key.set >= NetworkStats.SET_DEBUG_START) continue;
final Key groupKey = new Key(null, key.uid, key.set, key.tag);
NetworkStatsHistory groupHistory = grouped.get(groupKey);
@@ -534,6 +570,12 @@ public class NetworkStatsCollection implements FileRotator.Reader {
}
}
+ private static boolean isAccessibleToUser(int uid, int callerUid) {
+ return callerUid == android.os.Process.SYSTEM_UID ||
+ uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED || uid == UID_TETHERING
+ || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
+ }
+
/**
* Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
* in the given {@link NetworkIdentitySet}.
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 0b596aa..50e03a2 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -62,9 +62,13 @@ import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
+import android.Manifest;
import android.app.AlarmManager;
+import android.app.AppOpsManager;
import android.app.IAlarmManager;
import android.app.PendingIntent;
+import android.app.admin.DeviceAdminInfo;
+import android.app.admin.DevicePolicyManagerInternal;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -93,7 +97,9 @@ import android.os.HandlerThread;
import android.os.INetworkManagementService;
import android.os.Message;
import android.os.PowerManager;
+import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -116,6 +122,7 @@ import com.android.internal.util.ArrayUtils;
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.connectivity.Tethering;
import java.io.File;
@@ -429,7 +436,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public INetworkStatsSession openSession() {
- mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ return openSessionForUsageStats(null);
+ }
+
+ @Override
+ public INetworkStatsSession openSessionForUsageStats(final String callingPackage) {
assertBandwidthControlEnabled();
// return an IBinder which holds strong references to any loaded stats
@@ -438,6 +449,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return new INetworkStatsSession.Stub() {
private NetworkStatsCollection mUidComplete;
private NetworkStatsCollection mUidTagComplete;
+ private String mCallingPackage = callingPackage;
private NetworkStatsCollection getUidComplete() {
synchronized (mStatsLock) {
@@ -458,8 +470,29 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
@Override
+ public int[] getRelevantUids() {
+ enforcePermissionForManagedAdmin(mCallingPackage);
+ return getUidComplete().getRelevantUids();
+ }
+
+ @Override
+ public NetworkStats getDeviceSummaryForNetwork(NetworkTemplate template, long start,
+ long end) {
+ enforcePermission(mCallingPackage);
+ NetworkStats result = new NetworkStats(end - start, 1);
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ result.combineAllValues(internalGetSummaryForNetwork(template, start, end));
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ return result;
+ }
+
+ @Override
public NetworkStats getSummaryForNetwork(
NetworkTemplate template, long start, long end) {
+ enforcePermission(mCallingPackage);
return internalGetSummaryForNetwork(template, start, end);
}
@@ -471,6 +504,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public NetworkStats getSummaryForAllUid(
NetworkTemplate template, long start, long end, boolean includeTags) {
+ enforcePermissionForManagedAdmin(mCallingPackage);
final NetworkStats stats = getUidComplete().getSummary(template, start, end);
if (includeTags) {
final NetworkStats tagStats = getUidTagComplete()
@@ -483,6 +517,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public NetworkStatsHistory getHistoryForUid(
NetworkTemplate template, int uid, int set, int tag, int fields) {
+ enforcePermissionForManagedAdmin(mCallingPackage);
if (tag == TAG_NONE) {
return getUidComplete().getHistory(template, uid, set, tag, fields);
} else {
@@ -498,6 +533,53 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
};
}
+ private boolean hasAppOpsPermission(String callingPackage) {
+ final int callingUid = Binder.getCallingUid();
+ boolean appOpsAllow = false;
+ if (callingPackage != null) {
+ AppOpsManager appOps = (AppOpsManager) mContext.getSystemService(
+ Context.APP_OPS_SERVICE);
+
+ final int mode = appOps.checkOp(AppOpsManager.OP_GET_USAGE_STATS,
+ callingUid, callingPackage);
+ if (mode == AppOpsManager.MODE_DEFAULT) {
+ // The default behavior here is to check if PackageManager has given the app
+ // permission.
+ final int permissionCheck = mContext.checkCallingPermission(
+ Manifest.permission.PACKAGE_USAGE_STATS);
+ appOpsAllow = permissionCheck == PackageManager.PERMISSION_GRANTED;
+ }
+ appOpsAllow = (mode == AppOpsManager.MODE_ALLOWED);
+ }
+ return appOpsAllow;
+ }
+
+ private void enforcePermissionForManagedAdmin(String callingPackage) {
+ boolean hasPermission = hasAppOpsPermission(callingPackage);
+ if (!hasPermission) {
+ // Profile and device owners are exempt from permission checking.
+ final int callingUid = Binder.getCallingUid();
+ final DevicePolicyManagerInternal dpmi = LocalServices.getService(
+ DevicePolicyManagerInternal.class);
+ if (dpmi.isActiveAdminWithPolicy(callingUid, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER)
+ || dpmi.isActiveAdminWithPolicy(callingUid,
+ DeviceAdminInfo.USES_POLICY_DEVICE_OWNER)) {
+ return;
+ }
+ }
+ if (!hasPermission) {
+ mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ }
+ }
+
+ private void enforcePermission(String callingPackage) {
+ boolean appOpsAllow = hasAppOpsPermission(callingPackage);
+ if (!appOpsAllow) {
+ mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
+ }
+ }
+
+
/**
* Return network summary, splicing between DEV and XT stats when
* appropriate.
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2629e48..c7dc74f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -248,8 +248,8 @@ public class PackageManagerService extends IPackageManager.Stub {
private static final boolean DEBUG_DEXOPT = false;
private static final boolean DEBUG_ABI_SELECTION = false;
- private static final boolean RUNTIME_PERMISSIONS_ENABLED =
- SystemProperties.getInt("ro.runtime.premissions.enabled", 0) == 1;
+ static final boolean RUNTIME_PERMISSIONS_ENABLED =
+ SystemProperties.getInt("ro.runtime.permissions.enabled", 0) == 1;
private static final int RADIO_UID = Process.PHONE_UID;
private static final int LOG_UID = Process.LOG_UID;
@@ -275,6 +275,7 @@ public class PackageManagerService extends IPackageManager.Stub {
static final int SCAN_TRUSTED_OVERLAY = 1<<9;
static final int SCAN_DELETE_DATA_ON_FAILURES = 1<<10;
static final int SCAN_REPLACING = 1<<11;
+ static final int SCAN_REQUIRE_KNOWN = 1<<12;
static final int REMOVE_CHATTY = 1<<16;
@@ -339,7 +340,7 @@ public class PackageManagerService extends IPackageManager.Stub {
/** Permission grant: grant the permission as an install permission. */
private static final int GRANT_INSTALL = 2;
- /** Permission grant: grant the permission as a runtime permission. */
+ /** Permission grant: grant the permission as a runtime one. */
private static final int GRANT_RUNTIME = 3;
/** Permission grant: grant as runtime a permission that was granted as an install time one. */
@@ -1348,7 +1349,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mOnlyCore = onlyCore;
mLazyDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
mMetrics = new DisplayMetrics();
- mSettings = new Settings(mContext, mPackages);
+ mSettings = new Settings(mPackages);
mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
@@ -1699,10 +1700,10 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!mOnlyCore) {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
SystemClock.uptimeMillis());
- scanDirLI(mAppInstallDir, 0, scanFlags, 0);
+ scanDirLI(mAppInstallDir, 0, scanFlags | SCAN_REQUIRE_KNOWN, 0);
scanDirLI(mDrmAppPrivateInstallDir, PackageParser.PARSE_FORWARD_LOCK,
- scanFlags, 0);
+ scanFlags | SCAN_REQUIRE_KNOWN, 0);
/**
* Remove disable package settings for any updated system
@@ -1810,7 +1811,14 @@ public class PackageManagerService extends IPackageManager.Stub {
+ mSettings.mInternalSdkPlatform + " to " + mSdkVersion
+ "; regranting permissions for internal storage");
mSettings.mInternalSdkPlatform = mSdkVersion;
-
+
+ // For now runtime permissions are toggled via a system property.
+ if (!RUNTIME_PERMISSIONS_ENABLED) {
+ // Remove the runtime permissions state if the feature
+ // was disabled by flipping the system property.
+ mSettings.deleteRuntimePermissionsFiles();
+ }
+
updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL
| (regrantPermissions
? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
@@ -1842,7 +1850,6 @@ public class PackageManagerService extends IPackageManager.Stub {
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_READY,
SystemClock.uptimeMillis());
-
mRequiredVerifierPackage = getRequiredVerifierLPr();
} // synchronized (mPackages)
} // synchronized (mInstallLock)
@@ -1951,15 +1958,14 @@ public class PackageManagerService extends IPackageManager.Stub {
return null;
}
- PermissionsState permissionsState = ps.getPermissionsState();
+ final PermissionsState permissionsState = ps.getPermissionsState();
final int[] gids = permissionsState.computeGids(userId);
- Set<String> permissions = permissionsState.getPermissions(userId);
-
+ final Set<String> permissions = permissionsState.getPermissions(userId);
final PackageUserState state = ps.readUserState(userId);
+
return PackageParser.generatePackageInfo(p, gids, flags,
- ps.firstInstallTime, ps.lastUpdateTime, permissions,
- state, userId);
+ ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId);
}
@Override
@@ -2696,6 +2702,10 @@ public class PackageManagerService extends IPackageManager.Stub {
@Override
public boolean grantPermission(String packageName, String name, int userId) {
+ if (!RUNTIME_PERMISSIONS_ENABLED) {
+ return false;
+ }
+
if (!sUserManager.exists(userId)) {
return false;
}
@@ -2707,6 +2717,9 @@ public class PackageManagerService extends IPackageManager.Stub {
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"grantPermission");
+ boolean gidsChanged = false;
+ final SettingBase sb;
+
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
if (pkg == null) {
@@ -2720,7 +2733,7 @@ public class PackageManagerService extends IPackageManager.Stub {
enforceDeclaredAsUsedAndRuntimePermission(pkg, bp);
- final SettingBase sb = (SettingBase) pkg.mExtras;
+ sb = (SettingBase) pkg.mExtras;
if (sb == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
@@ -2734,19 +2747,27 @@ public class PackageManagerService extends IPackageManager.Stub {
}
case PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
- killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
+ gidsChanged = true;
} break;
}
// Not critical if that is lost - app has to request again.
mSettings.writeRuntimePermissionsForUserLPr(userId, false);
+ }
- return true;
+ if (gidsChanged) {
+ killSettingPackagesForUser(sb, userId, KILL_APP_REASON_GIDS_CHANGED);
}
+
+ return true;
}
@Override
public boolean revokePermission(String packageName, String name, int userId) {
+ if (!RUNTIME_PERMISSIONS_ENABLED) {
+ return false;
+ }
+
if (!sUserManager.exists(userId)) {
return false;
}
@@ -2758,6 +2779,8 @@ public class PackageManagerService extends IPackageManager.Stub {
enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false,
"revokePermission");
+ final SettingBase sb;
+
synchronized (mPackages) {
final PackageParser.Package pkg = mPackages.get(packageName);
if (pkg == null) {
@@ -2771,7 +2794,7 @@ public class PackageManagerService extends IPackageManager.Stub {
enforceDeclaredAsUsedAndRuntimePermission(pkg, bp);
- final SettingBase sb = (SettingBase) pkg.mExtras;
+ sb = (SettingBase) pkg.mExtras;
if (sb == null) {
throw new IllegalArgumentException("Unknown package: " + packageName);
}
@@ -2783,13 +2806,13 @@ public class PackageManagerService extends IPackageManager.Stub {
return false;
}
- killSettingPackagesForUser(sb, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
-
// Critical, after this call all should never have the permission.
mSettings.writeRuntimePermissionsForUserLPr(userId, true);
-
- return true;
}
+
+ killSettingPackagesForUser(sb, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
+
+ return true;
}
@Override
@@ -5260,6 +5283,28 @@ public class PackageManagerService extends IPackageManager.Stub {
+ " already installed. Skipping duplicate.");
}
+ // If we're only installing presumed-existing packages, require that the
+ // scanned APK is both already known and at the path previously established
+ // for it. Previously unknown packages we pick up normally, but if we have an
+ // a priori expectation about this package's install presence, enforce it.
+ if ((scanFlags & SCAN_REQUIRE_KNOWN) != 0) {
+ PackageSetting known = mSettings.peekPackageLPr(pkg.packageName);
+ if (known != null) {
+ if (DEBUG_PACKAGE_SCANNING) {
+ Log.d(TAG, "Examining " + pkg.codePath
+ + " and requiring known paths " + known.codePathString
+ + " & " + known.resourcePathString);
+ }
+ if (!pkg.applicationInfo.getCodePath().equals(known.codePathString)
+ || !pkg.applicationInfo.getResourcePath().equals(known.resourcePathString)) {
+ throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
+ "Application package " + pkg.packageName
+ + " found at " + pkg.applicationInfo.getCodePath()
+ + " but expected at " + known.codePathString + "; ignoring.");
+ }
+ }
+ }
+
// Initialize package source and resource directories
File destCodeFile = new File(pkg.applicationInfo.getCodePath());
File destResourceFile = new File(pkg.applicationInfo.getResourcePath());
@@ -6968,10 +7013,15 @@ public class PackageManagerService extends IPackageManager.Stub {
PermissionsState permissionsState = ps.getPermissionsState();
PermissionsState origPermissions = permissionsState;
- boolean changedPermission = false;
+ final int[] currentUserIds = UserManagerService.getInstance().getUserIds();
+
+ int[] upgradeUserIds = PermissionsState.USERS_NONE;
+ int[] changedRuntimePermissionUserIds = PermissionsState.USERS_NONE;
+
+ boolean changedInstallPermission = false;
if (replace) {
- ps.permissionsFixed = false;
+ ps.installPermissionsFixed = false;
origPermissions = new PermissionsState(permissionsState);
permissionsState.reset();
}
@@ -7022,17 +7072,33 @@ public class PackageManagerService extends IPackageManager.Stub {
<= Build.VERSION_CODES.LOLLIPOP_MR1) {
// For legacy apps dangerous permissions are install time ones.
grant = GRANT_INSTALL;
- } else if ((pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- // For modern system apps dangerous permissions are install time ones.
- grant = GRANT_INSTALL;
- } else {
+ } else if (ps.isSystem()) {
+ final int[] updatedUserIds = ps.getPermissionsUpdatedForUserIds();
if (origPermissions.hasInstallPermission(bp.name)) {
- // For legacy apps that became modern, install becomes runtime.
+ // If a system app had an install permission, then the app was
+ // upgraded and we grant the permissions as runtime to all users.
+ grant = GRANT_UPGRADE;
+ upgradeUserIds = currentUserIds;
+ } else if (!Arrays.equals(updatedUserIds, currentUserIds)) {
+ // If users changed since the last permissions update for a
+ // system app, we grant the permission as runtime to the new users.
grant = GRANT_UPGRADE;
- } else if (replace) {
- // For upgraded modern apps keep runtime permissions unchanged.
+ upgradeUserIds = currentUserIds;
+ for (int userId : updatedUserIds) {
+ upgradeUserIds = ArrayUtils.removeInt(upgradeUserIds, userId);
+ }
+ } else {
+ // Otherwise, we grant the permission as runtime if the app
+ // already had it, i.e. we preserve runtime permissions.
grant = GRANT_RUNTIME;
}
+ } else if (origPermissions.hasInstallPermission(bp.name)) {
+ // For legacy apps that became modern, install becomes runtime.
+ grant = GRANT_UPGRADE;
+ upgradeUserIds = currentUserIds;
+ } else if (replace) {
+ // For upgraded modern apps keep runtime permissions unchanged.
+ grant = GRANT_RUNTIME;
}
} break;
@@ -7050,7 +7116,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
if (grant != GRANT_DENIED) {
- if (!isSystemApp(ps) && ps.permissionsFixed) {
+ if (!isSystemApp(ps) && ps.installPermissionsFixed) {
// If this is an existing, non-system package, then
// we can't add any new permissions to it.
if (!allowedSig && !origPermissions.hasInstallPermission(perm)) {
@@ -7068,7 +7134,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Grant an install permission.
if (permissionsState.grantInstallPermission(bp) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
- changedPermission = true;
+ changedInstallPermission = true;
}
} break;
@@ -7076,9 +7142,11 @@ public class PackageManagerService extends IPackageManager.Stub {
// Grant previously granted runtime permissions.
for (int userId : UserManagerService.getInstance().getUserIds()) {
if (origPermissions.hasRuntimePermission(bp.name, userId)) {
- if (permissionsState.grantRuntimePermission(bp, userId) !=
+ if (permissionsState.grantRuntimePermission(bp, userId) ==
PermissionsState.PERMISSION_OPERATION_FAILURE) {
- changedPermission = true;
+ // If we cannot put the permission as it was, we have to write.
+ changedRuntimePermissionUserIds = ArrayUtils.appendInt(
+ changedRuntimePermissionUserIds, userId);
}
}
}
@@ -7087,10 +7155,12 @@ public class PackageManagerService extends IPackageManager.Stub {
case GRANT_UPGRADE: {
// Grant runtime permissions for a previously held install permission.
permissionsState.revokeInstallPermission(bp);
- for (int userId : UserManagerService.getInstance().getUserIds()) {
+ for (int userId : upgradeUserIds) {
if (permissionsState.grantRuntimePermission(bp, userId) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
- changedPermission = true;
+ // If we granted the permission, we have to write.
+ changedRuntimePermissionUserIds = ArrayUtils.appendInt(
+ changedRuntimePermissionUserIds, userId);
}
}
} break;
@@ -7107,7 +7177,7 @@ public class PackageManagerService extends IPackageManager.Stub {
} else {
if (permissionsState.revokeInstallPermission(bp) !=
PermissionsState.PERMISSION_OPERATION_FAILURE) {
- changedPermission = true;
+ changedInstallPermission = true;
Slog.i(TAG, "Un-granting permission " + perm
+ " from package " + pkg.packageName
+ " (protectionLevel=" + bp.protectionLevel
@@ -7127,12 +7197,21 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- if ((changedPermission || replace) && !ps.permissionsFixed &&
+ if ((changedInstallPermission || replace) && !ps.installPermissionsFixed &&
!isSystemApp(ps) || isUpdatedSystemApp(ps)){
// This is the first that we have heard about this package, so the
// permissions we have now selected are fixed until explicitly
// changed.
- ps.permissionsFixed = true;
+ ps.installPermissionsFixed = true;
+ }
+
+ ps.setPermissionsUpdatedForUserIds(currentUserIds);
+
+ // Persist the runtime permissions state for users with changes.
+ if (RUNTIME_PERMISSIONS_ENABLED) {
+ for (int userId : changedRuntimePermissionUserIds) {
+ mSettings.writeRuntimePermissionsForUserLPr(userId, true);
+ }
}
}
@@ -10971,15 +11050,18 @@ public class PackageManagerService extends IPackageManager.Stub {
for (int userId : UserManagerService.getInstance().getUserIds()) {
final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
userId);
- if (userIdToKill == userId) {
+ if (userIdToKill == UserHandle.USER_ALL
+ || userIdToKill >= UserHandle.USER_OWNER) {
// If gids changed for this user, kill all affected packages.
- killSettingPackagesForUser(deletedPs, userIdToKill,
- KILL_APP_REASON_GIDS_CHANGED);
- } else if (userIdToKill == UserHandle.USER_ALL) {
- // If gids changed for all users, kill them all - done.
- killSettingPackagesForUser(deletedPs, userIdToKill,
- KILL_APP_REASON_GIDS_CHANGED);
- break;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ // This has to happen with no lock held.
+ killSettingPackagesForUser(deletedPs, userIdToKill,
+ KILL_APP_REASON_GIDS_CHANGED);
+ }
+ });
+ break;
}
}
}
@@ -13359,6 +13441,11 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
+ void newUserCreatedLILPw(int userHandle) {
+ // Adding a user requires updating runtime permissions for system apps.
+ updatePermissionsLPw(null, null, UPDATE_PERMISSIONS_ALL);
+ }
+
@Override
public VerifierDeviceIdentity getVerifierDeviceIdentity() throws RemoteException {
mContext.enforceCallingOrSelfPermission(
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 889164c..a3f4c0b 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -70,4 +70,8 @@ final class PackageSetting extends PackageSettingBase {
public boolean isForwardLocked() {
return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
}
+
+ public boolean isSystem() {
+ return (pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 9e8b3df..35df33b 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -92,7 +92,7 @@ abstract class PackageSettingBase extends SettingBase {
PackageSignatures signatures = new PackageSignatures();
- boolean permissionsFixed;
+ boolean installPermissionsFixed;
PackageKeySetData keySetData = new PackageKeySetData();
@@ -145,7 +145,7 @@ abstract class PackageSettingBase extends SettingBase {
signatures = new PackageSignatures(base.signatures);
- permissionsFixed = base.permissionsFixed;
+ installPermissionsFixed = base.installPermissionsFixed;
userState.clear();
for (int i=0; i<base.userState.size(); i++) {
userState.put(base.userState.keyAt(i),
@@ -198,6 +198,7 @@ abstract class PackageSettingBase extends SettingBase {
* Make a shallow copy of this package settings.
*/
public void copyFrom(PackageSettingBase base) {
+ setPermissionsUpdatedForUserIds(base.getPermissionsUpdatedForUserIds());
getPermissionsState().copyFrom(base.getPermissionsState());
primaryCpuAbiString = base.primaryCpuAbiString;
secondaryCpuAbiString = base.secondaryCpuAbiString;
@@ -206,7 +207,7 @@ abstract class PackageSettingBase extends SettingBase {
firstInstallTime = base.firstInstallTime;
lastUpdateTime = base.lastUpdateTime;
signatures = base.signatures;
- permissionsFixed = base.permissionsFixed;
+ installPermissionsFixed = base.installPermissionsFixed;
userState.clear();
for (int i=0; i<base.userState.size(); i++) {
userState.put(base.userState.keyAt(i), base.userState.valueAt(i));
diff --git a/services/core/java/com/android/server/pm/PermissionsState.java b/services/core/java/com/android/server/pm/PermissionsState.java
index 3e0e342..705abf8 100644
--- a/services/core/java/com/android/server/pm/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/PermissionsState.java
@@ -55,9 +55,9 @@ public final class PermissionsState {
/** The permission operation failed. */
public static final int PERMISSION_OPERATION_FAILURE = 3;
- private static final int[] USERS_ALL = {UserHandle.USER_ALL};
+ public static final int[] USERS_ALL = {UserHandle.USER_ALL};
- private static final int[] USERS_NONE = {};
+ public static final int[] USERS_NONE = {};
private static final int[] NO_GIDS = {};
@@ -149,6 +149,9 @@ public final class PermissionsState {
* #PERMISSION_OPERATION_FAILURE}.
*/
public int grantRuntimePermission(BasePermission permission, int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ return PERMISSION_OPERATION_FAILURE;
+ }
return grantPermission(permission, userId);
}
@@ -162,6 +165,9 @@ public final class PermissionsState {
* #PERMISSION_OPERATION_FAILURE}.
*/
public int revokeRuntimePermission(BasePermission permission, int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ return PERMISSION_OPERATION_FAILURE;
+ }
return revokePermission(permission, userId);
}
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index d350c09..3a7b6ee 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -17,13 +17,15 @@
package com.android.server.pm;
import android.content.pm.ApplicationInfo;
-import android.util.ArraySet;
+
+import java.util.Arrays;
abstract class SettingBase {
int pkgFlags;
int pkgPrivateFlags;
private final PermissionsState mPermissionsState;
+ private int[] mPermissionsUpdatedForUserIds = PermissionsState.USERS_NONE;
SettingBase(int pkgFlags, int pkgPrivateFlags) {
setFlags(pkgFlags);
@@ -35,12 +37,29 @@ abstract class SettingBase {
pkgFlags = base.pkgFlags;
pkgPrivateFlags = base.pkgPrivateFlags;
mPermissionsState = new PermissionsState(base.mPermissionsState);
+ setPermissionsUpdatedForUserIds(base.mPermissionsUpdatedForUserIds);
}
public PermissionsState getPermissionsState() {
return mPermissionsState;
}
+ public int[] getPermissionsUpdatedForUserIds() {
+ return mPermissionsUpdatedForUserIds;
+ }
+
+ public void setPermissionsUpdatedForUserIds(int[] userIds) {
+ if (Arrays.equals(mPermissionsUpdatedForUserIds, userIds)) {
+ return;
+ }
+
+ if (userIds == PermissionsState.USERS_NONE || userIds == PermissionsState.USERS_ALL) {
+ mPermissionsUpdatedForUserIds = userIds;
+ } else {
+ mPermissionsUpdatedForUserIds = Arrays.copyOf(userIds, userIds.length);
+ }
+ }
+
void setFlags(int pkgFlags) {
this.pkgFlags = pkgFlags
& (ApplicationInfo.FLAG_SYSTEM
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 82aa74a..8f185ec 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -25,7 +25,6 @@ import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.os.Process.SYSTEM_UID;
import static android.os.Process.PACKAGE_INFO_GID;
-import android.content.Context;
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
@@ -177,7 +176,6 @@ final class Settings {
private static final String ATTR_BLOCK_UNINSTALL = "blockUninstall";
private final Object mLock;
- private final Context mContext;
private final RuntimePermissionPersistence mRuntimePermissionsPersistence;
@@ -277,12 +275,11 @@ final class Settings {
public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
- Settings(Context context, Object lock) {
- this(context, Environment.getDataDirectory(), lock);
+ Settings(Object lock) {
+ this(Environment.getDataDirectory(), lock);
}
- Settings(Context context, File dataDir, Object lock) {
- mContext = context;
+ Settings(File dataDir, Object lock) {
mLock = lock;
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
@@ -948,6 +945,17 @@ final class Settings {
return new File(userDir, RUNTIME_PERMISSIONS_FILE_NAME);
}
+ boolean isFirstRuntimePermissionsBoot() {
+ return !getUserRuntimePermissionsFile(UserHandle.USER_OWNER).exists();
+ }
+
+ void deleteRuntimePermissionsFiles() {
+ for (int userId : UserManagerService.getInstance().getUserIds()) {
+ File file = getUserRuntimePermissionsFile(userId);
+ file.delete();
+ }
+ }
+
private File getUserPackagesStateBackupFile(int userId) {
return new File(Environment.getUserSystemDirectory(userId),
"package-restrictions-backup.xml");
@@ -2730,6 +2738,18 @@ final class Settings {
}
}
+ // We keep track for which users we granted permissions to be able
+ // to grant runtime permissions to system apps for newly appeared
+ // users or newly appeared system apps. If we supported runtime
+ // permissions during the previous boot, then we already granted
+ // permissions for all device users. In such a case we set the users
+ // for which we granted permissions to avoid clobbering of runtime
+ // permissions we granted to system apps but the user revoked later.
+ if (!isFirstRuntimePermissionsBoot()) {
+ final int[] userIds = UserManagerService.getInstance().getUserIds();
+ ps.setPermissionsUpdatedForUserIds(userIds);
+ }
+
mDisabledSysPackages.put(name, ps);
}
@@ -2990,7 +3010,7 @@ final class Settings {
} else if (tagName.equals(TAG_PERMISSIONS)) {
readInstallPermissionsLPr(parser,
packageSetting.getPermissionsState());
- packageSetting.permissionsFixed = true;
+ packageSetting.installPermissionsFixed = true;
} else if (tagName.equals("proper-signing-keyset")) {
long id = Long.parseLong(parser.getAttributeValue(null, "identifier"));
packageSetting.keySetData.setProperSigningKeySet(id);
@@ -3011,7 +3031,17 @@ final class Settings {
}
}
-
+ // We keep track for which users we granted permissions to be able
+ // to grant runtime permissions to system apps for newly appeared
+ // users or newly appeared system apps. If we supported runtime
+ // permissions during the previous boot, then we already granted
+ // permissions for all device users. In such a case we set the users
+ // for which we granted permissions to avoid clobbering of runtime
+ // permissions we granted to system apps but the user revoked later.
+ if (!isFirstRuntimePermissionsBoot()) {
+ final int[] userIds = UserManagerService.getInstance().getUserIds();
+ packageSetting.setPermissionsUpdatedForUserIds(userIds);
+ }
} else {
XmlUtils.skipCurrentTag(parser);
}
@@ -3129,6 +3159,18 @@ final class Settings {
XmlUtils.skipCurrentTag(parser);
}
}
+
+ // We keep track for which users we granted permissions to be able
+ // to grant runtime permissions to system apps for newly appeared
+ // users or newly appeared system apps. If we supported runtime
+ // permissions during the previous boot, then we already granted
+ // permissions for all device users. In such a case we set the users
+ // for which we granted permissions to avoid clobbering of runtime
+ // permissions we granted to system apps but the user revoked later.
+ if (!isFirstRuntimePermissionsBoot()) {
+ final int[] userIds = UserManagerService.getInstance().getUserIds();
+ su.setPermissionsUpdatedForUserIds(userIds);
+ }
} else {
XmlUtils.skipCurrentTag(parser);
}
@@ -3565,7 +3607,8 @@ final class Settings {
pw.println(ps.installerPackageName);
}
pw.print(prefix); pw.print(" signatures="); pw.println(ps.signatures);
- pw.print(prefix); pw.print(" permissionsFixed="); pw.print(ps.permissionsFixed);
+ pw.print(prefix); pw.print(" installPermissionsFixed=");
+ pw.print(ps.installPermissionsFixed);
pw.print(" installStatus="); pw.println(ps.installStatus);
pw.print(prefix); pw.print(" pkgFlags="); printFlags(pw, ps.pkgFlags, FLAG_DUMP_SPEC);
pw.println();
@@ -3842,11 +3885,19 @@ final class Settings {
}
public void writePermissionsForUserSyncLPr(int userId) {
+ if (!PackageManagerService.RUNTIME_PERMISSIONS_ENABLED) {
+ return;
+ }
+
mHandler.removeMessages(userId);
writePermissionsSync(userId);
}
public void writePermissionsForUserAsyncLPr(int userId) {
+ if (!PackageManagerService.RUNTIME_PERMISSIONS_ENABLED) {
+ return;
+ }
+
final long currentTimeMillis = SystemClock.uptimeMillis();
if (mWriteScheduled.get(userId)) {
@@ -4006,128 +4057,67 @@ final class Settings {
private void parseRuntimePermissionsLPr(XmlPullParser parser, int userId)
throws IOException, XmlPullParserException {
- parser.next();
- skipEmptyTextTags(parser);
- if (!accept(parser, XmlPullParser.START_TAG, TAG_RUNTIME_PERMISSIONS)) {
- return;
- }
-
- parser.next();
-
- while (parsePackageLPr(parser, userId)
- || parseSharedUserLPr(parser, userId)) {
- parser.next();
- }
-
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_RUNTIME_PERMISSIONS);
- }
-
- private boolean parsePackageLPr(XmlPullParser parser, int userId)
- throws IOException, XmlPullParserException {
- skipEmptyTextTags(parser);
- if (!accept(parser, XmlPullParser.START_TAG, TAG_PACKAGE)) {
- return false;
- }
-
- String name = parser.getAttributeValue(null, ATTR_NAME);
-
- parser.next();
-
- PackageSetting ps = mPackages.get(name);
- if (ps != null) {
- while (parsePermissionLPr(parser, ps.getPermissionsState(), userId)) {
- parser.next();
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
}
- }
-
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_PACKAGE);
-
- return true;
- }
-
- private boolean parseSharedUserLPr(XmlPullParser parser, int userId)
- throws IOException, XmlPullParserException {
- skipEmptyTextTags(parser);
- if (!accept(parser, XmlPullParser.START_TAG, TAG_SHARED_USER)) {
- return false;
- }
-
- String name = parser.getAttributeValue(null, ATTR_NAME);
- parser.next();
-
- SharedUserSetting sus = mSharedUsers.get(name);
- if (sus != null) {
- while (parsePermissionLPr(parser, sus.getPermissionsState(), userId)) {
- parser.next();
+ switch (parser.getName()) {
+ case TAG_PACKAGE: {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ PackageSetting ps = mPackages.get(name);
+ if (ps == null) {
+ Slog.w(PackageManagerService.TAG, "Unknown package:" + name);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ parsePermissionsLPr(parser, ps.getPermissionsState(), userId);
+ } break;
+
+ case TAG_SHARED_USER: {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ SharedUserSetting sus = mSharedUsers.get(name);
+ if (sus == null) {
+ Slog.w(PackageManagerService.TAG, "Unknown shared user:" + name);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
+ parsePermissionsLPr(parser, sus.getPermissionsState(), userId);
+ } break;
}
}
-
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_SHARED_USER);
-
- return true;
}
- private boolean parsePermissionLPr(XmlPullParser parser, PermissionsState permissionsState,
+ private void parsePermissionsLPr(XmlPullParser parser, PermissionsState permissionsState,
int userId) throws IOException, XmlPullParserException {
- skipEmptyTextTags(parser);
- if (!accept(parser, XmlPullParser.START_TAG, TAG_ITEM)) {
- return false;
- }
-
- String name = parser.getAttributeValue(null, ATTR_NAME);
-
- parser.next();
-
- BasePermission bp = mPermissions.get(name);
- if (bp != null) {
- if (permissionsState.grantRuntimePermission(bp, userId) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+ continue;
}
- } else {
- Slog.w(PackageManagerService.TAG, "Unknown permission:" + name);
- }
-
- skipEmptyTextTags(parser);
- expect(parser, XmlPullParser.END_TAG, TAG_ITEM);
-
- return true;
- }
- private void expect(XmlPullParser parser, int type, String tag)
- throws IOException, XmlPullParserException {
- if (!accept(parser, type, tag)) {
- throw new XmlPullParserException("Expected event: " + type
- + " and tag: " + tag + " but got event: " + parser.getEventType()
- + " and tag:" + parser.getName());
- }
- }
-
- private void skipEmptyTextTags(XmlPullParser parser)
- throws IOException, XmlPullParserException {
- while (accept(parser, XmlPullParser.TEXT, null)
- && parser.isWhitespace()) {
- parser.next();
- }
- }
+ switch (parser.getName()) {
+ case TAG_ITEM: {
+ String name = parser.getAttributeValue(null, ATTR_NAME);
+ BasePermission bp = mPermissions.get(name);
+ if (bp == null) {
+ Slog.w(PackageManagerService.TAG, "Unknown permission:" + name);
+ XmlUtils.skipCurrentTag(parser);
+ continue;
+ }
- private boolean accept(XmlPullParser parser, int type, String tag)
- throws IOException, XmlPullParserException {
- if (parser.getEventType() != type) {
- return false;
- }
- if (tag != null) {
- if (!tag.equals(parser.getName())) {
- return false;
+ if (permissionsState.grantRuntimePermission(bp, userId) ==
+ PermissionsState.PERMISSION_OPERATION_FAILURE) {
+ Slog.w(PackageManagerService.TAG, "Duplicate permission:" + name);
+ }
+ } break;
}
- } else if (parser.getName() != null) {
- return false;
}
- return true;
}
private void writePermissions(XmlSerializer serializer, Set<String> permissions)
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 26ecb72..8cc9d19 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1219,6 +1219,7 @@ public class UserManagerService extends IUserManager.Stub {
updateUserIdsLocked();
Bundle restrictions = new Bundle();
mUserRestrictions.append(userId, restrictions);
+ mPm.newUserCreatedLILPw(userId);
}
}
if (userInfo != null) {
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/power/DeviceIdleController.java
index 062992d..dd00446 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/power/DeviceIdleController.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.power;
import android.app.AlarmManager;
import android.app.PendingIntent;
@@ -30,12 +30,16 @@ import android.hardware.TriggerEventListener;
import android.hardware.display.DisplayManager;
import android.net.INetworkPolicyManager;
import android.os.Binder;
+import android.os.PowerManager;
+import android.os.PowerManagerInternal;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.TimeUtils;
import android.view.Display;
import com.android.internal.app.IBatteryStats;
+import com.android.server.SystemService;
import com.android.server.am.BatteryStatsService;
import java.io.FileDescriptor;
@@ -60,6 +64,11 @@ public class DeviceIdleController extends SystemService {
*/
private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L;
/**
+ * This is the time, after seeing motion, that we wait after becoming inactive from
+ * that until we start looking for motion again.
+ */
+ private static final long DEFAULT_MOTION_INACTIVE_TIMEOUT = 10*60*1000L;
+ /**
* This is the time, after the inactive timeout elapses, that we will wait looking
* for significant motion until we truly consider the device to be idle.
*/
@@ -94,11 +103,13 @@ public class DeviceIdleController extends SystemService {
private AlarmManager mAlarmManager;
private IBatteryStats mBatteryStats;
+ private PowerManagerInternal mLocalPowerManager;
private INetworkPolicyManager mNetworkPolicyManager;
private DisplayManager mDisplayManager;
private SensorManager mSensorManager;
private Sensor mSigMotionSensor;
private PendingIntent mAlarmIntent;
+ private Intent mIdleIntent;
private Display mCurDisplay;
private boolean mScreenOn;
private boolean mCharging;
@@ -124,6 +135,7 @@ public class DeviceIdleController extends SystemService {
private int mState;
+ private long mInactiveTimeout;
private long mNextAlarmTime;
private long mNextIdlePendingDelay;
private long mNextIdleDelay;
@@ -181,6 +193,7 @@ public class DeviceIdleController extends SystemService {
synchronized (this) {
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mBatteryStats = BatteryStatsService.getService();
+ mLocalPowerManager = getLocalService(PowerManagerInternal.class);
mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
mDisplayManager = (DisplayManager) getContext().getSystemService(
@@ -193,6 +206,9 @@ public class DeviceIdleController extends SystemService {
.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
+ mIdleIntent = new Intent(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ mIdleIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(ACTION_STEP_IDLE_STATE);
@@ -205,6 +221,7 @@ public class DeviceIdleController extends SystemService {
// a battery update the next time the level drops.
mCharging = true;
mState = STATE_ACTIVE;
+ mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
updateDisplayLocked();
}
@@ -238,12 +255,17 @@ public class DeviceIdleController extends SystemService {
void becomeActiveLocked() {
if (mState != STATE_ACTIVE) {
+ mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
mBatteryStats.noteDeviceIdleMode(false, true, false);
} catch (RemoteException e) {
}
+ if (mState == STATE_IDLE) {
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ }
mState = STATE_ACTIVE;
+ mInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
mNextIdlePendingDelay = 0;
mNextIdleDelay = 0;
cancelAlarmLocked();
@@ -256,7 +278,9 @@ public class DeviceIdleController extends SystemService {
// Screen has turned off; we are now going to become inactive and start
// waiting to see if we will ultimately go idle.
mState = STATE_INACTIVE;
- scheduleAlarmLocked(DEFAULT_INACTIVE_TIMEOUT, false);
+ mNextIdlePendingDelay = 0;
+ mNextIdleDelay = 0;
+ scheduleAlarmLocked(mInactiveTimeout, false);
}
}
@@ -283,11 +307,13 @@ public class DeviceIdleController extends SystemService {
mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT;
}
mState = STATE_IDLE;
+ mLocalPowerManager.setDeviceIdleMode(true);
try {
mNetworkPolicyManager.setDeviceIdleMode(true);
mBatteryStats.noteDeviceIdleMode(true, false, false);
} catch (RemoteException e) {
}
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
break;
case STATE_IDLE:
// We have been idling long enough, now it is time to do some work.
@@ -297,11 +323,13 @@ public class DeviceIdleController extends SystemService {
mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT;
}
mState = STATE_IDLE_PENDING;
+ mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
mBatteryStats.noteDeviceIdleMode(false, false, false);
} catch (RemoteException e) {
}
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
break;
}
}
@@ -313,13 +341,18 @@ public class DeviceIdleController extends SystemService {
// state to wait again for no motion. Note that we only monitor for significant
// motion after moving out of the inactive state, so no need to worry about that.
if (mState != STATE_ACTIVE) {
- mState = STATE_INACTIVE;
+ mLocalPowerManager.setDeviceIdleMode(false);
try {
mNetworkPolicyManager.setDeviceIdleMode(false);
mBatteryStats.noteDeviceIdleMode(false, false, true);
} catch (RemoteException e) {
}
- stepIdleStateLocked();
+ if (mState == STATE_IDLE) {
+ getContext().sendBroadcastAsUser(mIdleIntent, UserHandle.ALL);
+ }
+ mState = STATE_ACTIVE;
+ mInactiveTimeout = DEFAULT_MOTION_INACTIVE_TIMEOUT;
+ becomeInactiveIfAppropriateLocked();
}
}
@@ -399,26 +432,30 @@ public class DeviceIdleController extends SystemService {
}
}
- pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
- pw.print(" mCurDisplay="); pw.println(mCurDisplay);
- pw.print(" mScreenOn="); pw.println(mScreenOn);
- pw.print(" mCharging="); pw.println(mCharging);
- pw.print(" mSigMotionActive="); pw.println(mSigMotionActive);
- pw.print(" mState="); pw.println(stateToString(mState));
- if (mNextAlarmTime != 0) {
- pw.print(" mNextAlarmTime=");
- TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
- pw.println();
- }
- if (mNextIdlePendingDelay != 0) {
- pw.print(" mNextIdlePendingDelay=");
- TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
- pw.println();
- }
- if (mNextIdleDelay != 0) {
- pw.print(" mNextIdleDelay=");
- TimeUtils.formatDuration(mNextIdleDelay, pw);
+ synchronized (this) {
+ pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor);
+ pw.print(" mCurDisplay="); pw.println(mCurDisplay);
+ pw.print(" mScreenOn="); pw.println(mScreenOn);
+ pw.print(" mCharging="); pw.println(mCharging);
+ pw.print(" mSigMotionActive="); pw.println(mSigMotionActive);
+ pw.print(" mState="); pw.println(stateToString(mState));
+ pw.print(" mInactiveTimeout="); TimeUtils.formatDuration(mInactiveTimeout, pw);
pw.println();
+ if (mNextAlarmTime != 0) {
+ pw.print(" mNextAlarmTime=");
+ TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw);
+ pw.println();
+ }
+ if (mNextIdlePendingDelay != 0) {
+ pw.print(" mNextIdlePendingDelay=");
+ TimeUtils.formatDuration(mNextIdlePendingDelay, pw);
+ pw.println();
+ }
+ if (mNextIdleDelay != 0) {
+ pw.print(" mNextIdleDelay=");
+ TimeUtils.formatDuration(mNextIdleDelay, pw);
+ pw.println();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 1349926..c48367e 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -78,6 +78,7 @@ final class Notifier {
private static final int MSG_USER_ACTIVITY = 1;
private static final int MSG_BROADCAST = 2;
private static final int MSG_WIRELESS_CHARGING_STARTED = 3;
+ private static final int MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED = 4;
private final Object mLock = new Object();
@@ -92,6 +93,7 @@ final class Notifier {
private final NotifierHandler mHandler;
private final Intent mScreenOnIntent;
private final Intent mScreenOffIntent;
+ private final Intent mScreenBrightnessBoostIntent;
// The current interactive state.
private int mActualInteractiveState;
@@ -128,6 +130,10 @@ final class Notifier {
mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
mScreenOffIntent.addFlags(
Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+ mScreenBrightnessBoostIntent =
+ new Intent(PowerManager.ACTION_SCREEN_BRIGHTNESS_BOOST_CHANGED);
+ mScreenBrightnessBoostIntent.addFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
// Initialize interactive state for battery stats.
try {
@@ -349,6 +355,19 @@ final class Notifier {
}
/**
+ * Called when screen brightness boost begins or ends.
+ */
+ public void onScreenBrightnessBoostChanged() {
+ if (DEBUG) {
+ Slog.d(TAG, "onScreenBrightnessBoostChanged");
+ }
+
+ mSuspendBlocker.acquire();
+ Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED);
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ }
+ /**
* Called when there has been user activity.
*/
public void onUserActivity(int event, int uid) {
@@ -457,6 +476,22 @@ final class Notifier {
}
}
+ private void sendBrightnessBoostChangedBroadcast() {
+ if (DEBUG) {
+ Slog.d(TAG, "Sending brightness boost changed broadcast.");
+ }
+
+ mContext.sendOrderedBroadcastAsUser(mScreenBrightnessBoostIntent, UserHandle.ALL, null,
+ mScreeBrightnessBoostChangedDone, mHandler, 0, null, null);
+ }
+
+ private final BroadcastReceiver mScreeBrightnessBoostChangedDone = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ mSuspendBlocker.release();
+ }
+ };
+
private void sendWakeUpBroadcast() {
if (DEBUG) {
Slog.d(TAG, "Sending wake up broadcast.");
@@ -539,6 +574,9 @@ final class Notifier {
case MSG_WIRELESS_CHARGING_STARTED:
playWirelessChargingStartedSound();
break;
+ case MSG_SCREEN_BRIGHTNESS_BOOST_CHANGED:
+ sendBrightnessBoostChangedBroadcast();
+ break;
}
}
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 9e373b7..6c8959c 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -420,6 +420,9 @@ public final class PowerManagerService extends SystemService
// True if the battery level is currently considered low.
private boolean mBatteryLevelLow;
+ // True if we are currently in device idle mode.
+ private boolean mDeviceIdleMode;
+
// True if theater mode is enabled
private boolean mTheaterModeEnabled;
@@ -1900,6 +1903,7 @@ public final class PowerManagerService extends SystemService
}
}
mScreenBrightnessBoostInProgress = false;
+ mNotifier.onScreenBrightnessBoostChanged();
userActivityNoUpdateLocked(now,
PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
@@ -2178,6 +2182,12 @@ public final class PowerManagerService extends SystemService
}
}
+ private boolean isDeviceIdleModeInternal() {
+ synchronized (mLock) {
+ return mDeviceIdleMode;
+ }
+ }
+
private void handleBatteryStateChangedLocked() {
mDirty |= DIRTY_BATTERY_STATE;
updatePowerStateLocked();
@@ -2275,7 +2285,10 @@ public final class PowerManagerService extends SystemService
Slog.i(TAG, "Brightness boost activated (uid " + uid +")...");
mLastScreenBrightnessBoostTime = eventTime;
- mScreenBrightnessBoostInProgress = true;
+ if (!mScreenBrightnessBoostInProgress) {
+ mScreenBrightnessBoostInProgress = true;
+ mNotifier.onScreenBrightnessBoostChanged();
+ }
mDirty |= DIRTY_SCREEN_BRIGHTNESS_BOOST;
userActivityNoUpdateLocked(eventTime,
@@ -2284,6 +2297,12 @@ public final class PowerManagerService extends SystemService
}
}
+ private boolean isScreenBrightnessBoostedInternal() {
+ synchronized (mLock) {
+ return mScreenBrightnessBoostInProgress;
+ }
+ }
+
/**
* Called when a screen brightness boost timeout has occurred.
*
@@ -3050,6 +3069,16 @@ public final class PowerManagerService extends SystemService
}
}
+ @Override // Binder call
+ public boolean isDeviceIdleMode() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isDeviceIdleModeInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
/**
* Reboots the device.
*
@@ -3218,6 +3247,16 @@ public final class PowerManagerService extends SystemService
}
@Override // Binder call
+ public boolean isScreenBrightnessBoosted() {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isScreenBrightnessBoostedInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
!= PackageManager.PERMISSION_GRANTED) {
@@ -3295,5 +3334,12 @@ public final class PowerManagerService extends SystemService
mLowPowerModeListeners.add(listener);
}
}
+
+ @Override
+ public void setDeviceIdleMode(boolean enabled) {
+ synchronized (mLock) {
+ mDeviceIdleMode = enabled;
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 0109313..dec195d 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -272,13 +272,14 @@ public class TrustAgentWrapper {
alarmFilter.addDataScheme(mAlarmIntent.getScheme());
final String pathUri = mAlarmIntent.toUri(Intent.URI_INTENT_SCHEME);
alarmFilter.addDataPath(pathUri, PatternMatcher.PATTERN_LITERAL);
- mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null);
// Schedules a restart for when connecting times out. If the connection succeeds,
// the restart is canceled in mCallback's onConnected.
scheduleRestart();
mBound = context.bindServiceAsUser(intent, mConnection, Context.BIND_AUTO_CREATE, user);
- if (!mBound) {
+ if (mBound) {
+ mContext.registerReceiver(mBroadcastReceiver, alarmFilter, PERMISSION, null);
+ } else {
Log.e(TAG, "Can't bind to TrustAgent " + mName.flattenToShortString());
}
}
@@ -398,7 +399,6 @@ public class TrustAgentWrapper {
}
public void destroy() {
- mContext.unregisterReceiver(mBroadcastReceiver);
mHandler.removeMessages(MSG_RESTART_TIMEOUT);
if (!mBound) {
@@ -408,6 +408,7 @@ public class TrustAgentWrapper {
mTrustManagerService.mArchive.logAgentStopped(mUserId, mName);
mContext.unbindService(mConnection);
mBound = false;
+ mContext.unregisterReceiver(mBroadcastReceiver);
mTrustAgentService = null;
mSetTrustAgentFeaturesToken = null;
mHandler.sendEmptyMessage(MSG_REVOKE_TRUST);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1dc027a..32bb78e 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -178,7 +178,7 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean DEBUG_ORIENTATION = false;
static final boolean DEBUG_APP_ORIENTATION = false;
static final boolean DEBUG_CONFIGURATION = false;
- static final boolean DEBUG_APP_TRANSITIONS = false;
+ static final boolean DEBUG_APP_TRANSITIONS = true;
static final boolean DEBUG_STARTING_WINDOW = false;
static final boolean DEBUG_WALLPAPER = false;
static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
@@ -189,7 +189,7 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean DEBUG_LAYOUT_REPEATS = true;
static final boolean DEBUG_SURFACE_TRACE = false;
static final boolean DEBUG_WINDOW_TRACE = false;
- static final boolean DEBUG_TASK_MOVEMENT = false;
+ static final boolean DEBUG_TASK_MOVEMENT = true;
static final boolean DEBUG_STACK = false;
static final boolean DEBUG_DISPLAY = false;
static final boolean DEBUG_POWER = false;
@@ -3056,7 +3056,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- if (DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
+ if (true || DEBUG_LAYOUT) Slog.v(TAG, "Relayout " + win + ": viewVisibility=" + viewVisibility
+ " req=" + requestedWidth + "x" + requestedHeight + " " + win.mAttrs);
win.mEnforceSizeCompat =
@@ -3720,10 +3720,8 @@ public class WindowManagerService extends IWindowManager.Stub
} else {
// TODO(multidisplay): Change to the correct display.
final WindowList windows = getDefaultWindowListLocked();
- int pos = windows.size() - 1;
- while (pos >= 0) {
+ for (int pos = windows.size() - 1; pos >= 0; --pos) {
WindowState win = windows.get(pos);
- pos--;
if (win.mAppToken != null) {
// We hit an application window. so the orientation will be determined by the
// app window. No point in continuing further.
@@ -4173,8 +4171,8 @@ public class WindowManagerService extends IWindowManager.Stub
}
synchronized(mWindowMap) {
- if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition,
- new RuntimeException("here").fillInStackTrace());
+ if (DEBUG_APP_TRANSITIONS) Slog.w(TAG, "Execute app transition: " + mAppTransition
+ + " Callers=" + Debug.getCallers(5));
if (mAppTransition.isTransitionSet()) {
mAppTransition.setReady();
final long origId = Binder.clearCallingIdentity();
@@ -4610,8 +4608,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (DEBUG_APP_TRANSITIONS || DEBUG_ORIENTATION) Slog.v(TAG, "setAppVisibility(" +
token + ", visible=" + visible + "): " + mAppTransition +
" hidden=" + wtoken.hidden + " hiddenRequested=" +
- wtoken.hiddenRequested, HIDE_STACK_CRAWLS ?
- null : new RuntimeException("here").fillInStackTrace());
+ wtoken.hiddenRequested + " Callers=" + Debug.getCallers(6));
// If we are preparing an app transition, then delay changing
// the visibility of this token until we execute that transition.
diff --git a/services/core/jni/com_android_server_UsbMidiDevice.cpp b/services/core/jni/com_android_server_UsbMidiDevice.cpp
index 94853b8..cb70144 100644
--- a/services/core/jni/com_android_server_UsbMidiDevice.cpp
+++ b/services/core/jni/com_android_server_UsbMidiDevice.cpp
@@ -94,9 +94,20 @@ android_server_UsbMidiDevice_open(JNIEnv *env, jobject /* thiz */, jint card, ji
return fds;
}
+static void
+android_server_UsbMidiDevice_close(JNIEnv *env, jobject /* thiz */, jobjectArray fds)
+{
+ int count = env->GetArrayLength(fds);
+ for (int i = 0; i < count; i++) {
+ jobject fd = env->GetObjectArrayElement(fds, i);
+ close(jniGetFDFromFileDescriptor(env, fd));
+ }
+}
+
static JNINativeMethod method_table[] = {
{ "nativeGetSubdeviceCount", "(II)I", (void*)android_server_UsbMidiDevice_get_subdevice_count },
{ "nativeOpen", "(III)[Ljava/io/FileDescriptor;", (void*)android_server_UsbMidiDevice_open },
+ { "nativeClose", "([Ljava/io/FileDescriptor;)V", (void*)android_server_UsbMidiDevice_close },
};
int register_android_server_UsbMidiDevice(JNIEnv *env)
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index d07cd98..73b5de1 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1140,70 +1140,85 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
ActiveAdmin getActiveAdminForCallerLocked(ComponentName who, int reqPolicy)
throws SecurityException {
final int callingUid = Binder.getCallingUid();
- final int userHandle = UserHandle.getUserId(callingUid);
- final DevicePolicyData policy = getUserData(userHandle);
- List<ActiveAdmin> candidates = new ArrayList<ActiveAdmin>();
+ ActiveAdmin result = getActiveAdminWithPolicyForUidLocked(who, reqPolicy, callingUid);
+ if (result != null) {
+ return result;
+ }
+
+ if (who != null) {
+ final int userId = UserHandle.getUserId(callingUid);
+ final DevicePolicyData policy = getUserData(userId);
+ ActiveAdmin admin = policy.mAdminMap.get(who);
+ if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
+ throw new SecurityException("Admin " + admin.info.getComponent()
+ + " does not own the device");
+ }
+ if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
+ throw new SecurityException("Admin " + admin.info.getComponent()
+ + " does not own the profile");
+ }
+ throw new SecurityException("Admin " + admin.info.getComponent()
+ + " did not specify uses-policy for: "
+ + admin.info.getTagForPolicy(reqPolicy));
+ } else {
+ throw new SecurityException("No active admin owned by uid "
+ + Binder.getCallingUid() + " for policy #" + reqPolicy);
+ }
+ }
- // Build a list of admins for this uid matching the given ComponentName
+ private ActiveAdmin getActiveAdminWithPolicyForUidLocked(ComponentName who, int reqPolicy,
+ int uid) {
+ // Try to find an admin which can use reqPolicy
+ final int userId = UserHandle.getUserId(uid);
+ final DevicePolicyData policy = getUserData(userId);
if (who != null) {
ActiveAdmin admin = policy.mAdminMap.get(who);
if (admin == null) {
throw new SecurityException("No active admin " + who);
}
- if (admin.getUid() != callingUid) {
+ if (admin.getUid() != uid) {
throw new SecurityException("Admin " + who + " is not owned by uid "
+ Binder.getCallingUid());
}
- candidates.add(admin);
+ if (isActiveAdminWithPolicyForUserLocked(admin, reqPolicy, userId)) {
+ return admin;
+ }
} else {
for (ActiveAdmin admin : policy.mAdminList) {
- if (admin.getUid() == callingUid) {
- candidates.add(admin);
+ if (admin.getUid() == uid && isActiveAdminWithPolicyForUserLocked(admin, reqPolicy,
+ userId)) {
+ return admin;
}
}
}
- // Try to find an admin which can use reqPolicy
- for (ActiveAdmin admin : candidates) {
- boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
- boolean ownsProfile = (getProfileOwner(userHandle) != null
- && getProfileOwner(userHandle).getPackageName()
- .equals(admin.info.getPackageName()));
- boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName())
- && !hasUserSetupCompleted(userHandle);
+ return null;
+ }
- if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
- if (ownsDevice || (userHandle == UserHandle.USER_OWNER && ownsInitialization)) {
- return admin;
- }
- } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
- if (ownsDevice || ownsProfile || ownsInitialization) {
- return admin;
- }
- } else {
- if (admin.info.usesPolicy(reqPolicy)) {
- return admin;
- }
- }
- }
+ private boolean isActiveAdminWithPolicyForUserLocked(ActiveAdmin admin, int reqPolicy,
+ int userId) {
+ boolean ownsDevice = isDeviceOwner(admin.info.getPackageName());
+ boolean ownsProfile = (getProfileOwner(userId) != null
+ && getProfileOwner(userId).getPackageName()
+ .equals(admin.info.getPackageName()));
+ boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName())
+ && !hasUserSetupCompleted(userId);
- if (who != null) {
- if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
- throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
- + " does not own the device");
+ if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) {
+ if (ownsDevice || (userId == UserHandle.USER_OWNER && ownsInitialization)) {
+ return true;
}
- if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
- throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
- + " does not own the profile");
+ } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) {
+ if (ownsDevice || ownsProfile || ownsInitialization) {
+ return true;
}
- throw new SecurityException("Admin " + candidates.get(0).info.getComponent()
- + " did not specify uses-policy for: "
- + candidates.get(0).info.getTagForPolicy(reqPolicy));
} else {
- throw new SecurityException("No active admin owned by uid "
- + Binder.getCallingUid() + " for policy #" + reqPolicy);
+ if (admin.info.usesPolicy(reqPolicy)) {
+ return true;
+ }
}
+ return false;
}
void sendAdminCommandLocked(ActiveAdmin admin, String action) {
@@ -3159,7 +3174,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
PersistentDataBlockManager manager = (PersistentDataBlockManager)
mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
- manager.wipe();
+ if (manager != null) {
+ manager.wipe();
+ }
}
boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
wipeDeviceOrUserLocked(wipeExtRequested, userHandle,
@@ -5702,6 +5719,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ @Override
+ public boolean isActiveAdminWithPolicy(int uid, int reqPolicy) {
+ final int userId = UserHandle.getUserId(uid);
+ synchronized(DevicePolicyManagerService.this) {
+ return getActiveAdminWithPolicyForUidLocked(null, reqPolicy, uid) != null;
+ }
+ }
+
private void notifyCrossProfileProvidersChanged(int userId, List<String> packages) {
final List<OnCrossProfileWidgetProvidersChangeListener> listeners;
synchronized (DevicePolicyManagerService.this) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index ae2c54b..8c653e2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -66,7 +66,6 @@ import com.android.server.lights.LightsService;
import com.android.server.media.MediaRouterService;
import com.android.server.media.MediaSessionService;
import com.android.server.media.projection.MediaProjectionManagerService;
-import com.android.server.MidiService;
import com.android.server.net.NetworkPolicyManagerService;
import com.android.server.net.NetworkStatsService;
import com.android.server.notification.NotificationManagerService;
@@ -76,6 +75,7 @@ import com.android.server.pm.Installer;
import com.android.server.pm.LauncherAppsService;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.UserManagerService;
+import com.android.server.power.DeviceIdleController;
import com.android.server.power.PowerManagerService;
import com.android.server.power.ShutdownThread;
import com.android.server.restrictions.RestrictionsManagerService;
@@ -124,6 +124,8 @@ public final class SystemServer {
"com.android.server.print.PrintManagerService";
private static final String USB_SERVICE_CLASS =
"com.android.server.usb.UsbService$Lifecycle";
+ private static final String MIDI_SERVICE_CLASS =
+ "com.android.server.midi.MidiService$Lifecycle";
private static final String WIFI_SERVICE_CLASS =
"com.android.server.wifi.WifiService";
private static final String WIFI_P2P_SERVICE_CLASS =
@@ -406,12 +408,9 @@ public final class SystemServer {
AudioService audioService = null;
MmsServiceBroker mmsService = null;
EntropyMixer entropyMixer = null;
- MidiService midiService = null;
boolean disableStorage = SystemProperties.getBoolean("config.disable_storage", false);
- boolean disableMedia = SystemProperties.getBoolean("config.disable_media", false);
boolean disableBluetooth = SystemProperties.getBoolean("config.disable_bluetooth", false);
- boolean disableTelephony = SystemProperties.getBoolean("config.disable_telephony", false);
boolean disableLocation = SystemProperties.getBoolean("config.disable_location", false);
boolean disableSystemUI = SystemProperties.getBoolean("config.disable_systemui", false);
boolean disableNonCoreServices = SystemProperties.getBoolean("config.disable_noncore", false);
@@ -520,7 +519,6 @@ public final class SystemServer {
LockSettingsService lockSettings = null;
AssetAtlasService atlas = null;
MediaRouterService mediaRouter = null;
- MidiService midi = null;
// Bring up services needed for UI.
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
@@ -792,32 +790,33 @@ public final class SystemServer {
}
}
- if (!disableMedia && !"0".equals(SystemProperties.get("system_init.startaudioservice"))) {
- try {
- Slog.i(TAG, "Audio Service");
- audioService = new AudioService(context);
- ServiceManager.addService(Context.AUDIO_SERVICE, audioService);
- } catch (Throwable e) {
- reportWtf("starting Audio Service", e);
- }
+ try {
+ Slog.i(TAG, "Audio Service");
+ audioService = new AudioService(context);
+ ServiceManager.addService(Context.AUDIO_SERVICE, audioService);
+ } catch (Throwable e) {
+ reportWtf("starting Audio Service", e);
}
if (!disableNonCoreServices) {
mSystemServiceManager.startService(DockObserver.class);
}
- if (!disableMedia) {
- try {
- Slog.i(TAG, "Wired Accessory Manager");
- // Listen for wired headset changes
- inputManager.setWiredAccessoryCallbacks(
- new WiredAccessoryManager(context, inputManager));
- } catch (Throwable e) {
- reportWtf("starting WiredAccessoryManager", e);
- }
+ try {
+ Slog.i(TAG, "Wired Accessory Manager");
+ // Listen for wired headset changes
+ inputManager.setWiredAccessoryCallbacks(
+ new WiredAccessoryManager(context, inputManager));
+ } catch (Throwable e) {
+ reportWtf("starting WiredAccessoryManager", e);
}
if (!disableNonCoreServices) {
+ if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_MIDI)) {
+ // Start MIDI Manager service
+ mSystemServiceManager.startService(MIDI_SERVICE_CLASS);
+ }
+
if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)
|| mPackageManager.hasSystemFeature(
PackageManager.FEATURE_USB_ACCESSORY)) {
@@ -835,16 +834,6 @@ public final class SystemServer {
}
}
- if (!disableNonCoreServices) {
- try {
- Slog.i(TAG, "MIDI Service");
- ServiceManager.addService(Context.MIDI_SERVICE,
- new MidiService(context));
- } catch (Throwable e) {
- reportWtf("starting MIDI Service", e);
- }
- }
-
mSystemServiceManager.startService(TwilightService.class);
mSystemServiceManager.startService(JobSchedulerService.class);
@@ -891,14 +880,12 @@ public final class SystemServer {
}
}
- if (!disableMedia) {
- try {
- Slog.i(TAG, "CommonTimeManagementService");
- commonTimeMgmtService = new CommonTimeManagementService(context);
- ServiceManager.addService("commontime_management", commonTimeMgmtService);
- } catch (Throwable e) {
- reportWtf("starting CommonTimeManagementService service", e);
- }
+ try {
+ Slog.i(TAG, "CommonTimeManagementService");
+ commonTimeMgmtService = new CommonTimeManagementService(context);
+ ServiceManager.addService("commontime_management", commonTimeMgmtService);
+ } catch (Throwable e) {
+ reportWtf("starting CommonTimeManagementService service", e);
}
if (!disableNetwork) {
diff --git a/services/midi/Android.mk b/services/midi/Android.mk
new file mode 100644
index 0000000..faac01c
--- /dev/null
+++ b/services/midi/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.midi
+
+LOCAL_SRC_FILES += \
+ $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := services.core
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/core/java/com/android/server/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index 3418930..1d2180e 100644
--- a/services/core/java/com/android/server/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package com.android.server;
+package com.android.server.midi;
import android.content.Context;
import android.content.Intent;
@@ -40,6 +40,7 @@ import android.util.Log;
import com.android.internal.content.PackageMonitor;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
+import com.android.server.SystemService;
import org.xmlpull.v1.XmlPullParser;
@@ -47,9 +48,25 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
public class MidiService extends IMidiManager.Stub {
+
+ public static class Lifecycle extends SystemService {
+ private MidiService mMidiService;
+
+ public Lifecycle(Context context) {
+ super(context);
+ }
+
+ @Override
+ public void onStart() {
+ mMidiService = new MidiService(getContext());
+ publishBinderService(Context.MIDI_SERVICE, mMidiService);
+ }
+ }
+
private static final String TAG = "MidiService";
private final Context mContext;
@@ -269,7 +286,9 @@ public class MidiService extends IMidiManager.Stub {
public void binderDied() {
synchronized (mDevicesByInfo) {
- removeDeviceLocked(this);
+ if (mDevicesByInfo.remove(mDeviceInfo) != null) {
+ removeDeviceLocked(this);
+ }
}
}
@@ -368,6 +387,7 @@ public class MidiService extends IMidiManager.Stub {
synchronized (mDevicesByInfo) {
Device device = mDevicesByServer.get(server.asBinder());
if (device != null) {
+ mDevicesByInfo.remove(device.getDeviceInfo());
removeDeviceLocked(device);
}
}
@@ -454,16 +474,14 @@ public class MidiService extends IMidiManager.Stub {
// synchronize on mDevicesByInfo
private void removeDeviceLocked(Device device) {
- if (mDevicesByInfo.remove(device.getDeviceInfo()) != null) {
- IMidiDeviceServer server = device.getDeviceServer();
- if (server != null) {
- mDevicesByServer.remove(server);
- }
+ IMidiDeviceServer server = device.getDeviceServer();
+ if (server != null) {
+ mDevicesByServer.remove(server);
+ }
- synchronized (mClients) {
- for (Client c : mClients.values()) {
- c.deviceRemoved(device);
- }
+ synchronized (mClients) {
+ for (Client c : mClients.values()) {
+ c.deviceRemoved(device);
}
}
}
@@ -616,8 +634,11 @@ public class MidiService extends IMidiManager.Stub {
private void removePackageDeviceServers(String packageName) {
synchronized (mDevicesByInfo) {
- for (Device device : mDevicesByInfo.values()) {
+ Iterator<Device> iterator = mDevicesByInfo.values().iterator();
+ while (iterator.hasNext()) {
+ Device device = iterator.next();
if (packageName.equals(device.getPackageName())) {
+ iterator.remove();
removeDeviceLocked(device);
}
}
@@ -634,15 +655,19 @@ public class MidiService extends IMidiManager.Stub {
pw.println("Devices:");
pw.increaseIndent();
- for (Device device : mDevicesByInfo.values()) {
- pw.println(device.toString());
+ synchronized (mDevicesByInfo) {
+ for (Device device : mDevicesByInfo.values()) {
+ pw.println(device.toString());
+ }
}
pw.decreaseIndent();
pw.println("Clients:");
pw.increaseIndent();
- for (Client client : mClients.values()) {
- pw.println(client.toString());
+ synchronized (mClients) {
+ for (Client client : mClients.values()) {
+ pw.println(client.toString());
+ }
}
pw.decreaseIndent();
}
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 4dc1131..a3f3a5d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -134,7 +134,7 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
public void testSettingsReadOld() {
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
- Settings settings = new Settings(getContext(), getContext().getFilesDir(), new Object());
+ Settings settings = new Settings(getContext().getFilesDir(), new Object());
assertEquals(true, settings.readLPw(null, null, 0, false));
assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_3));
assertNotNull(settings.peekPackageLPr(PACKAGE_NAME_1));
@@ -152,12 +152,12 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
public void testNewPackageRestrictionsFile() {
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
- Settings settings = new Settings(getContext(), getContext().getFilesDir(), new Object());
+ Settings settings = new Settings(getContext().getFilesDir(), new Object());
assertEquals(true, settings.readLPw(null, null, 0, false));
settings.writeLPr();
// Create Settings again to make it read from the new files
- settings = new Settings(getContext(), getContext().getFilesDir(), new Object());
+ settings = new Settings(getContext().getFilesDir(), new Object());
assertEquals(true, settings.readLPw(null, null, 0, false));
PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_2);
@@ -168,7 +168,7 @@ public class PackageManagerSettingsTests extends AndroidTestCase {
public void testEnableDisable() {
// Write the package files and make sure they're parsed properly the first time
writeOldFiles();
- Settings settings = new Settings(getContext(), getContext().getFilesDir(), new Object());
+ Settings settings = new Settings(getContext().getFilesDir(), new Object());
assertEquals(true, settings.readLPw(null, null, 0, false));
// Enable/Disable a package
diff --git a/services/usb/java/com/android/server/usb/UsbAlsaManager.java b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
index 23e1970..2728af1 100644
--- a/services/usb/java/com/android/server/usb/UsbAlsaManager.java
+++ b/services/usb/java/com/android/server/usb/UsbAlsaManager.java
@@ -17,6 +17,7 @@
package com.android.server.usb;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
@@ -55,6 +56,7 @@ public final class UsbAlsaManager {
private final Context mContext;
private IAudioService mAudioService;
+ private final boolean mHasMidiFeature;
private final AlsaCardsParser mCardsParser = new AlsaCardsParser();
private final AlsaDevicesParser mDevicesParser = new AlsaDevicesParser();
@@ -126,6 +128,7 @@ public final class UsbAlsaManager {
/* package */ UsbAlsaManager(Context context) {
mContext = context;
+ mHasMidiFeature = context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MIDI);
// initial scan
mCardsParser.scan();
@@ -389,7 +392,7 @@ public final class UsbAlsaManager {
// mDevicesParser.scan()
boolean hasMidi = mDevicesParser.hasMIDIDevices(addedCard);
- if (hasMidi) {
+ if (hasMidi && mHasMidiFeature) {
int device = mDevicesParser.getDefaultDeviceNum(addedCard);
AlsaDevice alsaDevice = waitForAlsaDevice(addedCard, device, AlsaDevice.TYPE_MIDI);
if (alsaDevice != null) {
@@ -459,7 +462,11 @@ public final class UsbAlsaManager {
}
/* package */ void setPeripheralMidiState(boolean enabled, int card, int device) {
- if (enabled) {
+ if (!mHasMidiFeature) {
+ return;
+ }
+
+ if (enabled && mPeripheralMidiDevice == null) {
Bundle properties = new Bundle();
Resources r = mContext.getResources();
properties.putString(MidiDeviceInfo.PROPERTY_MANUFACTURER, r.getString(
@@ -469,7 +476,7 @@ public final class UsbAlsaManager {
properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_CARD, card);
properties.putInt(MidiDeviceInfo.PROPERTY_ALSA_DEVICE, device);
mPeripheralMidiDevice = UsbMidiDevice.create(mContext, properties, card, device);
- } else if (mPeripheralMidiDevice != null) {
+ } else if (!enabled && mPeripheralMidiDevice != null) {
IoUtils.closeQuietly(mPeripheralMidiDevice);
mPeripheralMidiDevice = null;
}
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 41cf2ef..6adb8be 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -126,6 +126,8 @@ public class UsbDeviceManager {
private boolean mAdbEnabled;
private boolean mAudioSourceEnabled;
private boolean mMidiEnabled;
+ private int mMidiCard;
+ private int mMidiDevice;
private Map<String, List<Pair<String, String>>> mOemModeMap;
private String[] mAccessoryStrings;
private UsbDebuggingManager mDebuggingManager;
@@ -363,18 +365,6 @@ public class UsbDeviceManager {
updateState(state);
mAdbEnabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_ADB);
- // Upgrade step for previous versions that used persist.service.adb.enable
- String value = SystemProperties.get("persist.service.adb.enable", "");
- if (value.length() > 0) {
- char enable = value.charAt(0);
- if (enable == '1') {
- setAdbEnabled(true);
- } else if (enable == '0') {
- setAdbEnabled(false);
- }
- SystemProperties.set("persist.service.adb.enable", "");
- }
-
// register observer to listen for settings changes
mContentResolver.registerContentObserver(
Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
@@ -623,26 +613,24 @@ public class UsbDeviceManager {
private void updateMidiFunction() {
boolean enabled = containsFunction(mCurrentFunctions, UsbManager.USB_FUNCTION_MIDI);
if (enabled != mMidiEnabled) {
- int card = -1;
- int device = -1;
-
if (enabled) {
Scanner scanner = null;
try {
scanner = new Scanner(new File(MIDI_ALSA_PATH));
- card = scanner.nextInt();
- device = scanner.nextInt();
+ mMidiCard = scanner.nextInt();
+ mMidiDevice = scanner.nextInt();
} catch (FileNotFoundException e) {
Slog.e(TAG, "could not open MIDI PCM file", e);
+ enabled = false;
} finally {
if (scanner != null) {
scanner.close();
}
}
}
- mUsbAlsaManager.setPeripheralMidiState(enabled, card, device);
mMidiEnabled = enabled;
}
+ mUsbAlsaManager.setPeripheralMidiState(mMidiEnabled && mConfigured, mMidiCard, mMidiDevice);
}
@Override
diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
index f23bb93..7c101a4 100644
--- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java
+++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java
@@ -19,7 +19,6 @@ package com.android.server.usb;
import android.content.Context;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiDeviceServer;
-import android.media.midi.MidiDispatcher;
import android.media.midi.MidiManager;
import android.media.midi.MidiReceiver;
import android.media.midi.MidiSender;
@@ -47,6 +46,8 @@ public final class UsbMidiDevice implements Closeable {
private static final int BUFFER_SIZE = 512;
+ private final FileDescriptor[] mFileDescriptors;
+
// for polling multiple FileDescriptors for MIDI events
private final StructPollfd[] mPollFDs;
// streams for reading from ALSA driver
@@ -69,7 +70,7 @@ public final class UsbMidiDevice implements Closeable {
return null;
}
- UsbMidiDevice midiDevice = new UsbMidiDevice(fileDescriptors, fileDescriptors);
+ UsbMidiDevice midiDevice = new UsbMidiDevice(fileDescriptors);
if (!midiDevice.register(context, properties)) {
IoUtils.closeQuietly(midiDevice);
Log.e(TAG, "createDeviceServer failed");
@@ -78,14 +79,15 @@ public final class UsbMidiDevice implements Closeable {
return midiDevice;
}
- private UsbMidiDevice(FileDescriptor[] inputFiles, FileDescriptor[] outputFiles) {
- int inputCount = inputFiles.length;
- int outputCount = outputFiles.length;
+ private UsbMidiDevice(FileDescriptor[] fileDescriptors) {
+ mFileDescriptors = fileDescriptors;
+ int inputCount = fileDescriptors.length;
+ int outputCount = fileDescriptors.length;
mPollFDs = new StructPollfd[inputCount];
mInputStreams = new FileInputStream[inputCount];
for (int i = 0; i < inputCount; i++) {
- FileDescriptor fd = inputFiles[i];
+ FileDescriptor fd = fileDescriptors[i];
StructPollfd pollfd = new StructPollfd();
pollfd.fd = fd;
pollfd.events = (short)OsConstants.POLLIN;
@@ -95,7 +97,7 @@ public final class UsbMidiDevice implements Closeable {
mOutputStreams = new FileOutputStream[outputCount];
for (int i = 0; i < outputCount; i++) {
- mOutputStreams[i] = new FileOutputStream(outputFiles[i]);
+ mOutputStreams[i] = new FileOutputStream(fileDescriptors[i]);
}
mInputPortReceivers = new MidiReceiver[inputCount];
@@ -176,8 +178,10 @@ public final class UsbMidiDevice implements Closeable {
for (int i = 0; i < mOutputStreams.length; i++) {
mOutputStreams[i].close();
}
+ nativeClose(mFileDescriptors);
}
private static native int nativeGetSubdeviceCount(int card, int device);
private static native FileDescriptor[] nativeOpen(int card, int device, int subdeviceCount);
+ private static native void nativeClose(FileDescriptor[] fileDescriptors);
}