diff options
Diffstat (limited to 'services')
27 files changed, 1324 insertions, 563 deletions
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 94d400a..26510328 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -601,7 +601,7 @@ public class BackupManagerService { return token; } - // High level policy: apps are ineligible for backup if certain conditions apply + // High level policy: apps are generally ineligible for backup if certain conditions apply public static boolean appIsEligibleForBackup(ApplicationInfo app) { // 1. their manifest states android:allowBackup="false" if ((app.flags&ApplicationInfo.FLAG_ALLOW_BACKUP) == 0) { @@ -628,7 +628,7 @@ public class BackupManagerService { return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_FULL_BACKUP_ONLY) != 0; } - // No agent means we do full backups for it + // No agent or fullBackupOnly="true" means we do indeed perform full-data backups for it return true; } @@ -1266,7 +1266,23 @@ public class BackupManagerService { for (int i = 0; i < N; i++) { String pkgName = in.readUTF(); long lastBackup = in.readLong(); - schedule.add(new FullBackupEntry(pkgName, lastBackup)); + try { + PackageInfo pkg = mPackageManager.getPackageInfo(pkgName, 0); + if (appGetsFullBackup(pkg) + && appIsEligibleForBackup(pkg.applicationInfo)) { + schedule.add(new FullBackupEntry(pkgName, lastBackup)); + } else { + if (DEBUG) { + Slog.i(TAG, "Package " + pkgName + + " no longer eligible for full backup"); + } + } + } catch (NameNotFoundException e) { + if (DEBUG) { + Slog.i(TAG, "Package " + pkgName + + " not installed; dropping from full backup"); + } + } } Collections.sort(schedule); } catch (Exception e) { @@ -1289,7 +1305,7 @@ public class BackupManagerService { schedule = new ArrayList<FullBackupEntry>(N); for (int i = 0; i < N; i++) { PackageInfo info = apps.get(i); - if (appGetsFullBackup(info)) { + if (appGetsFullBackup(info) && appIsEligibleForBackup(info.applicationInfo)) { schedule.add(new FullBackupEntry(info.packageName, 0)); } } @@ -1761,11 +1777,11 @@ public class BackupManagerService { addPackageParticipantsLocked(pkgList); } // If they're full-backup candidates, add them there instead + final long now = System.currentTimeMillis(); for (String packageName : pkgList) { try { PackageInfo app = mPackageManager.getPackageInfo(packageName, 0); - long now = System.currentTimeMillis(); - if (appGetsFullBackup(app)) { + if (appGetsFullBackup(app) && appIsEligibleForBackup(app.applicationInfo)) { enqueueFullBackup(packageName, now); scheduleNextFullBackupJob(); } @@ -2462,7 +2478,7 @@ public class BackupManagerService { BackupRequest request = mQueue.get(0); mQueue.remove(0); - Slog.d(TAG, "starting agent for backup of " + request); + Slog.d(TAG, "starting key/value backup of " + request); addBackupTrace("launch agent for " + request.packageName); // Verify that the requested app exists; it might be something that @@ -2473,13 +2489,24 @@ public class BackupManagerService { try { mCurrentPackage = mPackageManager.getPackageInfo(request.packageName, PackageManager.GET_SIGNATURES); - if (mCurrentPackage.applicationInfo.backupAgentName == null) { + if (!appIsEligibleForBackup(mCurrentPackage.applicationInfo)) { // The manifest has changed but we had a stale backup request pending. // This won't happen again because the app won't be requesting further // backups. Slog.i(TAG, "Package " + request.packageName + " no longer supports backup; skipping"); - addBackupTrace("skipping - no agent, completion is noop"); + addBackupTrace("skipping - not eligible, completion is noop"); + executeNextState(BackupState.RUNNING_QUEUE); + return; + } + + if (appGetsFullBackup(mCurrentPackage)) { + // It's possible that this app *formerly* was enqueued for key/value backup, + // but has since been updated and now only supports the full-data path. + // Don't proceed with a key/value backup for it in this case. + Slog.i(TAG, "Package " + request.packageName + + " requests full-data rather than key/value; skipping"); + addBackupTrace("skipping - fullBackupOnly, completion is noop"); executeNextState(BackupState.RUNNING_QUEUE); return; } @@ -9161,6 +9188,8 @@ if (MORE_DEBUG) Slog.v(TAG, " + got " + nRead + "; now wanting " + (size - soF // check whether there is data for it in the current dataset, falling back // to the ancestral dataset if not. long token = getAvailableRestoreToken(packageName); + if (DEBUG) Slog.v(TAG, "restorePackage pkg=" + packageName + + " token=" + Long.toHexString(token)); // If we didn't come up with a place to look -- no ancestral dataset and // the app has never been backed up from this device -- there's nothing diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java index a2c87b9..e6dc1c7 100644 --- a/services/core/java/com/android/server/AssetAtlasService.java +++ b/services/core/java/com/android/server/AssetAtlasService.java @@ -291,7 +291,7 @@ public class AssetAtlasService extends IAssetAtlas.Stub { } canvas.drawBitmap(bitmap, 0.0f, 0.0f, null); canvas.restore(); - atlasMap[mapIndex++] = bitmap.mNativeBitmap; + atlasMap[mapIndex++] = bitmap.getSkBitmap(); atlasMap[mapIndex++] = entry.x; atlasMap[mapIndex++] = entry.y; atlasMap[mapIndex++] = entry.rotated ? 1 : 0; diff --git a/services/core/java/com/android/server/MidiService.java b/services/core/java/com/android/server/MidiService.java index 59b82da..7f98b30 100644 --- a/services/core/java/com/android/server/MidiService.java +++ b/services/core/java/com/android/server/MidiService.java @@ -17,10 +17,18 @@ package com.android.server; import android.content.Context; +import android.content.Intent; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.ServiceInfo; +import android.content.res.XmlResourceParser; +import android.media.midi.IMidiDeviceListener; import android.media.midi.IMidiDeviceServer; -import android.media.midi.IMidiListener; import android.media.midi.IMidiManager; import android.media.midi.MidiDeviceInfo; +import android.media.midi.MidiDeviceService; import android.os.Binder; import android.os.Bundle; import android.os.IBinder; @@ -28,12 +36,17 @@ import android.os.Process; import android.os.RemoteException; import android.util.Log; +import com.android.internal.content.PackageMonitor; import com.android.internal.util.IndentingPrintWriter; +import com.android.internal.util.XmlUtils; + +import org.xmlpull.v1.XmlPullParser; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; +import java.util.List; public class MidiService extends IMidiManager.Stub { private static final String TAG = "MidiService"; @@ -53,6 +66,27 @@ public class MidiService extends IMidiManager.Stub { // used for assigning IDs to MIDI devices private int mNextDeviceId = 1; + private final PackageManager mPackageManager; + + // PackageMonitor for listening to package changes + private final PackageMonitor mPackageMonitor = new PackageMonitor() { + @Override + public void onPackageAdded(String packageName, int uid) { + addPackageDeviceServers(packageName); + } + + @Override + public void onPackageModified(String packageName) { + removePackageDeviceServers(packageName); + addPackageDeviceServers(packageName); + } + + @Override + public void onPackageRemoved(String packageName, int uid) { + removePackageDeviceServers(packageName); + } + }; + private final class Client implements IBinder.DeathRecipient { // Binder token for this client private final IBinder mToken; @@ -61,7 +95,8 @@ public class MidiService extends IMidiManager.Stub { // This client's PID private final int mPid; // List of all receivers for this client - private final ArrayList<IMidiListener> mListeners = new ArrayList<IMidiListener>(); + private final ArrayList<IMidiDeviceListener> mListeners + = new ArrayList<IMidiDeviceListener>(); public Client(IBinder token) { mToken = token; @@ -73,11 +108,11 @@ public class MidiService extends IMidiManager.Stub { return mUid; } - public void addListener(IMidiListener listener) { + public void addListener(IMidiDeviceListener listener) { mListeners.add(listener); } - public void removeListener(IMidiListener listener) { + public void removeListener(IMidiDeviceListener listener) { mListeners.remove(listener); if (mListeners.size() == 0) { removeClient(mToken); @@ -90,7 +125,7 @@ public class MidiService extends IMidiManager.Stub { MidiDeviceInfo deviceInfo = device.getDeviceInfo(); try { - for (IMidiListener listener : mListeners) { + for (IMidiDeviceListener listener : mListeners) { listener.onDeviceAdded(deviceInfo); } } catch (RemoteException e) { @@ -104,7 +139,7 @@ public class MidiService extends IMidiManager.Stub { MidiDeviceInfo deviceInfo = device.getDeviceInfo(); try { - for (IMidiListener listener : mListeners) { + for (IMidiDeviceListener listener : mListeners) { listener.onDeviceRemoved(deviceInfo); } } catch (RemoteException e) { @@ -152,16 +187,17 @@ public class MidiService extends IMidiManager.Stub { private final class Device implements IBinder.DeathRecipient { private final IMidiDeviceServer mServer; private final MidiDeviceInfo mDeviceInfo; - // UID of device creator + // ServiceInfo for the device's MidiDeviceServer implementation (virtual devices only) + private final ServiceInfo mServiceInfo; + // UID of device implementation private final int mUid; - // PID of device creator - private final int mPid; - public Device(IMidiDeviceServer server, MidiDeviceInfo deviceInfo) { + public Device(IMidiDeviceServer server, MidiDeviceInfo deviceInfo, + ServiceInfo serviceInfo, int uid) { mServer = server; mDeviceInfo = deviceInfo; - mUid = Binder.getCallingUid(); - mPid = Binder.getCallingPid(); + mServiceInfo = serviceInfo; + mUid = uid; } public MidiDeviceInfo getDeviceInfo() { @@ -172,13 +208,20 @@ public class MidiService extends IMidiManager.Stub { return mServer; } + public ServiceInfo getServiceInfo() { + return mServiceInfo; + } + + public String getPackageName() { + return (mServiceInfo == null ? null : mServiceInfo.packageName); + } + public boolean isUidAllowed(int uid) { - // FIXME - return true; + return (!mDeviceInfo.isPrivate() || mUid == uid); } public void binderDied() { - synchronized (mDevicesByServer) { + synchronized (mDevicesByInfo) { removeDeviceLocked(this); } } @@ -189,32 +232,59 @@ public class MidiService extends IMidiManager.Stub { sb.append(mDeviceInfo); sb.append(" UID: "); sb.append(mUid); - sb.append(" PID: "); - sb.append(mPid); return sb.toString(); } } public MidiService(Context context) { mContext = context; - } + mPackageManager = context.getPackageManager(); + mPackageMonitor.register(context, null, true); + + Intent intent = new Intent(MidiDeviceService.SERVICE_INTERFACE); + List<ResolveInfo> resolveInfos = mPackageManager.queryIntentServices(intent, + PackageManager.GET_META_DATA); + if (resolveInfos != null) { + int count = resolveInfos.size(); + for (int i = 0; i < count; i++) { + ServiceInfo serviceInfo = resolveInfos.get(i).serviceInfo; + if (serviceInfo != null) { + addPackageDeviceServer(serviceInfo); + } + } + } + } - public void registerListener(IBinder token, IMidiListener listener) { + @Override + public void registerListener(IBinder token, IMidiDeviceListener listener) { Client client = getClient(token); if (client == null) return; client.addListener(listener); } - public void unregisterListener(IBinder token, IMidiListener listener) { + @Override + public void unregisterListener(IBinder token, IMidiDeviceListener listener) { Client client = getClient(token); if (client == null) return; client.removeListener(listener); } public MidiDeviceInfo[] getDeviceList() { - return mDevicesByInfo.keySet().toArray(new MidiDeviceInfo[0]); + ArrayList<MidiDeviceInfo> deviceInfos = new ArrayList<MidiDeviceInfo>(); + int uid = Binder.getCallingUid(); + + synchronized (mDevicesByInfo) { + for (Device device : mDevicesByInfo.values()) { + if (device.isUidAllowed(uid)) { + deviceInfos.add(device.getDeviceInfo()); + } + } + } + + return deviceInfos.toArray(new MidiDeviceInfo[0]); } + @Override public IMidiDeviceServer openDevice(IBinder token, MidiDeviceInfo deviceInfo) { Device device = mDevicesByInfo.get(deviceInfo); if (device == null) { @@ -229,28 +299,64 @@ public class MidiService extends IMidiManager.Stub { return device.getDeviceServer(); } + @Override public MidiDeviceInfo registerDeviceServer(IMidiDeviceServer server, int numInputPorts, - int numOutputPorts, Bundle properties, boolean isPrivate, int type) { + int numOutputPorts, Bundle properties, int type) { if (type != MidiDeviceInfo.TYPE_VIRTUAL && Binder.getCallingUid() != Process.SYSTEM_UID) { throw new SecurityException("only system can create non-virtual devices"); } - MidiDeviceInfo deviceInfo; - Device device; + synchronized (mDevicesByInfo) { + return addDeviceLocked(type, numInputPorts, numOutputPorts, properties, + server, null, false, -1); + } + } - synchronized (mDevicesByServer) { - int id = mNextDeviceId++; - deviceInfo = new MidiDeviceInfo(type, id, numInputPorts, numOutputPorts, properties); + @Override + public void unregisterDeviceServer(IMidiDeviceServer server) { + synchronized (mDevicesByInfo) { + Device device = mDevicesByServer.get(server.asBinder()); + if (device != null) { + removeDeviceLocked(device); + } + } + } + + @Override + public MidiDeviceInfo getServiceDeviceInfo(String packageName, String className) { + synchronized (mDevicesByInfo) { + for (Device device : mDevicesByInfo.values()) { + ServiceInfo serviceInfo = device.getServiceInfo(); + if (serviceInfo != null && + packageName.equals(serviceInfo.packageName) && + className.equals(serviceInfo.name)) { + return device.getDeviceInfo(); + } + } + return null; + } + } + + // synchronize on mDevicesByInfo + private MidiDeviceInfo addDeviceLocked(int type, int numInputPorts, int numOutputPorts, + Bundle properties, IMidiDeviceServer server, ServiceInfo serviceInfo, + boolean isPrivate, int uid) { + + int id = mNextDeviceId++; + MidiDeviceInfo deviceInfo = new MidiDeviceInfo(type, id, numInputPorts, numOutputPorts, + properties, isPrivate); + Device device = new Device(server, deviceInfo, serviceInfo, uid); + + if (server != null) { IBinder binder = server.asBinder(); - device = new Device(server, deviceInfo); try { binder.linkToDeath(device, 0); } catch (RemoteException e) { return null; } - mDevicesByInfo.put(deviceInfo, device); - mDevicesByServer.put(server.asBinder(), device); + mDevicesByServer.put(binder, device); } + mDevicesByInfo.put(deviceInfo, device); synchronized (mClients) { for (Client c : mClients.values()) { @@ -261,16 +367,13 @@ public class MidiService extends IMidiManager.Stub { return deviceInfo; } - public void unregisterDeviceServer(IMidiDeviceServer server) { - synchronized (mDevicesByServer) { - removeDeviceLocked(mDevicesByServer.get(server.asBinder())); - } - } - - // synchronize on mDevicesByServer + // synchronize on mDevicesByInfo private void removeDeviceLocked(Device device) { - if (mDevicesByServer.remove(device.getDeviceServer().asBinder()) != null) { - mDevicesByInfo.remove(device.getDeviceInfo()); + if (mDevicesByInfo.remove(device.getDeviceInfo()) != null) { + IMidiDeviceServer server = device.getDeviceServer(); + if (server != null) { + mDevicesByServer.remove(server); + } synchronized (mClients) { for (Client c : mClients.values()) { @@ -280,6 +383,134 @@ public class MidiService extends IMidiManager.Stub { } } + private void addPackageDeviceServers(String packageName) { + PackageInfo info; + + try { + info = mPackageManager.getPackageInfo(packageName, + PackageManager.GET_SERVICES | PackageManager.GET_META_DATA); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "handlePackageUpdate could not find package " + packageName, e); + return; + } + + ServiceInfo[] services = info.services; + if (services == null) return; + for (int i = 0; i < services.length; i++) { + addPackageDeviceServer(services[i]); + } + } + + private void addPackageDeviceServer(ServiceInfo serviceInfo) { + XmlResourceParser parser = null; + + try { + parser = serviceInfo.loadXmlMetaData(mPackageManager, + MidiDeviceService.SERVICE_INTERFACE); + if (parser == null) return; + + Bundle properties = null; + int numInputPorts = 0; + int numOutputPorts = 0; + boolean isPrivate = false; + + while (true) { + int eventType = parser.next(); + if (eventType == XmlPullParser.END_DOCUMENT) { + break; + } else if (eventType == XmlPullParser.START_TAG) { + String tagName = parser.getName(); + if ("device".equals(tagName)) { + if (properties != null) { + Log.w(TAG, "nested <device> elements in metadata for " + + serviceInfo.packageName); + continue; + } + properties = new Bundle(); + properties.putParcelable(MidiDeviceInfo.PROPERTY_SERVICE_INFO, serviceInfo); + numInputPorts = 0; + numOutputPorts = 0; + isPrivate = false; + + int count = parser.getAttributeCount(); + for (int i = 0; i < count; i++) { + String name = parser.getAttributeName(i); + String value = parser.getAttributeValue(i); + if ("private".equals(name)) { + isPrivate = "true".equals(value); + } else { + properties.putString(name, value); + } + } + } else if ("input-port".equals(tagName)) { + if (properties == null) { + Log.w(TAG, "<input-port> outside of <device> in metadata for " + + serviceInfo.packageName); + continue; + } + numInputPorts++; + // TODO - add support for port properties + } else if ("output-port".equals(tagName)) { + if (properties == null) { + Log.w(TAG, "<output-port> outside of <device> in metadata for " + + serviceInfo.packageName); + continue; + } + numOutputPorts++; + // TODO - add support for port properties + } + } else if (eventType == XmlPullParser.END_TAG) { + String tagName = parser.getName(); + if ("device".equals(tagName)) { + if (properties != null) { + if (numInputPorts == 0 && numOutputPorts == 0) { + Log.w(TAG, "<device> with no ports in metadata for " + + serviceInfo.packageName); + continue; + } + + int uid = -1; + if (isPrivate) { + try { + ApplicationInfo appInfo = mPackageManager.getApplicationInfo( + serviceInfo.packageName, 0); + uid = appInfo.uid; + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "could not fetch ApplicationInfo for " + + serviceInfo.packageName); + continue; + } + } + + synchronized (mDevicesByInfo) { + addDeviceLocked(MidiDeviceInfo.TYPE_VIRTUAL, + numInputPorts, numOutputPorts, properties, + null, serviceInfo, isPrivate, uid); + } + // setting properties to null signals that we are no longer + // processing a <device> + properties = null; + } + } + } + } + } catch (Exception e) { + Log.w(TAG, "Unable to load component info " + serviceInfo.toString(), e); + } finally { + if (parser != null) parser.close(); + } + } + + private void removePackageDeviceServers(String packageName) { + synchronized (mDevicesByInfo) { + for (Device device : mDevicesByInfo.values()) { + if (packageName.equals(device.getPackageName())) { + removeDeviceLocked(device); + } + } + } + } + @Override public void dump(FileDescriptor fd, PrintWriter writer, String[] args) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, TAG); diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 059dde1..fc95b00 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -16,6 +16,8 @@ package com.android.server.am; +import static com.android.server.am.ActivityManagerDebugConfig.*; + import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; @@ -33,6 +35,7 @@ import android.os.Looper; import android.os.SystemProperties; import android.util.ArrayMap; import android.util.ArraySet; + import com.android.internal.app.ProcessStats; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.TransferPipe; @@ -67,14 +70,15 @@ import android.util.SparseArray; import android.util.TimeUtils; public final class ActiveServices { - static final boolean DEBUG_SERVICE = ActivityManagerService.DEBUG_SERVICE; - static final boolean DEBUG_SERVICE_EXECUTING = ActivityManagerService.DEBUG_SERVICE_EXECUTING; - static final boolean DEBUG_DELAYED_SERVICE = ActivityManagerService.DEBUG_SERVICE; - static final boolean DEBUG_DELAYED_STARTS = DEBUG_DELAYED_SERVICE; - static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU; - static final boolean LOG_SERVICE_START_STOP = false; - static final String TAG = ActivityManagerService.TAG; - static final String TAG_MU = ActivityManagerService.TAG_MU; + private static final String TAG = TAG_WITH_CLASS_NAME ? "ActiveServices" : TAG_AM; + private static final String TAG_MU = TAG + POSTFIX_MU; + private static final String TAG_SERVICE = TAG + POSTFIX_SERVICE; + private static final String TAG_SERVICE_EXECUTING = TAG + POSTFIX_SERVICE_EXECUTING; + + private static final boolean DEBUG_DELAYED_SERVICE = DEBUG_SERVICE; + private static final boolean DEBUG_DELAYED_STARTS = DEBUG_DELAYED_SERVICE; + + private static final boolean LOG_SERVICE_START_STOP = false; // How long we wait for a service to finish executing. static final int SERVICE_TIMEOUT = 20*1000; @@ -206,11 +210,12 @@ public final class ActiveServices { void ensureNotStartingBackground(ServiceRecord r) { if (mStartingBackground.remove(r)) { - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "No longer background starting: " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, + "No longer background starting: " + r); rescheduleDelayedStarts(); } if (mDelayedStartList.remove(r)) { - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "No longer delaying start: " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "No longer delaying start: " + r); } } @@ -229,16 +234,17 @@ public final class ActiveServices { while (mDelayedStartList.size() > 0 && mStartingBackground.size() < mMaxStartingBackground) { ServiceRecord r = mDelayedStartList.remove(0); - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "REM FR DELAY LIST (exec next): " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, + "REM FR DELAY LIST (exec next): " + r); if (r.pendingStarts.size() <= 0) { Slog.w(TAG, "**** NO PENDING STARTS! " + r + " startReq=" + r.startRequested + " delayedStop=" + r.delayedStop); } if (DEBUG_DELAYED_SERVICE) { if (mDelayedStartList.size() > 0) { - Slog.v(TAG, "Remaining delayed list:"); + Slog.v(TAG_SERVICE, "Remaining delayed list:"); for (int i=0; i<mDelayedStartList.size(); i++) { - Slog.v(TAG, " #" + i + ": " + mDelayedStartList.get(i)); + Slog.v(TAG_SERVICE, " #" + i + ": " + mDelayedStartList.get(i)); } } } @@ -248,7 +254,7 @@ public final class ActiveServices { if (mStartingBackground.size() > 0) { ServiceRecord next = mStartingBackground.get(0); long when = next.startingBgTimeout > now ? next.startingBgTimeout : now; - if (DEBUG_DELAYED_SERVICE) Slog.v(TAG, "Top bg start is " + next + if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Top bg start is " + next + ", can delay others up to " + when); Message msg = obtainMessage(MSG_BG_START_TIMEOUT); sendMessageAtTime(msg, when); @@ -298,7 +304,7 @@ public final class ActiveServices { ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int callingPid, int callingUid, int userId) { - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "startService: " + service + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service + " type=" + resolvedType + " args=" + service.getExtras()); final boolean callerFg; @@ -337,7 +343,7 @@ public final class ActiveServices { NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked( callingUid, r.packageName, service, service.getFlags(), null, r.userId); if (unscheduleServiceRestartLocked(r, callingUid, false)) { - if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r); } r.lastActivity = SystemClock.uptimeMillis(); r.startRequested = true; @@ -360,29 +366,30 @@ public final class ActiveServices { // service is started. This is especially the case for receivers, which // may start a service in onReceive() to do some additional work and have // initialized some global state as part of that. - if (DEBUG_DELAYED_SERVICE) Slog.v(TAG, "Potential start delay of " + r + " in " - + proc); + if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Potential start delay of " + + r + " in " + proc); if (r.delayed) { // This service is already scheduled for a delayed start; just leave // it still waiting. - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Continuing to delay: " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r); return r.name; } if (smap.mStartingBackground.size() >= mMaxStartingBackground) { // Something else is starting, delay! - Slog.i(TAG, "Delaying start of: " + r); + Slog.i(TAG_SERVICE, "Delaying start of: " + r); smap.mDelayedStartList.add(r); r.delayed = true; return r.name; } - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Not delaying: " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r); addToStarting = true; } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) { // We slightly loosen when we will enqueue this new service as a background // starting service we are waiting for, to also include processes that are // currently running other services or receivers. addToStarting = true; - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Not delaying, but counting as bg: " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, + "Not delaying, but counting as bg: " + r); } else if (DEBUG_DELAYED_STARTS) { StringBuilder sb = new StringBuilder(128); sb.append("Not potential delay (state=").append(proc.curProcState) @@ -394,16 +401,17 @@ public final class ActiveServices { } sb.append("): "); sb.append(r.toString()); - Slog.v(TAG, sb.toString()); + Slog.v(TAG_SERVICE, sb.toString()); } } else if (DEBUG_DELAYED_STARTS) { if (callerFg) { - Slog.v(TAG, "Not potential delay (callerFg=" + callerFg + " uid=" + Slog.v(TAG_SERVICE, "Not potential delay (callerFg=" + callerFg + " uid=" + callingUid + " pid=" + callingPid + "): " + r); } else if (r.app != null) { - Slog.v(TAG, "Not potential delay (cur app=" + r.app + "): " + r); + Slog.v(TAG_SERVICE, "Not potential delay (cur app=" + r.app + "): " + r); } else { - Slog.v(TAG, "Not potential delay (user " + r.userId + " not started): " + r); + Slog.v(TAG_SERVICE, + "Not potential delay (user " + r.userId + " not started): " + r); } } @@ -432,9 +440,9 @@ public final class ActiveServices { if (DEBUG_DELAYED_SERVICE) { RuntimeException here = new RuntimeException("here"); here.fillInStackTrace(); - Slog.v(TAG, "Starting background (first=" + first + "): " + r, here); + Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here); } else if (DEBUG_DELAYED_STARTS) { - Slog.v(TAG, "Starting background (first=" + first + "): " + r); + Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r); } if (first) { smap.rescheduleDelayedStarts(); @@ -451,7 +459,7 @@ public final class ActiveServices { // If service isn't actually running, but is is being held in the // delayed list, then we need to keep it started but note that it // should be stopped once no longer delayed. - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Delaying stop of pending: " + service); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Delaying stop of pending: " + service); service.delayedStop = true; return; } @@ -469,7 +477,7 @@ public final class ActiveServices { int stopServiceLocked(IApplicationThread caller, Intent service, String resolvedType, int userId) { - if (DEBUG_SERVICE) Slog.v(TAG, "stopService: " + service + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopService: " + service + " type=" + resolvedType); final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); @@ -525,7 +533,7 @@ public final class ActiveServices { boolean stopServiceTokenLocked(ComponentName className, IBinder token, int startId) { - if (DEBUG_SERVICE) Slog.v(TAG, "stopServiceToken: " + className + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopServiceToken: " + className + " " + token + " startId=" + startId); ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId()); if (r != null) { @@ -687,7 +695,7 @@ public final class ActiveServices { int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) { - if (DEBUG_SERVICE) Slog.v(TAG, "bindService: " + service + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service + " type=" + resolvedType + " conn=" + connection.asBinder() + " flags=0x" + Integer.toHexString(flags)); final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller); @@ -751,7 +759,7 @@ public final class ActiveServices { try { if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) { - if (DEBUG_SERVICE) Slog.v(TAG, "BIND SERVICE WHILE RESTART PENDING: " + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: " + s); } @@ -819,7 +827,7 @@ public final class ActiveServices { mAm.updateOomAdjLocked(s.app); } - if (DEBUG_SERVICE) Slog.v(TAG, "Bind " + s + " with " + b + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b + ": received=" + b.intent.received + " apps=" + b.intent.apps.size() + " doRebind=" + b.intent.doRebind); @@ -857,7 +865,7 @@ public final class ActiveServices { void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { final long origId = Binder.clearCallingIdentity(); try { - if (DEBUG_SERVICE) Slog.v(TAG, "PUBLISHING " + r + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "PUBLISHING " + r + " " + intent + ": " + service); if (r != null) { Intent.FilterComparison filter @@ -873,14 +881,14 @@ public final class ActiveServices { ConnectionRecord c = clist.get(i); if (!filter.equals(c.binding.intent.intent)) { if (DEBUG_SERVICE) Slog.v( - TAG, "Not publishing to: " + c); + TAG_SERVICE, "Not publishing to: " + c); if (DEBUG_SERVICE) Slog.v( - TAG, "Bound intent: " + c.binding.intent.intent); + TAG_SERVICE, "Bound intent: " + c.binding.intent.intent); if (DEBUG_SERVICE) Slog.v( - TAG, "Published intent: " + intent); + TAG_SERVICE, "Published intent: " + intent); continue; } - if (DEBUG_SERVICE) Slog.v(TAG, "Publishing to: " + c); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Publishing to: " + c); try { c.conn.connected(r.name, service); } catch (Exception e) { @@ -901,7 +909,7 @@ public final class ActiveServices { boolean unbindServiceLocked(IServiceConnection connection) { IBinder binder = connection.asBinder(); - if (DEBUG_SERVICE) Slog.v(TAG, "unbindService: conn=" + binder); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindService: conn=" + binder); ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder); if (clist == null) { Slog.w(TAG, "Unbind failed: could not find connection for " @@ -945,7 +953,7 @@ public final class ActiveServices { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); - if (DEBUG_SERVICE) Slog.v(TAG, "unbindFinished in " + r + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindFinished in " + r + " at " + b + ": apps=" + (b != null ? b.apps.size() : 0)); @@ -1012,7 +1020,7 @@ public final class ActiveServices { String resolvedType, int callingPid, int callingUid, int userId, boolean createIfNeeded, boolean callingFromFg) { ServiceRecord r = null; - if (DEBUG_SERVICE) Slog.v(TAG, "retrieveServiceLocked: " + service + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "retrieveServiceLocked: " + service + " type=" + resolvedType + " callingUid=" + callingUid); userId = mAm.handleIncomingUser(callingPid, callingUid, userId, @@ -1036,7 +1044,7 @@ public final class ActiveServices { ServiceInfo sInfo = rInfo != null ? rInfo.serviceInfo : null; if (sInfo == null) { - Slog.w(TAG, "Unable to start service " + service + " U=" + userId + + Slog.w(TAG_SERVICE, "Unable to start service " + service + " U=" + userId + ": not found"); return null; } @@ -1110,9 +1118,9 @@ public final class ActiveServices { } private final void bumpServiceExecutingLocked(ServiceRecord r, boolean fg, String why) { - if (DEBUG_SERVICE) Slog.v(TAG, ">>> EXECUTING " + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, ">>> EXECUTING " + why + " of " + r + " in app " + r.app); - else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, ">>> EXECUTING " + else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, ">>> EXECUTING " + why + " of " + r.shortName); long now = SystemClock.uptimeMillis(); if (r.executeNesting == 0) { @@ -1155,7 +1163,7 @@ public final class ActiveServices { i.hasBound = true; i.doRebind = false; } catch (RemoteException e) { - if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while binding " + r); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while binding " + r); return false; } } @@ -1336,7 +1344,7 @@ public final class ActiveServices { return null; } - if (DEBUG_SERVICE) Slog.v(TAG, "Bringing up " + r + " " + r.intent); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent); // We are now bringing the service up, so no longer in the // restarting state. @@ -1347,7 +1355,7 @@ public final class ActiveServices { // Make sure this service is no longer considered delayed, we are starting it now. if (r.delayed) { - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "REM FR DELAY LIST (bring up): " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r); getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false; } @@ -1430,7 +1438,8 @@ public final class ActiveServices { // Oh and hey we've already been asked to stop! r.delayedStop = false; if (r.startRequested) { - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Applying delayed stop (in bring up): " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, + "Applying delayed stop (in bring up): " + r); stopServiceLocked(r); } } @@ -1509,7 +1518,7 @@ public final class ActiveServices { sendServiceArgsLocked(r, execInFg, true); if (r.delayed) { - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "REM FR DELAY LIST (new proc): " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r); getServiceMap(r.userId).mDelayedStartList.remove(r); r.delayed = false; } @@ -1518,7 +1527,8 @@ public final class ActiveServices { // Oh and hey we've already been asked to stop! r.delayedStop = false; if (r.startRequested) { - if (DEBUG_DELAYED_STARTS) Slog.v(TAG, "Applying delayed stop (from start): " + r); + if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, + "Applying delayed stop (from start): " + r); stopServiceLocked(r); } } @@ -1534,7 +1544,7 @@ public final class ActiveServices { while (r.pendingStarts.size() > 0) { try { ServiceRecord.StartItem si = r.pendingStarts.remove(0); - if (DEBUG_SERVICE) Slog.v(TAG, "Sending arguments to: " + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Sending arguments to: " + r + " " + r.intent + " args=" + si.intent); if (si.intent == null && N > 1) { // If somehow we got a dummy null intent in the middle, @@ -1566,7 +1576,7 @@ public final class ActiveServices { } catch (RemoteException e) { // Remote process gone... we'll let the normal cleanup take // care of this. - if (DEBUG_SERVICE) Slog.v(TAG, "Crashed while scheduling start: " + r); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Crashed while scheduling start: " + r); break; } catch (Exception e) { Slog.w(TAG, "Unexpected exception", e); @@ -1636,7 +1646,7 @@ public final class ActiveServices { if (r.app != null && r.app.thread != null) { for (int i=r.bindings.size()-1; i>=0; i--) { IntentBindRecord ibr = r.bindings.valueAt(i); - if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down binding " + ibr + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr + ": hasBound=" + ibr.hasBound); if (ibr.hasBound) { try { @@ -1654,7 +1664,7 @@ public final class ActiveServices { } } - if (DEBUG_SERVICE) Slog.v(TAG, "Bringing down " + r + " " + r.intent); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down " + r + " " + r.intent); r.destroyTime = SystemClock.uptimeMillis(); if (LOG_SERVICE_START_STOP) { EventLogTags.writeAmDestroyService( @@ -1671,7 +1681,7 @@ public final class ActiveServices { for (int i=mPendingServices.size()-1; i>=0; i--) { if (mPendingServices.get(i) == r) { mPendingServices.remove(i); - if (DEBUG_SERVICE) Slog.v(TAG, "Removed pending: " + r); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Removed pending: " + r); } } @@ -1704,11 +1714,11 @@ public final class ActiveServices { } } else { if (DEBUG_SERVICE) Slog.v( - TAG, "Removed service that has no process: " + r); + TAG_SERVICE, "Removed service that has no process: " + r); } } else { if (DEBUG_SERVICE) Slog.v( - TAG, "Removed service that is not running: " + r); + TAG_SERVICE, "Removed service that is not running: " + r); } if (r.bindings.size() > 0) { @@ -1775,7 +1785,7 @@ public final class ActiveServices { } if (!c.serviceDead) { - if (DEBUG_SERVICE) Slog.v(TAG, "Disconnecting binding " + b.intent + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Disconnecting binding " + b.intent + ": shouldUnbind=" + b.intent.hasBound); if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 && b.intent.hasBound) { @@ -1902,19 +1912,20 @@ public final class ActiveServices { private void serviceDoneExecutingLocked(ServiceRecord r, boolean inDestroying, boolean finishing) { - if (DEBUG_SERVICE) Slog.v(TAG, "<<< DONE EXECUTING " + r + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "<<< DONE EXECUTING " + r + ": nesting=" + r.executeNesting + ", inDestroying=" + inDestroying + ", app=" + r.app); - else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG, "<<< DONE EXECUTING " + r.shortName); + else if (DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, + "<<< DONE EXECUTING " + r.shortName); r.executeNesting--; if (r.executeNesting <= 0) { if (r.app != null) { - if (DEBUG_SERVICE) Slog.v(TAG, + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Nesting at 0 of " + r.shortName); r.app.execServicesFg = false; r.app.executingServices.remove(r); if (r.app.executingServices.size() == 0) { - if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG, + if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, "No more executingServices of " + r.shortName); mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app); } else if (r.executeFg) { @@ -1927,7 +1938,7 @@ public final class ActiveServices { } } if (inDestroying) { - if (DEBUG_SERVICE) Slog.v(TAG, + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "doneExecuting remove destroying " + r); mDestroyingServices.remove(r); r.bindings.clear(); @@ -2141,13 +2152,13 @@ public final class ActiveServices { sr.executeNesting = 0; sr.forceClearTracker(); if (mDestroyingServices.remove(sr)) { - if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr); } final int numClients = sr.bindings.size(); for (int bindingi=numClients-1; bindingi>=0; bindingi--) { IntentBindRecord b = sr.bindings.valueAt(bindingi); - if (DEBUG_SERVICE) Slog.v(TAG, "Killing binding " + b + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Killing binding " + b + ": shouldUnbind=" + b.hasBound); b.binder = null; b.requested = b.received = b.hasBound = false; @@ -2281,7 +2292,7 @@ public final class ActiveServices { if (sr.app == app) { sr.forceClearTracker(); mDestroyingServices.remove(i); - if (DEBUG_SERVICE) Slog.v(TAG, "killServices remove destroying " + sr); + if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "killServices remove destroying " + sr); } } diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java new file mode 100644 index 0000000..03f253b --- /dev/null +++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java @@ -0,0 +1,84 @@ +/* + * 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.am; + +/** + * Common class for the various debug {@link android.util.Log} output configuration in the activity + * manager package. + */ +class ActivityManagerDebugConfig { + + // All output logs in the activity manager package use the {@link #TAG_AM} string for tagging + // their log output. This makes it easy to identify the origin of the log message when sifting + // through a large amount of log output from multiple sources. However, it also makes trying + // to figure-out the origin of a log message while debugging the activity manager a little + // painful. By setting this constant to true, log messages from the activity manager package + // will be tagged with their class names instead fot the generic tag. + static final boolean TAG_WITH_CLASS_NAME = false; + + // While debugging it is sometimes useful to have the category name of the log prepended to the + // base log tag to make sifting through logs with the same base tag easier. By setting this + // constant to true, the category name of the log point will be prepended to the log tag. + static final boolean PREPEND_CATEGORY_NAME = false; + + // Default log tag for the activity manager package. + static final String TAG_AM = "ActivityManager"; + + // Enable all debug log categories. + static final boolean DEBUG_ALL = false; + + // Available log categories in the activity manager package. + static final boolean DEBUG_BACKUP = DEBUG_ALL || false; + static final boolean DEBUG_BROADCAST = DEBUG_ALL || false; + static final boolean DEBUG_BROADCAST_BACKGROUND = DEBUG_BROADCAST || false; + static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false; + static final boolean DEBUG_CLEANUP = DEBUG_ALL || false; + static final boolean DEBUG_CONFIGURATION = DEBUG_ALL || false; + static final boolean DEBUG_FOCUS = false; + static final boolean DEBUG_IMMERSIVE = DEBUG_ALL || false; + static final boolean DEBUG_LOCKSCREEN = DEBUG_ALL || false; + static final boolean DEBUG_LRU = DEBUG_ALL || false; + static final boolean DEBUG_MU = DEBUG_ALL || false; + static final boolean DEBUG_OOM_ADJ = DEBUG_ALL || false; + static final boolean DEBUG_PAUSE = DEBUG_ALL || false; + static final boolean DEBUG_POWER = DEBUG_ALL || false; + static final boolean DEBUG_POWER_QUICK = DEBUG_POWER || false; + static final boolean DEBUG_PROCESS_OBSERVERS = DEBUG_ALL || false; + static final boolean DEBUG_PROCESSES = DEBUG_ALL || false; + static final boolean DEBUG_PROVIDER = DEBUG_ALL || false; + static final boolean DEBUG_PSS = DEBUG_ALL || false; + static final boolean DEBUG_RECENTS = DEBUG_ALL || false; + static final boolean DEBUG_RESULTS = DEBUG_ALL || false; + static final boolean DEBUG_SERVICE = DEBUG_ALL || false; + static final boolean DEBUG_SERVICE_EXECUTING = DEBUG_ALL || false; + static final boolean DEBUG_STACK = DEBUG_ALL || false; + static final boolean DEBUG_SWITCH = DEBUG_ALL || false; + static final boolean DEBUG_TASKS = DEBUG_ALL || false; + static final boolean DEBUG_THUMBNAILS = DEBUG_ALL || false; + static final boolean DEBUG_TRANSITION = DEBUG_ALL || false; + static final boolean DEBUG_URI_PERMISSION = DEBUG_ALL || false; + static final boolean DEBUG_USER_LEAVING = DEBUG_ALL || false; + static final boolean DEBUG_VISBILITY = DEBUG_ALL || false; + + static final String POSTFIX_BACKUP = (PREPEND_CATEGORY_NAME) ? "_Backup" : ""; + static final String POSTFIX_BROADCAST = (PREPEND_CATEGORY_NAME) ? "_Broadcast" : ""; + static final String POSTFIX_MU = "_MU"; + static final String POSTFIX_SERVICE = (PREPEND_CATEGORY_NAME) ? "_Service" : ""; + static final String POSTFIX_SERVICE_EXECUTING = + (PREPEND_CATEGORY_NAME) ? "_ServiceExecuting" : ""; + +} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 008d718..46f07cc 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -30,6 +30,7 @@ import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST; import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT; import static org.xmlpull.v1.XmlPullParser.START_TAG; import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID; +import static com.android.server.am.ActivityManagerDebugConfig.*; import static com.android.server.am.TaskRecord.INVALID_TASK_ID; import android.Manifest; @@ -55,11 +56,13 @@ import android.os.storage.StorageManager; import android.service.voice.IVoiceInteractionSession; import android.util.ArrayMap; import android.util.ArraySet; +import android.util.DebugUtils; import android.util.SparseIntArray; import android.view.Display; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; +import com.android.internal.app.DumpHeapActivity; import com.android.internal.app.IAppOpsService; import com.android.internal.app.IVoiceInteractor; import com.android.internal.app.ProcessMap; @@ -245,10 +248,11 @@ public final class ActivityManagerService extends ActivityManagerNative // File that stores last updated system version and called preboot receivers static final String CALLED_PRE_BOOTS_FILENAME = "called_pre_boots.dat"; - static final String TAG = "ActivityManager"; - static final String TAG_MU = "ActivityManagerServiceMU"; - static final boolean DEBUG = false; - static final boolean localLOGV = DEBUG; + static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityManagerService" : TAG_AM; + private static final String TAG_MU = TAG + POSTFIX_MU; + + // TODO(ogunwale): Migrate all the constants below to use ActivityManagerDebugConfig class. + static final boolean localLOGV = DEBUG_ALL || false; static final boolean DEBUG_BACKUP = localLOGV || false; static final boolean DEBUG_BROADCAST = localLOGV || false; static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false; @@ -1124,6 +1128,11 @@ public final class ActivityManagerService extends ActivityManagerNative boolean mAutoStopProfiler = false; int mProfileType = 0; String mOpenGlTraceApp = null; + final ArrayMap<String, Long> mMemWatchProcesses = new ArrayMap<>(); + String mMemWatchDumpProcName; + String mMemWatchDumpFile; + int mMemWatchDumpPid; + int mMemWatchDumpUid; final long[] mTmpLong = new long[1]; @@ -1266,6 +1275,8 @@ public final class ActivityManagerService extends ActivityManagerNative static final int DISMISS_DIALOG_MSG = 48; static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 49; static final int NOTIFY_CLEARTEXT_NETWORK_MSG = 50; + static final int POST_DUMP_HEAP_NOTIFICATION_MSG = 51; + static final int DELETE_DUMPHEAP_MSG = 52; static final int FIRST_ACTIVITY_STACK_MSG = 100; static final int FIRST_BROADCAST_QUEUE_MSG = 200; @@ -1820,6 +1831,78 @@ public final class ActivityManagerService extends ActivityManagerNative } break; } + case POST_DUMP_HEAP_NOTIFICATION_MSG: { + final String procName; + final int uid; + final long memLimit; + synchronized (ActivityManagerService.this) { + procName = mMemWatchDumpProcName; + uid = mMemWatchDumpUid; + Long limit = mMemWatchProcesses.get(procName); + memLimit = limit != null ? limit : 0; + } + if (procName == null) { + return; + } + + if (DEBUG_PSS) Slog.d(TAG, "Showing dump heap notification from " + + procName + "/" + uid); + + INotificationManager inm = NotificationManager.getService(); + if (inm == null) { + return; + } + + String text = mContext.getString(R.string.dump_heap_notification, procName); + Notification notification = new Notification(); + notification.icon = com.android.internal.R.drawable.stat_sys_adb; + notification.when = 0; + notification.flags = Notification.FLAG_ONGOING_EVENT|Notification.FLAG_AUTO_CANCEL; + notification.tickerText = text; + notification.defaults = 0; // please be quiet + notification.sound = null; + notification.vibrate = null; + notification.color = mContext.getResources().getColor( + com.android.internal.R.color.system_notification_accent_color); + Intent deleteIntent = new Intent(); + deleteIntent.setAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP); + notification.deleteIntent = PendingIntent.getBroadcastAsUser(mContext, 0, + deleteIntent, 0, UserHandle.OWNER); + Intent intent = new Intent(); + intent.setClassName("android", DumpHeapActivity.class.getName()); + intent.putExtra(DumpHeapActivity.KEY_PROCESS, procName); + intent.putExtra(DumpHeapActivity.KEY_SIZE, memLimit); + int userId = UserHandle.getUserId(uid); + notification.setLatestEventInfo(mContext, text, + mContext.getText(R.string.dump_heap_notification_detail), + PendingIntent.getActivityAsUser(mContext, 0, intent, + PendingIntent.FLAG_CANCEL_CURRENT, null, + new UserHandle(userId))); + + try { + int[] outId = new int[1]; + inm.enqueueNotificationWithTag("android", "android", null, + R.string.dump_heap_notification, + notification, outId, userId); + } catch (RuntimeException e) { + Slog.w(ActivityManagerService.TAG, + "Error showing notification for dump heap", e); + } catch (RemoteException e) { + } + } break; + case DELETE_DUMPHEAP_MSG: { + revokeUriPermission(ActivityThread.currentActivityThread().getApplicationThread(), + DumpHeapActivity.JAVA_URI, + Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION, + UserHandle.myUserId()); + synchronized (ActivityManagerService.this) { + mMemWatchDumpFile = null; + mMemWatchDumpProcName = null; + mMemWatchDumpPid = -1; + mMemWatchDumpUid = -1; + } + } break; } } }; @@ -1906,7 +1989,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (pss != 0 && proc.thread != null && proc.setProcState == procState && proc.pid == pid && proc.lastPssTime == lastPssTime) { num++; - recordPssSample(proc, procState, pss, tmp[0], + recordPssSampleLocked(proc, procState, pss, tmp[0], SystemClock.uptimeMillis()); } } @@ -2318,7 +2401,7 @@ public final class ActivityManagerService extends ActivityManagerNative } ps.addCpuTimeLocked(st.rel_utime - otherUTime, st.rel_stime - otherSTime, cpuSpeedTimes); - pr.curCpuTime += (st.rel_utime+st.rel_stime) * 10; + pr.curCpuTime += st.rel_utime + st.rel_stime; } else { BatteryStatsImpl.Uid.Proc ps = st.batteryStats; if (ps == null || !ps.isActive()) { @@ -5704,7 +5787,7 @@ public final class ActivityManagerService extends ActivityManagerNative for (String pkg : pkgs) { synchronized (ActivityManagerService.this) { if (forceStopPackageLocked(pkg, -1, false, false, false, false, false, - 0, "finished booting")) { + 0, "query restart")) { setResultCode(Activity.RESULT_OK); return; } @@ -5714,6 +5797,19 @@ public final class ActivityManagerService extends ActivityManagerNative } }, pkgFilter); + IntentFilter dumpheapFilter = new IntentFilter(); + dumpheapFilter.addAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP); + mContext.registerReceiver(new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getBooleanExtra(DumpHeapActivity.EXTRA_DELAY_DELETE, false)) { + mHandler.sendEmptyMessageDelayed(POST_DUMP_HEAP_NOTIFICATION_MSG, 5*60*1000); + } else { + mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG); + } + } + }, dumpheapFilter); + // Let system services know. mSystemServiceManager.startBootPhase(SystemService.PHASE_BOOT_COMPLETED); @@ -8347,6 +8443,9 @@ public final class ActivityManagerService extends ActivityManagerNative synchronized (this) { pkg = task.intent.getComponent().getPackageName(); } + // isSystemInitiated is used to distinguish between locked and pinned mode, as pinned mode + // is initiated by system after the pinning request was shown and locked mode is initiated + // by an authorized app directly boolean isSystemInitiated = Binder.getCallingUid() == Process.SYSTEM_UID; if (!isSystemInitiated && !isLockTaskAuthorized(pkg)) { StatusBarManagerInternal statusBarManager = LocalServices.getService( @@ -8367,7 +8466,9 @@ public final class ActivityManagerService extends ActivityManagerNative || (task != mStackSupervisor.getFocusedStack().topTask()))) { throw new IllegalArgumentException("Invalid task, not in foreground"); } - mStackSupervisor.setLockTaskModeLocked(task, !isSystemInitiated, + mStackSupervisor.setLockTaskModeLocked(task, isSystemInitiated ? + ActivityManager.LOCK_TASK_MODE_PINNED : + ActivityManager.LOCK_TASK_MODE_LOCKED, "startLockTask"); } } @@ -8453,7 +8554,8 @@ public final class ActivityManagerService extends ActivityManagerNative Log.d(TAG, "stopLockTaskMode"); // Stop lock task synchronized (this) { - mStackSupervisor.setLockTaskModeLocked(null, false, "stopLockTask"); + mStackSupervisor.setLockTaskModeLocked(null, ActivityManager.LOCK_TASK_MODE_NONE, + "stopLockTask"); } } finally { Binder.restoreCallingIdentity(ident); @@ -8474,8 +8576,13 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public boolean isInLockTaskMode() { + return getLockTaskModeState() != ActivityManager.LOCK_TASK_MODE_NONE; + } + + @Override + public int getLockTaskModeState() { synchronized (this) { - return mStackSupervisor.isInLockTaskMode(); + return mStackSupervisor.getLockTaskModeState(); } } @@ -12728,6 +12835,22 @@ public final class ActivityManagerService extends ActivityManagerNative + " mOrigWaitForDebugger=" + mOrigWaitForDebugger); } } + if (mMemWatchProcesses.size() > 0) { + pw.println(" Mem watch processes:"); + for (int i=0; i<mMemWatchProcesses.size(); i++) { + if (needSep) { + pw.println(); + needSep = false; + } + pw.print(" "); pw.print(mMemWatchProcesses.keyAt(i)); + pw.print(": "); DebugUtils.printSizeValue(pw, mMemWatchProcesses.valueAt(i)); + pw.println(); + } + pw.print(" mMemWatchDumpProcName="); pw.println(mMemWatchDumpProcName); + pw.print(" mMemWatchDumpFile="); pw.println(mMemWatchDumpFile); + pw.print(" mMemWatchDumpPid="); pw.print(mMemWatchDumpPid); + pw.print(" mMemWatchDumpUid="); pw.println(mMemWatchDumpUid); + } if (mOpenGlTraceApp != null) { if (dumpPackage == null || dumpPackage.equals(mOpenGlTraceApp)) { if (needSep) { @@ -13410,8 +13533,9 @@ public final class ActivityManagerService extends ActivityManagerNative pw.print(" "); pw.print("state: cur="); pw.print(ProcessList.makeProcStateString(r.curProcState)); pw.print(" set="); pw.print(ProcessList.makeProcStateString(r.setProcState)); - pw.print(" lastPss="); pw.print(r.lastPss); - pw.print(" lastCachedPss="); pw.println(r.lastCachedPss); + pw.print(" lastPss="); DebugUtils.printSizeValue(pw, r.lastPss*1024); + pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, r.lastCachedPss*1024); + pw.println(); pw.print(prefix); pw.print(" "); pw.print("cached="); pw.print(r.cached); @@ -17219,7 +17343,7 @@ public final class ActivityManagerService extends ActivityManagerNative /** * Record new PSS sample for a process. */ - void recordPssSample(ProcessRecord proc, int procState, long pss, long uss, long now) { + void recordPssSampleLocked(ProcessRecord proc, int procState, long pss, long uss, long now) { EventLogTags.writeAmPss(proc.pid, proc.uid, proc.processName, pss*1024, uss*1024); proc.lastPssTime = now; proc.baseProcessTracker.addPss(pss, uss, true, proc.pkgList); @@ -17233,6 +17357,67 @@ public final class ActivityManagerService extends ActivityManagerNative if (procState >= ActivityManager.PROCESS_STATE_HOME) { proc.lastCachedPss = pss; } + + Long check = mMemWatchProcesses.get(proc.processName); + if (check != null) { + if ((pss*1024) >= check && proc.thread != null && mMemWatchDumpProcName == null) { + boolean isDebuggable = "1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")); + if (!isDebuggable) { + if ((proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0) { + isDebuggable = true; + } + } + if (isDebuggable) { + Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + "; reporting"); + final ProcessRecord myProc = proc; + final File heapdumpFile = DumpHeapProvider.getJavaFile(); + mMemWatchDumpProcName = proc.processName; + mMemWatchDumpFile = heapdumpFile.toString(); + mMemWatchDumpPid = proc.pid; + mMemWatchDumpUid = proc.uid; + BackgroundThread.getHandler().post(new Runnable() { + @Override + public void run() { + revokeUriPermission(ActivityThread.currentActivityThread() + .getApplicationThread(), + DumpHeapActivity.JAVA_URI, + Intent.FLAG_GRANT_READ_URI_PERMISSION + | Intent.FLAG_GRANT_WRITE_URI_PERMISSION, + UserHandle.myUserId()); + ParcelFileDescriptor fd = null; + try { + heapdumpFile.delete(); + fd = ParcelFileDescriptor.open(heapdumpFile, + ParcelFileDescriptor.MODE_CREATE | + ParcelFileDescriptor.MODE_TRUNCATE | + ParcelFileDescriptor.MODE_READ_WRITE); + IApplicationThread thread = myProc.thread; + if (thread != null) { + try { + if (DEBUG_PSS) Slog.d(TAG, "Requesting dump heap from " + + myProc + " to " + heapdumpFile); + thread.dumpHeap(true, heapdumpFile.toString(), fd); + } catch (RemoteException e) { + } + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } finally { + if (fd != null) { + try { + fd.close(); + } catch (IOException e) { + } + } + } + } + }); + } else { + Slog.w(TAG, "Process " + proc + " exceeded pss limit " + check + + ", but debugging not enabled"); + } + } + } } /** @@ -17591,7 +17776,7 @@ public final class ActivityManagerService extends ActivityManagerNative // states, which well tend to give noisy data. long start = SystemClock.uptimeMillis(); long pss = Debug.getPss(app.pid, mTmpLong, null); - recordPssSample(app, app.curProcState, pss, mTmpLong[0], now); + recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0], now); mPendingPssProcesses.remove(app); Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState + " to " + app.curProcState + ": " @@ -18411,6 +18596,38 @@ public final class ActivityManagerService extends ActivityManagerNative } } + @Override + public void setDumpHeapDebugLimit(String processName, long maxMemSize) { + enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP, + "setDumpHeapDebugLimit()"); + synchronized (this) { + if (maxMemSize > 0) { + mMemWatchProcesses.put(processName, maxMemSize); + mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG); + } else { + mMemWatchProcesses.remove(processName); + } + } + } + + @Override + public void dumpHeapFinished(String path) { + synchronized (this) { + if (Binder.getCallingPid() != mMemWatchDumpPid) { + Slog.w(TAG, "dumpHeapFinished: Calling pid " + Binder.getCallingPid() + + " does not match last pid " + mMemWatchDumpPid); + return; + } + if (mMemWatchDumpFile == null || !mMemWatchDumpFile.equals(path)) { + Slog.w(TAG, "dumpHeapFinished: Calling path " + path + + " does not match last path " + mMemWatchDumpFile); + return; + } + if (DEBUG_PSS) Slog.d(TAG, "Dump heap finished for " + path); + mHandler.sendEmptyMessage(POST_DUMP_HEAP_NOTIFICATION_MSG); + } + } + /** In this method we try to acquire our lock to make sure that we have not deadlocked */ public void monitor() { synchronized (this) { } @@ -18534,7 +18751,8 @@ public final class ActivityManagerService extends ActivityManagerNative return true; } - mStackSupervisor.setLockTaskModeLocked(null, false, "startUser"); + mStackSupervisor.setLockTaskModeLocked(null, ActivityManager.LOCK_TASK_MODE_NONE, + "startUser"); final UserInfo userInfo = getUserManagerLocked().getUserInfo(userId); if (userInfo == null) { diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index a260330..8b95ae8 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -20,6 +20,7 @@ import static android.Manifest.permission.START_ANY_ACTIVITY; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME; import static android.content.pm.PackageManager.PERMISSION_GRANTED; +import static com.android.server.am.ActivityManagerDebugConfig.*; import static com.android.server.am.ActivityManagerService.localLOGV; import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION; import static com.android.server.am.ActivityManagerService.DEBUG_FOCUS; @@ -116,7 +117,7 @@ import java.util.ArrayList; import java.util.List; public final class ActivityStackSupervisor implements DisplayListener { - static final boolean DEBUG = ActivityManagerService.DEBUG || false; + static final boolean DEBUG = DEBUG_ALL || false; static final boolean DEBUG_ADD_REMOVE = DEBUG || false; static final boolean DEBUG_APP = DEBUG || false; static final boolean DEBUG_CONTAINERS = DEBUG || false; @@ -267,9 +268,11 @@ public final class ActivityStackSupervisor implements DisplayListener { /** If non-null then the task specified remains in front and no other tasks may be started * until the task exits or #stopLockTaskMode() is called. */ TaskRecord mLockTaskModeTask; - /** Whether lock task has been entered by an authorized app and cannot - * be exited. */ - private boolean mLockTaskIsLocked; + /** Store the current lock task mode. Possible values: + * {@link ActivityManager#LOCK_TASK_MODE_NONE}, {@link ActicityManager#LOCK_TASK_MODE_LOCKED}, + * {@link ActicityManager#LOCK_TASK_MODE_PINNED} + */ + private int mLockTaskModeState; /** * Notifies the user when entering/exiting lock-task. */ @@ -3546,10 +3549,10 @@ public final class ActivityStackSupervisor implements DisplayListener { } void showLockTaskToast() { - mLockTaskNotify.showToast(mLockTaskIsLocked); + mLockTaskNotify.showToast(mLockTaskModeState); } - void setLockTaskModeLocked(TaskRecord task, boolean isLocked, String reason) { + void setLockTaskModeLocked(TaskRecord task, int lockTaskModeState, String reason) { if (task == null) { // Take out of lock task mode if necessary if (mLockTaskModeTask != null) { @@ -3573,7 +3576,7 @@ public final class ActivityStackSupervisor implements DisplayListener { lockTaskMsg.obj = mLockTaskModeTask.intent.getComponent().getPackageName(); lockTaskMsg.arg1 = mLockTaskModeTask.userId; lockTaskMsg.what = LOCK_TASK_START_MSG; - lockTaskMsg.arg2 = !isLocked ? 1 : 0; + lockTaskMsg.arg2 = lockTaskModeState; mHandler.sendMessage(lockTaskMsg); } @@ -3591,8 +3594,8 @@ public final class ActivityStackSupervisor implements DisplayListener { } } - boolean isInLockTaskMode() { - return mLockTaskModeTask != null; + int getLockTaskModeState() { + return mLockTaskModeState; } private final class ActivityStackSupervisorHandler extends Handler { @@ -3684,13 +3687,18 @@ public final class ActivityStackSupervisor implements DisplayListener { mLockTaskNotify = new LockTaskNotify(mService.mContext); } mLockTaskNotify.show(true); - mLockTaskIsLocked = msg.arg2 == 0; + mLockTaskModeState = msg.arg2; if (getStatusBarService() != null) { - int flags = - StatusBarManager.DISABLE_MASK ^ StatusBarManager.DISABLE_BACK; - if (!mLockTaskIsLocked) { - flags ^= StatusBarManager.DISABLE_HOME - | StatusBarManager.DISABLE_RECENT; + int flags = 0; + if (mLockTaskModeState == ActivityManager.LOCK_TASK_MODE_LOCKED) { + flags = StatusBarManager.DISABLE_MASK + & (~StatusBarManager.DISABLE_BACK); + } else if (mLockTaskModeState == + ActivityManager.LOCK_TASK_MODE_PINNED) { + flags = StatusBarManager.DISABLE_MASK + & (~StatusBarManager.DISABLE_BACK) + & (~StatusBarManager.DISABLE_HOME) + & (~StatusBarManager.DISABLE_RECENT); } getStatusBarService().disable(flags, mToken, mService.mContext.getPackageName()); @@ -3724,7 +3732,8 @@ public final class ActivityStackSupervisor implements DisplayListener { boolean shouldLockKeyguard = Settings.Secure.getInt( mService.mContext.getContentResolver(), Settings.Secure.LOCK_TO_APP_EXIT_LOCKED) != 0; - if (!mLockTaskIsLocked && shouldLockKeyguard) { + if (mLockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED && + shouldLockKeyguard) { mWindowManager.lockNow(null); mWindowManager.dismissKeyguard(); new LockPatternUtils(mService.mContext) @@ -3735,6 +3744,8 @@ public final class ActivityStackSupervisor implements DisplayListener { } } catch (RemoteException ex) { throw new RuntimeException(ex); + } finally { + mLockTaskModeState = ActivityManager.LOCK_TASK_MODE_NONE; } } break; case CONTAINER_CALLBACK_TASK_LIST_EMPTY: { diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index 5083b1d..8fe1238 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -41,6 +41,8 @@ import android.os.UserHandle; import android.util.EventLog; import android.util.Slog; +import static com.android.server.am.ActivityManagerDebugConfig.*; + /** * BROADCASTS * @@ -48,11 +50,9 @@ import android.util.Slog; * foreground priority, and one for normal (background-priority) broadcasts. */ public final class BroadcastQueue { - static final String TAG = "BroadcastQueue"; - static final String TAG_MU = ActivityManagerService.TAG_MU; - static final boolean DEBUG_BROADCAST = ActivityManagerService.DEBUG_BROADCAST; - static final boolean DEBUG_BROADCAST_LIGHT = ActivityManagerService.DEBUG_BROADCAST_LIGHT; - static final boolean DEBUG_MU = ActivityManagerService.DEBUG_MU; + private static final String TAG = TAG_WITH_CLASS_NAME ? "BroadcastQueue" : TAG_AM; + private static final String TAG_MU = TAG + POSTFIX_MU; + private static final String TAG_BROADCAST = TAG + POSTFIX_BROADCAST; static final int MAX_BROADCAST_HISTORY = ActivityManager.isLowRamDeviceStatic() ? 10 : 50; static final int MAX_BROADCAST_SUMMARY_HISTORY @@ -143,7 +143,7 @@ public final class BroadcastQueue { switch (msg.what) { case BROADCAST_INTENT_MSG: { if (DEBUG_BROADCAST) Slog.v( - TAG, "Received BROADCAST_INTENT_MSG"); + TAG_BROADCAST, "Received BROADCAST_INTENT_MSG"); processNextBroadcast(true); } break; case BROADCAST_TIMEOUT_MSG: { @@ -196,7 +196,7 @@ public final class BroadcastQueue { public final boolean replaceParallelBroadcastLocked(BroadcastRecord r) { for (int i=mParallelBroadcasts.size()-1; i>=0; i--) { if (r.intent.filterEquals(mParallelBroadcasts.get(i).intent)) { - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "***** DROPPING PARALLEL [" + mQueueName + "]: " + r.intent); mParallelBroadcasts.set(i, r); @@ -209,7 +209,7 @@ public final class BroadcastQueue { public final boolean replaceOrderedBroadcastLocked(BroadcastRecord r) { for (int i=mOrderedBroadcasts.size()-1; i>0; i--) { if (r.intent.filterEquals(mOrderedBroadcasts.get(i).intent)) { - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "***** DROPPING ORDERED [" + mQueueName + "]: " + r.intent); mOrderedBroadcasts.set(i, r); @@ -221,7 +221,7 @@ public final class BroadcastQueue { private final void processCurBroadcastLocked(BroadcastRecord r, ProcessRecord app) throws RemoteException { - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Process cur broadcast " + r + " for app " + app); if (app.thread == null) { throw new RemoteException(); @@ -238,7 +238,7 @@ public final class BroadcastQueue { boolean started = false; try { - if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, + if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Delivering to component " + r.curComponent + ": " + r); mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); @@ -246,12 +246,12 @@ public final class BroadcastQueue { mService.compatibilityInfoForPackageLocked(r.curReceiver.applicationInfo), r.resultCode, r.resultData, r.resultExtras, r.ordered, r.userId, app.repProcState); - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Process cur broadcast " + r + " DELIVERED for app " + app); started = true; } finally { if (!started) { - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Process cur broadcast " + r + ": NOT STARTED!"); r.receiver = null; r.curApp = null; @@ -305,23 +305,22 @@ public final class BroadcastQueue { r.resultExtras, r.resultAbort, false); reschedule = true; } - - r = mPendingBroadcast; - if (r != null && r.curApp == app) { - if (DEBUG_BROADCAST) Slog.v(TAG, + if (r == null && mPendingBroadcast != null && mPendingBroadcast.curApp == app) { + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "[" + mQueueName + "] skip & discard pending app " + r); + r = mPendingBroadcast; + } + + if (r != null) { logBroadcastReceiverDiscardLocked(r); finishReceiverLocked(r, r.resultCode, r.resultData, r.resultExtras, r.resultAbort, false); - reschedule = true; - } - if (reschedule) { scheduleBroadcastsLocked(); } } public void scheduleBroadcastsLocked() { - if (DEBUG_BROADCAST) Slog.v(TAG, "Schedule broadcasts [" + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Schedule broadcasts [" + mQueueName + "]: current=" + mBroadcastsScheduled); @@ -391,8 +390,7 @@ public final class BroadcastQueue { // on. If there are background services currently starting, then we will go into a // special state where we hold off on continuing this broadcast until they are done. if (mService.mServices.hasBackgroundServices(r.userId)) { - Slog.i(ActivityManagerService.TAG, "Delay finish: " - + r.curComponent.flattenToShortString()); + Slog.i(TAG, "Delay finish: " + r.curComponent.flattenToShortString()); r.state = BroadcastRecord.WAITING_SERVICES; return false; } @@ -412,7 +410,7 @@ public final class BroadcastQueue { if (mOrderedBroadcasts.size() > 0) { BroadcastRecord br = mOrderedBroadcasts.get(0); if (br.userId == userId && br.state == BroadcastRecord.WAITING_SERVICES) { - Slog.i(ActivityManagerService.TAG, "Resuming delayed broadcast"); + Slog.i(TAG, "Resuming delayed broadcast"); br.curComponent = null; br.state = BroadcastRecord.IDLE; processNextBroadcast(false); @@ -475,7 +473,7 @@ public final class BroadcastQueue { int mode = mService.mAppOpsService.noteOperation(r.appOp, filter.receiverList.uid, filter.packageName); if (mode != AppOpsManager.MODE_ALLOWED) { - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "App op " + r.appOp + " not allowed for broadcast to uid " + filter.receiverList.uid + " pkg " + filter.packageName); skip = true; @@ -513,10 +511,11 @@ public final class BroadcastQueue { } } try { - if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG, "Delivering to " + filter + " : " + r); + if (DEBUG_BROADCAST_LIGHT) Slog.i(TAG_BROADCAST, + "Delivering to " + filter + " : " + r); performReceiveLocked(filter.receiverList.app, filter.receiverList.receiver, - new Intent(r.intent), r.resultCode, r.resultData, - r.resultExtras, r.ordered, r.initialSticky, r.userId); + new Intent(r.intent), r.resultCode, r.resultData, + r.resultExtras, r.ordered, r.initialSticky, r.userId); if (ordered) { r.state = BroadcastRecord.CALL_DONE_RECEIVE; } @@ -538,7 +537,7 @@ public final class BroadcastQueue { synchronized(mService) { BroadcastRecord r; - if (DEBUG_BROADCAST) Slog.v(TAG, "processNextBroadcast [" + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "processNextBroadcast [" + mQueueName + "]: " + mParallelBroadcasts.size() + " broadcasts, " + mOrderedBroadcasts.size() + " ordered broadcasts"); @@ -555,17 +554,17 @@ public final class BroadcastQueue { r.dispatchTime = SystemClock.uptimeMillis(); r.dispatchClockTime = System.currentTimeMillis(); final int N = r.receivers.size(); - if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing parallel broadcast [" + if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing parallel broadcast [" + mQueueName + "] " + r); for (int i=0; i<N; i++) { Object target = r.receivers.get(i); - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Delivering non-ordered on [" + mQueueName + "] to registered " + target + ": " + r); deliverToRegisteredReceiverLocked(r, (BroadcastFilter)target, false); } addBroadcastToHistoryLocked(r); - if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Done with parallel broadcast [" + if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Done with parallel broadcast [" + mQueueName + "] " + r); } @@ -575,11 +574,9 @@ public final class BroadcastQueue { // broadcast, then do nothing at this point. Just in case, we // check that the process we're waiting for still exists. if (mPendingBroadcast != null) { - if (DEBUG_BROADCAST_LIGHT) { - Slog.v(TAG, "processNextBroadcast [" - + mQueueName + "]: waiting for " - + mPendingBroadcast.curApp); - } + if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, + "processNextBroadcast [" + mQueueName + "]: waiting for " + + mPendingBroadcast.curApp); boolean isDead; synchronized (mService.mPidsSelfLocked) { @@ -645,7 +642,7 @@ public final class BroadcastQueue { } if (r.state != BroadcastRecord.IDLE) { - if (DEBUG_BROADCAST) Slog.d(TAG, + if (DEBUG_BROADCAST) Slog.d(TAG_BROADCAST, "processNextBroadcast(" + mQueueName + ") called when not idle (state=" + r.state + ")"); @@ -658,7 +655,7 @@ public final class BroadcastQueue { // result if requested... if (r.resultTo != null) { try { - if (DEBUG_BROADCAST) Slog.i(TAG, + if (DEBUG_BROADCAST) Slog.i(TAG_BROADCAST, "Finishing broadcast [" + mQueueName + "] " + r.intent.getAction() + " app=" + r.callerApp); performReceiveLocked(r.callerApp, r.resultTo, @@ -675,11 +672,11 @@ public final class BroadcastQueue { } } - if (DEBUG_BROADCAST) Slog.v(TAG, "Cancelling BROADCAST_TIMEOUT_MSG"); + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Cancelling BROADCAST_TIMEOUT_MSG"); cancelBroadcastTimeoutLocked(); - if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Finished with ordered broadcast " - + r); + if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, + "Finished with ordered broadcast " + r); // ... and on to the next... addBroadcastToHistoryLocked(r); @@ -699,12 +696,12 @@ public final class BroadcastQueue { if (recIdx == 0) { r.dispatchTime = r.receiverTime; r.dispatchClockTime = System.currentTimeMillis(); - if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG, "Processing ordered broadcast [" + if (DEBUG_BROADCAST_LIGHT) Slog.v(TAG_BROADCAST, "Processing ordered broadcast [" + mQueueName + "] " + r); } if (! mPendingBroadcastTimeoutMessage) { long timeoutTime = r.receiverTime + mTimeoutPeriod; - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Submitting BROADCAST_TIMEOUT_MSG [" + mQueueName + "] for " + r + " at " + timeoutTime); setBroadcastTimeoutLocked(timeoutTime); @@ -715,7 +712,7 @@ public final class BroadcastQueue { // Simple case: this is a registered receiver who gets // a direct call. BroadcastFilter filter = (BroadcastFilter)nextReceiver; - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Delivering ordered [" + mQueueName + "] to registered " + filter + ": " + r); @@ -723,7 +720,7 @@ public final class BroadcastQueue { if (r.receiver == null || !r.ordered) { // The receiver has already finished, so schedule to // process the next one. - if (DEBUG_BROADCAST) Slog.v(TAG, "Quick finishing [" + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Quick finishing [" + mQueueName + "]: ordered=" + r.ordered + " receiver=" + r.receiver); r.state = BroadcastRecord.IDLE; @@ -786,7 +783,7 @@ public final class BroadcastQueue { int mode = mService.mAppOpsService.noteOperation(r.appOp, info.activityInfo.applicationInfo.uid, info.activityInfo.packageName); if (mode != AppOpsManager.MODE_ALLOWED) { - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "App op " + r.appOp + " not allowed for broadcast to uid " + info.activityInfo.applicationInfo.uid + " pkg " + info.activityInfo.packageName); @@ -835,19 +832,18 @@ public final class BroadcastQueue { + info.activityInfo.packageName, e); } if (!isAvailable) { - if (DEBUG_BROADCAST) { - Slog.v(TAG, "Skipping delivery to " + info.activityInfo.packageName - + " / " + info.activityInfo.applicationInfo.uid - + " : package no longer available"); - } + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, + "Skipping delivery to " + info.activityInfo.packageName + " / " + + info.activityInfo.applicationInfo.uid + + " : package no longer available"); skip = true; } } if (skip) { - if (DEBUG_BROADCAST) Slog.v(TAG, - "Skipping delivery of ordered [" - + mQueueName + "] " + r + " for whatever reason"); + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, + "Skipping delivery of ordered [" + mQueueName + "] " + + r + " for whatever reason"); r.receiver = null; r.curFilter = null; r.state = BroadcastRecord.IDLE; @@ -915,7 +911,7 @@ public final class BroadcastQueue { } // Not running -- get it started, to be executed when the app comes up. - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Need to start app [" + mQueueName + "] " + targetProcess + " for broadcast " + r); if ((r.curApp=mService.startProcessLocked(targetProcess, @@ -990,7 +986,7 @@ public final class BroadcastQueue { // broadcast timeout message after each receiver finishes. Instead, we set up // an initial timeout then kick it down the road a little further as needed // when it expires. - if (DEBUG_BROADCAST) Slog.v(TAG, + if (DEBUG_BROADCAST) Slog.v(TAG_BROADCAST, "Premature timeout [" + mQueueName + "] @ " + now + ": resetting BROADCAST_TIMEOUT_MSG for " + timeoutTime); @@ -1005,7 +1001,7 @@ public final class BroadcastQueue { // for started services to finish as well before going on. So if we have actually // waited long enough time timeout the broadcast, let's give up on the whole thing // and just move on to the next. - Slog.i(ActivityManagerService.TAG, "Waited long enough for: " + (br.curComponent != null + Slog.i(TAG, "Waited long enough for: " + (br.curComponent != null ? br.curComponent.flattenToShortString() : "(null)")); br.curComponent = null; br.state = BroadcastRecord.IDLE; diff --git a/services/core/java/com/android/server/am/DumpHeapProvider.java b/services/core/java/com/android/server/am/DumpHeapProvider.java new file mode 100644 index 0000000..a8b639e --- /dev/null +++ b/services/core/java/com/android/server/am/DumpHeapProvider.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.am; + +import android.content.ContentProvider; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; +import android.os.Environment; +import android.os.ParcelFileDescriptor; + +import java.io.File; +import java.io.FileNotFoundException; + +public class DumpHeapProvider extends ContentProvider { + static final Object sLock = new Object(); + static File sHeapDumpJavaFile; + + static public File getJavaFile() { + synchronized (sLock) { + return sHeapDumpJavaFile; + } + } + + @Override + public boolean onCreate() { + synchronized (sLock) { + File dataDir = Environment.getDataDirectory(); + File systemDir = new File(dataDir, "system"); + File heapdumpDir = new File(systemDir, "heapdump"); + heapdumpDir.mkdir(); + sHeapDumpJavaFile = new File(heapdumpDir, "javaheap.bin"); + } + return true; + } + + @Override + public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { + return null; + } + + @Override + public String getType(Uri uri) { + return "application/octet-stream"; + } + + @Override + public Uri insert(Uri uri, ContentValues values) { + return null; + } + + @Override + public int delete(Uri uri, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { + return 0; + } + + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + synchronized (sLock) { + String path = uri.getEncodedPath(); + final String tag = Uri.decode(path); + if (tag.equals("/java")) { + return ParcelFileDescriptor.open(sHeapDumpJavaFile, + ParcelFileDescriptor.MODE_READ_ONLY); + } else { + throw new FileNotFoundException("Invalid path for " + uri); + } + } + } +} diff --git a/services/core/java/com/android/server/am/LockTaskNotify.java b/services/core/java/com/android/server/am/LockTaskNotify.java index b3777ed..afde322 100644 --- a/services/core/java/com/android/server/am/LockTaskNotify.java +++ b/services/core/java/com/android/server/am/LockTaskNotify.java @@ -16,6 +16,7 @@ package com.android.server.am; +import android.app.ActivityManager; import android.content.Context; import android.os.Handler; import android.os.Message; @@ -44,15 +45,20 @@ public class LockTaskNotify { mHandler = new H(); } - public void showToast(boolean isLocked) { - mHandler.obtainMessage(H.SHOW_TOAST, isLocked ? 1 : 0, 0 /* Not used */).sendToTarget(); + public void showToast(int lockTaskModeState) { + mHandler.obtainMessage(H.SHOW_TOAST, lockTaskModeState, 0 /* Not used */).sendToTarget(); } - public void handleShowToast(boolean isLocked) { - String text = mContext.getString(isLocked - ? R.string.lock_to_app_toast_locked : R.string.lock_to_app_toast); - if (!isLocked && mAccessibilityManager.isEnabled()) { - text = mContext.getString(R.string.lock_to_app_toast_accessible); + public void handleShowToast(int lockTaskModeState) { + String text = null; + if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_LOCKED) { + text = mContext.getString(R.string.lock_to_app_toast_locked); + } else if (lockTaskModeState == ActivityManager.LOCK_TASK_MODE_PINNED) { + text = mContext.getString(mAccessibilityManager.isEnabled() + ? R.string.lock_to_app_toast_accessible : R.string.lock_to_app_toast); + } + if (text == null) { + return; } if (mLastToast != null) { mLastToast.cancel(); @@ -83,7 +89,7 @@ public class LockTaskNotify { public void handleMessage(Message msg) { switch(msg.what) { case SHOW_TOAST: - handleShowToast(msg.arg1 != 0); + handleShowToast(msg.arg1); break; } } diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java index a6c616a..f374c86 100644 --- a/services/core/java/com/android/server/am/ProcessRecord.java +++ b/services/core/java/com/android/server/am/ProcessRecord.java @@ -17,6 +17,7 @@ package com.android.server.am; import android.util.ArraySet; +import android.util.DebugUtils; import android.util.EventLog; import android.util.Slog; import com.android.internal.app.ProcessStats; @@ -248,8 +249,9 @@ final class ProcessRecord { pw.println(); pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq); pw.print(" lruSeq="); pw.print(lruSeq); - pw.print(" lastPss="); pw.print(lastPss); - pw.print(" lastCachedPss="); pw.println(lastCachedPss); + pw.print(" lastPss="); DebugUtils.printSizeValue(pw, lastPss*1024); + pw.print(" lastCachedPss="); DebugUtils.printSizeValue(pw, lastCachedPss*1024); + pw.println(); pw.print(prefix); pw.print("cached="); pw.print(cached); pw.print(" empty="); pw.println(empty); if (serviceb) { diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 018d77a..61a7263 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -188,7 +188,6 @@ public class AudioService extends IAudioService.Stub { // AudioHandler messages private static final int MSG_SET_DEVICE_VOLUME = 0; private static final int MSG_PERSIST_VOLUME = 1; - private static final int MSG_PERSIST_MASTER_VOLUME = 2; private static final int MSG_PERSIST_RINGER_MODE = 3; private static final int MSG_MEDIA_SERVER_DIED = 4; private static final int MSG_PLAY_SOUND_EFFECT = 5; @@ -239,10 +238,6 @@ public class AudioService extends IAudioService.Stub { private final Object mSoundEffectsLock = new Object(); private static final int NUM_SOUNDPOOL_CHANNELS = 4; - // Internally master volume is a float in the 0.0 - 1.0 range, - // but to support integer based AudioManager API we translate it to 0 - 100 - private static final int MAX_MASTER_VOLUME = 100; - // Maximum volume adjust steps allowed in a single batch call. private static final int MAX_BATCH_VOLUME_ADJUST_STEPS = 4; @@ -386,11 +381,6 @@ public class AudioService extends IAudioService.Stub { // Forced device usage for communications private int mForcedUseForComm; - // True if we have master volume support - private final boolean mUseMasterVolume; - - private final int[] mMasterVolumeRamp; - // List of binder death handlers for setMode() client processes. // The last process to have called setMode() is at the top of the list. private final ArrayList <SetModeDeathHandler> mSetModeDeathHandlers = new ArrayList <SetModeDeathHandler>(); @@ -595,10 +585,6 @@ public class AudioService extends IAudioService.Stub { mUseFixedVolume = mContext.getResources().getBoolean( com.android.internal.R.bool.config_useFixedVolume); - mUseMasterVolume = context.getResources().getBoolean( - com.android.internal.R.bool.config_useMasterVolume); - mMasterVolumeRamp = context.getResources().getIntArray( - com.android.internal.R.array.config_masterVolumeRamp); // must be called before readPersistedSettings() which needs a valid mStreamVolumeAlias[] // array initialized by updateStreamVolumeAlias() @@ -647,8 +633,6 @@ public class AudioService extends IAudioService.Stub { context.registerReceiver(mReceiver, intentFilter); - restoreMasterVolume(); - LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal()); } @@ -882,7 +866,7 @@ public class AudioService extends IAudioService.Stub { UserHandle.USER_CURRENT); boolean masterMute = System.getIntForUser(cr, System.VOLUME_MASTER_MUTE, - 0, UserHandle.USER_CURRENT) == 1; + 0, UserHandle.USER_CURRENT) == 1; if (mUseFixedVolume) { masterMute = false; AudioSystem.setMasterVolume(1.0f); @@ -1050,7 +1034,7 @@ public class AudioService extends IAudioService.Stub { // If either the client forces allowing ringer modes for this adjustment, // or the stream type is one that is affected by ringer modes if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || - (streamTypeAlias == getMasterStreamType())) { + (streamTypeAlias == getUiSoundsStreamType())) { int ringerMode = getRingerModeInternal(); // do not vibrate if already in vibrate mode if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) { @@ -1183,33 +1167,6 @@ public class AudioService extends IAudioService.Stub { } } - /** @see AudioManager#adjustMasterVolume(int, int) */ - public void adjustMasterVolume(int steps, int flags, String callingPackage) { - adjustMasterVolume(steps, flags, callingPackage, Binder.getCallingUid()); - } - - public void adjustMasterVolume(int steps, int flags, String callingPackage, int uid) { - if (mUseFixedVolume) { - return; - } - if (isMuteAdjust(steps)) { - setMasterMuteInternal(steps, flags, callingPackage, uid); - return; - } - ensureValidSteps(steps); - int volume = Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); - int delta = 0; - int numSteps = Math.abs(steps); - int direction = steps > 0 ? AudioManager.ADJUST_RAISE : AudioManager.ADJUST_LOWER; - for (int i = 0; i < numSteps; ++i) { - delta = findVolumeDelta(direction, volume); - volume += delta; - } - - //Log.d(TAG, "adjustMasterVolume volume: " + volume + " steps: " + steps); - setMasterVolume(volume, flags, callingPackage, uid); - } - // StreamVolumeCommand contains the information needed to defer the process of // setStreamVolume() in case the user has to acknowledge the safe volume warning message. class StreamVolumeCommand { @@ -1235,9 +1192,9 @@ public class AudioService extends IAudioService.Stub { private void onSetStreamVolume(int streamType, int index, int flags, int device) { setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, false); - // setting volume on master stream type also controls silent mode + // setting volume on ui sounds stream type also controls silent mode if (((flags & AudioManager.FLAG_ALLOW_RINGER_MODES) != 0) || - (mStreamVolumeAlias[streamType] == getMasterStreamType())) { + (mStreamVolumeAlias[streamType] == getUiSoundsStreamType())) { int newRingerMode; if (index == 0) { newRingerMode = mHasVibrator ? AudioManager.RINGER_MODE_VIBRATE @@ -1381,41 +1338,6 @@ public class AudioService extends IAudioService.Stub { } } - private int findVolumeDelta(int direction, int volume) { - int delta = 0; - if (direction == AudioManager.ADJUST_RAISE) { - if (volume == MAX_MASTER_VOLUME) { - return 0; - } - // This is the default value if we make it to the end - delta = mMasterVolumeRamp[1]; - // If we're raising the volume move down the ramp array until we - // find the volume we're above and use that groups delta. - for (int i = mMasterVolumeRamp.length - 1; i > 1; i -= 2) { - if (volume >= mMasterVolumeRamp[i - 1]) { - delta = mMasterVolumeRamp[i]; - break; - } - } - } else if (direction == AudioManager.ADJUST_LOWER){ - if (volume == 0) { - return 0; - } - int length = mMasterVolumeRamp.length; - // This is the default value if we make it to the end - delta = -mMasterVolumeRamp[length - 1]; - // If we're lowering the volume move up the ramp array until we - // find the volume we're below and use the group below it's delta - for (int i = 2; i < length; i += 2) { - if (volume <= mMasterVolumeRamp[i]) { - delta = -mMasterVolumeRamp[i - 1]; - break; - } - } - } - return delta; - } - private void sendBroadcastToAll(Intent intent) { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); @@ -1464,16 +1386,6 @@ public class AudioService extends IAudioService.Stub { } // UI update and Broadcast Intent - private void sendMasterVolumeUpdate(int flags, int oldVolume, int newVolume) { - mVolumeController.postMasterVolumeChanged(updateFlagsForSystemAudio(flags)); - - Intent intent = new Intent(AudioManager.MASTER_VOLUME_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_PREV_MASTER_VOLUME_VALUE, oldVolume); - intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_VALUE, newVolume); - sendBroadcastToAll(intent); - } - - // UI update and Broadcast Intent private void sendMasterMuteUpdate(boolean muted, int flags) { mVolumeController.postMasterMuteChanged(updateFlagsForSystemAudio(flags)); broadcastMasterMuteStatus(muted); @@ -1641,27 +1553,21 @@ public class AudioService extends IAudioService.Stub { } } - private void setMasterMuteInternal(int adjust, int flags, String callingPackage, int uid) { + private void setMasterMuteInternal(boolean mute, int flags, String callingPackage, int uid) { if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage) != AppOpsManager.MODE_ALLOWED) { return; } - boolean state; - if (adjust == AudioManager.ADJUST_TOGGLE_MUTE) { - state = !AudioSystem.getMasterMute(); - } else { - state = adjust == AudioManager.ADJUST_MUTE; - } - if (state != AudioSystem.getMasterMute()) { - setSystemAudioMute(state); - AudioSystem.setMasterMute(state); + if (mute != AudioSystem.getMasterMute()) { + setSystemAudioMute(mute); + AudioSystem.setMasterMute(mute); // Post a persist master volume msg - sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, state ? 1 + sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME_MUTE, SENDMSG_REPLACE, mute ? 1 : 0, UserHandle.getCallingUserId(), null, PERSIST_DELAY); - sendMasterMuteUpdate(state, flags); + sendMasterMuteUpdate(mute, flags); Intent intent = new Intent(AudioManager.MASTER_MUTE_CHANGED_ACTION); - intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, state); + intent.putExtra(AudioManager.EXTRA_MASTER_VOLUME_MUTED, mute); sendBroadcastToAll(intent); } } @@ -1671,6 +1577,10 @@ public class AudioService extends IAudioService.Stub { return AudioSystem.getMasterMute(); } + public void setMasterMute(boolean mute, int flags, String callingPackage) { + setMasterMuteInternal(mute, flags, callingPackage, Binder.getCallingUid()); + } + protected static int getMaxStreamVolume(int streamType) { return MAX_STREAM_VOLUME[streamType]; } @@ -1694,63 +1604,12 @@ public class AudioService extends IAudioService.Stub { } } - @Override - public int getMasterVolume() { - if (isMasterMute()) return 0; - return getLastAudibleMasterVolume(); - } - - @Override - public void setMasterVolume(int volume, int flags, String callingPackage) { - setMasterVolume(volume, flags, callingPackage, Binder.getCallingUid()); - } - - public void setMasterVolume(int volume, int flags, String callingPackage, int uid) { - if (mUseFixedVolume) { - return; - } - - if (mAppOps.noteOp(AppOpsManager.OP_AUDIO_MASTER_VOLUME, uid, callingPackage) - != AppOpsManager.MODE_ALLOWED) { - return; - } - - if (volume < 0) { - volume = 0; - } else if (volume > MAX_MASTER_VOLUME) { - volume = MAX_MASTER_VOLUME; - } - doSetMasterVolume((float)volume / MAX_MASTER_VOLUME, flags); - } - - private void doSetMasterVolume(float volume, int flags) { - // don't allow changing master volume when muted - if (!AudioSystem.getMasterMute()) { - int oldVolume = getMasterVolume(); - AudioSystem.setMasterVolume(volume); - - int newVolume = getMasterVolume(); - if (newVolume != oldVolume) { - // Post a persist master volume msg - sendMsg(mAudioHandler, MSG_PERSIST_MASTER_VOLUME, SENDMSG_REPLACE, - Math.round(volume * (float)1000.0), 0, null, PERSIST_DELAY); - setSystemAudioVolume(oldVolume, newVolume, getMasterMaxVolume(), flags); - } - // Send the volume update regardless whether there was a change. - sendMasterVolumeUpdate(flags, oldVolume, newVolume); - } - } - /** @see AudioManager#getStreamMaxVolume(int) */ public int getStreamMaxVolume(int streamType) { ensureValidStreamType(streamType); return (mStreamStates[streamType].getMaxIndex() + 5) / 10; } - public int getMasterMaxVolume() { - return MAX_MASTER_VOLUME; - } - /** Get last audible volume before stream was muted. */ public int getLastAudibleStreamVolume(int streamType) { ensureValidStreamType(streamType); @@ -1758,13 +1617,8 @@ public class AudioService extends IAudioService.Stub { return (mStreamStates[streamType].getIndex(device) + 5) / 10; } - /** Get last audible master volume before it was muted. */ - public int getLastAudibleMasterVolume() { - return Math.round(AudioSystem.getMasterVolume() * MAX_MASTER_VOLUME); - } - - /** @see AudioManager#getMasterStreamType() */ - public int getMasterStreamType() { + /** @see AudioManager#getUiSoundsStreamType() */ + public int getUiSoundsStreamType() { return mStreamVolumeAlias[AudioSystem.STREAM_SYSTEM]; } @@ -1932,20 +1786,6 @@ public class AudioService extends IAudioService.Stub { } } - private void restoreMasterVolume() { - if (mUseFixedVolume) { - AudioSystem.setMasterVolume(1.0f); - return; - } - if (mUseMasterVolume) { - float volume = Settings.System.getFloatForUser(mContentResolver, - Settings.System.VOLUME_MASTER, -1.0f, UserHandle.USER_CURRENT); - if (volume >= 0.0f) { - AudioSystem.setMasterVolume(volume); - } - } - } - /** @see AudioManager#shouldVibrate(int) */ public boolean shouldVibrate(int vibrateType) { if (!mHasVibrator) return false; @@ -3510,9 +3350,8 @@ public class AudioService extends IAudioService.Stub { public void readSettings() { synchronized (VolumeStreamState.class) { - // force maximum volume on all streams if fixed volume property - // or master volume property is set - if (mUseFixedVolume || mUseMasterVolume) { + // force maximum volume on all streams if fixed volume property is set + if (mUseFixedVolume) { mIndexMap.put(AudioSystem.DEVICE_OUT_DEFAULT, mIndexMax); return; } @@ -3747,7 +3586,7 @@ public class AudioService extends IAudioService.Stub { private int getValidIndex(int index) { if (index < 0) { return 0; - } else if (mUseFixedVolume || mUseMasterVolume || index > mIndexMax) { + } else if (mUseFixedVolume || index > mIndexMax) { return mIndexMax; } @@ -3777,6 +3616,21 @@ public class AudioService extends IAudioService.Stub { final int index = (mIndexMap.valueAt(i) + 5) / 10; pw.print(index); } + pw.println(); + pw.print(" Devices: "); + final int devices = AudioSystem.getDevicesForStream(mStreamType); + int device, i = 0, n = 0; + // iterate all devices from 1 to DEVICE_OUT_DEFAULT exclusive + // (the default device is not returned by getDevicesForStream) + while ((device = 1 << i) != AudioSystem.DEVICE_OUT_DEFAULT) { + if ((devices & device) != 0) { + if (n++ > 0) { + pw.print(", "); + } + pw.print(AudioSystem.getOutputDeviceName(device)); + } + i++; + } } } @@ -4119,16 +3973,6 @@ public class AudioService extends IAudioService.Stub { persistVolume((VolumeStreamState) msg.obj, msg.arg1); break; - case MSG_PERSIST_MASTER_VOLUME: - if (mUseFixedVolume) { - return; - } - Settings.System.putFloatForUser(mContentResolver, - Settings.System.VOLUME_MASTER, - msg.arg1 / (float)1000.0, - UserHandle.USER_CURRENT); - break; - case MSG_PERSIST_MASTER_VOLUME_MUTE: if (mUseFixedVolume) { return; @@ -4197,9 +4041,6 @@ public class AudioService extends IAudioService.Stub { // Restore ringer mode setRingerModeInt(getRingerModeInternal(), false); - // Restore master volume - restoreMasterVolume(); - // Reset device orientation (if monitored for this device) if (mMonitorOrientation) { setOrientationForAudioSystem(); @@ -5666,16 +5507,6 @@ public class AudioService extends IAudioService.Stub { } } - public void postMasterVolumeChanged(int flags) { - if (mController == null) - return; - try { - mController.masterVolumeChanged(flags); - } catch (RemoteException e) { - Log.w(TAG, "Error calling masterVolumeChanged", e); - } - } - public void postMasterMuteChanged(int flags) { if (mController == null) return; @@ -5741,12 +5572,6 @@ public class AudioService extends IAudioService.Stub { } @Override - public void adjustMasterVolumeForUid(int steps, int flags, String callingPackage, - int uid) { - adjustMasterVolume(steps, flags, callingPackage, uid); - } - - @Override public int getRingerModeInternal() { return AudioService.this.getRingerModeInternal(); } diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index 82c99f7..7c93e56 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -202,7 +202,6 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { reason != HdmiControlService.INITIATED_BY_BOOT_UP); mLocalDeviceAddresses = initLocalDeviceAddresses(); launchDeviceDiscovery(); - startQueuedActions(); } diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java index 3345e46..5363968 100644 --- a/services/core/java/com/android/server/media/MediaSessionRecord.java +++ b/services/core/java/com/android/server/media/MediaSessionRecord.java @@ -90,14 +90,12 @@ 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 = new ArrayList<ISessionControllerCallback>(); private long mFlags; - private IMediaRouter mMediaRouter; private PendingIntent mMediaButtonReceiver; private PendingIntent mLaunchIntent; @@ -141,8 +139,6 @@ 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); } /** @@ -247,13 +243,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { flags &= ~AudioManager.FLAG_PLAY_SOUND; } 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)) { @@ -729,7 +718,6 @@ public class MediaSessionRecord implements IBinder.DeathRecipient { @Override public void setMediaRouter(IMediaRouter router) { - mMediaRouter = router; mHandler.post(MessageHandler.MSG_UPDATE_SESSION_STATE); } diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java index 4383bb1..72205d6 100644 --- a/services/core/java/com/android/server/media/MediaSessionService.java +++ b/services/core/java/com/android/server/media/MediaSessionService.java @@ -89,11 +89,9 @@ 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; - private AudioManager mAudioManager; private AudioManagerInternal mAudioManagerInternal; private ContentResolver mContentResolver; private SettingsObserver mSettingsObserver; @@ -110,8 +108,6 @@ 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 @@ -121,7 +117,6 @@ public class MediaSessionService extends SystemService implements Monitor { mKeyguardManager = (KeyguardManager) getContext().getSystemService(Context.KEYGUARD_SERVICE); mAudioService = getAudioService(); - mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); mContentResolver = getContext().getContentResolver(); mSettingsObserver = new SettingsObserver(); @@ -468,11 +463,6 @@ public class MediaSessionService extends SystemService implements Monitor { return -1; } - private boolean isSessionDiscoverable(MediaSessionRecord record) { - // TODO probably want to check more than if it's active. - return record.isActive(); - } - private void pushSessionsChanged(int userId) { synchronized (mLock) { List<MediaSessionRecord> records = mPriorityStack.getActiveSessions(userId); @@ -889,12 +879,8 @@ public class MediaSessionService extends SystemService implements Monitor { } try { String packageName = getContext().getOpPackageName(); - if (mUseMasterVolume) { - mAudioService.adjustMasterVolume(direction, flags, packageName); - } else { - mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream, - flags, packageName); - } + mAudioService.adjustSuggestedStreamVolume(direction, suggestedStream, + flags, packageName); } catch (RemoteException e) { Log.e(TAG, "Error adjusting default volume.", e); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 9b6b5fb..bedcabe 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -2584,8 +2584,8 @@ public class NotificationManagerService extends SystemService { @Override public void run() { String listenerName = listener == null ? null : listener.component.toShortString(); - EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, id, tag, userId, - mustHaveFlags, mustNotHaveFlags, reason, listenerName); + if (DBG) EventLogTags.writeNotificationCancel(callingUid, callingPid, pkg, id, tag, + userId, mustHaveFlags, mustNotHaveFlags, reason, listenerName); synchronized (mNotificationList) { int index = indexOfNotificationLocked(pkg, tag, id, userId); diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java index 773b164..aa63932 100644 --- a/services/core/java/com/android/server/pm/KeySetManagerService.java +++ b/services/core/java/com/android/server/pm/KeySetManagerService.java @@ -414,9 +414,9 @@ public class KeySetManagerService { // Get the package's known keys and KeySets ArraySet<Long> deletableKeySets = getOriginalKeySetsByPackageNameLPr(packageName); ArraySet<Long> deletableKeys = new ArraySet<Long>(); - ArraySet<Long> knownKeys = null; - for (Long ks : deletableKeySets) { - knownKeys = mKeySetMapping.get(ks); + final int origDksSize = deletableKeySets.size(); + for (int i = 0; i < origDksSize; i++) { + ArraySet<Long> knownKeys = mKeySetMapping.get(deletableKeySets.valueAt(i)); if (knownKeys != null) { deletableKeys.addAll(knownKeys); } @@ -429,9 +429,9 @@ public class KeySetManagerService { } ArraySet<Long> knownKeySets = getOriginalKeySetsByPackageNameLPr(pkgName); deletableKeySets.removeAll(knownKeySets); - knownKeys = new ArraySet<Long>(); - for (Long ks : knownKeySets) { - knownKeys = mKeySetMapping.get(ks); + final int kksSize = knownKeySets.size(); + for (int i = 0; i < kksSize; i++) { + ArraySet<Long> knownKeys = mKeySetMapping.get(knownKeySets.valueAt(i)); if (knownKeys != null) { deletableKeys.removeAll(knownKeys); } @@ -440,18 +440,22 @@ public class KeySetManagerService { // The remaining keys and KeySets are not relied on by any other // application and so can be safely deleted. - for (Long ks : deletableKeySets) { + final int dksSize = deletableKeySets.size(); + for (int i = 0; i < dksSize; i++) { + Long ks = deletableKeySets.valueAt(i); mKeySets.delete(ks); mKeySetMapping.delete(ks); } - for (Long keyId : deletableKeys) { - mPublicKeys.delete(keyId); + final int dkSize = deletableKeys.size(); + for (int i = 0; i < dkSize; i++) { + mPublicKeys.delete(deletableKeys.valueAt(i)); } // Now remove the deleted KeySets from each package's signingKeySets for (String pkgName : mPackages.keySet()) { PackageSetting p = mPackages.get(pkgName); - for (Long ks : deletableKeySets) { + for (int i = 0; i < dksSize; i++) { + Long ks = deletableKeySets.valueAt(i); p.keySetData.removeSigningKeySet(ks); } } diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 2729392..e4f5e7d 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -917,6 +917,7 @@ public class UserManagerService extends IUserManager.Stub { writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS); writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE); writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_WALLPAPER); serializer.endTag(null, TAG_RESTRICTIONS); } @@ -1063,6 +1064,7 @@ public class UserManagerService extends IUserManager.Stub { readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS); readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE); readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM); + readBoolean(parser, restrictions, UserManager.DISALLOW_WALLPAPER); } private void readBoolean(XmlPullParser parser, Bundle restrictions, diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 9746142..62e7af4 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -380,7 +380,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mHasSoftInput = false; boolean mTranslucentDecorEnabled = true; boolean mUseTvRouting; - boolean mUseMasterVolume; int mPointerLocationMode = 0; // guarded by mLock @@ -540,6 +539,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mAllowTheaterModeWakeFromLidSwitch; private boolean mAllowTheaterModeWakeFromWakeGesture; + // Whether to support long press from power button in non-interactive mode + private boolean mSupportLongPressPowerWhenNonInteractive; + // Whether to go to sleep entering theater mode from power button private boolean mGoToSleepOnButtonPressTheaterMode; @@ -886,12 +888,21 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } else { wakeUpFromPowerKey(event.getDownTime()); - final int maxCount = getMaxMultiPressPowerCount(); - if (maxCount <= 1) { - mPowerKeyHandled = true; - } else { + if (mSupportLongPressPowerWhenNonInteractive && hasLongPressOnPowerBehavior()) { + Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS); + msg.setAsynchronous(true); + mHandler.sendMessageDelayed(msg, + ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout()); mBeganFromNonInteractive = true; + } else { + final int maxCount = getMaxMultiPressPowerCount(); + + if (maxCount <= 1) { + mPowerKeyHandled = true; + } else { + mBeganFromNonInteractive = true; + } } } } @@ -1260,6 +1271,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean( com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode); + mSupportLongPressPowerWhenNonInteractive = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_supportLongPressPowerWhenNonInteractive); + mShortPressOnPowerBehavior = mContext.getResources().getInteger( com.android.internal.R.integer.config_shortPressOnPowerBehavior); mLongPressOnPowerBehavior = mContext.getResources().getInteger( @@ -1270,8 +1284,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { com.android.internal.R.integer.config_triplePressOnPowerBehavior); mUseTvRouting = AudioSystem.getPlatformType(mContext) == AudioSystem.PLATFORM_TELEVISION; - mUseMasterVolume = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_useMasterVolume); readConfigurationDependentBehaviors(); @@ -4859,26 +4871,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { switch (keyCode) { case KeyEvent.KEYCODE_VOLUME_UP: try { - if (mUseMasterVolume) { - getAudioService().adjustMasterVolume(AudioManager.ADJUST_RAISE, flags, - pkgName); - } else { - getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, - AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName); - } + getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_RAISE, + AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName); } catch (RemoteException e) { Log.e(TAG, "Error dispatching volume up in dispatchTvAudioEvent.", e); } break; case KeyEvent.KEYCODE_VOLUME_DOWN: try { - if (mUseMasterVolume) { - getAudioService().adjustMasterVolume(AudioManager.ADJUST_LOWER, flags, - pkgName); - } else { - getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, - AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName); - } + getAudioService().adjustSuggestedStreamVolume(AudioManager.ADJUST_LOWER, + AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName); } catch (RemoteException e) { Log.e(TAG, "Error dispatching volume down in dispatchTvAudioEvent.", e); } @@ -4886,14 +4888,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_VOLUME_MUTE: try { if (event.getRepeatCount() == 0) { - if (mUseMasterVolume) { - getAudioService().adjustMasterVolume(AudioManager.ADJUST_TOGGLE_MUTE, - flags, pkgName); - } else { - getAudioService().adjustSuggestedStreamVolume( - AudioManager.ADJUST_TOGGLE_MUTE, - AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName); - } + getAudioService().adjustSuggestedStreamVolume( + AudioManager.ADJUST_TOGGLE_MUTE, + AudioManager.USE_DEFAULT_STREAM_TYPE, flags, pkgName); } } catch (RemoteException e) { Log.e(TAG, "Error dispatching mute in dispatchTvAudioEvent.", e); diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java index c3fc195..75c33af 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.pm.ActivityInfo; +import android.content.res.Resources; import android.graphics.PixelFormat; import android.os.Bundle; import android.os.IBinder; @@ -27,9 +28,6 @@ import com.android.internal.policy.IKeyguardShowCallback; * local or remote instances of keyguard. */ public class KeyguardServiceDelegate { - public static final String KEYGUARD_PACKAGE = "com.android.systemui"; - public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService"; - private static final String TAG = "KeyguardServiceDelegate"; private static final boolean DEBUG = true; @@ -111,10 +109,15 @@ public class KeyguardServiceDelegate { public void bindService(Context context) { Intent intent = new Intent(); - intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS); + final Resources resources = context.getApplicationContext().getResources(); + + final ComponentName keyguardComponent = ComponentName.unflattenFromString( + resources.getString(com.android.internal.R.string.config_keyguardComponent)); + intent.setComponent(keyguardComponent); + if (!context.bindServiceAsUser(intent, mKeyguardConnection, Context.BIND_AUTO_CREATE, UserHandle.OWNER)) { - Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS); + Log.v(TAG, "*** Keyguard: can't bind to " + keyguardComponent); mKeyguardState.showing = false; mKeyguardState.showingAndNotOccluded = false; mKeyguardState.secure = false; diff --git a/services/core/java/com/android/server/trust/TrustAgentWrapper.java b/services/core/java/com/android/server/trust/TrustAgentWrapper.java index 57b204d..583cc6b 100644 --- a/services/core/java/com/android/server/trust/TrustAgentWrapper.java +++ b/services/core/java/com/android/server/trust/TrustAgentWrapper.java @@ -395,6 +395,7 @@ public class TrustAgentWrapper { } public void destroy() { + mContext.unregisterReceiver(mBroadcastReceiver); mHandler.removeMessages(MSG_RESTART_TIMEOUT); if (!mBound) { diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java index e57396f..ac8ad30 100644 --- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java +++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java @@ -102,7 +102,6 @@ class TvInputHardwareManager implements TvInputHal.Callback { }; private int mCurrentIndex = 0; private int mCurrentMaxIndex = 0; - private final boolean mUseMasterVolume; // TODO: Should handle STANDBY case. private final SparseBooleanArray mHdmiStateMap = new SparseBooleanArray(); @@ -117,8 +116,6 @@ class TvInputHardwareManager implements TvInputHal.Callback { mContext = context; mListener = listener; mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - mUseMasterVolume = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_useMasterVolume); mHal.init(); } @@ -139,12 +136,10 @@ class TvInputHardwareManager implements TvInputHal.Callback { } else { Slog.w(TAG, "HdmiControlService is not available"); } - if (!mUseMasterVolume) { - final IntentFilter filter = new IntentFilter(); - filter.addAction(AudioManager.VOLUME_CHANGED_ACTION); - filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION); - mContext.registerReceiver(mVolumeReceiver, filter); - } + final IntentFilter filter = new IntentFilter(); + filter.addAction(AudioManager.VOLUME_CHANGED_ACTION); + filter.addAction(AudioManager.STREAM_MUTE_CHANGED_ACTION); + mContext.registerReceiver(mVolumeReceiver, filter); updateVolume(); } } @@ -545,7 +540,7 @@ class TvInputHardwareManager implements TvInputHal.Callback { } private float getMediaStreamVolume() { - return mUseMasterVolume ? 1.0f : ((float) mCurrentIndex / (float) mCurrentMaxIndex); + return (float) mCurrentIndex / (float) mCurrentMaxIndex; } private class Connection implements IBinder.DeathRecipient { diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index b48fadb..99cf8df 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -20,6 +20,7 @@ import static android.os.ParcelFileDescriptor.*; import android.app.ActivityManagerNative; import android.app.AppGlobals; +import android.app.AppOpsManager; import android.app.IUserSwitchObserver; import android.app.IWallpaperManager; import android.app.IWallpaperManagerCallback; @@ -164,6 +165,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { final IWindowManager mIWindowManager; final IPackageManager mIPackageManager; final MyPackageMonitor mMonitor; + final AppOpsManager mAppOpsManager; WallpaperData mLastWallpaper; /** @@ -478,6 +480,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { mIWindowManager = IWindowManager.Stub.asInterface( ServiceManager.getService(Context.WINDOW_SERVICE)); mIPackageManager = AppGlobals.getPackageManager(); + mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE); mMonitor = new MyPackageMonitor(); mMonitor.register(context, null, UserHandle.ALL, true); getWallpaperDir(UserHandle.USER_OWNER).mkdirs(); @@ -613,8 +616,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } - public void clearWallpaper() { + public void clearWallpaper(String callingPackage) { if (DEBUG) Slog.v(TAG, "clearWallpaper"); + checkPermission(android.Manifest.permission.SET_WALLPAPER); + if (!isWallpaperSupported(callingPackage)) { + return; + } synchronized (mLock) { clearWallpaperLocked(false, UserHandle.getCallingUserId(), null); } @@ -622,6 +629,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { void clearWallpaperLocked(boolean defaultFailed, int userId, IRemoteCallback reply) { WallpaperData wallpaper = mWallpaperMap.get(userId); + if (wallpaper == null) { + return; + } File f = new File(getWallpaperDir(userId), WALLPAPER); if (f.exists()) { f.delete(); @@ -668,6 +678,10 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { Binder.restoreCallingIdentity(ident); } for (UserInfo user: users) { + // ignore managed profiles + if (user.isManagedProfile()) { + continue; + } WallpaperData wd = mWallpaperMap.get(user.id); if (wd == null) { // User hasn't started yet, so load her settings to peek at the wallpaper @@ -690,8 +704,12 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { return p; } - public void setDimensionHints(int width, int height) throws RemoteException { + public void setDimensionHints(int width, int height, String callingPackage) + throws RemoteException { checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS); + if (!isWallpaperSupported(callingPackage)) { + return; + } synchronized (mLock) { int userId = UserHandle.getCallingUserId(); WallpaperData wallpaper = mWallpaperMap.get(userId); @@ -733,19 +751,30 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { public int getWidthHint() throws RemoteException { synchronized (mLock) { WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId()); - return wallpaper.width; + if (wallpaper != null) { + return wallpaper.width; + } else { + return 0; + } } } public int getHeightHint() throws RemoteException { synchronized (mLock) { WallpaperData wallpaper = mWallpaperMap.get(UserHandle.getCallingUserId()); - return wallpaper.height; + if (wallpaper != null) { + return wallpaper.height; + } else { + return 0; + } } } - public void setDisplayPadding(Rect padding) { + public void setDisplayPadding(Rect padding, String callingPackage) { checkPermission(android.Manifest.permission.SET_WALLPAPER_HINTS); + if (!isWallpaperSupported(callingPackage)) { + return; + } synchronized (mLock) { int userId = UserHandle.getCallingUserId(); WallpaperData wallpaper = mWallpaperMap.get(userId); @@ -791,6 +820,9 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { wallpaperUserId = UserHandle.getUserId(callingUid); } WallpaperData wallpaper = mWallpaperMap.get(wallpaperUserId); + if (wallpaper == null) { + return null; + } try { if (outParams != null) { outParams.putInt("width", wallpaper.width); @@ -814,15 +846,18 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { int userId = UserHandle.getCallingUserId(); synchronized (mLock) { WallpaperData wallpaper = mWallpaperMap.get(userId); - if (wallpaper.connection != null) { + if (wallpaper != null && wallpaper.connection != null) { return wallpaper.connection.mInfo; } return null; } } - public ParcelFileDescriptor setWallpaper(String name) { + public ParcelFileDescriptor setWallpaper(String name, String callingPackage) { checkPermission(android.Manifest.permission.SET_WALLPAPER); + if (!isWallpaperSupported(callingPackage)) { + return null; + } synchronized (mLock) { if (DEBUG) Slog.v(TAG, "setWallpaper"); int userId = UserHandle.getCallingUserId(); @@ -868,6 +903,13 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { return null; } + public void setWallpaperComponentChecked(ComponentName name, String callingPackage) { + if (isWallpaperSupported(callingPackage)) { + setWallpaperComponent(name); + } + } + + // ToDo: Remove this version of the function public void setWallpaperComponent(ComponentName name) { checkPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT); synchronized (mLock) { @@ -1097,6 +1139,15 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } } + /** + * Certain user types do not support wallpapers (e.g. managed profiles). The check is + * implemented through through the OP_WRITE_WALLPAPER AppOp. + */ + public boolean isWallpaperSupported(String callingPackage) { + return mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_WRITE_WALLPAPER, Binder.getCallingUid(), + callingPackage) == AppOpsManager.MODE_ALLOWED; + } + private static JournaledFile makeJournaledFile(int userId) { final String base = new File(getWallpaperDir(userId), WALLPAPER_INFO).getAbsolutePath(); return new JournaledFile(new File(base), new File(base + ".tmp")); @@ -1174,7 +1225,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { private void loadSettingsLocked(int userId) { if (DEBUG) Slog.v(TAG, "loadSettingsLocked"); - + JournaledFile journal = makeJournaledFile(userId); FileInputStream stream = null; File file = journal.chooseForRead(); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java index 57ed876..ea59d4b 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java @@ -53,6 +53,7 @@ class DeviceOwner { private static final String DEVICE_OWNER_XML = "device_owner.xml"; private static final String TAG_DEVICE_OWNER = "device-owner"; + private static final String TAG_DEVICE_INITIALIZER = "device-initializer"; private static final String TAG_PROFILE_OWNER = "profile-owner"; private static final String ATTR_NAME = "name"; private static final String ATTR_PACKAGE = "package"; @@ -68,6 +69,9 @@ class DeviceOwner { // Internal state for the device owner package. private OwnerInfo mDeviceOwner; + // Internal state for the device initializer package. + private OwnerInfo mDeviceInitializer; + // Internal state for the profile owner packages. private final HashMap<Integer, OwnerInfo> mProfileOwners = new HashMap<Integer, OwnerInfo>(); @@ -104,6 +108,15 @@ class DeviceOwner { } /** + * Creates an instance of the device owner object with the device initializer set. + */ + static DeviceOwner createWithDeviceInitializer(String packageName, String ownerName) { + DeviceOwner owner = new DeviceOwner(); + owner.mDeviceInitializer = new OwnerInfo(ownerName, packageName); + return owner; + } + + /** * Creates an instance of the device owner object with the profile owner set. */ static DeviceOwner createWithProfileOwner(ComponentName admin, String ownerName, int userId) { @@ -128,6 +141,26 @@ class DeviceOwner { mDeviceOwner = null; } + String getDeviceInitializerPackageName() { + return mDeviceInitializer != null ? mDeviceInitializer.packageName : null; + } + + String getDeviceInitializerName() { + return mDeviceInitializer != null ? mDeviceInitializer.name : null; + } + + void setDeviceInitializer(String packageName, String ownerName) { + mDeviceInitializer = new OwnerInfo(ownerName, packageName); + } + + void clearDeviceInitializer() { + mDeviceInitializer = null; + } + + boolean hasDeviceInitializer() { + return mDeviceInitializer != null; + } + void setProfileOwner(ComponentName admin, String ownerName, int userId) { mProfileOwners.put(userId, new OwnerInfo(ownerName, admin)); } @@ -199,6 +232,10 @@ class DeviceOwner { String name = parser.getAttributeValue(null, ATTR_NAME); String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); mDeviceOwner = new OwnerInfo(name, packageName); + } else if (tag.equals(TAG_DEVICE_INITIALIZER)) { + String name = parser.getAttributeValue(null, ATTR_NAME); + String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); + mDeviceInitializer = new OwnerInfo(name, packageName); } else if (tag.equals(TAG_PROFILE_OWNER)) { String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME); @@ -259,6 +296,16 @@ class DeviceOwner { out.endTag(null, TAG_DEVICE_OWNER); } + // Write device initializer tag + if (mDeviceInitializer != null) { + out.startTag(null, TAG_DEVICE_INITIALIZER); + out.attribute(null, ATTR_PACKAGE, mDeviceInitializer.packageName); + if (mDeviceInitializer.name != null) { + out.attribute(null, ATTR_NAME, mDeviceInitializer.name); + } + out.endTag(null, TAG_DEVICE_INITIALIZER); + } + // Write profile owner tags if (mProfileOwners.size() > 0) { for (HashMap.Entry<Integer, OwnerInfo> owner : mProfileOwners.entrySet()) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index a19cd9f..00d7971 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -51,6 +51,7 @@ import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.content.pm.UserInfo; import android.database.ContentObserver; +import android.graphics.Bitmap; import android.hardware.usb.UsbManager; import android.media.AudioManager; import android.media.IAudioService; @@ -179,6 +180,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { DEVICE_OWNER_USER_RESTRICTIONS.add(UserManager.DISALLOW_SMS); } + // The following user restrictions cannot be changed by any active admin, including device + // owner and profile owner. + private static final Set<String> IMMUTABLE_USER_RESTRICTIONS; + static { + IMMUTABLE_USER_RESTRICTIONS = new HashSet(); + IMMUTABLE_USER_RESTRICTIONS.add(UserManager.DISALLOW_WALLPAPER); + } + private static final Set<String> SECURE_SETTINGS_WHITELIST; private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_WHITELIST; private static final Set<String> GLOBAL_SETTINGS_WHITELIST; @@ -1139,13 +1148,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean ownsProfile = (getProfileOwner(userHandle) != null && getProfileOwner(userHandle).getPackageName() .equals(admin.info.getPackageName())); + boolean ownsInitialization = isDeviceInitializer(admin.info.getPackageName()) + && !hasUserSetupCompleted(userHandle); if (reqPolicy == DeviceAdminInfo.USES_POLICY_DEVICE_OWNER) { - if (ownsDevice) { + if (ownsDevice || (userHandle == UserHandle.USER_OWNER && ownsInitialization)) { return admin; } } else if (reqPolicy == DeviceAdminInfo.USES_POLICY_PROFILE_OWNER) { - if (ownsDevice || ownsProfile) { + if (ownsDevice || ownsProfile || ownsInitialization) { return admin; } } else { @@ -1899,7 +1910,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { return; } if (admin.getUid() != Binder.getCallingUid()) { - // If trying to remove device owner, refuse when the caller is not the owner. + // Active device owners must remain active admins. if (isDeviceOwner(adminReceiver.getPackageName())) { return; } @@ -3866,6 +3877,110 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override + public boolean setDeviceInitializer(ComponentName who, ComponentName initializer, + String ownerName) { + if (!mHasFeature) { + return false; + } + if (initializer == null || !DeviceOwner.isInstalled( + initializer.getPackageName(), mContext.getPackageManager())) { + throw new IllegalArgumentException("Invalid component name " + initializer + + " for device initializer"); + } + synchronized (this) { + enforceCanSetDeviceInitializer(who); + + if (mDeviceOwner != null && mDeviceOwner.hasDeviceInitializer()) { + throw new IllegalStateException( + "Trying to set device initializer but device initializer is already set."); + } + + if (mDeviceOwner == null) { + // Device owner state does not exist, create it. + mDeviceOwner = DeviceOwner.createWithDeviceInitializer( + initializer.getPackageName(), ownerName); + mDeviceOwner.writeOwnerFile(); + return true; + } else { + // Device owner already exists, update it. + mDeviceOwner.setDeviceInitializer(initializer.getPackageName(), ownerName); + mDeviceOwner.writeOwnerFile(); + return true; + } + } + } + + private void enforceCanSetDeviceInitializer(ComponentName who) { + if (who == null) { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.MANAGE_DEVICE_ADMINS, null); + if (hasUserSetupCompleted(UserHandle.USER_OWNER)) { + throw new IllegalStateException( + "Trying to set device initializer but device is already provisioned."); + } + } else { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER); + } + } + + @Override + public boolean isDeviceInitializer(String packageName) { + if (!mHasFeature) { + return false; + } + synchronized (this) { + return mDeviceOwner != null + && mDeviceOwner.hasDeviceInitializer() + && mDeviceOwner.getDeviceInitializerPackageName().equals(packageName); + } + } + + @Override + public String getDeviceInitializer() { + if (!mHasFeature) { + return null; + } + synchronized (this) { + if (mDeviceOwner != null && mDeviceOwner.hasDeviceInitializer()) { + return mDeviceOwner.getDeviceInitializerPackageName(); + } + } + return null; + } + + @Override + public void clearDeviceInitializer(ComponentName who) { + if (!mHasFeature) { + return; + } + Preconditions.checkNotNull(who, "ComponentName is null"); + + ActiveAdmin admin = getActiveAdminUncheckedLocked(who, UserHandle.getCallingUserId()); + + if (admin.getUid() != Binder.getCallingUid()) { + throw new SecurityException("Admin " + who + " is not owned by uid " + + Binder.getCallingUid()); + } + + if (!isDeviceInitializer(admin.info.getPackageName()) + && !isDeviceOwner(admin.info.getPackageName())) { + throw new SecurityException( + "clearDeviceInitializer can only be called by the device initializer/owner"); + } + synchronized (this) { + long ident = Binder.clearCallingIdentity(); + try { + if (mDeviceOwner != null) { + mDeviceOwner.clearDeviceInitializer(); + mDeviceOwner.writeOwnerFile(); + } + } finally { + Binder.restoreCallingIdentity(ident); + } + } + } + + @Override public boolean setProfileOwner(ComponentName who, String ownerName, int userHandle) { if (!mHasFeature) { return false; @@ -3938,7 +4053,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Bundle userRestrictions = mUserManager.getUserRestrictions(); mUserManager.setUserRestrictions(new Bundle(), userHandle); if (userRestrictions.getBoolean(UserManager.DISALLOW_ADJUST_VOLUME)) { - audioManager.adjustMasterVolume(AudioManager.ADJUST_UNMUTE, 0); + audioManager.setMasterMute(false, 0); } if (userRestrictions.getBoolean(UserManager.DISALLOW_UNMUTE_MICROPHONE)) { audioManager.setMicrophoneMute(false); @@ -3960,6 +4075,51 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } @Override + public boolean setUserEnabled(ComponentName who) { + if (!mHasFeature) { + return false; + } + synchronized (this) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + int userId = UserHandle.getCallingUserId(); + + ActiveAdmin activeAdmin = + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + if (!isDeviceInitializer(activeAdmin.info.getPackageName())) { + throw new SecurityException( + "This method can only be called by device initializers"); + } + + long id = Binder.clearCallingIdentity(); + try { + if (!isDeviceOwner(activeAdmin.info.getPackageName())) { + IPackageManager ipm = AppGlobals.getPackageManager(); + ipm.setComponentEnabledSetting(who, + PackageManager.COMPONENT_ENABLED_STATE_DISABLED, + PackageManager.DONT_KILL_APP, userId); + + removeActiveAdmin(who, userId); + } + + if (userId == UserHandle.USER_OWNER) { + Settings.Global.putInt(mContext.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 1); + } + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE, 1, userId); + } catch (RemoteException e) { + Log.i(LOG_TAG, "Can't talk to package manager", e); + return false; + } finally { + restoreCallingIdentity(id); + } + return true; + } + } + + @Override public void setProfileEnabled(ComponentName who) { if (!mHasFeature) { return; @@ -4801,6 +4961,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) { throw new SecurityException("Profile owners cannot set user restriction " + key); } + if (IMMUTABLE_USER_RESTRICTIONS.contains(key)) { + throw new SecurityException("User restriction " + key + " cannot be changed"); + } boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user); IAudioService iAudioService = null; @@ -4815,8 +4978,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) { iAudioService.setMicrophoneMute(true, who.getPackageName()); } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) { - iAudioService.adjustMasterVolume(AudioManager.ADJUST_MUTE, 0, - who.getPackageName()); + iAudioService.setMasterMute(true, 0, who.getPackageName()); } } catch (RemoteException re) { Slog.e(LOG_TAG, "Failed to talk to AudioService.", re); @@ -4881,8 +5043,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key)) { iAudioService.setMicrophoneMute(false, who.getPackageName()); } else if (UserManager.DISALLOW_ADJUST_VOLUME.equals(key)) { - iAudioService.adjustMasterVolume(AudioManager.ADJUST_UNMUTE, 0, - who.getPackageName()); + iAudioService.setMasterMute(false, 0, who.getPackageName()); } } catch (RemoteException re) { Slog.e(LOG_TAG, "Failed to talk to AudioService.", re); @@ -5322,10 +5483,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { IAudioService iAudioService = IAudioService.Stub.asInterface( ServiceManager.getService(Context.AUDIO_SERVICE)); - try{ - iAudioService.adjustMasterVolume( - on ? AudioManager.ADJUST_MUTE : AudioManager.ADJUST_UNMUTE, 0, - who.getPackageName()); + try { + iAudioService.setMasterMute(on, 0, who.getPackageName()); } catch (RemoteException re) { Slog.e(LOG_TAG, "Failed to setMasterMute", re); } @@ -5344,6 +5503,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override + public void setUserIcon(ComponentName who, Bitmap icon) { + synchronized (this) { + Preconditions.checkNotNull(who, "ComponentName is null"); + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + + int userId = UserHandle.getCallingUserId(); + long id = Binder.clearCallingIdentity(); + try { + mUserManager.setUserIcon(userId, icon); + } finally { + restoreCallingIdentity(id); + } + } + } + /** * We need to update the internal state of whether a user has completed setup once. After * that, we ignore any changes that reset the Settings.Secure.USER_SETUP_COMPLETE changes diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index cd6e786..a0c7f86 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -669,7 +669,8 @@ public final class SystemServer { mSystemServiceManager.startService("com.android.server.wifi.RttService"); - if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET)) { + if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_ETHERNET) || + mPackageManager.hasSystemFeature(PackageManager.FEATURE_USB_HOST)) { mSystemServiceManager.startService(ETHERNET_SERVICE_CLASS); } diff --git a/services/usb/java/com/android/server/usb/UsbMidiDevice.java b/services/usb/java/com/android/server/usb/UsbMidiDevice.java index e17abc0..51d61bb 100644 --- a/services/usb/java/com/android/server/usb/UsbMidiDevice.java +++ b/services/usb/java/com/android/server/usb/UsbMidiDevice.java @@ -19,8 +19,8 @@ package com.android.server.usb; import android.content.Context; import android.media.midi.MidiDeviceInfo; import android.media.midi.MidiDeviceServer; +import android.media.midi.MidiDispatcher; import android.media.midi.MidiManager; -import android.media.midi.MidiPort; import android.media.midi.MidiReceiver; import android.media.midi.MidiSender; import android.os.Bundle; @@ -30,6 +30,8 @@ import android.system.OsConstants; import android.system.StructPollfd; import android.util.Log; +import libcore.io.IoUtils; + import java.io.Closeable; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -39,8 +41,11 @@ import java.io.IOException; public final class UsbMidiDevice implements Closeable { private static final String TAG = "UsbMidiDevice"; - private final MidiDeviceServer mServer; - private final MidiReceiver[] mOutputPortReceivers; + private MidiDeviceServer mServer; + + private final MidiReceiver[] mInputPortReceivers; + + private static final int BUFFER_SIZE = 512; // for polling multiple FileDescriptors for MIDI events private final StructPollfd[] mPollFDs; @@ -50,12 +55,6 @@ public final class UsbMidiDevice implements Closeable { private final FileOutputStream[] mOutputStreams; public static UsbMidiDevice create(Context context, Bundle properties, int card, int device) { - MidiManager midiManager = (MidiManager)context.getSystemService(Context.MIDI_SERVICE); - if (midiManager == null) { - Log.e(TAG, "No MidiManager in UsbMidiDevice.create()"); - return null; - } - // FIXME - support devices with different number of input and output ports int subDevices = nativeGetSubdeviceCount(card, device); if (subDevices <= 0) { @@ -70,19 +69,16 @@ public final class UsbMidiDevice implements Closeable { return null; } - MidiDeviceServer server = midiManager.createDeviceServer(subDevices, subDevices, properties, - false, MidiDeviceInfo.TYPE_USB); - if (server == null) { + UsbMidiDevice midiDevice = new UsbMidiDevice(fileDescriptors, fileDescriptors); + if (!midiDevice.register(context, properties)) { + IoUtils.closeQuietly(midiDevice); Log.e(TAG, "createDeviceServer failed"); return null; } - - return new UsbMidiDevice(server, fileDescriptors, fileDescriptors); + return midiDevice; } - private UsbMidiDevice(MidiDeviceServer server, FileDescriptor[] inputFiles, - FileDescriptor[] outputFiles) { - mServer = server; + private UsbMidiDevice(FileDescriptor[] inputFiles, FileDescriptor[] outputFiles) { int inputCount = inputFiles.length; int outputCount = outputFiles.length; @@ -102,30 +98,40 @@ public final class UsbMidiDevice implements Closeable { mOutputStreams[i] = new FileOutputStream(outputFiles[i]); } - mOutputPortReceivers = new MidiReceiver[outputCount]; - for (int port = 0; port < outputCount; port++) { - mOutputPortReceivers[port] = server.openOutputPortReceiver(port); - } - + mInputPortReceivers = new MidiReceiver[inputCount]; for (int port = 0; port < inputCount; port++) { - final int portNumberF = port; - MidiReceiver receiver = new MidiReceiver() { - + final int portF = port; + mInputPortReceivers[port] = new MidiReceiver() { @Override - public void post(byte[] data, int offset, int count, long timestamp) + public void receive(byte[] data, int offset, int count, long timestamp) throws IOException { // FIXME - timestamps are ignored, future posting not supported yet. - mOutputStreams[portNumberF].write(data, offset, count); + mOutputStreams[portF].write(data, offset, count); } }; - MidiSender sender = server.openInputPortSender(port); - sender.connect(receiver); } + } + private boolean register(Context context, Bundle properties) { + MidiManager midiManager = (MidiManager)context.getSystemService(Context.MIDI_SERVICE); + if (midiManager == null) { + Log.e(TAG, "No MidiManager in UsbMidiDevice.create()"); + return false; + } + + int outputCount = mOutputStreams.length; + mServer = midiManager.createDeviceServer(mInputPortReceivers, outputCount, + properties, MidiDeviceInfo.TYPE_USB); + if (mServer == null) { + return false; + } + final MidiReceiver[] outputReceivers = mServer.getOutputPortReceivers(); + + // FIXME can we only run this when we have a dispatcher that has listeners? new Thread() { @Override public void run() { - byte[] buffer = new byte[MidiPort.MAX_PACKET_DATA_SIZE]; + byte[] buffer = new byte[BUFFER_SIZE]; try { boolean done = false; while (!done) { @@ -137,8 +143,8 @@ public final class UsbMidiDevice implements Closeable { pfd.revents = 0; int count = mInputStreams[index].read(buffer); - mOutputPortReceivers[index].post(buffer, 0, count, - System.nanoTime()); + long timestamp = System.nanoTime(); + outputReceivers[index].receive(buffer, 0, count, timestamp); } else if ((pfd.revents & (OsConstants.POLLERR | OsConstants.POLLHUP)) != 0) { done = true; @@ -155,11 +161,15 @@ public final class UsbMidiDevice implements Closeable { } } }.start(); + + return true; } @Override public void close() throws IOException { - mServer.close(); + if (mServer != null) { + mServer.close(); + } for (int i = 0; i < mInputStreams.length; i++) { mInputStreams[i].close(); |