summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
Diffstat (limited to 'services')
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java21
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java29
-rw-r--r--services/core/java/com/android/server/DropBoxManagerService.java11
-rw-r--r--services/core/java/com/android/server/MmsServiceBroker.java19
-rw-r--r--services/core/java/com/android/server/PersistentDataBlockService.java215
-rw-r--r--services/core/java/com/android/server/SystemConfig.java12
-rw-r--r--services/core/java/com/android/server/accounts/AccountManagerService.java107
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityManagerService.java524
-rwxr-xr-xservices/core/java/com/android/server/am/ActivityStack.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java2
-rw-r--r--services/core/java/com/android/server/am/TaskPersister.java6
-rw-r--r--services/core/java/com/android/server/connectivity/Nat464Xlat.java10
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java27
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java25
-rw-r--r--services/core/java/com/android/server/display/VirtualDisplayAdapter.java10
-rw-r--r--services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java133
-rw-r--r--services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java2
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java61
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java27
-rw-r--r--services/core/java/com/android/server/hdmi/NewDeviceAction.java3
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java9
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java25
-rw-r--r--services/core/java/com/android/server/net/IpConfigStore.java6
-rw-r--r--services/core/java/com/android/server/notification/ConditionProviders.java10
-rw-r--r--services/core/java/com/android/server/notification/DowntimeConditionProvider.java28
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java11
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java5
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java17
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java81
-rw-r--r--services/core/java/com/android/server/trust/TrustAgentWrapper.java29
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java147
-rw-r--r--services/core/java/com/android/server/tv/TvInputHardwareManager.java107
-rw-r--r--services/core/java/com/android/server/wm/AccessibilityController.java15
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java13
-rw-r--r--services/core/java/com/android/server/wm/WindowAnimator.java50
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java5
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java42
-rw-r--r--services/usb/java/com/android/server/usb/UsbDebuggingManager.java22
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java9
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java19
40 files changed, 1318 insertions, 581 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 8b524dd..08c47dc 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -75,6 +75,12 @@ class AlarmManagerService extends SystemService {
// warning message. The time duration is in milliseconds.
private static final long LATE_ALARM_THRESHOLD = 10 * 1000;
+ // Minimum futurity of a new alarm
+ private static final long MIN_FUTURITY = 5 * 1000; // 5 seconds, in millis
+
+ // Minimum alarm recurrence interval
+ private static final long MIN_INTERVAL = 60 * 1000; // one minute, in millis
+
private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
private static final int RTC_MASK = 1 << RTC;
private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
@@ -696,6 +702,15 @@ class AlarmManagerService extends SystemService {
windowLength = AlarmManager.INTERVAL_HOUR;
}
+ // Sanity check the recurrence interval. This will catch people who supply
+ // seconds when the API expects milliseconds.
+ if (interval > 0 && interval < MIN_INTERVAL) {
+ Slog.w(TAG, "Suspiciously short interval " + interval
+ + " millis; expanding to " + (int)(MIN_INTERVAL/1000)
+ + " seconds");
+ interval = MIN_INTERVAL;
+ }
+
if (type < RTC_WAKEUP || type > ELAPSED_REALTIME) {
throw new IllegalArgumentException("Invalid alarm type " + type);
}
@@ -709,7 +724,11 @@ class AlarmManagerService extends SystemService {
}
final long nowElapsed = SystemClock.elapsedRealtime();
- final long triggerElapsed = convertToElapsed(triggerAtTime, type);
+ final long nominalTrigger = convertToElapsed(triggerAtTime, type);
+ // Try to prevent spamming by making sure we aren't firing alarms in the immediate future
+ final long minTrigger = nowElapsed + MIN_FUTURITY;
+ final long triggerElapsed = (nominalTrigger > minTrigger) ? nominalTrigger : minTrigger;
+
final long maxElapsed;
if (windowLength == AlarmManager.WINDOW_EXACT) {
maxElapsed = triggerElapsed;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5997680..fa6d349 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2598,7 +2598,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
String exclList = "";
String pacFileUrl = "";
if (proxyProperties != null && (!TextUtils.isEmpty(proxyProperties.getHost()) ||
- (proxyProperties.getPacFileUrl() != null))) {
+ !Uri.EMPTY.equals(proxyProperties.getPacFileUrl()))) {
if (!proxyProperties.isValid()) {
if (DBG)
log("Invalid proxy properties, ignoring: " + proxyProperties.toString());
@@ -2608,7 +2608,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
host = mGlobalProxy.getHost();
port = mGlobalProxy.getPort();
exclList = mGlobalProxy.getExclusionListAsString();
- if (proxyProperties.getPacFileUrl() != null) {
+ if (!Uri.EMPTY.equals(proxyProperties.getPacFileUrl())) {
pacFileUrl = proxyProperties.getPacFileUrl().toString();
}
} else {
@@ -2670,7 +2670,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void handleApplyDefaultProxy(ProxyInfo proxy) {
if (proxy != null && TextUtils.isEmpty(proxy.getHost())
- && (proxy.getPacFileUrl() == null)) {
+ && Uri.EMPTY.equals(proxy.getPacFileUrl())) {
proxy = null;
}
synchronized (mProxyLock) {
@@ -2686,7 +2686,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
// global (to get the correct local port), and send a broadcast.
// TODO: Switch PacManager to have its own message to send back rather than
// reusing EVENT_HAS_CHANGED_PROXY and this call to handleApplyDefaultProxy.
- if ((mGlobalProxy != null) && (proxy != null) && (proxy.getPacFileUrl() != null)
+ if ((mGlobalProxy != null) && (proxy != null)
+ && (!Uri.EMPTY.equals(proxy.getPacFileUrl()))
&& proxy.getPacFileUrl().equals(mGlobalProxy.getPacFileUrl())) {
mGlobalProxy = proxy;
sendProxyBroadcast(mGlobalProxy);
@@ -2813,9 +2814,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
/**
- * Prepare for a VPN application. This method is used by VpnDialogs
- * and not available in ConnectivityManager. Permissions are checked
- * in Vpn class.
+ * Prepare for a VPN application. This method is used by system-privileged apps.
+ * Permissions are checked in Vpn class.
* @hide
*/
@Override
@@ -2829,8 +2829,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* Set whether the current VPN package has the ability to launch VPNs without
- * user intervention. This method is used by system UIs and not available
- * in ConnectivityManager. Permissions are checked in Vpn class.
+ * user intervention. This method is used by system-privileged apps.
+ * Permissions are checked in Vpn class.
* @hide
*/
@Override
@@ -3247,7 +3247,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, enable ? 1 : 0);
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
intent.putExtra("state", enable);
- mContext.sendBroadcast(intent);
+ mContext.sendBroadcastAsUser(intent, UserHandle.ALL);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -3840,9 +3840,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
int notificationType) {
if (notificationType == ConnectivityManager.CALLBACK_AVAILABLE) {
Intent intent = new Intent();
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK, nri.request);
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST_NETWORK_REQUEST,
- networkAgent.network);
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK, nri.request);
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK_REQUEST, networkAgent.network);
sendIntent(nri.mPendingIntent, intent);
}
// else not handled
@@ -3974,7 +3973,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// another higher scoring network by another call to rematchNetworkAndRequests()
// and this other call also lingered newNetwork.
private void rematchNetworkAndRequests(NetworkAgentInfo newNetwork, boolean nascent) {
- if (!newNetwork.created) loge("ERROR: uncreated network being rematched.");
+ if (!newNetwork.created) return;
if (nascent && !newNetwork.validated) loge("ERROR: nascent network not validated.");
boolean keep = newNetwork.isVPN();
boolean isNewDefault = false;
@@ -4273,7 +4272,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
final int oldScore = nai.getCurrentScore();
nai.setCurrentScore(score);
- if (nai.created) rematchAllNetworksAndRequests(nai, oldScore);
+ rematchAllNetworksAndRequests(nai, oldScore);
sendUpdatedScoreToFactories(nai);
}
diff --git a/services/core/java/com/android/server/DropBoxManagerService.java b/services/core/java/com/android/server/DropBoxManagerService.java
index 29b04da..a44cb72 100644
--- a/services/core/java/com/android/server/DropBoxManagerService.java
+++ b/services/core/java/com/android/server/DropBoxManagerService.java
@@ -408,9 +408,14 @@ public final class DropBoxManagerService extends IDropBoxManagerService.Stub {
if (!newline) out.append("\n");
} else {
String text = dbe.getText(70);
- boolean truncated = (text.length() == 70);
- out.append(" ").append(text.trim().replace('\n', '/'));
- if (truncated) out.append(" ...");
+ out.append(" ");
+ if (text == null) {
+ out.append("[null]");
+ } else {
+ boolean truncated = (text.length() == 70);
+ out.append(text.trim().replace('\n', '/'));
+ if (truncated) out.append(" ...");
+ }
out.append("\n");
}
} catch (IOException e) {
diff --git a/services/core/java/com/android/server/MmsServiceBroker.java b/services/core/java/com/android/server/MmsServiceBroker.java
index 9596b57..da50751 100644
--- a/services/core/java/com/android/server/MmsServiceBroker.java
+++ b/services/core/java/com/android/server/MmsServiceBroker.java
@@ -16,8 +16,6 @@
package com.android.server;
-import com.android.internal.telephony.IMms;
-
import android.Manifest;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -38,6 +36,8 @@ import android.os.SystemClock;
import android.telephony.TelephonyManager;
import android.util.Slog;
+import com.android.internal.telephony.IMms;
+
/**
* This class is a proxy for MmsService APIs. We need this because MmsService runs
* in phone process and may crash anytime. This manages a connection to the actual
@@ -118,7 +118,7 @@ public class MmsServiceBroker extends SystemService {
}
public void systemRunning() {
- tryConnecting();
+ Slog.i(TAG, "Delay connecting to MmsService until an API is called");
}
private void tryConnecting() {
@@ -206,7 +206,7 @@ public class MmsServiceBroker extends SystemService {
* Throws a security exception unless the caller has carrier privilege.
*/
private void enforceCarrierPrivilege() {
- String[] packages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
+ final String[] packages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
for (String pkg : packages) {
if (getTelephonyManager().checkCarrierPrivilegesForPackage(pkg) ==
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
@@ -216,12 +216,21 @@ public class MmsServiceBroker extends SystemService {
throw new SecurityException("No carrier privilege");
}
+ private String getCallingPackageName() {
+ final String[] packages = getPackageManager().getPackagesForUid(Binder.getCallingUid());
+ if (packages != null && packages.length > 0) {
+ return packages[0];
+ }
+ return "unknown";
+ }
+
// Service API calls implementation, proxied to the real MmsService in "com.android.mms.service"
private final class BinderService extends IMms.Stub {
@Override
public void sendMessage(int subId, String callingPkg, Uri contentUri,
String locationUrl, Bundle configOverrides, PendingIntent sentIntent)
throws RemoteException {
+ Slog.d(TAG, "sendMessage() by " + callingPkg);
mContext.enforceCallingPermission(Manifest.permission.SEND_SMS, "Send MMS message");
if (getAppOpsManager().noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(),
callingPkg) != AppOpsManager.MODE_ALLOWED) {
@@ -235,6 +244,7 @@ public class MmsServiceBroker extends SystemService {
public void downloadMessage(int subId, String callingPkg, String locationUrl,
Uri contentUri, Bundle configOverrides,
PendingIntent downloadedIntent) throws RemoteException {
+ Slog.d(TAG, "downloadMessage() by " + callingPkg);
mContext.enforceCallingPermission(Manifest.permission.RECEIVE_MMS,
"Download MMS message");
if (getAppOpsManager().noteOp(AppOpsManager.OP_RECEIVE_MMS, Binder.getCallingUid(),
@@ -260,6 +270,7 @@ public class MmsServiceBroker extends SystemService {
@Override
public Bundle getCarrierConfigValues(int subId) throws RemoteException {
+ Slog.d(TAG, "getCarrierConfigValues() by " + getCallingPackageName());
return getServiceGuarded().getCarrierConfigValues(subId);
}
diff --git a/services/core/java/com/android/server/PersistentDataBlockService.java b/services/core/java/com/android/server/PersistentDataBlockService.java
index de90aa2..17edb53 100644
--- a/services/core/java/com/android/server/PersistentDataBlockService.java
+++ b/services/core/java/com/android/server/PersistentDataBlockService.java
@@ -41,6 +41,9 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
/**
* Service for reading and writing blocks to a persistent partition.
@@ -63,22 +66,16 @@ public class PersistentDataBlockService extends SystemService {
private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
private static final int HEADER_SIZE = 8;
// Magic number to mark block device as adhering to the format consumed by this service
- private static final int PARTITION_TYPE_MARKER = 0x1990;
+ private static final int PARTITION_TYPE_MARKER = 0x19901873;
// Limit to 100k as blocks larger than this might cause strain on Binder.
- // TODO(anmorales): Consider splitting up too-large blocks in PersistentDataBlockManager
private static final int MAX_DATA_BLOCK_SIZE = 1024 * 100;
+ public static final int DIGEST_SIZE_BYTES = 32;
private final Context mContext;
private final String mDataBlockFile;
private final Object mLock = new Object();
private int mAllowedUid = -1;
- /*
- * Separate lock for OEM unlock related operations as they can happen in parallel with regular
- * block operations.
- */
- private final Object mOemLock = new Object();
-
private long mBlockDeviceSize;
public PersistentDataBlockService(Context context) {
@@ -89,7 +86,6 @@ public class PersistentDataBlockService extends SystemService {
mAllowedUid = getAllowedUid(UserHandle.USER_OWNER);
}
-
private int getAllowedUid(int userHandle) {
String allowedPackage = mContext.getResources()
.getString(R.string.config_persistentDataPackageName);
@@ -106,6 +102,7 @@ public class PersistentDataBlockService extends SystemService {
@Override
public void onStart() {
+ enforceChecksumValidity();
publishBinderService(Context.PERSISTENT_DATA_BLOCK_SERVICE, mService);
}
@@ -128,6 +125,9 @@ public class PersistentDataBlockService extends SystemService {
}
private int getTotalDataSizeLocked(DataInputStream inputStream) throws IOException {
+ // skip over checksum
+ inputStream.skipBytes(DIGEST_SIZE_BYTES);
+
int totalDataSize;
int blockId = inputStream.readInt();
if (blockId == PARTITION_TYPE_MARKER) {
@@ -148,6 +148,143 @@ public class PersistentDataBlockService extends SystemService {
return mBlockDeviceSize;
}
+ private boolean enforceChecksumValidity() {
+ byte[] storedDigest = new byte[DIGEST_SIZE_BYTES];
+
+ synchronized (mLock) {
+ byte[] digest = computeDigestLocked(storedDigest);
+ if (digest == null || !Arrays.equals(storedDigest, digest)) {
+ Slog.i(TAG, "Formatting FRP partition...");
+ formatPartitionLocked();
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private boolean computeAndWriteDigestLocked() {
+ byte[] digest = computeDigestLocked(null);
+ if (digest != null) {
+ DataOutputStream outputStream;
+ try {
+ outputStream = new DataOutputStream(
+ new FileOutputStream(new File(mDataBlockFile)));
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "partition not available?", e);
+ return false;
+ }
+
+ try {
+ outputStream.write(digest, 0, DIGEST_SIZE_BYTES);
+ outputStream.flush();
+ } catch (IOException e) {
+ Slog.e(TAG, "failed to write block checksum", e);
+ return false;
+ } finally {
+ IoUtils.closeQuietly(outputStream);
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private byte[] computeDigestLocked(byte[] storedDigest) {
+ DataInputStream inputStream;
+ try {
+ inputStream = new DataInputStream(new FileInputStream(new File(mDataBlockFile)));
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "partition not available?", e);
+ return null;
+ }
+
+ MessageDigest md;
+ try {
+ md = MessageDigest.getInstance("SHA-256");
+ } catch (NoSuchAlgorithmException e) {
+ // won't ever happen -- every implementation is required to support SHA-256
+ Slog.e(TAG, "SHA-256 not supported?", e);
+ IoUtils.closeQuietly(inputStream);
+ return null;
+ }
+
+ try {
+ if (storedDigest != null && storedDigest.length == DIGEST_SIZE_BYTES) {
+ inputStream.read(storedDigest);
+ } else {
+ inputStream.skipBytes(DIGEST_SIZE_BYTES);
+ }
+
+ int read;
+ byte[] data = new byte[1024];
+ md.update(data, 0, DIGEST_SIZE_BYTES); // include 0 checksum in digest
+ while ((read = inputStream.read(data)) != -1) {
+ md.update(data, 0, read);
+ }
+ } catch (IOException e) {
+ Slog.e(TAG, "failed to read partition", e);
+ return null;
+ } finally {
+ IoUtils.closeQuietly(inputStream);
+ }
+
+ return md.digest();
+ }
+
+ private void formatPartitionLocked() {
+ DataOutputStream outputStream;
+ try {
+ outputStream = new DataOutputStream(new FileOutputStream(new File(mDataBlockFile)));
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "partition not available?", e);
+ return;
+ }
+
+ byte[] data = new byte[DIGEST_SIZE_BYTES];
+ try {
+ outputStream.write(data, 0, DIGEST_SIZE_BYTES);
+ outputStream.writeInt(PARTITION_TYPE_MARKER);
+ outputStream.writeInt(0); // data size
+ outputStream.flush();
+ } catch (IOException e) {
+ Slog.e(TAG, "failed to format block", e);
+ return;
+ } finally {
+ IoUtils.closeQuietly(outputStream);
+ }
+
+ doSetOemUnlockEnabledLocked(false);
+ computeAndWriteDigestLocked();
+ }
+
+ private void doSetOemUnlockEnabledLocked(boolean enabled) {
+ FileOutputStream outputStream;
+ try {
+ outputStream = new FileOutputStream(new File(mDataBlockFile));
+ } catch (FileNotFoundException e) {
+ Slog.e(TAG, "partition not available", e);
+ return;
+ }
+
+ try {
+ FileChannel channel = outputStream.getChannel();
+
+ channel.position(getBlockDeviceSize() - 1);
+
+ ByteBuffer data = ByteBuffer.allocate(1);
+ data.put(enabled ? (byte) 1 : (byte) 0);
+ data.flip();
+ channel.write(data);
+ outputStream.flush();
+ } catch (IOException e) {
+ Slog.e(TAG, "unable to access persistent partition", e);
+ return;
+ } finally {
+ IoUtils.closeQuietly(outputStream);
+ }
+ }
+
private native long nativeGetBlockDeviceSize(String path);
private native int nativeWipe(String path);
@@ -176,19 +313,23 @@ public class PersistentDataBlockService extends SystemService {
headerAndData.putInt(data.length);
headerAndData.put(data);
- try {
- synchronized (mLock) {
- outputStream.write(headerAndData.array());
- return data.length;
- }
- } catch (IOException e) {
- Slog.e(TAG, "failed writing to the persistent data block", e);
- return -1;
- } finally {
+ synchronized (mLock) {
try {
- outputStream.close();
+ byte[] checksum = new byte[DIGEST_SIZE_BYTES];
+ outputStream.write(checksum, 0, DIGEST_SIZE_BYTES);
+ outputStream.write(headerAndData.array());
+ outputStream.flush();
} catch (IOException e) {
- Slog.e(TAG, "failed closing output stream", e);
+ Slog.e(TAG, "failed writing to the persistent data block", e);
+ return -1;
+ } finally {
+ IoUtils.closeQuietly(outputStream);
+ }
+
+ if (computeAndWriteDigestLocked()) {
+ return data.length;
+ } else {
+ return -1;
}
}
}
@@ -196,6 +337,9 @@ public class PersistentDataBlockService extends SystemService {
@Override
public byte[] read() {
enforceUid(Binder.getCallingUid());
+ if (!enforceChecksumValidity()) {
+ return new byte[0];
+ }
DataInputStream inputStream;
try {
@@ -256,30 +400,10 @@ public class PersistentDataBlockService extends SystemService {
}
enforceOemUnlockPermission();
enforceIsOwner();
- FileOutputStream outputStream;
- try {
- outputStream = new FileOutputStream(new File(mDataBlockFile));
- } catch (FileNotFoundException e) {
- Slog.e(TAG, "parition not available", e);
- return;
- }
-
- try {
- FileChannel channel = outputStream.getChannel();
- channel.position(getBlockDeviceSize() - 1);
-
- ByteBuffer data = ByteBuffer.allocate(1);
- data.put(enabled ? (byte) 1 : (byte) 0);
- data.flip();
-
- synchronized (mOemLock) {
- channel.write(data);
- }
- } catch (IOException e) {
- Slog.e(TAG, "unable to access persistent partition", e);
- } finally {
- IoUtils.closeQuietly(outputStream);
+ synchronized (mLock) {
+ doSetOemUnlockEnabledLocked(enabled);
+ computeAndWriteDigestLocked();
}
}
@@ -295,8 +419,8 @@ public class PersistentDataBlockService extends SystemService {
}
try {
- inputStream.skip(getBlockDeviceSize() - 1);
- synchronized (mOemLock) {
+ synchronized (mLock) {
+ inputStream.skip(getBlockDeviceSize() - 1);
return inputStream.readByte() != 0;
}
} catch (IOException e) {
@@ -336,6 +460,5 @@ public class PersistentDataBlockService extends SystemService {
long actualSize = getBlockDeviceSize() - HEADER_SIZE - 1;
return actualSize <= MAX_DATA_BLOCK_SIZE ? actualSize : MAX_DATA_BLOCK_SIZE;
}
-
};
}
diff --git a/services/core/java/com/android/server/SystemConfig.java b/services/core/java/com/android/server/SystemConfig.java
index f4fb519..92fbc1e 100644
--- a/services/core/java/com/android/server/SystemConfig.java
+++ b/services/core/java/com/android/server/SystemConfig.java
@@ -16,6 +16,7 @@
package com.android.server;
+import android.app.ActivityManager;
import android.content.pm.FeatureInfo;
import android.os.*;
import android.os.Process;
@@ -177,6 +178,8 @@ public class SystemConfig {
return;
}
+ final boolean lowRam = ActivityManager.isLowRamDeviceStatic();
+
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(permReader);
@@ -276,10 +279,17 @@ public class SystemConfig {
} else if ("feature".equals(name)) {
String fname = parser.getAttributeValue(null, "name");
+ boolean allowed;
+ if (!lowRam) {
+ allowed = true;
+ } else {
+ String notLowRam = parser.getAttributeValue(null, "notLowRam");
+ allowed = !"true".equals(notLowRam);
+ }
if (fname == null) {
Slog.w(TAG, "<feature> without name at "
+ parser.getPositionDescription());
- } else {
+ } else if (allowed) {
//Log.i(TAG, "Got feature " + fname);
FeatureInfo fi = new FeatureInfo();
fi.name = fname;
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index d480f68..a2f4d56 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -77,7 +77,6 @@ import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.server.FgThread;
-
import com.google.android.collect.Lists;
import com.google.android.collect.Sets;
@@ -487,7 +486,7 @@ public class AccountManagerService
for (Account sa : sharedAccounts) {
if (ArrayUtils.contains(accounts, sa)) continue;
// Account doesn't exist. Copy it now.
- copyAccountToUser(sa, UserHandle.USER_OWNER, userId);
+ copyAccountToUser(null /*no response*/, sa, UserHandle.USER_OWNER, userId);
}
}
@@ -673,16 +672,31 @@ public class AccountManagerService
}
}
- private boolean copyAccountToUser(final Account account, int userFrom, int userTo) {
+ @Override
+ public void copyAccountToUser(final IAccountManagerResponse response, final Account account,
+ int userFrom, int userTo) {
+ enforceCrossUserPermission(UserHandle.USER_ALL, "Calling copyAccountToUser requires "
+ + android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
final UserAccounts fromAccounts = getUserAccounts(userFrom);
final UserAccounts toAccounts = getUserAccounts(userTo);
if (fromAccounts == null || toAccounts == null) {
- return false;
+ if (response != null) {
+ Bundle result = new Bundle();
+ result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
+ try {
+ response.onResult(result);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to report error back to the client." + e);
+ }
+ }
+ return;
}
+ Slog.d(TAG, "Copying account " + account.name
+ + " from user " + userFrom + " to user " + userTo);
long identityToken = clearCallingIdentity();
try {
- new Session(fromAccounts, null, account.type, false,
+ new Session(fromAccounts, response, account.type, false,
false /* stripAuthTokenFromResult */) {
@Override
protected String toDebugString(long now) {
@@ -697,12 +711,10 @@ public class AccountManagerService
@Override
public void onResult(Bundle result) {
- if (result != null) {
- if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
- // Create a Session for the target user and pass in the bundle
- completeCloningAccount(result, account, toAccounts);
- }
- return;
+ if (result != null
+ && result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
+ // Create a Session for the target user and pass in the bundle
+ completeCloningAccount(response, result, account, toAccounts);
} else {
super.onResult(result);
}
@@ -711,14 +723,13 @@ public class AccountManagerService
} finally {
restoreCallingIdentity(identityToken);
}
- return true;
}
- void completeCloningAccount(final Bundle result, final Account account,
- final UserAccounts targetUser) {
+ private void completeCloningAccount(IAccountManagerResponse response,
+ final Bundle accountCredentials, final Account account, final UserAccounts targetUser) {
long id = clearCallingIdentity();
try {
- new Session(targetUser, null, account.type, false,
+ new Session(targetUser, response, account.type, false,
false /* stripAuthTokenFromResult */) {
@Override
protected String toDebugString(long now) {
@@ -731,10 +742,10 @@ public class AccountManagerService
// Confirm that the owner's account still exists before this step.
UserAccounts owner = getUserAccounts(UserHandle.USER_OWNER);
synchronized (owner.cacheLock) {
- Account[] ownerAccounts = getAccounts(UserHandle.USER_OWNER);
- for (Account acc : ownerAccounts) {
+ for (Account acc : getAccounts(UserHandle.USER_OWNER)) {
if (acc.equals(account)) {
- mAuthenticator.addAccountFromCredentials(this, account, result);
+ mAuthenticator.addAccountFromCredentials(
+ this, account, accountCredentials);
break;
}
}
@@ -743,17 +754,10 @@ public class AccountManagerService
@Override
public void onResult(Bundle result) {
- if (result != null) {
- if (result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT, false)) {
- // TODO: Anything?
- } else {
- // TODO: Show error notification
- // TODO: Should we remove the shadow account to avoid retries?
- }
- return;
- } else {
- super.onResult(result);
- }
+ // TODO: Anything to do if if succedded?
+ // TODO: If it failed: Show error notification? Should we remove the shadow
+ // account to avoid retries?
+ super.onResult(result);
}
@Override
@@ -1043,7 +1047,8 @@ public class AccountManagerService
}
@Override
- public void removeAccount(IAccountManagerResponse response, Account account) {
+ public void removeAccount(IAccountManagerResponse response, Account account,
+ boolean expectActivityLaunch) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "removeAccount: " + account
+ ", response " + response
@@ -1088,7 +1093,7 @@ public class AccountManagerService
}
try {
- new RemoveAccountSession(accounts, response, account).bind();
+ new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind();
} finally {
restoreCallingIdentity(identityToken);
}
@@ -1096,7 +1101,7 @@ public class AccountManagerService
@Override
public void removeAccountAsUser(IAccountManagerResponse response, Account account,
- int userId) {
+ boolean expectActivityLaunch, int userId) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "removeAccount: " + account
+ ", response " + response
@@ -1145,7 +1150,30 @@ public class AccountManagerService
}
try {
- new RemoveAccountSession(accounts, response, account).bind();
+ new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind();
+ } finally {
+ restoreCallingIdentity(identityToken);
+ }
+ }
+
+ @Override
+ public boolean removeAccountExplicitly(Account account) {
+ if (Log.isLoggable(TAG, Log.VERBOSE)) {
+ Log.v(TAG, "removeAccountExplicitly: " + account
+ + ", caller's uid " + Binder.getCallingUid()
+ + ", pid " + Binder.getCallingPid());
+ }
+ if (account == null) throw new IllegalArgumentException("account is null");
+ checkAuthenticateAccountsPermission(account);
+
+ UserAccounts accounts = getUserAccountsForCaller();
+ int userId = Binder.getCallingUserHandle().getIdentifier();
+ if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
+ return false;
+ }
+ long identityToken = clearCallingIdentity();
+ try {
+ return removeAccountInternal(accounts, account);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -1154,8 +1182,8 @@ public class AccountManagerService
private class RemoveAccountSession extends Session {
final Account mAccount;
public RemoveAccountSession(UserAccounts accounts, IAccountManagerResponse response,
- Account account) {
- super(accounts, response, account.type, false /* expectActivityLaunch */,
+ Account account, boolean expectActivityLaunch) {
+ super(accounts, response, account.type, expectActivityLaunch,
true /* stripAuthTokenFromResult */);
mAccount = account;
}
@@ -1203,10 +1231,12 @@ public class AccountManagerService
removeAccountInternal(getUserAccountsForCaller(), account);
}
- private void removeAccountInternal(UserAccounts accounts, Account account) {
+ private boolean removeAccountInternal(UserAccounts accounts, Account account) {
+ int deleted;
synchronized (accounts.cacheLock) {
final SQLiteDatabase db = accounts.openHelper.getWritableDatabase();
- db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
+ deleted = db.delete(TABLE_ACCOUNTS, ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE
+ + "=?",
new String[]{account.name, account.type});
removeAccountFromCacheLocked(accounts, account);
sendAccountsChangedBroadcast(accounts.userId);
@@ -1226,6 +1256,7 @@ public class AccountManagerService
Binder.restoreCallingIdentity(id);
}
}
+ return (deleted > 0);
}
@Override
@@ -2714,7 +2745,7 @@ public class AccountManagerService
break;
case MESSAGE_COPY_SHARED_ACCOUNT:
- copyAccountToUser((Account) msg.obj, msg.arg1, msg.arg2);
+ copyAccountToUser(/*no response*/ null, (Account) msg.obj, msg.arg1, msg.arg2);
break;
default:
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index d0f5eed..f0fb9e6 100755
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -61,7 +61,6 @@ import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.app.ProcessMap;
import com.android.internal.app.ProcessStats;
-import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.os.BatteryStatsImpl;
import com.android.internal.os.ProcessCpuTracker;
@@ -796,7 +795,11 @@ public final class ActivityManagerService extends ActivityManagerNative
@Override
public int hashCode() {
- return toString().hashCode();
+ int hashCode = 1;
+ hashCode = 31 * hashCode + sourceUserId;
+ hashCode = 31 * hashCode + uri.hashCode();
+ hashCode = 31 * hashCode + (prefix ? 1231 : 1237);
+ return hashCode;
}
@Override
@@ -835,10 +838,12 @@ public final class ActivityManagerService extends ActivityManagerNative
* indirect content-provider access.
*/
private class Identity {
- public int pid;
- public int uid;
+ public final IBinder token;
+ public final int pid;
+ public final int uid;
- Identity(int _pid, int _uid) {
+ Identity(IBinder _token, int _pid, int _uid) {
+ token = _token;
pid = _pid;
uid = _uid;
}
@@ -1183,7 +1188,7 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int SERVICE_TIMEOUT_MSG = 12;
static final int UPDATE_TIME_ZONE = 13;
static final int SHOW_UID_ERROR_MSG = 14;
- static final int IM_FEELING_LUCKY_MSG = 15;
+ static final int SHOW_FINGERPRINT_ERROR_MSG = 15;
static final int PROC_START_TIMEOUT_MSG = 20;
static final int DO_PENDING_ACTIVITY_LAUNCHES_MSG = 21;
static final int KILL_APPLICATION_MSG = 22;
@@ -1212,13 +1217,13 @@ public final class ActivityManagerService extends ActivityManagerNative
static final int FINISH_BOOTING_MSG = 45;
static final int START_USER_SWITCH_MSG = 46;
static final int SEND_LOCALE_TO_MOUNT_DAEMON_MSG = 47;
+ static final int DISMISS_DIALOG_MSG = 48;
static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
static final int FIRST_COMPAT_MODE_MSG = 300;
static final int FIRST_SUPERVISOR_STACK_MSG = 100;
- AlertDialog mUidAlert;
CompatModeDialog mCompatModeDialog;
long mLastMemUsageReportTime = 0;
@@ -1447,27 +1452,27 @@ public final class ActivityManagerService extends ActivityManagerNative
}
} break;
case SHOW_UID_ERROR_MSG: {
- String title = "System UIDs Inconsistent";
- String text = "UIDs on the system are inconsistent, you need to wipe your"
- + " data partition or your device will be unstable.";
- Log.e(TAG, title + ": " + text);
if (mShowDialogs) {
- // XXX This is a temporary dialog, no need to localize.
AlertDialog d = new BaseErrorDialog(mContext);
d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
d.setCancelable(false);
- d.setTitle(title);
- d.setMessage(text);
- d.setButton(DialogInterface.BUTTON_POSITIVE, "I'm Feeling Lucky",
- mHandler.obtainMessage(IM_FEELING_LUCKY_MSG));
- mUidAlert = d;
+ d.setTitle(mContext.getText(R.string.android_system_label));
+ d.setMessage(mContext.getText(R.string.system_error_wipe_data));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+ mHandler.obtainMessage(DISMISS_DIALOG_MSG, d));
d.show();
}
} break;
- case IM_FEELING_LUCKY_MSG: {
- if (mUidAlert != null) {
- mUidAlert.dismiss();
- mUidAlert = null;
+ case SHOW_FINGERPRINT_ERROR_MSG: {
+ if (mShowDialogs) {
+ AlertDialog d = new BaseErrorDialog(mContext);
+ d.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
+ d.setCancelable(false);
+ d.setTitle(mContext.getText(R.string.android_system_label));
+ d.setMessage(mContext.getText(R.string.system_error_manufacturer));
+ d.setButton(DialogInterface.BUTTON_POSITIVE, mContext.getText(R.string.ok),
+ mHandler.obtainMessage(DISMISS_DIALOG_MSG, d));
+ d.show();
}
} break;
case PROC_START_TIMEOUT_MSG: {
@@ -1727,6 +1732,11 @@ public final class ActivityManagerService extends ActivityManagerNative
}
break;
}
+ case DISMISS_DIALOG_MSG: {
+ final Dialog d = (Dialog) msg.obj;
+ d.dismiss();
+ break;
+ }
}
}
};
@@ -1776,7 +1786,8 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- int i=0, num=0;
+ int i = 0;
+ int num = 0;
long[] tmp = new long[1];
do {
ProcessRecord proc;
@@ -1826,99 +1837,6 @@ public final class ActivityManagerService extends ActivityManagerNative
}
};
- /**
- * Monitor for package changes and update our internal state.
- */
- private final PackageMonitor mPackageMonitor = new PackageMonitor() {
- @Override
- public void onPackageRemoved(String packageName, int uid) {
- // Remove all tasks with activities in the specified package from the list of recent tasks
- final int eventUserId = getChangingUserId();
- synchronized (ActivityManagerService.this) {
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- TaskRecord tr = mRecentTasks.get(i);
- if (tr.userId != eventUserId) continue;
-
- ComponentName cn = tr.intent.getComponent();
- if (cn != null && cn.getPackageName().equals(packageName)) {
- // If the package name matches, remove the task
- removeTaskByIdLocked(tr.taskId, true);
- }
- }
- }
- }
-
- @Override
- public boolean onPackageChanged(String packageName, int uid, String[] components) {
- onPackageModified(packageName);
- return true;
- }
-
- @Override
- public void onPackageModified(String packageName) {
- final int eventUserId = getChangingUserId();
- final IPackageManager pm = AppGlobals.getPackageManager();
- final ArrayList<Pair<Intent, Integer>> recentTaskIntents =
- new ArrayList<Pair<Intent, Integer>>();
- final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
- final ArrayList<Integer> tasksToRemove = new ArrayList<Integer>();
- // Copy the list of recent tasks so that we don't hold onto the lock on
- // ActivityManagerService for long periods while checking if components exist.
- synchronized (ActivityManagerService.this) {
- for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
- TaskRecord tr = mRecentTasks.get(i);
- if (tr.userId != eventUserId) continue;
-
- recentTaskIntents.add(new Pair<Intent, Integer>(tr.intent, tr.taskId));
- }
- }
- // Check the recent tasks and filter out all tasks with components that no longer exist.
- for (int i = recentTaskIntents.size() - 1; i >= 0; i--) {
- Pair<Intent, Integer> p = recentTaskIntents.get(i);
- ComponentName cn = p.first.getComponent();
- if (cn != null && cn.getPackageName().equals(packageName)) {
- if (componentsKnownToExist.contains(cn)) {
- // If we know that the component still exists in the package, then skip
- continue;
- }
- try {
- ActivityInfo info = pm.getActivityInfo(cn, 0, eventUserId);
- if (info != null) {
- componentsKnownToExist.add(cn);
- } else {
- tasksToRemove.add(p.second);
- }
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to query activity info for component: " + cn, e);
- }
- }
- }
- // Prune all the tasks with removed components from the list of recent tasks
- synchronized (ActivityManagerService.this) {
- for (int i = tasksToRemove.size() - 1; i >= 0; i--) {
- removeTaskByIdLocked(tasksToRemove.get(i), false);
- }
- }
- }
-
- @Override
- public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
- // Force stop the specified packages
- int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
- if (packages != null) {
- for (String pkg : packages) {
- synchronized (ActivityManagerService.this) {
- if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
- userId, "finished booting")) {
- return true;
- }
- }
- }
- }
- return false;
- }
- };
-
public void setSystemProcess() {
try {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
@@ -2359,15 +2277,19 @@ public final class ActivityManagerService extends ActivityManagerNative
* process when the bindApplication() IPC is sent to the process. They're
* lazily setup to make sure the services are running when they're asked for.
*/
- private HashMap<String, IBinder> getCommonServicesLocked() {
+ private HashMap<String, IBinder> getCommonServicesLocked(boolean isolated) {
if (mAppBindArgs == null) {
- mAppBindArgs = new HashMap<String, IBinder>();
+ mAppBindArgs = new HashMap<>();
- // Setup the application init args
- mAppBindArgs.put("package", ServiceManager.getService("package"));
- mAppBindArgs.put("window", ServiceManager.getService("window"));
- mAppBindArgs.put(Context.ALARM_SERVICE,
- ServiceManager.getService(Context.ALARM_SERVICE));
+ // Isolated processes won't get this optimization, so that we don't
+ // violate the rules about which services they have access to.
+ if (!isolated) {
+ // Setup the application init args
+ mAppBindArgs.put("package", ServiceManager.getService("package"));
+ mAppBindArgs.put("window", ServiceManager.getService("window"));
+ mAppBindArgs.put(Context.ALARM_SERVICE,
+ ServiceManager.getService(Context.ALARM_SERVICE));
+ }
}
return mAppBindArgs;
}
@@ -5990,7 +5912,8 @@ public final class ActivityManagerService extends ActivityManagerNative
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
- new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
+ new Configuration(mConfiguration), app.compat,
+ getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
@@ -6166,8 +6089,26 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- // Register receivers to handle package update events
- mPackageMonitor.register(mContext, Looper.getMainLooper(), UserHandle.ALL, false);
+ IntentFilter pkgFilter = new IntentFilter();
+ pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
+ pkgFilter.addDataScheme("package");
+ mContext.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
+ if (pkgs != null) {
+ for (String pkg : pkgs) {
+ synchronized (ActivityManagerService.this) {
+ if (forceStopPackageLocked(pkg, -1, false, false, false, false, false,
+ 0, "finished booting")) {
+ setResultCode(Activity.RESULT_OK);
+ return;
+ }
+ }
+ }
+ }
+ }
+ }, pkgFilter);
// Let system services know.
mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED);
@@ -6326,7 +6267,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (this) {
ActivityStack stack = ActivityRecord.getStackLocked(token);
if (stack != null) {
- stack.backgroundResourcesReleased(token);
+ stack.backgroundResourcesReleased();
}
}
} finally {
@@ -6792,21 +6733,9 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
int checkComponentPermission(String permission, int pid, int uid,
int owningUid, boolean exported) {
- // We might be performing an operation on behalf of an indirect binder
- // invocation, e.g. via {@link #openContentUri}. Check and adjust the
- // client identity accordingly before proceeding.
- Identity tlsIdentity = sCallerIdentity.get();
- if (tlsIdentity != null) {
- Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
- + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
- uid = tlsIdentity.uid;
- pid = tlsIdentity.pid;
- }
-
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
}
-
return ActivityManager.checkComponentPermission(permission, uid,
owningUid, exported);
}
@@ -6828,6 +6757,26 @@ public final class ActivityManagerService extends ActivityManagerNative
return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);
}
+ @Override
+ public int checkPermissionWithToken(String permission, int pid, int uid, IBinder callerToken) {
+ if (permission == null) {
+ return PackageManager.PERMISSION_DENIED;
+ }
+
+ // We might be performing an operation on behalf of an indirect binder
+ // invocation, e.g. via {@link #openContentUri}. Check and adjust the
+ // client identity accordingly before proceeding.
+ Identity tlsIdentity = sCallerIdentity.get();
+ if (tlsIdentity != null && tlsIdentity.token == callerToken) {
+ Slog.d(TAG, "checkComponentPermission() adjusting {pid,uid} to {"
+ + tlsIdentity.pid + "," + tlsIdentity.uid + "}");
+ uid = tlsIdentity.uid;
+ pid = tlsIdentity.pid;
+ }
+
+ return checkComponentPermission(permission, pid, UserHandle.getAppId(uid), -1, true);
+ }
+
/**
* Binder IPC calls go through the public entry point.
* This can be called with or without the global lock held.
@@ -7033,13 +6982,13 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
@Override
public int checkUriPermission(Uri uri, int pid, int uid,
- final int modeFlags, int userId) {
+ final int modeFlags, int userId, IBinder callerToken) {
enforceNotIsolatedCaller("checkUriPermission");
// Another redirected-binder-call permissions check as in
- // {@link checkComponentPermission}.
+ // {@link checkPermissionWithToken}.
Identity tlsIdentity = sCallerIdentity.get();
- if (tlsIdentity != null) {
+ if (tlsIdentity != null && tlsIdentity.token == callerToken) {
uid = tlsIdentity.uid;
pid = tlsIdentity.pid;
}
@@ -8401,6 +8350,47 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
+ private void removeTasksByPackageNameLocked(String packageName, int userId) {
+ // Remove all tasks with activities in the specified package from the list of recent tasks
+ for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+ TaskRecord tr = mRecentTasks.get(i);
+ if (tr.userId != userId) continue;
+
+ ComponentName cn = tr.intent.getComponent();
+ if (cn != null && cn.getPackageName().equals(packageName)) {
+ // If the package name matches, remove the task.
+ removeTaskByIdLocked(tr.taskId, true);
+ }
+ }
+ }
+
+ private void removeTasksByRemovedPackageComponentsLocked(String packageName, int userId) {
+ final IPackageManager pm = AppGlobals.getPackageManager();
+ final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>();
+
+ for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+ TaskRecord tr = mRecentTasks.get(i);
+ if (tr.userId != userId) continue;
+
+ ComponentName cn = tr.intent.getComponent();
+ if (cn != null && cn.getPackageName().equals(packageName)) {
+ // Skip if component still exists in the package.
+ if (componentsKnownToExist.contains(cn)) continue;
+
+ try {
+ ActivityInfo info = pm.getActivityInfo(cn, 0, userId);
+ if (info != null) {
+ componentsKnownToExist.add(cn);
+ } else {
+ removeTaskByIdLocked(tr.taskId, false);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Activity info query failed. component=" + cn, e);
+ }
+ }
+ }
+ }
+
/**
* Removes the task with the specified task id.
*
@@ -8460,6 +8450,7 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
final TaskRecord task = mStackSupervisor.anyTaskForIdLocked(taskId);
if (task == null) {
+ Slog.d(TAG, "Could not find task for id: "+ taskId);
return;
}
if (mStackSupervisor.isLockTaskModeViolation(task)) {
@@ -9904,10 +9895,11 @@ public final class ActivityManagerService extends ActivityManagerNative
// we do the check against the caller's permissions even though it looks
// to the content provider like the Activity Manager itself is making
// the request.
+ Binder token = new Binder();
sCallerIdentity.set(new Identity(
- Binder.getCallingPid(), Binder.getCallingUid()));
+ token, Binder.getCallingPid(), Binder.getCallingUid()));
try {
- pfd = cph.provider.openFile(null, uri, "r", null);
+ pfd = cph.provider.openFile(null, uri, "r", null, token);
} catch (FileNotFoundException e) {
// do nothing; pfd will be returned null
} finally {
@@ -11249,13 +11241,18 @@ public final class ActivityManagerService extends ActivityManagerNative
try {
if (AppGlobals.getPackageManager().hasSystemUidErrors()) {
- Message msg = Message.obtain();
- msg.what = SHOW_UID_ERROR_MSG;
- mHandler.sendMessage(msg);
+ Slog.e(TAG, "UIDs on the system are inconsistent, you need to wipe your"
+ + " data partition or your device will be unstable.");
+ mHandler.obtainMessage(SHOW_UID_ERROR_MSG).sendToTarget();
}
} catch (RemoteException e) {
}
+ if (!Build.isFingerprintConsistent()) {
+ Slog.e(TAG, "Build fingerprint is not consistent, warning user");
+ mHandler.obtainMessage(SHOW_FINGERPRINT_ERROR_MSG).sendToTarget();
+ }
+
long ident = Binder.clearCallingIdentity();
try {
Intent intent = new Intent(Intent.ACTION_USER_STARTED);
@@ -13961,7 +13958,9 @@ public final class ActivityManagerService extends ActivityManagerNative
ArrayList<MemItem> procMems = new ArrayList<MemItem>();
final SparseArray<MemItem> procMemsMap = new SparseArray<MemItem>();
- long nativePss=0, dalvikPss=0, otherPss=0;
+ long nativePss = 0;
+ long dalvikPss = 0;
+ long otherPss = 0;
long[] miscPss = new long[Debug.MemoryInfo.NUM_OTHER_STATS];
long oomPss[] = new long[DUMP_MEM_OOM_LABEL.length];
@@ -15660,128 +15659,135 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
- // Handle special intents: if this broadcast is from the package
- // manager about a package being removed, we need to remove all of
- // its activities from the history stack.
- final boolean uidRemoved = Intent.ACTION_UID_REMOVED.equals(
- intent.getAction());
- if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())
- || Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction())
- || Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())
- || Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(intent.getAction())
- || uidRemoved) {
- if (checkComponentPermission(
- android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
- callingPid, callingUid, -1, true)
- == PackageManager.PERMISSION_GRANTED) {
- if (uidRemoved) {
- final Bundle intentExtras = intent.getExtras();
- final int uid = intentExtras != null
- ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
- if (uid >= 0) {
- BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
- synchronized (bs) {
- bs.removeUidStatsLocked(uid);
- }
- mAppOpsService.uidRemoved(uid);
+ final String action = intent.getAction();
+ if (action != null) {
+ switch (action) {
+ case Intent.ACTION_UID_REMOVED:
+ case Intent.ACTION_PACKAGE_REMOVED:
+ case Intent.ACTION_PACKAGE_CHANGED:
+ case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+ case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
+ // Handle special intents: if this broadcast is from the package
+ // manager about a package being removed, we need to remove all of
+ // its activities from the history stack.
+ if (checkComponentPermission(
+ android.Manifest.permission.BROADCAST_PACKAGE_REMOVED,
+ callingPid, callingUid, -1, true)
+ != PackageManager.PERMISSION_GRANTED) {
+ String msg = "Permission Denial: " + intent.getAction()
+ + " broadcast from " + callerPackage + " (pid=" + callingPid
+ + ", uid=" + callingUid + ")"
+ + " requires "
+ + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
}
- } else {
- // If resources are unavailable just force stop all
- // those packages and flush the attribute cache as well.
- if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(intent.getAction())) {
- String list[] = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
- if (list != null && (list.length > 0)) {
- for (String pkg : list) {
- forceStopPackageLocked(pkg, -1, false, true, true, false, false, userId,
- "storage unmount");
+ switch (action) {
+ case Intent.ACTION_UID_REMOVED:
+ final Bundle intentExtras = intent.getExtras();
+ final int uid = intentExtras != null
+ ? intentExtras.getInt(Intent.EXTRA_UID) : -1;
+ if (uid >= 0) {
+ BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
+ synchronized (bs) {
+ bs.removeUidStatsLocked(uid);
+ }
+ mAppOpsService.uidRemoved(uid);
}
- cleanupRecentTasksLocked(UserHandle.USER_ALL);
- sendPackageBroadcastLocked(
- IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list, userId);
- }
- } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(
- intent.getAction())) {
- cleanupRecentTasksLocked(UserHandle.USER_ALL);
- } else {
- Uri data = intent.getData();
- String ssp;
- if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
- boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(
- intent.getAction());
- boolean fullUninstall = removed &&
- !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
- if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
- forceStopPackageLocked(ssp, UserHandle.getAppId(
- intent.getIntExtra(Intent.EXTRA_UID, -1)), false, true, true,
- false, fullUninstall, userId,
- removed ? "pkg removed" : "pkg changed");
+ break;
+ case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
+ // If resources are unavailable just force stop all those packages
+ // and flush the attribute cache as well.
+ String list[] =
+ intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ if (list != null && list.length > 0) {
+ for (int i = 0; i < list.length; i++) {
+ forceStopPackageLocked(list[i], -1, false, true, true,
+ false, false, userId, "storage unmount");
+ }
+ cleanupRecentTasksLocked(UserHandle.USER_ALL);
+ sendPackageBroadcastLocked(
+ IApplicationThread.EXTERNAL_STORAGE_UNAVAILABLE, list,
+ userId);
}
- if (removed) {
- sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
- new String[] {ssp}, userId);
- if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
- mAppOpsService.packageRemoved(
- intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
-
- // Remove all permissions granted from/to this package
- removeUriPermissionsForPackageLocked(ssp, userId, true);
+ break;
+ case Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE:
+ cleanupRecentTasksLocked(UserHandle.USER_ALL);
+ break;
+ case Intent.ACTION_PACKAGE_REMOVED:
+ case Intent.ACTION_PACKAGE_CHANGED:
+ Uri data = intent.getData();
+ String ssp;
+ if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
+ boolean removed = Intent.ACTION_PACKAGE_REMOVED.equals(action);
+ boolean fullUninstall = removed &&
+ !intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+ if (!intent.getBooleanExtra(Intent.EXTRA_DONT_KILL_APP, false)) {
+ forceStopPackageLocked(ssp, UserHandle.getAppId(
+ intent.getIntExtra(Intent.EXTRA_UID, -1)),
+ false, true, true, false, fullUninstall, userId,
+ removed ? "pkg removed" : "pkg changed");
+ }
+ if (removed) {
+ sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REMOVED,
+ new String[] {ssp}, userId);
+ if (fullUninstall) {
+ mAppOpsService.packageRemoved(
+ intent.getIntExtra(Intent.EXTRA_UID, -1), ssp);
+
+ // Remove all permissions granted from/to this package
+ removeUriPermissionsForPackageLocked(ssp, userId, true);
+
+ removeTasksByPackageNameLocked(ssp, userId);
+ }
+ } else {
+ removeTasksByRemovedPackageComponentsLocked(ssp, userId);
}
}
+ break;
+ }
+ break;
+ case Intent.ACTION_PACKAGE_ADDED:
+ // Special case for adding a package: by default turn on compatibility mode.
+ Uri data = intent.getData();
+ String ssp;
+ if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
+ final boolean replacing =
+ intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+ mCompatModePackages.handlePackageAddedLocked(ssp, replacing);
+
+ if (replacing) {
+ removeTasksByRemovedPackageComponentsLocked(ssp, userId);
}
}
- }
- } else {
- String msg = "Permission Denial: " + intent.getAction()
- + " broadcast from " + callerPackage + " (pid=" + callingPid
- + ", uid=" + callingUid + ")"
- + " requires "
- + android.Manifest.permission.BROADCAST_PACKAGE_REMOVED;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
-
- // Special case for adding a package: by default turn on compatibility
- // mode.
- } else if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
- Uri data = intent.getData();
- String ssp;
- if (data != null && (ssp=data.getSchemeSpecificPart()) != null) {
- mCompatModePackages.handlePackageAddedLocked(ssp,
- intent.getBooleanExtra(Intent.EXTRA_REPLACING, false));
- }
- }
-
- /*
- * If this is the time zone changed action, queue up a message that will reset the timezone
- * of all currently running processes. This message will get queued up before the broadcast
- * happens.
- */
- if (Intent.ACTION_TIMEZONE_CHANGED.equals(intent.getAction())) {
- mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
- }
-
- /*
- * If the user set the time, let all running processes know.
- */
- if (Intent.ACTION_TIME_CHANGED.equals(intent.getAction())) {
- final int is24Hour = intent.getBooleanExtra(
- Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1 : 0;
- mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
- BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
- synchronized (stats) {
- stats.noteCurrentTimeChangedLocked();
+ break;
+ case Intent.ACTION_TIMEZONE_CHANGED:
+ // If this is the time zone changed action, queue up a message that will reset
+ // the timezone of all currently running processes. This message will get
+ // queued up before the broadcast happens.
+ mHandler.sendEmptyMessage(UPDATE_TIME_ZONE);
+ break;
+ case Intent.ACTION_TIME_CHANGED:
+ // If the user set the time, let all running processes know.
+ final int is24Hour =
+ intent.getBooleanExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, false) ? 1
+ : 0;
+ mHandler.sendMessage(mHandler.obtainMessage(UPDATE_TIME, is24Hour, 0));
+ BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
+ synchronized (stats) {
+ stats.noteCurrentTimeChangedLocked();
+ }
+ break;
+ case Intent.ACTION_CLEAR_DNS_CACHE:
+ mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
+ break;
+ case Proxy.PROXY_CHANGE_ACTION:
+ ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
+ mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
+ break;
}
}
- if (Intent.ACTION_CLEAR_DNS_CACHE.equals(intent.getAction())) {
- mHandler.sendEmptyMessage(CLEAR_DNS_CACHE_MSG);
- }
-
- if (Proxy.PROXY_CHANGE_ACTION.equals(intent.getAction())) {
- ProxyInfo proxy = intent.getParcelableExtra(Proxy.EXTRA_PROXY_INFO);
- mHandler.sendMessage(mHandler.obtainMessage(UPDATE_HTTP_PROXY_MSG, proxy));
- }
-
// Add to the sticky list if requested.
if (sticky) {
if (checkPermission(android.Manifest.permission.BROADCAST_STICKY,
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index 3a1fafe..c8b7205 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -3317,17 +3317,18 @@ final class ActivityStack {
mHandler.sendEmptyMessageDelayed(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG, 500);
} else {
Slog.e(TAG, "releaseBackgroundResources: activity " + r + " no longer running");
- backgroundResourcesReleased(r.appToken);
+ backgroundResourcesReleased();
}
}
}
- final void backgroundResourcesReleased(IBinder token) {
+ final void backgroundResourcesReleased() {
mHandler.removeMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG);
final ActivityRecord r = getVisibleBehindActivity();
if (r != null) {
mStackSupervisor.mStoppingActivities.add(r);
setVisibleBehindActivity(null);
+ mStackSupervisor.scheduleIdleTimeoutLocked(null);
}
mStackSupervisor.resumeTopActivitiesLocked();
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 120002e..38809cb 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -121,7 +121,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 || true;
+ static final boolean DEBUG_STATES = DEBUG || false;
static final boolean DEBUG_VISIBLE_BEHIND = DEBUG || false;
public static final int HOME_STACK_ID = 0;
diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java
index b331c84..9311f25 100644
--- a/services/core/java/com/android/server/am/TaskPersister.java
+++ b/services/core/java/com/android/server/am/TaskPersister.java
@@ -63,6 +63,12 @@ public class TaskPersister {
private static final String IMAGES_DIRNAME = "recent_images";
static final String IMAGE_EXTENSION = ".png";
+ // Directory where restored historical task XML/PNG files are placed. This directory
+ // contains subdirs named after TASKS_DIRNAME and IMAGES_DIRNAME mirroring the
+ // ancestral device's dataset. This needs to match the RECENTS_TASK_RESTORE_DIR
+ // value in RecentsBackupHelper.
+ private static final String RESTORED_TASKS = "restored_" + TASKS_DIRNAME;
+
private static final String TAG_TASK = "task";
static File sImagesDir;
diff --git a/services/core/java/com/android/server/connectivity/Nat464Xlat.java b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
index 576556b..3fa21d0 100644
--- a/services/core/java/com/android/server/connectivity/Nat464Xlat.java
+++ b/services/core/java/com/android/server/connectivity/Nat464Xlat.java
@@ -63,8 +63,8 @@ public class Nat464Xlat extends BaseNetworkObserver {
// - Idle: start() not called. Everything is null.
// - Starting: start() called. Interfaces are non-null. isStarted() returns true.
// mIsRunning is false.
- // - Running: start() called, and interfaceAdded() told us that mIface is up. Clat IP address
- // is non-null. mIsRunning is true.
+ // - Running: start() called, and interfaceLinkStateChanged() told us that mIface is up.
+ // mIsRunning is true.
//
// Once mIface is non-null and isStarted() is true, methods called by ConnectivityService on
// its handler thread must not modify any internal state variables; they are only updated by the
@@ -236,10 +236,10 @@ public class Nat464Xlat extends BaseNetworkObserver {
}
@Override
- public void interfaceAdded(String iface) {
+ public void interfaceLinkStateChanged(String iface, boolean up) {
// Called by the InterfaceObserver on its own thread, so can race with stop().
- if (isStarted() && mIface.equals(iface)) {
- Slog.i(TAG, "interface " + iface + " added, mIsRunning " + mIsRunning + "->true");
+ if (isStarted() && up && mIface.equals(iface)) {
+ Slog.i(TAG, "interface " + iface + " is up, mIsRunning " + mIsRunning + "->true");
if (!mIsRunning) {
LinkAddress clatAddress = getLinkAddress(iface);
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 83756aa..03c05ec 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -23,6 +23,7 @@ import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
+import android.Manifest;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.PendingIntent;
@@ -739,31 +740,7 @@ public class Vpn {
};
private void enforceControlPermission() {
- // System user is allowed to control VPN.
- if (Binder.getCallingUid() == Process.SYSTEM_UID) {
- return;
- }
- int appId = UserHandle.getAppId(Binder.getCallingUid());
- final long token = Binder.clearCallingIdentity();
- try {
- // System VPN dialogs are also allowed to control VPN.
- PackageManager pm = mContext.getPackageManager();
- ApplicationInfo app = pm.getApplicationInfo(VpnConfig.DIALOGS_PACKAGE, 0);
- if (((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (appId == app.uid)) {
- return;
- }
- // SystemUI dialogs are also allowed to control VPN.
- ApplicationInfo sysUiApp = pm.getApplicationInfo("com.android.systemui", 0);
- if (((sysUiApp.flags & ApplicationInfo.FLAG_SYSTEM) != 0) && (appId == sysUiApp.uid)) {
- return;
- }
- } catch (Exception e) {
- // ignore
- } finally {
- Binder.restoreCallingIdentity(token);
- }
-
- throw new SecurityException("Unauthorized Caller");
+ mContext.enforceCallingPermission(Manifest.permission.CONTROL_VPN, "Unauthorized Caller");
}
private class Connection implements ServiceConnection {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 81cd94b..78610ff 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -582,11 +582,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
state = mPowerState.getScreenState();
// Use zero brightness when screen is off.
- // Use full brightness when screen brightness is boosted.
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF;
- } else if (mPowerRequest.boostScreenBrightness) {
- brightness = PowerManager.BRIGHTNESS_ON;
}
// Configure auto-brightness.
@@ -601,6 +598,16 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mPowerRequest.screenAutoBrightnessAdjustment, state != Display.STATE_ON);
}
+ // Apply brightness boost.
+ // We do this here after configuring auto-brightness so that we don't
+ // disable the light sensor during this temporary state. That way when
+ // boost ends we will be able to resume normal auto-brightness behavior
+ // without any delay.
+ if (mPowerRequest.boostScreenBrightness
+ && brightness != PowerManager.BRIGHTNESS_OFF) {
+ brightness = PowerManager.BRIGHTNESS_ON;
+ }
+
// Apply auto-brightness.
boolean slowChange = false;
if (brightness < 0) {
@@ -662,11 +669,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Animate the screen brightness when the screen is on or dozing.
// Skip the animation when the screen is off or suspended.
- if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
- animateScreenBrightness(brightness,
- slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
- } else {
- animateScreenBrightness(brightness, 0);
+ if (!mPendingScreenOff) {
+ if (state == Display.STATE_ON || state == Display.STATE_DOZE) {
+ animateScreenBrightness(brightness,
+ slowChange ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
+ } else {
+ animateScreenBrightness(brightness, 0);
+ }
}
// Determine whether the display is ready for use in the newly requested state.
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 0232bad..28d5fc0 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -23,6 +23,7 @@ import android.media.projection.IMediaProjection;
import android.media.projection.IMediaProjectionCallback;
import android.os.Handler;
import android.os.IBinder;
+import android.os.SystemProperties;
import android.os.IBinder.DeathRecipient;
import android.os.Message;
import android.os.RemoteException;
@@ -278,6 +279,15 @@ final class VirtualDisplayAdapter extends DisplayAdapter {
}
if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION) != 0) {
mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
+
+ if ((mFlags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
+ // For demonstration purposes, allow rotation of the external display.
+ // In the future we might allow the user to configure this directly.
+ if ("portrait".equals(SystemProperties.get(
+ "persist.demo.remoterotation"))) {
+ mInfo.rotation = Surface.ROTATION_270;
+ }
+ }
}
mInfo.type = Display.TYPE_VIRTUAL;
mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
diff --git a/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
new file mode 100644
index 0000000..68311de
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/DelayedMessageBuffer.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiDeviceInfo;
+import android.util.Slog;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * Buffer storage to keep incoming messages for later processing. Used to
+ * handle messages that arrive when the device is not ready. Useful when
+ * keeping the messages from a connected device which are not discovered yet.
+ */
+final class DelayedMessageBuffer {
+ private final ArrayList<HdmiCecMessage> mBuffer = new ArrayList<>();
+ private final HdmiCecLocalDevice mDevice;
+
+ DelayedMessageBuffer(HdmiCecLocalDevice device) {
+ mDevice = device;
+ }
+
+ /**
+ * Add a new message to the buffer. The buffer keeps selected messages in
+ * the order they are received.
+ *
+ * @param message {@link HdmiCecMessage} to add
+ */
+ void add(HdmiCecMessage message) {
+ boolean buffered = true;
+
+ // Note that all the messages are not handled in the same manner.
+ // For &lt;Active Source&gt; we keep the latest one only.
+ // TODO: This might not be the best way to choose the active source.
+ // Devise a better way to pick up the best one.
+ switch (message.getOpcode()) {
+ case Constants.MESSAGE_ACTIVE_SOURCE:
+ removeActiveSource();
+ mBuffer.add(message);
+ break;
+ case Constants.MESSAGE_INITIATE_ARC:
+ mBuffer.add(message);
+ break;
+ default:
+ buffered = false;
+ break;
+ }
+ if (buffered) {
+ HdmiLogger.debug("Buffering message:" + message);
+ }
+ }
+
+ private void removeActiveSource() {
+ // Uses iterator to remove elements while looping through the list.
+ for (Iterator<HdmiCecMessage> iter = mBuffer.iterator(); iter.hasNext(); ) {
+ HdmiCecMessage message = iter.next();
+ if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE) {
+ iter.remove();
+ }
+ }
+ }
+
+ void processAllMessages() {
+ for (HdmiCecMessage message : mBuffer) {
+ mDevice.onMessage(message);
+ HdmiLogger.debug("Processing message:" + message);
+ }
+ mBuffer.clear();
+ }
+
+ /**
+ * Process messages from a given logical device. Called by
+ * {@link NewDeviceAction} actions when they finish adding the device
+ * information.
+ * <p>&lt;Active Source&gt; is not processed in this method but processed
+ * separately via {@link #processActiveSource()}.
+ *
+ * @param address logical address of CEC device which the messages to process
+ * are associated with
+ */
+ void processMessagesForDevice(int address) {
+ HdmiLogger.debug("Processing message for address:" + address);
+ for (Iterator<HdmiCecMessage> iter = mBuffer.iterator(); iter.hasNext(); ) {
+ HdmiCecMessage message = iter.next();
+ if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE) {
+ continue;
+ }
+ if (message.getSource() == address) {
+ mDevice.onMessage(message);
+ HdmiLogger.debug("Processing message:" + message);
+ iter.remove();
+ }
+ }
+ }
+
+ /**
+ * Process &lt;Active Source&gt;.
+ *
+ * <p>The message has a dependency on TV input framework. Should be invoked
+ * after we get the callback
+ * {@link android.media.tv.TvInputManager.TvInputCallback#onInputAdded(String)}
+ * to ensure the processing of the message takes effect when transformed
+ * to input change callback.
+ *
+ * @param address logical address of the device to be the active source
+ */
+ void processActiveSource(int address) {
+ for (Iterator<HdmiCecMessage> iter = mBuffer.iterator(); iter.hasNext(); ) {
+ HdmiCecMessage message = iter.next();
+ if (message.getOpcode() == Constants.MESSAGE_ACTIVE_SOURCE
+ && message.getSource() == address) {
+ mDevice.onMessage(message);
+ HdmiLogger.debug("Processing message:" + message);
+ iter.remove();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
index 2ec9778..da404c4 100644
--- a/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
+++ b/services/core/java/com/android/server/hdmi/DeviceDiscoveryAction.java
@@ -326,6 +326,8 @@ final class DeviceDiscoveryAction extends HdmiCecFeatureAction {
Slog.v(TAG, "--------------------------------------------");
mCallback.onDeviceDiscoveryDone(result);
finish();
+ // Process any commands buffered while device discovery action was in progress.
+ tv().processAllDelayedMessages();
}
private void checkAndProceedStage() {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index 6536165..ec38124 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -30,6 +30,8 @@ import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_ANAL
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_DIGITAL;
import static android.hardware.hdmi.HdmiControlManager.TIMER_RECORDING_TYPE_EXTERNAL;
+import android.annotation.Nullable;
+import android.content.Context;
import android.hardware.hdmi.HdmiControlManager;
import android.hardware.hdmi.HdmiDeviceInfo;
import android.hardware.hdmi.HdmiRecordSources;
@@ -37,6 +39,9 @@ import android.hardware.hdmi.HdmiTimerRecordSources;
import android.hardware.hdmi.IHdmiControlCallback;
import android.media.AudioManager;
import android.media.AudioSystem;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvInputManager.TvInputCallback;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.provider.Settings.Global;
@@ -49,6 +54,7 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.server.hdmi.DeviceDiscoveryAction.DeviceDiscoveryCallback;
import com.android.server.hdmi.HdmiAnnotations.ServiceThreadOnly;
import com.android.server.hdmi.HdmiControlService.SendMessageCallback;
+import com.android.server.SystemService;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
@@ -123,6 +129,26 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
// other CEC devices since they might not have logical address.
private final ArraySet<Integer> mCecSwitches = new ArraySet<Integer>();
+ // Message buffer used to buffer selected messages to process later. <Active Source>
+ // from a source device, for instance, needs to be buffered if the device is not
+ // discovered yet. The buffered commands are taken out and when they are ready to
+ // handle.
+ private final DelayedMessageBuffer mDelayedMessageBuffer = new DelayedMessageBuffer(this);
+
+ // Defines the callback invoked when TV input framework is updated with input status.
+ // We are interested in the notification for HDMI input addition event, in order to
+ // process any CEC commands that arrived before the input is added.
+ private final TvInputCallback mTvInputCallback = new TvInputCallback() {
+ @Override
+ public void onInputAdded(String inputId) {
+ TvInputInfo tvInfo = mService.getTvInputManager().getTvInputInfo(inputId);
+ HdmiDeviceInfo info = tvInfo.getHdmiDeviceInfo();
+ if (info != null && info.isCecDevice()) {
+ mDelayedMessageBuffer.processActiveSource(info.getLogicalAddress());
+ }
+ }
+ };
+
HdmiCecLocalDeviceTv(HdmiControlService service) {
super(service, HdmiDeviceInfo.DEVICE_TV);
mPrevPortId = Constants.INVALID_PORT_ID;
@@ -136,6 +162,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
protected void onAddressAllocated(int logicalAddress, int reason) {
assertRunOnServiceThread();
+ mService.registerTvInputCallback(mTvInputCallback);
mService.sendCecCommand(HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
mAddress, mService.getPhysicalAddress(), mDeviceType));
mService.sendCecCommand(HdmiCecMessageBuilder.buildDeviceVendorIdCommand(
@@ -407,7 +434,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
int physicalAddress = HdmiUtils.twoBytesToInt(message.getParams());
HdmiDeviceInfo info = getCecDeviceInfo(logicalAddress);
if (info == null) {
- handleNewDeviceAtTheTailOfActivePath(physicalAddress);
+ if (!handleNewDeviceAtTheTailOfActivePath(physicalAddress)) {
+ mDelayedMessageBuffer.add(message);
+ }
} else {
ActiveSource activeSource = ActiveSource.of(logicalAddress, physicalAddress);
ActiveSourceHandler.create(this, null).process(activeSource, info.getDeviceType());
@@ -555,7 +584,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
activeSource.physicalAddress, deviceType));
}
- private void handleNewDeviceAtTheTailOfActivePath(int path) {
+ private boolean handleNewDeviceAtTheTailOfActivePath(int path) {
// Seq #22
if (isTailOfActivePath(path, getActivePath())) {
removeAction(RoutingControlAction.class);
@@ -564,7 +593,9 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
mService.sendCecCommand(HdmiCecMessageBuilder.buildRoutingChange(
mAddress, getActivePath(), newPath));
addAndStartAction(new RoutingControlAction(this, newPath, false, null));
+ return true;
}
+ return false;
}
/**
@@ -706,8 +737,10 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
@ServiceThreadOnly
void onNewAvrAdded(HdmiDeviceInfo avr) {
assertRunOnServiceThread();
- addAndStartAction(new SystemAudioAutoInitiationAction(this, avr.getLogicalAddress()));
- if (isArcFeatureEnabled()) {
+ if (getSystemAudioModeSetting()) {
+ addAndStartAction(new SystemAudioAutoInitiationAction(this, avr.getLogicalAddress()));
+ }
+ if (isArcFeatureEnabled() && !hasAction(SetArcTransmissionStateAction.class)) {
startArcAction(true);
}
}
@@ -765,7 +798,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
}
boolean isSystemAudioActivated() {
- if (getAvrDeviceInfo() == null) {
+ if (!hasSystemAudioDevice()) {
return false;
}
synchronized (mLock) {
@@ -941,6 +974,11 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
assertRunOnServiceThread();
if (!canStartArcUpdateAction(message.getSource(), true)) {
+ if (getAvrDeviceInfo() == null) {
+ // AVR may not have been discovered yet. Delay the message processing.
+ mDelayedMessageBuffer.add(message);
+ return true;
+ }
mService.maySendFeatureAbortCommand(message, Constants.ABORT_REFUSED);
if (!isConnectedToArcPort(message.getSource())) {
displayOsd(OSD_MESSAGE_ARC_CONNECTED_INVALID_PORT);
@@ -1436,6 +1474,7 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
protected void disableDevice(boolean initiatedByCec, PendingActionClearedCallback callback) {
super.disableDevice(initiatedByCec, callback);
assertRunOnServiceThread();
+ mService.unregisterTvInputCallback(mTvInputCallback);
// Remove any repeated working actions.
// HotplugDetectionAction will be reinstated during the wake up process.
// HdmiControlService.onWakeUp() -> initializeLocalDevices() ->
@@ -1714,6 +1753,18 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice {
mService.sendCecCommand(HdmiCecMessageBuilder.buildStandby(mAddress, targetAddress));
}
+ @ServiceThreadOnly
+ void processAllDelayedMessages() {
+ assertRunOnServiceThread();
+ mDelayedMessageBuffer.processAllMessages();
+ }
+
+ @ServiceThreadOnly
+ void processDelayedMessages(int address) {
+ assertRunOnServiceThread();
+ mDelayedMessageBuffer.processMessagesForDevice(address);
+ }
+
@Override
protected void dump(final IndentingPrintWriter pw) {
super.dump(pw);
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 907a49a..8a25f62 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -48,6 +48,8 @@ import android.hardware.hdmi.IHdmiRecordListener;
import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener;
import android.hardware.hdmi.IHdmiVendorCommandListener;
import android.media.AudioManager;
+import android.media.tv.TvInputManager;
+import android.media.tv.TvInputManager.TvInputCallback;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
@@ -272,6 +274,9 @@ public final class HdmiControlService extends SystemService {
@Nullable
private HdmiMhlControllerStub mMhlController;
+ @Nullable
+ private TvInputManager mTvInputManager;
+
// Last input port before switching to the MHL port. Should switch back to this port
// when the mobile device sends the request one touch play with off.
// Gets invalidated if we go to other port/input.
@@ -343,6 +348,28 @@ public final class HdmiControlService extends SystemService {
}
}
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY) {
+ mTvInputManager = (TvInputManager) getContext().getSystemService(
+ Context.TV_INPUT_SERVICE);
+ }
+ }
+
+ TvInputManager getTvInputManager() {
+ return mTvInputManager;
+ }
+
+ void registerTvInputCallback(TvInputCallback callback) {
+ if (mTvInputManager == null) return;
+ mTvInputManager.registerCallback(callback, mHandler);
+ }
+
+ void unregisterTvInputCallback(TvInputCallback callback) {
+ if (mTvInputManager == null) return;
+ mTvInputManager.unregisterCallback(callback);
+ }
+
/**
* Called when the initialization of local devices is complete.
*/
diff --git a/services/core/java/com/android/server/hdmi/NewDeviceAction.java b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
index 998889b..64f0703 100644
--- a/services/core/java/com/android/server/hdmi/NewDeviceAction.java
+++ b/services/core/java/com/android/server/hdmi/NewDeviceAction.java
@@ -161,6 +161,9 @@ final class NewDeviceAction extends HdmiCecFeatureAction {
mDeviceType, mVendorId, mDisplayName);
tv().addCecDevice(deviceInfo);
+ // Consume CEC messages we already got for this newly found device.
+ tv().processDelayedMessages(mDeviceLogicalAddress);
+
if (HdmiUtils.getTypeFromAddress(mDeviceLogicalAddress)
== HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM) {
tv().onNewAvrAdded(deviceInfo);
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 921b68b..9440697 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -90,6 +90,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private final SessionStub mSession;
private final SessionCb mSessionCb;
private final MediaSessionService mService;
+ private final boolean mUseMasterVolume;
private final Object mLock = new Object();
private final ArrayList<ISessionControllerCallback> mControllerCallbacks =
@@ -139,6 +140,8 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
mAudioManager = (AudioManager) service.getContext().getSystemService(Context.AUDIO_SERVICE);
mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class);
mAudioAttrs = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build();
+ mUseMasterVolume = service.getContext().getResources().getBoolean(
+ com.android.internal.R.bool.config_useMasterVolume);
}
/**
@@ -248,6 +251,12 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
direction = -1;
}
if (mVolumeType == PlaybackInfo.PLAYBACK_TYPE_LOCAL) {
+ if (mUseMasterVolume) {
+ // If this device only uses master volume and playback is local
+ // just adjust the master volume and return.
+ mAudioManagerInternal.adjustMasterVolumeForUid(direction, flags, packageName, uid);
+ return;
+ }
int stream = AudioAttributes.toLegacyStreamType(mAudioAttrs);
if (useSuggested) {
if (AudioSystem.isStreamActive(stream, 0)) {
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 02c9fcb5..98a3970 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -86,6 +86,7 @@ public class MediaSessionService extends SystemService implements Monitor {
private final Object mLock = new Object();
private final MessageHandler mHandler = new MessageHandler();
private final PowerManager.WakeLock mMediaEventWakeLock;
+ private final boolean mUseMasterVolume;
private KeyguardManager mKeyguardManager;
private IAudioService mAudioService;
@@ -104,6 +105,8 @@ public class MediaSessionService extends SystemService implements Monitor {
mPriorityStack = new MediaSessionStack();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mMediaEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleMediaEvent");
+ mUseMasterVolume = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_useMasterVolume);
}
@Override
@@ -805,7 +808,12 @@ public class MediaSessionService extends SystemService implements Monitor {
+ flags + ", suggestedStream=" + suggestedStream);
}
- if (session == null) {
+ boolean preferSuggestedStream = false;
+ if (isValidLocalStreamType(suggestedStream)
+ && AudioSystem.isStreamActive(suggestedStream, 0)) {
+ preferSuggestedStream = true;
+ }
+ if (session == null || preferSuggestedStream) {
if ((flags & AudioManager.FLAG_ACTIVE_MEDIA_ONLY) != 0
&& !AudioSystem.isStreamActive(AudioManager.STREAM_MUSIC, 0)) {
if (DEBUG) {
@@ -814,8 +822,13 @@ public class MediaSessionService extends SystemService implements Monitor {
return;
}
try {
- mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream, flags,
- getContext().getOpPackageName());
+ if (mUseMasterVolume) {
+ mAudioService.adjustMasterVolume(direction, flags,
+ getContext().getOpPackageName());
+ } else {
+ mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream, flags,
+ getContext().getOpPackageName());
+ }
} catch (RemoteException e) {
Log.e(TAG, "Error adjusting default volume.", e);
}
@@ -959,6 +972,12 @@ public class MediaSessionService extends SystemService implements Monitor {
return keyCode == KeyEvent.KEYCODE_HEADSETHOOK;
}
+ // we only handle public stream types, which are 0-5
+ private boolean isValidLocalStreamType(int streamType) {
+ return streamType >= AudioManager.STREAM_VOICE_CALL
+ && streamType <= AudioManager.STREAM_NOTIFICATION;
+ }
+
private KeyEventWakeLockReceiver mKeyEventReceiver = new KeyEventWakeLockReceiver(mHandler);
class KeyEventWakeLockReceiver extends ResultReceiver implements Runnable,
diff --git a/services/core/java/com/android/server/net/IpConfigStore.java b/services/core/java/com/android/server/net/IpConfigStore.java
index 857b9e9..b5a450d 100644
--- a/services/core/java/com/android/server/net/IpConfigStore.java
+++ b/services/core/java/com/android/server/net/IpConfigStore.java
@@ -122,8 +122,10 @@ public class IpConfigStore {
out.writeUTF(proxyProperties.getHost());
out.writeUTF(PROXY_PORT_KEY);
out.writeInt(proxyProperties.getPort());
- out.writeUTF(EXCLUSION_LIST_KEY);
- out.writeUTF(exclusionList);
+ if (exclusionList != null) {
+ out.writeUTF(EXCLUSION_LIST_KEY);
+ out.writeUTF(exclusionList);
+ }
written = true;
break;
case PAC:
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index a1085d3..5de1a64 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -260,9 +260,11 @@ public class ConditionProviders extends ManagedServices {
for (int i = 0; i < N; i++) {
final Condition c = conditions[i];
final ConditionRecord r = getRecordLocked(c.id, info.component);
+ final Condition oldCondition = r.condition;
+ final boolean conditionUpdate = oldCondition != null && !oldCondition.equals(c);
r.info = info;
r.condition = c;
- // if manual, exit zen if false (or failed)
+ // if manual, exit zen if false (or failed), update if true (and changed)
if (r.isManual) {
if (c.state == Condition.STATE_FALSE || c.state == Condition.STATE_ERROR) {
final boolean failed = c.state == Condition.STATE_ERROR;
@@ -275,6 +277,10 @@ public class ConditionProviders extends ManagedServices {
"manualConditionExit");
unsubscribeLocked(r);
r.isManual = false;
+ } else if (c.state == Condition.STATE_TRUE && conditionUpdate) {
+ if (DEBUG) Slog.d(TAG, "Current condition updated, still true. old="
+ + oldCondition + " new=" + c);
+ setZenModeCondition(c, "conditionUpdate");
}
}
// if automatic, exit zen if false (or failed), enter zen if true
@@ -559,7 +565,7 @@ public class ConditionProviders extends ManagedServices {
// enter downtime, or update mode if reconfigured during an active downtime
if (inDowntime && (mode == Global.ZEN_MODE_OFF || downtimeCurrent) && config != null) {
final Condition condition = mDowntime.createCondition(config.toDowntimeInfo(),
- Condition.STATE_TRUE);
+ config.sleepNone, Condition.STATE_TRUE);
mZenModeHelper.setZenMode(downtimeMode, "downtimeEnter");
setZenModeCondition(condition, "downtime");
}
diff --git a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
index 0fb5732..097589a 100644
--- a/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
+++ b/services/core/java/com/android/server/notification/DowntimeConditionProvider.java
@@ -122,7 +122,8 @@ public class DowntimeConditionProvider extends ConditionProviderService {
if (DEBUG) Slog.d(TAG, "onRequestConditions relevance=" + relevance);
if ((relevance & Condition.FLAG_RELEVANT_NOW) != 0) {
if (isInDowntime() && mConfig != null) {
- notifyCondition(createCondition(mConfig.toDowntimeInfo(), Condition.STATE_TRUE));
+ notifyCondition(createCondition(mConfig.toDowntimeInfo(), mConfig.sleepNone,
+ Condition.STATE_TRUE));
}
}
}
@@ -135,7 +136,7 @@ public class DowntimeConditionProvider extends ConditionProviderService {
final int state = mConfig.toDowntimeInfo().equals(downtime) && isInDowntime()
? Condition.STATE_TRUE : Condition.STATE_FALSE;
if (DEBUG) Slog.d(TAG, "notify condition state: " + Condition.stateToString(state));
- notifyCondition(createCondition(downtime, state));
+ notifyCondition(createCondition(downtime, mConfig.sleepNone, state));
}
}
@@ -157,14 +158,22 @@ public class DowntimeConditionProvider extends ConditionProviderService {
return mDowntimeMode != Global.ZEN_MODE_OFF;
}
- public Condition createCondition(DowntimeInfo downtime, int state) {
+ public Condition createCondition(DowntimeInfo downtime, boolean orAlarm, int state) {
if (downtime == null) return null;
final Uri id = ZenModeConfig.toDowntimeConditionId(downtime);
final String skeleton = DateFormat.is24HourFormat(mContext) ? "Hm" : "hma";
final Locale locale = Locale.getDefault();
final String pattern = DateFormat.getBestDateTimePattern(locale, skeleton);
- final long time = getTime(System.currentTimeMillis(), downtime.endHour, downtime.endMinute);
- final String formatted = new SimpleDateFormat(pattern, locale).format(new Date(time));
+ final long now = System.currentTimeMillis();
+ long endTime = getTime(now, downtime.endHour, downtime.endMinute);
+ if (orAlarm) {
+ final AlarmClockInfo nextAlarm = mTracker.getNextAlarm();
+ final long nextAlarmTime = nextAlarm != null ? nextAlarm.getTriggerTime() : 0;
+ if (nextAlarmTime > now && nextAlarmTime < endTime) {
+ endTime = nextAlarmTime;
+ }
+ }
+ final String formatted = new SimpleDateFormat(pattern, locale).format(new Date(endTime));
final String summary = mContext.getString(R.string.downtime_condition_summary, formatted);
final String line1 = mContext.getString(R.string.downtime_condition_line_one);
return new Condition(id, summary, line1, formatted, 0, state, Condition.FLAG_RELEVANT_NOW);
@@ -302,6 +311,11 @@ public class DowntimeConditionProvider extends ConditionProviderService {
private void onEvaluateNextAlarm(AlarmClockInfo nextAlarm, long wakeupTime, boolean booted) {
if (!booted) return; // we don't know yet
+ // update condition description if we're in downtime (mode = none)
+ if (isInDowntime() && mConfig != null && mConfig.sleepNone) {
+ notifyCondition(createCondition(mConfig.toDowntimeInfo(), true /*orAlarm*/,
+ Condition.STATE_TRUE));
+ }
if (nextAlarm == null) return; // not fireable
if (DEBUG) Slog.d(TAG, "onEvaluateNextAlarm " + mTracker.formatAlarmDebug(nextAlarm));
if (System.currentTimeMillis() > wakeupTime) {
@@ -336,6 +350,10 @@ public class DowntimeConditionProvider extends ConditionProviderService {
} else if (Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
if (DEBUG) Slog.d(TAG, "timezone changed to " + TimeZone.getDefault());
mCalendar.setTimeZone(TimeZone.getDefault());
+ mFiredAlarms.clear();
+ } else if (Intent.ACTION_TIME_CHANGED.equals(action)) {
+ if (DEBUG) Slog.d(TAG, "time changed to " + now);
+ mFiredAlarms.clear();
} else {
if (DEBUG) Slog.d(TAG, action + " fired at " + now);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 42a8551..6958ff8 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1931,12 +1931,7 @@ public class NotificationManagerService extends SystemService {
if (hasValidSound) {
boolean looping =
(notification.flags & Notification.FLAG_INSISTENT) != 0;
- AudioAttributes audioAttributes;
- if (notification.audioAttributes != null) {
- audioAttributes = notification.audioAttributes;
- } else {
- audioAttributes = Notification.AUDIO_ATTRIBUTES_DEFAULT;
- }
+ AudioAttributes audioAttributes = audioAttributesForNotification(notification);
mSoundNotification = record;
// do not play notifications if stream volume is 0 (typically because
// ringer mode is silent) or if there is a user of exclusive audio focus
@@ -2030,7 +2025,9 @@ public class NotificationManagerService extends SystemService {
}
private static AudioAttributes audioAttributesForNotification(Notification n) {
- if (n.audioAttributes != null) {
+ if (n.audioAttributes != null
+ && !Notification.AUDIO_ATTRIBUTES_DEFAULT.equals(n.audioAttributes)) {
+ // the audio attributes are set and different from the default, use them
return n.audioAttributes;
} else if (n.audioStreamType >= 0 && n.audioStreamType < AudioSystem.getNumStreamTypes()) {
// the stream type is valid, use it
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 9a2451e..195a886 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4278,7 +4278,7 @@ public class PackageManagerService extends IPackageManager.Stub {
if (pkg.mVersionCode < ps.versionCode) {
// The system package has been updated and the code path does not match
// Ignore entry. Skip it.
- logCriticalInfo(Log.INFO, "Package " + ps.name + " at " + scanFile
+ Slog.i(TAG, "Package " + ps.name + " at " + scanFile
+ " ignored: updated version " + ps.versionCode
+ " better than this " + pkg.mVersionCode);
if (!updatedPkg.codePath.equals(scanFile)) {
@@ -6437,7 +6437,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mResolveActivity.applicationInfo = pkg.applicationInfo;
mResolveActivity.name = mCustomResolverComponentName.getClassName();
mResolveActivity.packageName = pkg.applicationInfo.packageName;
- mResolveActivity.processName = null;
+ mResolveActivity.processName = pkg.applicationInfo.packageName;
mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS |
ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
@@ -8982,6 +8982,7 @@ public class PackageManagerService extends IPackageManager.Stub {
&& isVerificationEnabled(userIdentifier, installFlags)) {
final Intent verification = new Intent(
Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
+ verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
verification.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
PACKAGE_MIME_TYPE);
verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 0cf2249..db0f53b 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1298,7 +1298,12 @@ public class UserManagerService extends IUserManager.Stub {
if (userHandle == 0 || user == null || mRemovingUserIds.get(userHandle)) {
return false;
}
+
+ // We remember deleted user IDs to prevent them from being
+ // reused during the current boot; they can still be reused
+ // after a reboot.
mRemovingUserIds.put(userHandle, true);
+
try {
mAppOpsService.removeUser(userHandle);
} catch (RemoteException e) {
@@ -1387,18 +1392,6 @@ public class UserManagerService extends IUserManager.Stub {
// Remove this user from the list
mUsers.remove(userHandle);
- // Have user ID linger for several seconds to let external storage VFS
- // cache entries expire. This must be greater than the 'entry_valid'
- // timeout used by the FUSE daemon.
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- synchronized (mPackagesLock) {
- mRemovingUserIds.delete(userHandle);
- }
- }
- }, MINUTE_IN_MILLIS);
-
mRestrictionsPinStates.remove(userHandle);
// Remove user file
AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX));
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c054e6c..4d8b98f 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -1234,6 +1234,7 @@ public final class PowerManagerService extends SystemService
// Phase 0: Basic state updates.
updateIsPoweredLocked(mDirty);
updateStayOnLocked(mDirty);
+ updateScreenBrightnessBoostLocked(mDirty);
// Phase 1: Update wakefulness.
// Loop because the wake lock and user activity computations are influenced
@@ -1641,7 +1642,8 @@ public final class PowerManagerService extends SystemService
|| mProximityPositive
|| (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) != 0
|| (mUserActivitySummary & (USER_ACTIVITY_SCREEN_BRIGHT
- | USER_ACTIVITY_SCREEN_DIM)) != 0;
+ | USER_ACTIVITY_SCREEN_DIM)) != 0
+ || mScreenBrightnessBoostInProgress;
}
/**
@@ -1828,9 +1830,6 @@ public final class PowerManagerService extends SystemService
| DIRTY_SETTINGS | DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
mDisplayPowerRequest.policy = getDesiredScreenPolicyLocked();
- // Handle screen brightness boost timeout.
- updateScreenBrightnessBoostLocked();
-
// Determine appropriate screen brightness and auto-brightness adjustments.
int screenBrightness = mScreenBrightnessSettingDefault;
float screenAutoBrightnessAdjustment = 0.0f;
@@ -1879,7 +1878,7 @@ public final class PowerManagerService extends SystemService
}
mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
- mRequestWaitForNegativeProximity) && !mScreenBrightnessBoostInProgress;
+ mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
if (DEBUG_SPEW) {
@@ -1896,20 +1895,25 @@ public final class PowerManagerService extends SystemService
return mDisplayReady && !oldDisplayReady;
}
- private void updateScreenBrightnessBoostLocked() {
- if (mScreenBrightnessBoostInProgress) {
- mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
- if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
- final long boostTimeout = mLastScreenBrightnessBoostTime +
- SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
- if (boostTimeout > SystemClock.uptimeMillis()) {
- Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
- msg.setAsynchronous(true);
- mHandler.sendMessageAtTime(msg, boostTimeout);
- return;
+ private void updateScreenBrightnessBoostLocked(int dirty) {
+ if ((dirty & DIRTY_SCREEN_BRIGHTNESS_BOOST) != 0) {
+ if (mScreenBrightnessBoostInProgress) {
+ final long now = SystemClock.uptimeMillis();
+ mHandler.removeMessages(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
+ if (mLastScreenBrightnessBoostTime > mLastSleepTime) {
+ final long boostTimeout = mLastScreenBrightnessBoostTime +
+ SCREEN_BRIGHTNESS_BOOST_TIMEOUT;
+ if (boostTimeout > now) {
+ Message msg = mHandler.obtainMessage(MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageAtTime(msg, boostTimeout);
+ return;
+ }
}
+ mScreenBrightnessBoostInProgress = false;
+ userActivityNoUpdateLocked(now,
+ PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
- mScreenBrightnessBoostInProgress = false;
}
}
@@ -1940,7 +1944,8 @@ public final class PowerManagerService extends SystemService
if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
|| (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
- || !mBootCompleted) {
+ || !mBootCompleted
+ || mScreenBrightnessBoostInProgress) {
return DisplayPowerRequest.POLICY_BRIGHT;
}
@@ -2037,15 +2042,13 @@ public final class PowerManagerService extends SystemService
final boolean needWakeLockSuspendBlocker = ((mWakeLockSummary & WAKE_LOCK_CPU) != 0);
final boolean needDisplaySuspendBlocker = needDisplaySuspendBlockerLocked();
final boolean autoSuspend = !needDisplaySuspendBlocker;
+ final boolean interactive = mDisplayPowerRequest.isBrightOrDim();
// Disable auto-suspend if needed.
- if (!autoSuspend) {
- if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
- setHalAutoSuspendModeLocked(false);
- }
- if (mDecoupleHalInteractiveModeFromDisplayConfig) {
- setHalInteractiveModeLocked(true);
- }
+ // FIXME We should consider just leaving auto-suspend enabled forever since
+ // we already hold the necessary wakelocks.
+ if (!autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+ setHalAutoSuspendModeLocked(false);
}
// First acquire suspend blockers if needed.
@@ -2058,6 +2061,22 @@ public final class PowerManagerService extends SystemService
mHoldingDisplaySuspendBlocker = true;
}
+ // Inform the power HAL about interactive mode.
+ // Although we could set interactive strictly based on the wakefulness
+ // as reported by isInteractive(), it is actually more desirable to track
+ // the display policy state instead so that the interactive state observed
+ // by the HAL more accurately tracks transitions between AWAKE and DOZING.
+ // Refer to getDesiredScreenPolicyLocked() for details.
+ if (mDecoupleHalInteractiveModeFromDisplayConfig) {
+ // When becoming non-interactive, we want to defer sending this signal
+ // until the display is actually ready so that all transitions have
+ // completed. This is probably a good sign that things have gotten
+ // too tangled over here...
+ if (interactive || mDisplayReady) {
+ setHalInteractiveModeLocked(interactive);
+ }
+ }
+
// Then release suspend blockers if needed.
if (!needWakeLockSuspendBlocker && mHoldingWakeLockSuspendBlocker) {
mWakeLockSuspendBlocker.release();
@@ -2069,13 +2088,8 @@ public final class PowerManagerService extends SystemService
}
// Enable auto-suspend if needed.
- if (autoSuspend) {
- if (mDecoupleHalInteractiveModeFromDisplayConfig) {
- setHalInteractiveModeLocked(false);
- }
- if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
- setHalAutoSuspendModeLocked(true);
- }
+ if (autoSuspend && mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+ setHalAutoSuspendModeLocked(true);
}
}
@@ -2097,6 +2111,9 @@ public final class PowerManagerService extends SystemService
return true;
}
}
+ if (mScreenBrightnessBoostInProgress) {
+ return true;
+ }
// Let the system suspend if the screen is off or dozing.
return false;
}
diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
index 4906bd1..57b204d 100644
--- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java
+++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java
@@ -232,6 +232,12 @@ public class TrustAgentWrapper {
mTrustManagerService.mArchive.logAgentConnected(mUserId, name);
setCallback(mCallback);
updateDevicePolicyFeatures();
+
+ if (mTrustManagerService.isDeviceLockedInner(mUserId)) {
+ onDeviceLocked();
+ } else {
+ onDeviceUnlocked();
+ }
}
@Override
@@ -287,6 +293,7 @@ public class TrustAgentWrapper {
onError(e);
}
}
+
/**
* @see android.service.trust.TrustAgentService#onUnlockAttempt(boolean)
*/
@@ -298,6 +305,28 @@ public class TrustAgentWrapper {
}
}
+ /**
+ * @see android.service.trust.TrustAgentService#onDeviceLocked()
+ */
+ public void onDeviceLocked() {
+ try {
+ if (mTrustAgentService != null) mTrustAgentService.onDeviceLocked();
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
+ /**
+ * @see android.service.trust.TrustAgentService#onDeviceUnlocked()
+ */
+ public void onDeviceUnlocked() {
+ try {
+ if (mTrustAgentService != null) mTrustAgentService.onDeviceUnlocked();
+ } catch (RemoteException e) {
+ onError(e);
+ }
+ }
+
private void setCallback(ITrustAgentServiceCallback callback) {
try {
if (mTrustAgentService != null) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 2388c85..a2ea1c8 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -26,7 +26,6 @@ import org.xmlpull.v1.XmlPullParserException;
import android.Manifest;
import android.app.ActivityManager;
-import android.app.ActivityManagerNative;
import android.app.admin.DevicePolicyManager;
import android.app.trust.ITrustListener;
import android.app.trust.ITrustManager;
@@ -61,6 +60,8 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.Xml;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -96,6 +97,10 @@ public class TrustManagerService extends SystemService {
private static final int MSG_DISPATCH_UNLOCK_ATTEMPT = 3;
private static final int MSG_ENABLED_AGENTS_CHANGED = 4;
private static final int MSG_REQUIRE_CREDENTIAL_ENTRY = 5;
+ private static final int MSG_KEYGUARD_SHOWING_CHANGED = 6;
+ private static final int MSG_START_USER = 7;
+ private static final int MSG_CLEANUP_USER = 8;
+ private static final int MSG_SWITCH_USER = 9;
private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<AgentInfo>();
private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<ITrustListener>();
@@ -110,7 +115,11 @@ public class TrustManagerService extends SystemService {
@GuardedBy("mUserIsTrusted")
private final SparseBooleanArray mUserIsTrusted = new SparseBooleanArray();
+ @GuardedBy("mDeviceLockedForUser")
+ private final SparseBooleanArray mDeviceLockedForUser = new SparseBooleanArray();
+
private boolean mTrustAgentsCanRun = false;
+ private int mCurrentUser = UserHandle.USER_OWNER;
public TrustManagerService(Context context) {
super(context);
@@ -177,10 +186,15 @@ public class TrustManagerService extends SystemService {
public void updateTrust(int userId, boolean initiatedByUser) {
dispatchOnTrustManagedChanged(aggregateIsTrustManaged(userId), userId);
boolean trusted = aggregateIsTrusted(userId);
+ boolean changed;
synchronized (mUserIsTrusted) {
+ changed = mUserIsTrusted.get(userId) != trusted;
mUserIsTrusted.put(userId, trusted);
}
dispatchOnTrustChanged(trusted, userId, initiatedByUser);
+ if (changed) {
+ refreshDeviceLockedForUser(userId);
+ }
}
void refreshAgentList(int userId) {
@@ -212,8 +226,7 @@ public class TrustManagerService extends SystemService {
|| userInfo.guestToRemove) continue;
if (!userInfo.supportsSwitchTo()) continue;
if (!mActivityManager.isUserRunning(userInfo.id)) continue;
- if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id)
- == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue;
+ if (!lockPatternUtils.isSecure(userInfo.id)) continue;
if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue;
DevicePolicyManager dpm = lockPatternUtils.getDevicePolicyManager();
int disabledFeatures = dpm.getKeyguardDisabledFeatures(null, userInfo.id);
@@ -273,6 +286,73 @@ public class TrustManagerService extends SystemService {
}
}
+ boolean isDeviceLockedInner(int userId) {
+ synchronized (mDeviceLockedForUser) {
+ return mDeviceLockedForUser.get(userId, true);
+ }
+ }
+
+ private void refreshDeviceLockedForUser(int userId) {
+ if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) {
+ Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle,"
+ + " must be USER_ALL or a specific user.", new Throwable("here"));
+ userId = UserHandle.USER_ALL;
+ }
+
+ List<UserInfo> userInfos;
+ if (userId == UserHandle.USER_ALL) {
+ userInfos = mUserManager.getUsers(true /* excludeDying */);
+ } else {
+ userInfos = new ArrayList<>();
+ userInfos.add(mUserManager.getUserInfo(userId));
+ }
+
+ IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
+
+ for (int i = 0; i < userInfos.size(); i++) {
+ UserInfo info = userInfos.get(i);
+
+ if (info == null || info.partial || !info.isEnabled() || info.guestToRemove
+ || !info.supportsSwitchTo()) {
+ continue;
+ }
+
+ int id = info.id;
+ boolean secure = mLockPatternUtils.isSecure(id);
+ boolean trusted = aggregateIsTrusted(id);
+ boolean showingKeyguard = true;
+ if (mCurrentUser == id) {
+ try {
+ showingKeyguard = wm.isKeyguardLocked();
+ } catch (RemoteException e) {
+ }
+ }
+ boolean deviceLocked = secure && showingKeyguard && !trusted;
+
+ boolean changed;
+ synchronized (mDeviceLockedForUser) {
+ changed = isDeviceLockedInner(id) != deviceLocked;
+ mDeviceLockedForUser.put(id, deviceLocked);
+ }
+ if (changed) {
+ dispatchDeviceLocked(id, deviceLocked);
+ }
+ }
+ }
+
+ private void dispatchDeviceLocked(int userId, boolean isLocked) {
+ for (int i = 0; i < mActiveAgents.size(); i++) {
+ AgentInfo agent = mActiveAgents.valueAt(i);
+ if (agent.userId == userId) {
+ if (isLocked) {
+ agent.agent.onDeviceLocked();
+ } else{
+ agent.agent.onDeviceUnlocked();
+ }
+ }
+ }
+ }
+
void updateDevicePolicyFeatures() {
for (int i = 0; i < mActiveAgents.size(); i++) {
AgentInfo info = mActiveAgents.valueAt(i);
@@ -540,12 +620,17 @@ public class TrustManagerService extends SystemService {
@Override
public void onStartUser(int userId) {
- refreshAgentList(userId);
+ mHandler.obtainMessage(MSG_START_USER, userId, 0, null).sendToTarget();
}
@Override
public void onCleanupUser(int userId) {
- refreshAgentList(userId);
+ mHandler.obtainMessage(MSG_CLEANUP_USER, userId, 0, null).sendToTarget();
+ }
+
+ @Override
+ public void onSwitchUser(int userId) {
+ mHandler.obtainMessage(MSG_SWITCH_USER, userId, 0, null).sendToTarget();
}
// Plumbing
@@ -578,6 +663,14 @@ public class TrustManagerService extends SystemService {
}
@Override
+ public void reportKeyguardShowingChanged() throws RemoteException {
+ enforceReportPermission();
+ // coalesce refresh messages.
+ mHandler.removeMessages(MSG_KEYGUARD_SHOWING_CHANGED);
+ mHandler.sendEmptyMessage(MSG_KEYGUARD_SHOWING_CHANGED);
+ }
+
+ @Override
public void registerTrustListener(ITrustListener trustListener) throws RemoteException {
enforceListenerPermission();
mHandler.obtainMessage(MSG_REGISTER_LISTENER, trustListener).sendToTarget();
@@ -590,13 +683,12 @@ public class TrustManagerService extends SystemService {
}
@Override
- public boolean isTrusted(int userId) throws RemoteException {
+ public boolean isDeviceLocked(int userId) throws RemoteException {
userId = ActivityManager.handleIncomingUser(getCallingPid(), getCallingUid(), userId,
- false /* allowAll */, true /* requireFull */, "isTrusted", null);
+ false /* allowAll */, true /* requireFull */, "isDeviceLocked", null);
userId = resolveProfileParent(userId);
- synchronized (mUserIsTrusted) {
- return mUserIsTrusted.get(userId);
- }
+
+ return isDeviceLockedInner(userId);
}
private void enforceReportPermission() {
@@ -621,19 +713,13 @@ public class TrustManagerService extends SystemService {
fout.println("disabled because the third-party apps can't run yet.");
return;
}
- final UserInfo currentUser;
final List<UserInfo> userInfos = mUserManager.getUsers(true /* excludeDying */);
- try {
- currentUser = ActivityManagerNative.getDefault().getCurrentUser();
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
mHandler.runWithScissors(new Runnable() {
@Override
public void run() {
fout.println("Trust manager state:");
for (UserInfo user : userInfos) {
- dumpUser(fout, user, user.id == currentUser.id);
+ dumpUser(fout, user, user.id == mCurrentUser);
}
}
}, 1500);
@@ -642,11 +728,17 @@ public class TrustManagerService extends SystemService {
private void dumpUser(PrintWriter fout, UserInfo user, boolean isCurrent) {
fout.printf(" User \"%s\" (id=%d, flags=%#x)",
user.name, user.id, user.flags);
+ if (!user.supportsSwitchTo()) {
+ fout.println("(managed profile)");
+ fout.println(" disabled because switching to this user is not possible.");
+ return;
+ }
if (isCurrent) {
fout.print(" (current)");
}
fout.print(": trusted=" + dumpBool(aggregateIsTrusted(user.id)));
fout.print(", trustManaged=" + dumpBool(aggregateIsTrustManaged(user.id)));
+ fout.print(", deviceLocked=" + dumpBool(isDeviceLockedInner(user.id)));
fout.println();
fout.println(" Enabled agents:");
boolean duplicateSimpleNames = false;
@@ -711,10 +803,23 @@ public class TrustManagerService extends SystemService {
break;
case MSG_ENABLED_AGENTS_CHANGED:
refreshAgentList(UserHandle.USER_ALL);
+ // This is also called when the security mode of a user changes.
+ refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
case MSG_REQUIRE_CREDENTIAL_ENTRY:
requireCredentialEntry(msg.arg1);
break;
+ case MSG_KEYGUARD_SHOWING_CHANGED:
+ refreshDeviceLockedForUser(UserHandle.USER_CURRENT);
+ break;
+ case MSG_START_USER:
+ case MSG_CLEANUP_USER:
+ refreshAgentList(msg.arg1);
+ break;
+ case MSG_SWITCH_USER:
+ mCurrentUser = msg.arg1;
+ refreshDeviceLockedForUser(UserHandle.USER_ALL);
+ break;
}
}
};
@@ -756,8 +861,14 @@ public class TrustManagerService extends SystemService {
int userId = getUserId(intent);
if (userId > 0) {
mUserHasAuthenticatedSinceBoot.delete(userId);
- mUserIsTrusted.delete(userId);
+ synchronized (mUserIsTrusted) {
+ mUserIsTrusted.delete(userId);
+ }
+ synchronized (mDeviceLockedForUser) {
+ mDeviceLockedForUser.delete(userId);
+ }
refreshAgentList(userId);
+ refreshDeviceLockedForUser(userId);
}
}
}
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 85659cf..716487c 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -299,6 +299,13 @@ class TvInputHardwareManager implements TvInputHal.Callback {
return -1;
}
+ private static boolean intArrayContains(int[] array, int value) {
+ for (int element : array) {
+ if (element == value) return true;
+ }
+ return false;
+ }
+
public void addHdmiTvInput(int id, TvInputInfo info) {
if (info.getType() != TvInputInfo.TYPE_HDMI) {
throw new IllegalArgumentException("info (" + info + ") has non-HDMI type.");
@@ -673,28 +680,35 @@ class TvInputHardwareManager implements TvInputHal.Callback {
if (mReleased) {
throw new IllegalStateException("Device already released.");
}
- if (surface != null && config == null) {
- return false;
- }
- if (surface == null && mActiveConfig == null) {
- return false;
- }
- int result = TvInputHal.ERROR_UNKNOWN;
+ int result = TvInputHal.SUCCESS;
if (surface == null) {
- result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
- mActiveConfig = null;
+ // The value of config is ignored when surface == null.
+ if (mActiveConfig != null) {
+ result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
+ mActiveConfig = null;
+ } else {
+ // We already have no active stream.
+ return true;
+ }
} else {
- if (!config.equals(mActiveConfig)) {
+ // It's impossible to set a non-null surface with a null config.
+ if (config == null) {
+ return false;
+ }
+ // Remove stream only if we have an existing active configuration.
+ if (mActiveConfig != null && !config.equals(mActiveConfig)) {
result = mHal.removeStream(mInfo.getDeviceId(), mActiveConfig);
if (result != TvInputHal.SUCCESS) {
mActiveConfig = null;
- return false;
}
}
- result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config);
+ // Proceed only if all previous operations succeeded.
if (result == TvInputHal.SUCCESS) {
- mActiveConfig = config;
+ result = mHal.addOrUpdateStream(mInfo.getDeviceId(), surface, config);
+ if (result == TvInputHal.SUCCESS) {
+ mActiveConfig = config;
+ }
}
}
updateAudioConfigLocked();
@@ -755,20 +769,64 @@ class TvInputHardwareManager implements TvInputHal.Callback {
AudioPortConfig sinkConfig = mAudioSink.activeConfig();
AudioPatch[] audioPatchArray = new AudioPatch[] { mAudioPatch };
boolean shouldRecreateAudioPatch = sourceUpdated || sinkUpdated;
+
+ int sinkSamplingRate = mDesiredSamplingRate;
+ int sinkChannelMask = mDesiredChannelMask;
+ int sinkFormat = mDesiredFormat;
+ // If sinkConfig != null and values are set to default, fill in the sinkConfig values.
+ if (sinkConfig != null) {
+ if (sinkSamplingRate == 0) {
+ sinkSamplingRate = sinkConfig.samplingRate();
+ }
+ if (sinkChannelMask == AudioFormat.CHANNEL_OUT_DEFAULT) {
+ sinkChannelMask = sinkConfig.channelMask();
+ }
+ if (sinkFormat == AudioFormat.ENCODING_DEFAULT) {
+ sinkChannelMask = sinkConfig.format();
+ }
+ }
+
if (sinkConfig == null
- || (mDesiredSamplingRate != 0
- && sinkConfig.samplingRate() != mDesiredSamplingRate)
- || (mDesiredChannelMask != AudioFormat.CHANNEL_OUT_DEFAULT
- && sinkConfig.channelMask() != mDesiredChannelMask)
- || (mDesiredFormat != AudioFormat.ENCODING_DEFAULT
- && sinkConfig.format() != mDesiredFormat)) {
- sinkConfig = mAudioSink.buildConfig(mDesiredSamplingRate, mDesiredChannelMask,
- mDesiredFormat, null);
+ || sinkConfig.samplingRate() != sinkSamplingRate
+ || sinkConfig.channelMask() != sinkChannelMask
+ || sinkConfig.format() != sinkFormat) {
+ // Check for compatibility and reset to default if necessary.
+ if (!intArrayContains(mAudioSink.samplingRates(), sinkSamplingRate)
+ && mAudioSink.samplingRates().length > 0) {
+ sinkSamplingRate = mAudioSink.samplingRates()[0];
+ }
+ if (!intArrayContains(mAudioSink.channelMasks(), sinkChannelMask)) {
+ sinkChannelMask = AudioFormat.CHANNEL_OUT_DEFAULT;
+ }
+ if (!intArrayContains(mAudioSink.formats(), sinkFormat)) {
+ sinkFormat = AudioFormat.ENCODING_DEFAULT;
+ }
+ sinkConfig = mAudioSink.buildConfig(sinkSamplingRate, sinkChannelMask,
+ sinkFormat, null);
shouldRecreateAudioPatch = true;
}
if (sourceConfig == null || sourceGainConfig != null) {
- sourceConfig = mAudioSource.buildConfig(sinkConfig.samplingRate(),
- sinkConfig.channelMask(), sinkConfig.format(), sourceGainConfig);
+ int sourceSamplingRate = 0;
+ if (intArrayContains(mAudioSource.samplingRates(), sinkConfig.samplingRate())) {
+ sourceSamplingRate = sinkConfig.samplingRate();
+ } else if (mAudioSource.samplingRates().length > 0) {
+ // Use any sampling rate and hope audio patch can handle resampling...
+ sourceSamplingRate = mAudioSource.samplingRates()[0];
+ }
+ int sourceChannelMask = AudioFormat.CHANNEL_IN_DEFAULT;
+ for (int inChannelMask : mAudioSource.channelMasks()) {
+ if (AudioFormat.channelCountFromOutChannelMask(sinkConfig.channelMask())
+ == AudioFormat.channelCountFromInChannelMask(inChannelMask)) {
+ sourceChannelMask = inChannelMask;
+ break;
+ }
+ }
+ int sourceFormat = AudioFormat.ENCODING_DEFAULT;
+ if (intArrayContains(mAudioSource.formats(), sinkConfig.format())) {
+ sourceFormat = sinkConfig.format();
+ }
+ sourceConfig = mAudioSource.buildConfig(sourceSamplingRate, sourceChannelMask,
+ sourceFormat, sourceGainConfig);
shouldRecreateAudioPatch = true;
}
if (shouldRecreateAudioPatch) {
@@ -778,6 +836,9 @@ class TvInputHardwareManager implements TvInputHal.Callback {
new AudioPortConfig[] { sourceConfig },
new AudioPortConfig[] { sinkConfig });
mAudioPatch = audioPatchArray[0];
+ if (sourceGainConfig != null) {
+ mAudioManager.setAudioPortGain(mAudioSource, sourceGainConfig);
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index f947b6a..0cbf03a 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -984,12 +984,7 @@ final class AccessibilityController {
final int visibleWindowCount = visibleWindows.size();
for (int i = visibleWindowCount - 1; i >= 0; i--) {
- WindowState windowState = visibleWindows.valueAt(i);
-
- // Compute the bounds in the screen.
- Rect boundsInScreen = mTempRect;
- computeWindowBoundsInScreen(windowState, boundsInScreen);
-
+ final WindowState windowState = visibleWindows.valueAt(i);
final int flags = windowState.mAttrs.flags;
// If the window is not touchable - ignore.
@@ -997,6 +992,10 @@ final class AccessibilityController {
continue;
}
+ // Compute the bounds in the screen.
+ final Rect boundsInScreen = mTempRect;
+ computeWindowBoundsInScreen(windowState, boundsInScreen);
+
// If the window is completely covered by other windows - ignore.
if (unaccountedSpace.quickReject(boundsInScreen)) {
continue;
@@ -1016,8 +1015,8 @@ final class AccessibilityController {
// Account for the space this window takes if the window
// is not an accessibility overlay which does not change
// the reported windows.
- if (windowState.mAttrs.type == WindowManager.LayoutParams
- .TYPE_ACCESSIBILITY_OVERLAY) {
+ if (windowState.mAttrs.type !=
+ WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY) {
unaccountedSpace.op(boundsInScreen, unaccountedSpace,
Region.Op.REVERSE_DIFFERENCE);
}
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 1086eb2..f859fd2 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -254,15 +254,18 @@ class AppWindowToken extends WindowToken {
@Override
void removeAllWindows() {
- int winNdx;
- while ((winNdx = allAppWindows.size()) > 0) {
- WindowState win = allAppWindows.get(winNdx - 1);
+ for (int winNdx = allAppWindows.size() - 1; winNdx >= 0;
+ // removeWindowLocked at bottom of loop may remove multiple entries from
+ // allAppWindows if the window to be removed has child windows. It also may
+ // not remove any windows from allAppWindows at all if win is exiting and
+ // currently animating away. This ensures that winNdx is monotonically decreasing
+ // and never beyond allAppWindows bounds.
+ winNdx = Math.min(winNdx - 1, allAppWindows.size() - 1)) {
+ WindowState win = allAppWindows.get(winNdx);
if (WindowManagerService.DEBUG_WINDOW_MOVEMENT) {
Slog.w(WindowManagerService.TAG, "removeAllWindows: removing win=" + win);
}
- // {@link WindowManagerService.removeWindowLocked} may remove multiple entries from
- // {@link #allAppWindows} if the window to be removed has child windows.
win.mService.removeWindowLocked(win.mSession, win);
}
}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index 345e8af..fe2e0a6 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -221,6 +221,24 @@ public class WindowAnimator {
}
}
+ private boolean shouldForceHide(WindowState win) {
+ final WindowState imeTarget = mService.mInputMethodTarget;
+ final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
+ (imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
+
+ final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
+ final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
+ null : winShowWhenLocked.mAppToken;
+ final boolean hideWhenLocked =
+ !(((win.mIsImWindow || imeTarget == win) && showImeOverKeyguard)
+ || (appShowWhenLocked != null && (appShowWhenLocked == win.mAppToken ||
+ // Show error dialogs over apps that dismiss keyguard.
+ (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0)));
+ return ((mForceHiding == KEYGUARD_ANIMATING_IN)
+ && (!win.mWinAnimator.isAnimating() || hideWhenLocked))
+ || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked);
+ }
+
private void updateWindowsLocked(final int displayId) {
++mAnimTransactionSequence;
@@ -256,14 +274,6 @@ public class WindowAnimator {
mForceHiding = KEYGUARD_NOT_SHOWN;
- final WindowState imeTarget = mService.mInputMethodTarget;
- final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() &&
- (imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0;
-
- final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw();
- final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ?
- null : winShowWhenLocked.mAppToken;
-
boolean wallpaperInUnForceHiding = false;
boolean startingInUnForceHiding = false;
ArrayList<WindowStateAnimator> unForceHiding = null;
@@ -272,7 +282,8 @@ public class WindowAnimator {
WindowState win = windows.get(i);
WindowStateAnimator winAnimator = win.mWinAnimator;
final int flags = win.mAttrs.flags;
-
+ boolean canBeForceHidden = mPolicy.canBeForceHidden(win, win.mAttrs);
+ boolean shouldBeForceHidden = shouldForceHide(win);
if (winAnimator.mSurfaceControl != null) {
final boolean wasAnimating = winAnimator.mWasAnimating;
final boolean nowAnimating = winAnimator.stepAnimationLocked(mCurrentTime);
@@ -332,15 +343,8 @@ public class WindowAnimator {
+ " vis=" + win.mViewVisibility
+ " hidden=" + win.mRootToken.hidden
+ " anim=" + win.mWinAnimator.mAnimation);
- } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
- final boolean hideWhenLocked =
- !(((win.mIsImWindow || imeTarget == win) && showImeOverKeyguard)
- || (appShowWhenLocked != null && (appShowWhenLocked == win.mAppToken ||
- // Show error dialogs over apps that dismiss keyguard.
- (win.mAttrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0)));
- if (((mForceHiding == KEYGUARD_ANIMATING_IN)
- && (!winAnimator.isAnimating() || hideWhenLocked))
- || ((mForceHiding == KEYGUARD_SHOWN) && hideWhenLocked)) {
+ } else if (canBeForceHidden) {
+ if (shouldBeForceHidden) {
if (!win.hideLw(false, false)) {
// Was already hidden
continue;
@@ -411,6 +415,16 @@ public class WindowAnimator {
}
}
+ // If the window doesn't have a surface, the only thing we care about is the correct
+ // policy visibility.
+ else if (canBeForceHidden) {
+ if (shouldBeForceHidden) {
+ win.hideLw(false, false);
+ } else {
+ win.showLw(false, false);
+ }
+ }
+
final AppWindowToken atoken = win.mAppToken;
if (winAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW) {
if (atoken == null || atoken.allDrawn) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index eb418ed..bcfd7f0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2541,7 +2541,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
mInputMonitor.updateInputWindowsLw(false /*force*/);
- if (true || localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG, "addWindow: New client "
+ if (localLOGV || DEBUG_ADD_REMOVE) Slog.v(TAG, "addWindow: New client "
+ client.asBinder() + ": window=" + win + " Callers=" + Debug.getCallers(5));
if (win.isVisibleOrAdding() && updateOrientationFromAppTokensLocked(false)) {
@@ -2706,8 +2706,7 @@ public class WindowManagerService extends IWindowManager.Stub
mPolicy.removeWindowLw(win);
win.removeLocked();
- if (true || DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win +
- " Callers=" + Debug.getCallers(5));
+ if (DEBUG_ADD_REMOVE) Slog.v(TAG, "removeWindowInnerLocked: " + win);
mWindowMap.remove(win.mClient.asBinder());
if (win.mAppOp != AppOpsManager.OP_NONE) {
mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6bf2606..b97f4f9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -901,23 +901,25 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (DBG) Slog.d(LOG_TAG, "Handling package changes for user " + userHandle);
DevicePolicyData policy = getUserData(userHandle);
IPackageManager pm = AppGlobals.getPackageManager();
- for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
- ActiveAdmin aa = policy.mAdminList.get(i);
- try {
- if (pm.getPackageInfo(aa.info.getPackageName(), 0, userHandle) == null
- || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) {
- removed = true;
- policy.mAdminList.remove(i);
- policy.mAdminMap.remove(aa.info.getComponent());
+ synchronized (this) {
+ for (int i = policy.mAdminList.size() - 1; i >= 0; i--) {
+ ActiveAdmin aa = policy.mAdminList.get(i);
+ try {
+ if (pm.getPackageInfo(aa.info.getPackageName(), 0, userHandle) == null
+ || pm.getReceiverInfo(aa.info.getComponent(), 0, userHandle) == null) {
+ removed = true;
+ policy.mAdminList.remove(i);
+ policy.mAdminMap.remove(aa.info.getComponent());
+ }
+ } catch (RemoteException re) {
+ // Shouldn't happen
}
- } catch (RemoteException re) {
- // Shouldn't happen
}
- }
- if (removed) {
- validatePasswordOwnerLocked(policy);
- syncDeviceCapabilitiesLocked(policy);
- saveSettingsLocked(policy.mUserHandle);
+ if (removed) {
+ validatePasswordOwnerLocked(policy);
+ syncDeviceCapabilitiesLocked(policy);
+ saveSettingsLocked(policy.mUserHandle);
+ }
}
}
@@ -3934,7 +3936,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int n = policy.mAdminList.size();
for (int i = 0; i < n; i++) {
ActiveAdmin admin = policy.mAdminList.get(i);
- if (profileOwner.equals(admin.info)) {
+ if (profileOwner.equals(admin.info.getComponent())) {
return admin;
}
}
@@ -5051,13 +5053,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
public boolean isUninstallBlocked(ComponentName who, String packageName) {
+ // This function should return true if and only if the package is blocked by
+ // setUninstallBlocked(). It should still return false for other cases of blocks, such as
+ // when the package is a system app, or when it is an active device admin.
final int userId = UserHandle.getCallingUserId();
synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
+ if (who != null) {
+ getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
}
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
long id = Binder.clearCallingIdentity();
try {
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index cc5d004..1cf00d2 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -207,7 +207,12 @@ public class UsbDebuggingManager implements Runnable {
case MESSAGE_ADB_CONFIRM: {
String key = (String)msg.obj;
- mFingerprints = getFingerprints(key);
+ String fingerprints = getFingerprints(key);
+ if ("".equals(fingerprints)) {
+ sendResponse("NO");
+ break;
+ }
+ mFingerprints = fingerprints;
startConfirmation(key, mFingerprints);
break;
}
@@ -224,16 +229,25 @@ public class UsbDebuggingManager implements Runnable {
StringBuilder sb = new StringBuilder();
MessageDigest digester;
+ if (key == null) {
+ return "";
+ }
+
try {
digester = MessageDigest.getInstance("MD5");
} catch (Exception ex) {
- Slog.e(TAG, "Error getting digester: " + ex);
+ Slog.e(TAG, "Error getting digester", ex);
return "";
}
byte[] base64_data = key.split("\\s+")[0].getBytes();
- byte[] digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT));
-
+ byte[] digest;
+ try {
+ digest = digester.digest(Base64.decode(base64_data, Base64.DEFAULT));
+ } catch (IllegalArgumentException e) {
+ Slog.e(TAG, "error doing base64 decoding", e);
+ return "";
+ }
for (int i = 0; i < digest.length; i++) {
sb.append(hex.charAt((digest[i] >> 4) & 0xf));
sb.append(hex.charAt(digest[i] & 0xf));
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index c63eb18..23ba3b6 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -209,8 +209,13 @@ public class UsbDeviceManager {
mUseUsbNotification = !massStorageSupported;
// make sure the ADB_ENABLED setting value matches the current state
- Settings.Global.putInt(mContentResolver, Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
-
+ try {
+ Settings.Global.putInt(mContentResolver,
+ Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+ } catch (SecurityException e) {
+ // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed.
+ Slog.d(TAG, "ADB_ENABLED is restricted.");
+ }
mHandler.sendEmptyMessage(MSG_SYSTEM_READY);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 82b7f8b..f5d4867 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -136,11 +136,14 @@ public class VoiceInteractionManagerService extends SystemService {
Settings.Secure.VOICE_INTERACTION_SERVICE, userHandle);
ComponentName curRecognizer = getCurRecognizer(userHandle);
VoiceInteractionServiceInfo curInteractorInfo = null;
- if (curInteractorStr == null && curRecognizer != null) {
+ if (curInteractorStr == null && curRecognizer != null
+ && !ActivityManager.isLowRamDeviceStatic()) {
// If there is no interactor setting, that means we are upgrading
// from an older platform version. If the current recognizer is not
// set or matches the preferred recognizer, then we want to upgrade
// the user to have the default voice interaction service enabled.
+ // Note that we don't do this for low-RAM devices, since we aren't
+ // supporting voice interaction services there.
curInteractorInfo = findAvailInteractor(userHandle, curRecognizer);
if (curInteractorInfo != null) {
// Looks good! We'll apply this one. To make it happen, we clear the
@@ -150,6 +153,15 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
+ // If we are on a svelte device, make sure an interactor is not currently
+ // enabled; if it is, turn it off.
+ if (ActivityManager.isLowRamDeviceStatic() && curInteractorStr != null) {
+ if (!TextUtils.isEmpty(curInteractorStr)) {
+ setCurInteractor(null, userHandle);
+ curInteractorStr = "";
+ }
+ }
+
if (curRecognizer != null) {
// If we already have at least a recognizer, then we probably want to
// leave things as they are... unless something has disappeared.
@@ -171,10 +183,11 @@ public class VoiceInteractionManagerService extends SystemService {
}
}
- // Initializing settings, look for an interactor first.
- if (curInteractorInfo == null) {
+ // Initializing settings, look for an interactor first (but only on non-svelte).
+ if (curInteractorInfo == null && !ActivityManager.isLowRamDeviceStatic()) {
curInteractorInfo = findAvailInteractor(userHandle, null);
}
+
if (curInteractorInfo != null) {
// Eventually it will be an error to not specify this.
setCurInteractor(new ComponentName(curInteractorInfo.getServiceInfo().packageName,