diff options
Diffstat (limited to 'services')
30 files changed, 704 insertions, 530 deletions
diff --git a/services/core/java/com/android/server/AssetAtlasService.java b/services/core/java/com/android/server/AssetAtlasService.java index 26f4232..ebc810f 100644 --- a/services/core/java/com/android/server/AssetAtlasService.java +++ b/services/core/java/com/android/server/AssetAtlasService.java @@ -119,7 +119,6 @@ public class AssetAtlasService extends IAssetAtlas.Stub { // long0: SkBitmap*, the native bitmap object // long1: x position // long2: y position - // long3: rotated, 1 if the bitmap must be rotated, 0 otherwise private long[] mAtlasMap; /** @@ -236,7 +235,7 @@ public class AssetAtlasService extends IAssetAtlas.Stub { /** * Renders a list of bitmaps into the atlas. The position of each bitmap * was decided by the packing algorithm and will be honored by this - * method. If need be this method will also rotate bitmaps. + * method. * * @param buffer The buffer to render the atlas entries into * @param atlas The atlas to pack the bitmaps into @@ -280,16 +279,11 @@ public class AssetAtlasService extends IAssetAtlas.Stub { canvas.save(); canvas.translate(entry.x, entry.y); - if (entry.rotated) { - canvas.translate(bitmap.getHeight(), 0.0f); - canvas.rotate(90.0f); - } canvas.drawBitmap(bitmap, 0.0f, 0.0f, null); canvas.restore(); atlasMap[mapIndex++] = bitmap.refSkPixelRef(); atlasMap[mapIndex++] = entry.x; atlasMap[mapIndex++] = entry.y; - atlasMap[mapIndex++] = entry.rotated ? 1 : 0; } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 8d1d124..1dc2d7e 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -190,7 +190,7 @@ public class ConnectivityService extends IConnectivityManager.Stub /** Set of ifaces that are costly. */ private HashSet<String> mMeteredIfaces = Sets.newHashSet(); - private Context mContext; + final private Context mContext; private int mNetworkPreference; // 0 is full bad, 100 is full good private int mDefaultInetConditionPublished = 0; @@ -344,6 +344,11 @@ public class ConnectivityService extends IConnectivityManager.Stub */ private static final int EVENT_PROMPT_UNVALIDATED = 29; + /** + * used internally to (re)configure mobile data always-on settings. + */ + private static final int EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON = 30; + /** Handler used for internal events. */ final private InternalHandler mHandler; /** Handler used for incoming {@link NetworkStateTracker} events. */ @@ -374,7 +379,7 @@ public class ConnectivityService extends IConnectivityManager.Stub private PacManager mPacManager = null; - private SettingsObserver mSettingsObserver; + final private SettingsObserver mSettingsObserver; private UserManager mUserManager; @@ -555,13 +560,12 @@ public class ConnectivityService extends IConnectivityManager.Stub INetworkStatsService statsService, INetworkPolicyManager policyManager) { if (DBG) log("ConnectivityService starting up"); - NetworkCapabilities netCap = new NetworkCapabilities(); - netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); - netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); - mDefaultRequest = new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId()); - NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(), - NetworkRequestInfo.REQUEST); - mNetworkRequests.put(mDefaultRequest, nri); + mDefaultRequest = createInternetRequestForTransport(-1); + mNetworkRequests.put(mDefaultRequest, new NetworkRequestInfo( + null, mDefaultRequest, new Binder(), NetworkRequestInfo.REQUEST)); + + mDefaultMobileDataRequest = createInternetRequestForTransport( + NetworkCapabilities.TRANSPORT_CELLULAR); HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread"); handlerThread.start(); @@ -696,8 +700,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mInetLog = new ArrayList(); } - mSettingsObserver = new SettingsObserver(mHandler, EVENT_APPLY_GLOBAL_HTTP_PROXY); - mSettingsObserver.observe(mContext); + mSettingsObserver = new SettingsObserver(mContext, mHandler); + registerSettingsCallbacks(); mDataConnectionStats = new DataConnectionStats(mContext); mDataConnectionStats.startMonitoring(); @@ -707,6 +711,44 @@ public class ConnectivityService extends IConnectivityManager.Stub mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); } + private NetworkRequest createInternetRequestForTransport(int transportType) { + NetworkCapabilities netCap = new NetworkCapabilities(); + netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET); + netCap.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED); + if (transportType > -1) { + netCap.addTransportType(transportType); + } + return new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId()); + } + + private void handleMobileDataAlwaysOn() { + final boolean enable = (Settings.Global.getInt( + mContext.getContentResolver(), Settings.Global.MOBILE_DATA_ALWAYS_ON, 0) == 1); + final boolean isEnabled = (mNetworkRequests.get(mDefaultMobileDataRequest) != null); + if (enable == isEnabled) { + return; // Nothing to do. + } + + if (enable) { + handleRegisterNetworkRequest(new NetworkRequestInfo( + null, mDefaultMobileDataRequest, new Binder(), NetworkRequestInfo.REQUEST)); + } else { + handleReleaseNetworkRequest(mDefaultMobileDataRequest, Process.SYSTEM_UID); + } + } + + private void registerSettingsCallbacks() { + // Watch for global HTTP proxy changes. + mSettingsObserver.observe( + Settings.Global.getUriFor(Settings.Global.HTTP_PROXY), + EVENT_APPLY_GLOBAL_HTTP_PROXY); + + // Watch for whether or not to keep mobile data always on. + mSettingsObserver.observe( + Settings.Global.getUriFor(Settings.Global.MOBILE_DATA_ALWAYS_ON), + EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON); + } + private synchronized int nextNetworkRequestId() { return mNextNetworkRequestId++; } @@ -1491,6 +1533,9 @@ public class ConnectivityService extends IConnectivityManager.Stub mContext.registerReceiver(mUserPresentReceiver, filter); } + // Configure whether mobile data is always on. + mHandler.sendMessage(mHandler.obtainMessage(EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON)); + mHandler.sendMessage(mHandler.obtainMessage(EVENT_SYSTEM_READY)); mPermissionMonitor.startMonitoring(); @@ -2107,12 +2152,10 @@ public class ConnectivityService extends IConnectivityManager.Stub + nri.request + " because their intents matched."); handleReleaseNetworkRequest(existingRequest.request, getCallingUid()); } - handleRegisterNetworkRequest(msg); + handleRegisterNetworkRequest(nri); } - private void handleRegisterNetworkRequest(Message msg) { - final NetworkRequestInfo nri = (NetworkRequestInfo) (msg.obj); - + private void handleRegisterNetworkRequest(NetworkRequestInfo nri) { mNetworkRequests.put(nri.request, nri); // TODO: This logic may be better replaced with a call to rematchNetworkAndRequests @@ -2423,7 +2466,7 @@ public class ConnectivityService extends IConnectivityManager.Stub } case EVENT_REGISTER_NETWORK_REQUEST: case EVENT_REGISTER_NETWORK_LISTENER: { - handleRegisterNetworkRequest(msg); + handleRegisterNetworkRequest((NetworkRequestInfo) msg.obj); break; } case EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT: { @@ -2446,6 +2489,10 @@ public class ConnectivityService extends IConnectivityManager.Stub handlePromptUnvalidated((Network) msg.obj); break; } + case EVENT_CONFIGURE_MOBILE_DATA_ALWAYS_ON: { + handleMobileDataAlwaysOn(); + break; + } case EVENT_SYSTEM_READY: { for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) { nai.networkMonitor.systemReady = true; @@ -2837,23 +2884,36 @@ public class ConnectivityService extends IConnectivityManager.Stub } private static class SettingsObserver extends ContentObserver { - private int mWhat; - private Handler mHandler; - SettingsObserver(Handler handler, int what) { - super(handler); + final private HashMap<Uri, Integer> mUriEventMap; + final private Context mContext; + final private Handler mHandler; + + SettingsObserver(Context context, Handler handler) { + super(null); + mUriEventMap = new HashMap<Uri, Integer>(); + mContext = context; mHandler = handler; - mWhat = what; } - void observe(Context context) { - ContentResolver resolver = context.getContentResolver(); - resolver.registerContentObserver(Settings.Global.getUriFor( - Settings.Global.HTTP_PROXY), false, this); + void observe(Uri uri, int what) { + mUriEventMap.put(uri, what); + final ContentResolver resolver = mContext.getContentResolver(); + resolver.registerContentObserver(uri, false, this); } @Override public void onChange(boolean selfChange) { - mHandler.obtainMessage(mWhat).sendToTarget(); + Slog.wtf(TAG, "Should never be reached."); + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + final Integer what = mUriEventMap.get(uri); + if (what != null) { + mHandler.obtainMessage(what.intValue()).sendToTarget(); + } else { + loge("No matching event to send for URI=" + uri); + } } } @@ -3643,6 +3703,10 @@ public class ConnectivityService extends IConnectivityManager.Stub // Note: if mDefaultRequest is changed, NetworkMonitor needs to be updated. private final NetworkRequest mDefaultRequest; + // Request used to optionally keep mobile data active even when higher + // priority networks like Wi-Fi are active. + private final NetworkRequest mDefaultMobileDataRequest; + private NetworkAgentInfo getDefaultNetwork() { return mNetworkForRequestId.get(mDefaultRequest.requestId); } diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index 9511f54..e856a93 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -1695,6 +1695,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub vis = 0; } mImeWindowVis = vis; + mInputShown = ((mImeWindowVis & InputMethodService.IME_VISIBLE) != 0); mBackDisposition = backDisposition; final boolean iconVisibility = ((vis & (InputMethodService.IME_ACTIVE)) != 0) && (mWindowManagerService.isHardKeyboardAvailable() diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index 5df74c5..ed2de4a 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -356,28 +356,23 @@ public class LockSettingsService extends ILockSettings.Stub { return mStorage.hasPattern(userId); } - private void maybeUpdateKeystore(String password, int userHandle) { + private void setKeystorePassword(String password, int userHandle) { final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); final KeyStore ks = KeyStore.getInstance(); final List<UserInfo> profiles = um.getProfiles(userHandle); - boolean shouldReset = TextUtils.isEmpty(password); - - // For historical reasons, don't wipe a non-empty keystore if we have a single user with a - // single profile. - if (userHandle == UserHandle.USER_OWNER && profiles.size() == 1) { - if (!ks.isEmpty()) { - shouldReset = false; - } + for (UserInfo pi : profiles) { + ks.onUserPasswordChanged(pi.id, password); } + } + + private void unlockKeystore(String password, int userHandle) { + final UserManager um = (UserManager) mContext.getSystemService(USER_SERVICE); + final KeyStore ks = KeyStore.getInstance(); + final List<UserInfo> profiles = um.getProfiles(userHandle); for (UserInfo pi : profiles) { - final int profileUid = UserHandle.getUid(pi.id, Process.SYSTEM_UID); - if (shouldReset) { - ks.resetUid(profileUid); - } else { - ks.passwordUid(password, profileUid); - } + ks.unlock(pi.id, password); } } @@ -423,7 +418,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (pattern == null) { getGateKeeperService().clearSecureUserId(userId); mStorage.writePatternHash(null, userId); - maybeUpdateKeystore(null, userId); + setKeystorePassword(null, userId); return; } @@ -451,7 +446,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (password == null) { getGateKeeperService().clearSecureUserId(userId); mStorage.writePasswordHash(null, userId); - maybeUpdateKeystore(null, userId); + setKeystorePassword(null, userId); return; } @@ -484,7 +479,7 @@ public class LockSettingsService extends ILockSettings.Stub { toEnrollBytes); if (hash != null) { - maybeUpdateKeystore(toEnroll, userId); + setKeystorePassword(toEnroll, userId); } return hash; @@ -530,7 +525,7 @@ public class LockSettingsService extends ILockSettings.Stub { byte[] hash = mLockPatternUtils.patternToHash( mLockPatternUtils.stringToPattern(pattern)); if (Arrays.equals(hash, storedHash.hash)) { - maybeUpdateKeystore(pattern, userId); + unlockKeystore(pattern, userId); // migrate password to GateKeeper setLockPattern(pattern, null, userId); if (!hasChallenge) { @@ -556,7 +551,7 @@ public class LockSettingsService extends ILockSettings.Stub { } // pattern has matched - maybeUpdateKeystore(pattern, userId); + unlockKeystore(pattern, userId); return token; } @@ -599,7 +594,7 @@ public class LockSettingsService extends ILockSettings.Stub { if (storedHash.version == CredentialHash.VERSION_LEGACY) { byte[] hash = mLockPatternUtils.passwordToHash(password, userId); if (Arrays.equals(hash, storedHash.hash)) { - maybeUpdateKeystore(password, userId); + unlockKeystore(password, userId); // migrate password to GateKeeper setLockPassword(password, null, userId); if (!hasChallenge) { @@ -625,7 +620,7 @@ public class LockSettingsService extends ILockSettings.Stub { } // password has matched - maybeUpdateKeystore(password, userId); + unlockKeystore(password, userId); return token; } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index 0925fa5..93ac51a 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -242,6 +242,7 @@ class MountService extends IMountService.Stub private static final int VERSION_INIT = 1; private static final int VERSION_ADD_PRIMARY = 2; + private static final int VERSION_FIX_PRIMARY = 3; private static final String TAG_VOLUMES = "volumes"; private static final String ATTR_VERSION = "version"; @@ -1187,8 +1188,17 @@ class MountService extends IMountService.Stub mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget(); } + private String getDefaultPrimaryStorageUuid() { + if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, false)) { + return StorageManager.UUID_PRIMARY_PHYSICAL; + } else { + return StorageManager.UUID_PRIVATE_INTERNAL; + } + } + private void readSettingsLocked() { mRecords.clear(); + mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); FileInputStream fis = null; try { @@ -1202,16 +1212,13 @@ class MountService extends IMountService.Stub final String tag = in.getName(); if (TAG_VOLUMES.equals(tag)) { final int version = readIntAttribute(in, ATTR_VERSION, VERSION_INIT); - if (version >= VERSION_ADD_PRIMARY) { + final boolean primaryPhysical = SystemProperties.getBoolean( + StorageManager.PROP_PRIMARY_PHYSICAL, false); + final boolean validAttr = (version >= VERSION_FIX_PRIMARY) + || (version >= VERSION_ADD_PRIMARY && !primaryPhysical); + if (validAttr) { mPrimaryStorageUuid = readStringAttribute(in, ATTR_PRIMARY_STORAGE_UUID); - } else { - if (SystemProperties.getBoolean(StorageManager.PROP_PRIMARY_PHYSICAL, - false)) { - mPrimaryStorageUuid = StorageManager.UUID_PRIMARY_PHYSICAL; - } else { - mPrimaryStorageUuid = StorageManager.UUID_PRIVATE_INTERNAL; - } } } else if (TAG_VOLUME.equals(tag)) { @@ -1240,7 +1247,7 @@ class MountService extends IMountService.Stub out.setOutput(fos, "utf-8"); out.startDocument(null, true); out.startTag(null, TAG_VOLUMES); - writeIntAttribute(out, ATTR_VERSION, VERSION_ADD_PRIMARY); + writeIntAttribute(out, ATTR_VERSION, VERSION_FIX_PRIMARY); writeStringAttribute(out, ATTR_PRIMARY_STORAGE_UUID, mPrimaryStorageUuid); final int size = mRecords.size(); for (int i = 0; i < size; i++) { @@ -1482,7 +1489,7 @@ class MountService extends IMountService.Stub // If this had been primary storage, revert back to internal and // reset vold so we bind into new volume into place. if (Objects.equals(mPrimaryStorageUuid, fsUuid)) { - mPrimaryStorageUuid = StorageManager.UUID_PRIVATE_INTERNAL; + mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); resetIfReadyAndConnected(); } @@ -1497,11 +1504,13 @@ class MountService extends IMountService.Stub final String fsUuid = mRecords.keyAt(i); mCallbacks.notifyVolumeForgotten(fsUuid); } - mRecords.clear(); - writeSettingsLocked(); - mPrimaryStorageUuid = StorageManager.UUID_PRIVATE_INTERNAL; + if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)) { + mPrimaryStorageUuid = getDefaultPrimaryStorageUuid(); + } + + writeSettingsLocked(); resetIfReadyAndConnected(); } } @@ -1522,13 +1531,8 @@ class MountService extends IMountService.Stub waitForReady(); synchronized (mLock) { - final VolumeInfo from = Preconditions.checkNotNull( - findStorageForUuid(mPrimaryStorageUuid)); - final VolumeInfo to = Preconditions.checkNotNull( - findStorageForUuid(volumeUuid)); - - if (Objects.equals(from, to)) { - throw new IllegalArgumentException("Primary storage already at " + from); + if (Objects.equals(mPrimaryStorageUuid, volumeUuid)) { + throw new IllegalArgumentException("Primary storage already at " + volumeUuid); } if (mMoveCallback != null) { @@ -1537,10 +1541,26 @@ class MountService extends IMountService.Stub mMoveCallback = callback; mMoveTargetUuid = volumeUuid; - try { - mConnector.execute("volume", "move_storage", from.id, to.id); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + // When moving to/from primary physical volume, we probably just nuked + // the current storage location, so we have nothing to move. + if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid) + || Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, volumeUuid)) { + Slog.d(TAG, "Skipping move to/from primary physical"); + onMoveStatusLocked(MOVE_STATUS_COPY_FINISHED); + onMoveStatusLocked(PackageManager.MOVE_SUCCEEDED); + resetIfReadyAndConnected(); + + } else { + final VolumeInfo from = Preconditions.checkNotNull( + findStorageForUuid(mPrimaryStorageUuid)); + final VolumeInfo to = Preconditions.checkNotNull( + findStorageForUuid(volumeUuid)); + + try { + mConnector.execute("volume", "move_storage", from.id, to.id); + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } } } } diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 3dece49..fa4d204 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; import android.app.ActivityThread; import android.os.Build; @@ -119,14 +120,13 @@ public final class ActiveServices { // at the same time. final int mMaxStartingBackground; - final SparseArray<ServiceMap> mServiceMap = new SparseArray<ServiceMap>(); + final SparseArray<ServiceMap> mServiceMap = new SparseArray<>(); /** * All currently bound service connections. Keys are the IBinder of * the client's IServiceConnection. */ - final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections - = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>(); + final ArrayMap<IBinder, ArrayList<ConnectionRecord>> mServiceConnections = new ArrayMap<>(); /** * List of services that we have been asked to start, @@ -134,20 +134,20 @@ public final class ActiveServices { * while waiting for their corresponding application thread to get * going. */ - final ArrayList<ServiceRecord> mPendingServices - = new ArrayList<ServiceRecord>(); + final ArrayList<ServiceRecord> mPendingServices = new ArrayList<>(); /** * List of services that are scheduled to restart following a crash. */ - final ArrayList<ServiceRecord> mRestartingServices - = new ArrayList<ServiceRecord>(); + final ArrayList<ServiceRecord> mRestartingServices = new ArrayList<>(); /** * List of services that are in the process of being destroyed. */ - final ArrayList<ServiceRecord> mDestroyingServices - = new ArrayList<ServiceRecord>(); + final ArrayList<ServiceRecord> mDestroyingServices = new ArrayList<>(); + + /** Temporary list for holding the results of calls to {@link #collectPackageServicesLocked} */ + private ArrayList<ServiceRecord> mTmpCollectionResults = null; /** Amount of time to allow a last ANR message to exist before freeing the memory. */ static final int LAST_ANR_LIFETIME_DURATION_MSECS = 2 * 60 * 60 * 1000; // Two hours @@ -162,10 +162,6 @@ public final class ActiveServices { } }; - static final class DelayingProcess extends ArrayList<ServiceRecord> { - long timeoout; - } - /** * Information about services for a single user. */ @@ -2076,14 +2072,16 @@ public final class ActiveServices { } } - private boolean collectForceStopServicesLocked(String name, int userId, - boolean evenPersistent, boolean doit, - ArrayMap<ComponentName, ServiceRecord> services, - ArrayList<ServiceRecord> result) { + private boolean collectPackageServicesLocked(String packageName, Set<String> filterByClasses, + boolean evenPersistent, boolean doit, ArrayMap<ComponentName, ServiceRecord> services) { boolean didSomething = false; - for (int i=0; i<services.size(); i++) { + for (int i = services.size() - 1; i >= 0; i--) { ServiceRecord service = services.valueAt(i); - if ((name == null || service.packageName.equals(name)) + final boolean sameComponent = packageName == null + || (service.packageName.equals(packageName) + && (filterByClasses == null + || filterByClasses.contains(service.name.getClassName()))); + if (sameComponent && (service.app == null || evenPersistent || !service.app.persistent)) { if (!doit) { return true; @@ -2098,19 +2096,27 @@ public final class ActiveServices { } service.app = null; service.isolatedProc = null; - result.add(service); + if (mTmpCollectionResults == null) { + mTmpCollectionResults = new ArrayList<>(); + } + mTmpCollectionResults.add(service); } } return didSomething; } - boolean forceStopLocked(String name, int userId, boolean evenPersistent, boolean doit) { + boolean bringDownDisabledPackageServicesLocked(String packageName, Set<String> filterByClasses, + int userId, boolean evenPersistent, boolean doit) { boolean didSomething = false; - ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>(); + + if (mTmpCollectionResults != null) { + mTmpCollectionResults.clear(); + } + if (userId == UserHandle.USER_ALL) { - for (int i=0; i<mServiceMap.size(); i++) { - didSomething |= collectForceStopServicesLocked(name, userId, evenPersistent, - doit, mServiceMap.valueAt(i).mServicesByName, services); + for (int i = mServiceMap.size() - 1; i >= 0; i--) { + didSomething |= collectPackageServicesLocked(packageName, filterByClasses, + evenPersistent, doit, mServiceMap.valueAt(i).mServicesByName); if (!doit && didSomething) { return true; } @@ -2119,22 +2125,24 @@ public final class ActiveServices { ServiceMap smap = mServiceMap.get(userId); if (smap != null) { ArrayMap<ComponentName, ServiceRecord> items = smap.mServicesByName; - didSomething = collectForceStopServicesLocked(name, userId, evenPersistent, - doit, items, services); + didSomething = collectPackageServicesLocked(packageName, filterByClasses, + evenPersistent, doit, items); } } - int N = services.size(); - for (int i=0; i<N; i++) { - bringDownServiceLocked(services.get(i)); + if (mTmpCollectionResults != null) { + for (int i = mTmpCollectionResults.size() - 1; i >= 0; i--) { + bringDownServiceLocked(mTmpCollectionResults.get(i)); + } + mTmpCollectionResults.clear(); } return didSomething; } void cleanUpRemovedTaskLocked(TaskRecord tr, ComponentName component, Intent baseIntent) { - ArrayList<ServiceRecord> services = new ArrayList<ServiceRecord>(); + ArrayList<ServiceRecord> services = new ArrayList<>(); ArrayMap<ComponentName, ServiceRecord> alls = getServices(tr.userId); - for (int i=0; i<alls.size(); i++) { + for (int i = alls.size() - 1; i >= 0; i--) { ServiceRecord sr = alls.valueAt(i); if (sr.packageName.equals(component.getPackageName())) { services.add(sr); @@ -2142,7 +2150,7 @@ public final class ActiveServices { } // Take care of any running services associated with the app. - for (int i=0; i<services.size(); i++) { + for (int i = services.size() - 1; i >= 0; i--) { ServiceRecord sr = services.get(i); if (sr.startRequested) { if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 82dbfee..10855e2 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -375,6 +375,10 @@ public final class ActivityManagerService extends ActivityManagerNative // Delay in notifying task stack change listeners (in millis) static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 1000; + // Necessary ApplicationInfo flags to mark an app as persistent + private static final int PERSISTENT_MASK = + ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT; + /** All system services */ SystemServiceManager mSystemServiceManager; @@ -5363,39 +5367,117 @@ public final class ActivityManagerService extends ActivityManagerNative return N > 0; } - private final boolean forceStopPackageLocked(String name, int appId, + private void cleanupDisabledPackageComponentsLocked( + String packageName, int userId, String[] changedClasses) { + + Set<String> disabledClasses = null; + boolean packageDisabled = false; + IPackageManager pm = AppGlobals.getPackageManager(); + + if (changedClasses == null) { + // Nothing changed... + return; + } + + // Determine enable/disable state of the package and its components. + int enabled = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; + for (int i = changedClasses.length - 1; i >= 0; i--) { + final String changedClass = changedClasses[i]; + + if (changedClass.equals(packageName)) { + try { + // Entire package setting changed + enabled = pm.getApplicationEnabledSetting(packageName, + (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_OWNER); + } catch (RemoteException e) { + // Can't happen... + } + packageDisabled = enabled != PackageManager.COMPONENT_ENABLED_STATE_ENABLED + && enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT; + if (packageDisabled) { + // Entire package is disabled. + // No need to continue to check component states. + disabledClasses = null; + break; + } + } else { + try { + enabled = pm.getComponentEnabledSetting( + new ComponentName(packageName, changedClass), + (userId != UserHandle.USER_ALL) ? userId : UserHandle.USER_OWNER); + } catch (RemoteException e) { + // Can't happen... + } + if (enabled != PackageManager.COMPONENT_ENABLED_STATE_ENABLED + && enabled != PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) { + if (disabledClasses == null) { + disabledClasses = new ArraySet<>(changedClasses.length); + } + disabledClasses.add(changedClass); + } + } + } + + if (!packageDisabled && disabledClasses == null) { + // Nothing to do here... + return; + } + + // Clean-up disabled activities. + if (mStackSupervisor.finishDisabledPackageActivitiesLocked( + packageName, disabledClasses, true, false, userId) && mBooted) { + mStackSupervisor.resumeTopActivitiesLocked(); + mStackSupervisor.scheduleIdleLocked(); + } + + // Clean-up disabled tasks + cleanupDisabledPackageTasksLocked(packageName, disabledClasses, userId); + + // Clean-up disabled services. + mServices.bringDownDisabledPackageServicesLocked( + packageName, disabledClasses, userId, false, true); + + // Clean-up disabled providers. + ArrayList<ContentProviderRecord> providers = new ArrayList<>(); + mProviderMap.collectPackageProvidersLocked( + packageName, disabledClasses, true, false, userId, providers); + for (int i = providers.size() - 1; i >= 0; i--) { + removeDyingProviderLocked(null, providers.get(i), true); + } + } + + private final boolean forceStopPackageLocked(String packageName, int appId, boolean callerWillRestart, boolean purgeCache, boolean doit, boolean evenPersistent, boolean uninstalling, int userId, String reason) { int i; - int N; - if (userId == UserHandle.USER_ALL && name == null) { + if (userId == UserHandle.USER_ALL && packageName == null) { Slog.w(TAG, "Can't force stop all processes of all users, that is insane!"); } - if (appId < 0 && name != null) { + if (appId < 0 && packageName != null) { try { appId = UserHandle.getAppId( - AppGlobals.getPackageManager().getPackageUid(name, 0)); + AppGlobals.getPackageManager().getPackageUid(packageName, 0)); } catch (RemoteException e) { } } if (doit) { - if (name != null) { - Slog.i(TAG, "Force stopping " + name + " appid=" + appId + if (packageName != null) { + Slog.i(TAG, "Force stopping " + packageName + " appid=" + appId + " user=" + userId + ": " + reason); } else { Slog.i(TAG, "Force stopping u" + userId + ": " + reason); } final ArrayMap<String, SparseArray<Long>> pmap = mProcessCrashTimes.getMap(); - for (int ip=pmap.size()-1; ip>=0; ip--) { + for (int ip = pmap.size() - 1; ip >= 0; ip--) { SparseArray<Long> ba = pmap.valueAt(ip); - for (i=ba.size()-1; i>=0; i--) { + for (i = ba.size() - 1; i >= 0; i--) { boolean remove = false; final int entUid = ba.keyAt(i); - if (name != null) { + if (packageName != null) { if (userId == UserHandle.USER_ALL) { if (UserHandle.getAppId(entUid) == appId) { remove = true; @@ -5418,46 +5500,47 @@ public final class ActivityManagerService extends ActivityManagerNative } } - boolean didSomething = killPackageProcessesLocked(name, appId, userId, + boolean didSomething = killPackageProcessesLocked(packageName, appId, userId, -100, callerWillRestart, true, doit, evenPersistent, - name == null ? ("stop user " + userId) : ("stop " + name)); + packageName == null ? ("stop user " + userId) : ("stop " + packageName)); - if (mStackSupervisor.forceStopPackageLocked(name, doit, evenPersistent, userId)) { + if (mStackSupervisor.finishDisabledPackageActivitiesLocked( + packageName, null, doit, evenPersistent, userId)) { if (!doit) { return true; } didSomething = true; } - if (mServices.forceStopLocked(name, userId, evenPersistent, doit)) { + if (mServices.bringDownDisabledPackageServicesLocked( + packageName, null, userId, evenPersistent, doit)) { if (!doit) { return true; } didSomething = true; } - if (name == null) { + if (packageName == null) { // Remove all sticky broadcasts from this user. mStickyBroadcasts.remove(userId); } - ArrayList<ContentProviderRecord> providers = new ArrayList<ContentProviderRecord>(); - if (mProviderMap.collectForceStopProviders(name, appId, doit, evenPersistent, + ArrayList<ContentProviderRecord> providers = new ArrayList<>(); + if (mProviderMap.collectPackageProvidersLocked(packageName, null, doit, evenPersistent, userId, providers)) { if (!doit) { return true; } didSomething = true; } - N = providers.size(); - for (i=0; i<N; i++) { + for (i = providers.size() - 1; i >= 0; i--) { removeDyingProviderLocked(null, providers.get(i), true); } // Remove transient permissions granted from/to this package/user - removeUriPermissionsForPackageLocked(name, userId, false); + removeUriPermissionsForPackageLocked(packageName, userId, false); - if (name == null || uninstalling) { + if (packageName == null || uninstalling) { // Remove pending intents. For now we only do this when force // stopping users, because we have some problems when doing this // for packages -- app widgets are not currently cleaned up for @@ -5476,7 +5559,7 @@ public final class ActivityManagerService extends ActivityManagerNative it.remove(); continue; } - if (name == null) { + if (packageName == null) { // Stopping user, remove all objects for the user. if (pir.key.userId != userId) { // Not the same user, skip it. @@ -5491,7 +5574,7 @@ public final class ActivityManagerService extends ActivityManagerNative // Different user, skip it. continue; } - if (!pir.key.packageName.equals(name)) { + if (!pir.key.packageName.equals(packageName)) { // Different package, skip it. continue; } @@ -5510,10 +5593,10 @@ public final class ActivityManagerService extends ActivityManagerNative } if (doit) { - if (purgeCache && name != null) { + if (purgeCache && packageName != null) { AttributeCache ac = AttributeCache.instance(); if (ac != null) { - ac.removePackage(name); + ac.removePackage(packageName); } } if (mBooted) { @@ -8331,29 +8414,20 @@ public final class ActivityManagerService extends ActivityManagerNative } } - private void removeTasksByRemovedPackageComponentsLocked(String packageName, int userId) { - final IPackageManager pm = AppGlobals.getPackageManager(); - final HashSet<ComponentName> componentsKnownToExist = new HashSet<ComponentName>(); + private void cleanupDisabledPackageTasksLocked(String packageName, Set<String> filterByClasses, + int userId) { for (int i = mRecentTasks.size() - 1; i >= 0; i--) { TaskRecord tr = mRecentTasks.get(i); - if (tr.userId != userId) continue; + if (userId != UserHandle.USER_ALL && tr.userId != userId) { + continue; + } ComponentName cn = tr.intent.getComponent(); - if (cn != null && cn.getPackageName().equals(packageName)) { - // Skip if component still exists in the package. - if (componentsKnownToExist.contains(cn)) continue; - - try { - ActivityInfo info = pm.getActivityInfo(cn, 0, userId); - if (info != null) { - componentsKnownToExist.add(cn); - } else { - removeTaskByIdLocked(tr.taskId, false); - } - } catch (RemoteException e) { - Log.e(TAG, "Activity info query failed. component=" + cn, e); - } + final boolean sameComponent = cn != null && cn.getPackageName().equals(packageName) + && (filterByClasses == null || filterByClasses.contains(cn.getClassName())); + if (sameComponent) { + removeTaskByIdLocked(tr.taskId, false); } } } @@ -9773,10 +9847,10 @@ public final class ActivityManagerService extends ActivityManagerNative String proc = customProcess != null ? customProcess : info.processName; BatteryStatsImpl.Uid.Proc ps = null; BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); + final int userId = UserHandle.getUserId(info.uid); int uid = info.uid; if (isolated) { if (isolatedUid == 0) { - int userId = UserHandle.getUserId(uid); int stepsLeft = Process.LAST_ISOLATED_UID - Process.FIRST_ISOLATED_UID + 1; while (true) { if (mNextIsolatedProcessUid < Process.FIRST_ISOLATED_UID @@ -9800,7 +9874,13 @@ public final class ActivityManagerService extends ActivityManagerNative uid = isolatedUid; } } - return new ProcessRecord(stats, info, proc, uid); + final ProcessRecord r = new ProcessRecord(stats, info, proc, uid); + if (!mBooted && !mBooting + && userId == UserHandle.USER_OWNER + && (info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { + r.persistent = true; + } + return r; } final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated, @@ -9832,8 +9912,7 @@ public final class ActivityManagerService extends ActivityManagerNative + info.packageName + ": " + e); } - if ((info.flags&(ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) - == (ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PERSISTENT)) { + if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { app.persistent = true; app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ; } @@ -14121,6 +14200,7 @@ public final class ActivityManagerService extends ActivityManagerNative boolean dumpDetails = false; boolean dumpFullDetails = false; boolean dumpDalvik = false; + boolean dumpSummaryOnly = false; boolean oomOnly = false; boolean isCompact = false; boolean localOnly = false; @@ -14141,6 +14221,9 @@ public final class ActivityManagerService extends ActivityManagerNative dumpDalvik = true; } else if ("-c".equals(opt)) { isCompact = true; + } else if ("-s".equals(opt)) { + dumpDetails = true; + dumpSummaryOnly = true; } else if ("--oom".equals(opt)) { oomOnly = true; } else if ("--local".equals(opt)) { @@ -14148,10 +14231,11 @@ public final class ActivityManagerService extends ActivityManagerNative } else if ("--package".equals(opt)) { packages = true; } else if ("-h".equals(opt)) { - pw.println("meminfo dump options: [-a] [-d] [-c] [--oom] [process]"); + pw.println("meminfo dump options: [-a] [-d] [-c] [-s] [--oom] [process]"); pw.println(" -a: include all available information for each process."); pw.println(" -d: include dalvik details."); pw.println(" -c: dump in a compact machine-parseable representation."); + pw.println(" -s: dump only summary of application memory usage."); pw.println(" --oom: only show processes organized by oom adj."); pw.println(" --local: only collect details locally, don't call process."); pw.println(" --package: interpret process arg as package, dumping all"); @@ -14212,7 +14296,7 @@ public final class ActivityManagerService extends ActivityManagerNative mi.dalvikPrivateDirty = (int)tmpLong[0]; } ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails, - dumpDalvik, pid, r.baseName, 0, 0, 0, 0, 0, 0); + dumpDalvik, dumpSummaryOnly, pid, r.baseName, 0, 0, 0, 0, 0, 0); if (isCheckinRequest) { pw.println(); } @@ -14278,7 +14362,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (dumpDetails) { if (localOnly) { ActivityThread.dumpMemInfoTable(pw, mi, isCheckinRequest, dumpFullDetails, - dumpDalvik, pid, r.processName, 0, 0, 0, 0, 0, 0); + dumpDalvik, dumpSummaryOnly, pid, r.processName, 0, 0, 0, 0, 0, 0); if (isCheckinRequest) { pw.println(); } @@ -14286,7 +14370,7 @@ public final class ActivityManagerService extends ActivityManagerNative try { pw.flush(); thread.dumpMemInfo(fd, mi, isCheckinRequest, dumpFullDetails, - dumpDalvik, innerArgs); + dumpDalvik, dumpSummaryOnly, innerArgs); } catch (RemoteException e) { if (!isCheckinRequest) { pw.println("Got RemoteException!"); @@ -16071,7 +16155,9 @@ public final class ActivityManagerService extends ActivityManagerNative mBatteryStatsService.notePackageUninstalled(ssp); } } else { - removeTasksByRemovedPackageComponentsLocked(ssp, userId); + cleanupDisabledPackageComponentsLocked(ssp, userId, + intent.getStringArrayExtra( + Intent.EXTRA_CHANGED_COMPONENT_NAME_LIST)); if (userId == UserHandle.USER_OWNER) { mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp); } @@ -16089,9 +16175,6 @@ public final class ActivityManagerService extends ActivityManagerNative intent.getBooleanExtra(Intent.EXTRA_REPLACING, false); mCompatModePackages.handlePackageAddedLocked(ssp, replacing); - if (replacing) { - removeTasksByRemovedPackageComponentsLocked(ssp, userId); - } if (userId == UserHandle.USER_OWNER) { mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp); } @@ -19868,6 +19951,14 @@ public final class ActivityManagerService extends ActivityManagerNative return token; } } + + @Override + public ComponentName getHomeActivityForUser(int userId) { + synchronized (ActivityManagerService.this) { + ActivityRecord homeActivity = mStackSupervisor.getHomeActivityForUser(userId); + return homeActivity.realActivity; + } + } } private final class SleepTokenImpl extends SleepToken { diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index 62d70d2..a86df2d 100644 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -81,6 +81,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Objects; +import java.util.Set; /** * State and management of a single stack of activities. @@ -4000,7 +4001,8 @@ final class ActivityStack { } } - boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) { + boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, + boolean doit, boolean evenPersistent, int userId) { boolean didSomething = false; TaskRecord lastTask = null; ComponentName homeActivity = null; @@ -4009,10 +4011,12 @@ final class ActivityStack { int numActivities = activities.size(); for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) { ActivityRecord r = activities.get(activityNdx); - final boolean samePackage = r.packageName.equals(name) - || (name == null && r.userId == userId); + final boolean sameComponent = + (r.packageName.equals(packageName) && (filterByClasses == null + || filterByClasses.contains(r.realActivity.getClassName()))) + || (packageName == null && r.userId == userId); if ((userId == UserHandle.USER_ALL || r.userId == userId) - && (samePackage || r.task == lastTask) + && (sameComponent || r.task == lastTask) && (r.app == null || evenPersistent || !r.app.persistent)) { if (!doit) { if (r.finishing) { @@ -4032,7 +4036,7 @@ final class ActivityStack { } didSomething = true; Slog.i(TAG, " Force finishing activity " + r); - if (samePackage) { + if (sameComponent) { if (r.app != null) { r.app.removed = true; } diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java index 8c98f9f..cb5ba8e 100644 --- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java +++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java @@ -118,6 +118,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import java.util.Set; public final class ActivityStackSupervisor implements DisplayListener { private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStackSupervisor" : TAG_AM; @@ -2507,14 +2508,16 @@ public final class ActivityStackSupervisor implements DisplayListener { /** * @return true if some activity was finished (or would have finished if doit were true). */ - boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) { + boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, + boolean doit, boolean evenPersistent, int userId) { boolean didSomething = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; final int numStacks = stacks.size(); for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { final ActivityStack stack = stacks.get(stackNdx); - if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) { + if (stack.finishDisabledPackageActivitiesLocked( + packageName, filterByClasses, doit, evenPersistent, userId)) { didSomething = true; } } @@ -2653,6 +2656,10 @@ public final class ActivityStackSupervisor implements DisplayListener { } ActivityRecord getHomeActivity() { + return getHomeActivityForUser(UserHandle.USER_ALL); + } + + ActivityRecord getHomeActivityForUser(int userId) { final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks(); for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) { final TaskRecord task = tasks.get(taskNdx); @@ -2660,7 +2667,8 @@ public final class ActivityStackSupervisor implements DisplayListener { final ArrayList<ActivityRecord> activities = task.mActivities; for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { final ActivityRecord r = activities.get(activityNdx); - if (r.isHomeActivity()) { + if (r.isHomeActivity() + && ((userId == UserHandle.USER_ALL) || (r.userId == userId))) { return r; } } diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java index e5c5dff..e89ef57 100644 --- a/services/core/java/com/android/server/am/BroadcastQueue.java +++ b/services/core/java/com/android/server/am/BroadcastQueue.java @@ -85,7 +85,7 @@ public final class BroadcastQueue { * a bunch of processes to execute IntentReceiver components. Background- * and foreground-priority broadcasts are queued separately. */ - final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<BroadcastRecord>(); + final ArrayList<BroadcastRecord> mParallelBroadcasts = new ArrayList<>(); /** * List of all active broadcasts that are to be executed one at a time. @@ -94,7 +94,7 @@ public final class BroadcastQueue { * broadcasts, separate background- and foreground-priority queues are * maintained. */ - final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<BroadcastRecord>(); + final ArrayList<BroadcastRecord> mOrderedBroadcasts = new ArrayList<>(); /** * Historical data of past broadcasts, for debugging. This is a ring buffer diff --git a/services/core/java/com/android/server/am/ProviderMap.java b/services/core/java/com/android/server/am/ProviderMap.java index 7da8c48..a1dc3e3 100644 --- a/services/core/java/com/android/server/am/ProviderMap.java +++ b/services/core/java/com/android/server/am/ProviderMap.java @@ -31,6 +31,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.Map; +import java.util.Set; /** * Keeps track of content providers by authority (name) and class. It separates the mapping by @@ -184,13 +185,17 @@ public final class ProviderMap { } } - private boolean collectForceStopProvidersLocked(String name, int appId, - boolean doit, boolean evenPersistent, int userId, + private boolean collectPackageProvidersLocked(String packageName, + Set<String> filterByClasses, boolean doit, boolean evenPersistent, HashMap<ComponentName, ContentProviderRecord> providers, ArrayList<ContentProviderRecord> result) { boolean didSomething = false; for (ContentProviderRecord provider : providers.values()) { - if ((name == null || provider.info.packageName.equals(name)) + final boolean sameComponent = packageName == null + || (provider.info.packageName.equals(packageName) + && (filterByClasses == null + || filterByClasses.contains(provider.name.getClassName()))); + if (sameComponent && (provider.proc == null || evenPersistent || !provider.proc.persistent)) { if (!doit) { return true; @@ -202,18 +207,18 @@ public final class ProviderMap { return didSomething; } - boolean collectForceStopProviders(String name, int appId, + boolean collectPackageProvidersLocked(String packageName, Set<String> filterByClasses, boolean doit, boolean evenPersistent, int userId, ArrayList<ContentProviderRecord> result) { - boolean didSomething = collectForceStopProvidersLocked(name, appId, doit, - evenPersistent, userId, mSingletonByClass, result); + boolean didSomething = collectPackageProvidersLocked(packageName, filterByClasses, + doit, evenPersistent, mSingletonByClass, result); if (!doit && didSomething) { return true; } if (userId == UserHandle.USER_ALL) { - for (int i=0; i<mProvidersByClassPerUser.size(); i++) { - if (collectForceStopProvidersLocked(name, appId, doit, evenPersistent, - userId, mProvidersByClassPerUser.valueAt(i), result)) { + for (int i = 0; i < mProvidersByClassPerUser.size(); i++) { + if (collectPackageProvidersLocked(packageName, filterByClasses, + doit, evenPersistent, mProvidersByClassPerUser.valueAt(i), result)) { if (!doit) { return true; } @@ -224,8 +229,8 @@ public final class ProviderMap { HashMap<ComponentName, ContentProviderRecord> items = getProvidersByClass(userId); if (items != null) { - didSomething |= collectForceStopProvidersLocked(name, appId, doit, - evenPersistent, userId, items, result); + didSomething |= collectPackageProvidersLocked(packageName, filterByClasses, + doit, evenPersistent, items, result); } } return didSomething; diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 06fba34..aa365ea 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -21,8 +21,11 @@ import static android.media.AudioManager.RINGER_MODE_NORMAL; import static android.media.AudioManager.RINGER_MODE_SILENT; import static android.media.AudioManager.RINGER_MODE_VIBRATE; +import android.Manifest; import android.app.ActivityManager; +import android.app.ActivityManagerInternal; import android.app.ActivityManagerNative; +import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.KeyguardManager; import android.bluetooth.BluetoothA2dp; @@ -37,7 +40,10 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.content.pm.UserInfo; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.XmlResourceParser; @@ -82,11 +88,13 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; +import android.os.UserManager; import android.os.Vibrator; import android.provider.Settings; import android.provider.Settings.System; import android.telecom.TelecomManager; import android.text.TextUtils; +import android.util.AndroidRuntimeException; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; @@ -102,6 +110,7 @@ import android.view.accessibility.AccessibilityManager; import com.android.internal.util.XmlUtils; import com.android.server.EventLogTags; import com.android.server.LocalServices; +import com.android.server.pm.UserManagerService; import org.xmlpull.v1.XmlPullParserException; @@ -645,6 +654,8 @@ public class AudioService extends IAudioService.Stub { intentFilter.addAction(Intent.ACTION_SCREEN_ON); intentFilter.addAction(Intent.ACTION_SCREEN_OFF); intentFilter.addAction(Intent.ACTION_USER_SWITCHED); + intentFilter.addAction(Intent.ACTION_USER_BACKGROUND); + intentFilter.addAction(Intent.ACTION_USER_FOREGROUND); intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED); @@ -668,7 +679,7 @@ public class AudioService extends IAudioService.Stub { setRotationForAudioSystem(); } - context.registerReceiver(mReceiver, intentFilter); + context.registerReceiverAsUser(mReceiver, UserHandle.ALL, intentFilter, null, null); LocalServices.addService(AudioManagerInternal.class, new AudioServiceInternal()); } @@ -4975,10 +4986,58 @@ public class AudioService extends IAudioService.Stub { 0, 0, mStreamStates[AudioSystem.STREAM_MUSIC], 0); + } else if (action.equals(Intent.ACTION_USER_BACKGROUND)) { + // Disable audio recording for the background user/profile + int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + if (userId >= 0) { + // TODO Kill recording streams instead of killing processes holding permission + UserInfo userInfo = UserManagerService.getInstance().getUserInfo(userId); + killBackgroundUserProcessesWithRecordAudioPermission(userInfo); + } + UserManagerService.getInstance().setSystemControlledUserRestriction( + UserManager.DISALLOW_RECORD_AUDIO, true, userId); + } else if (action.equals(Intent.ACTION_USER_FOREGROUND)) { + // Enable audio recording for foreground user/profile + int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); + UserManagerService.getInstance().setSystemControlledUserRestriction( + UserManager.DISALLOW_RECORD_AUDIO, false, userId); } } } // end class AudioServiceBroadcastReceiver + private void killBackgroundUserProcessesWithRecordAudioPermission(UserInfo oldUser) { + PackageManager pm = mContext.getPackageManager(); + // Find the home activity of the user. It should not be killed to avoid expensive restart, + // when the user switches back. For managed profiles, we should kill all recording apps + ComponentName homeActivityName = null; + if (!oldUser.isManagedProfile()) { + homeActivityName = LocalServices.getService(ActivityManagerInternal.class) + .getHomeActivityForUser(oldUser.id); + } + final String[] permissions = { Manifest.permission.RECORD_AUDIO }; + List<PackageInfo> packages; + try { + packages = AppGlobals.getPackageManager() + .getPackagesHoldingPermissions(permissions, 0, oldUser.id).getList(); + } catch (RemoteException e) { + throw new AndroidRuntimeException(e); + } + for (int j = packages.size() - 1; j >= 0; j--) { + PackageInfo pkg = packages.get(j); + if (homeActivityName != null + && pkg.packageName.equals(homeActivityName.getPackageName()) + && pkg.applicationInfo.isSystemApp()) { + continue; + } + try { + ActivityManagerNative.getDefault().killUid(pkg.applicationInfo.uid, + "killBackgroundUserProcessesWithAudioRecordPermission"); + } catch (RemoteException e) { + Log.w(TAG, "Error calling killUid", e); + } + } + } + //========================================================================================== // RemoteControlDisplay / RemoteControlClient / Remote info //========================================================================================== diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index 6f59b54..7f961ae 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -82,7 +82,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { appToken.linkToDeath(device, 0); } catch (RemoteException ex) { mVirtualDisplayDevices.remove(appToken); - device.destroyLocked(); + device.destroyLocked(false); return null; } @@ -110,7 +110,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) { VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken); if (device != null) { - device.destroyLocked(); + device.destroyLocked(true); appToken.unlinkToDeath(device, 0); } @@ -147,7 +147,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { if (device != null) { Slog.i(TAG, "Virtual display device released because application token died: " + device.mOwnerPackageName); - device.destroyLocked(); + device.destroyLocked(false); sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_REMOVED); } } @@ -205,19 +205,19 @@ final class VirtualDisplayAdapter extends DisplayAdapter { @Override public void binderDied() { synchronized (getSyncRoot()) { - if (mSurface != null) { - handleBinderDiedLocked(mAppToken); - } + handleBinderDiedLocked(mAppToken); } } - public void destroyLocked() { + public void destroyLocked(boolean binderAlive) { if (mSurface != null) { mSurface.release(); mSurface = null; } SurfaceControl.destroyDisplay(getDisplayTokenLocked()); - mCallback.dispatchDisplayStopped(); + if (binderAlive) { + mCallback.dispatchDisplayStopped(); + } } @Override diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java index e650456..51ba32d 100644 --- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java +++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java @@ -906,14 +906,22 @@ final class HdmiCecLocalDeviceTv extends HdmiCecLocalDevice { @ServiceThreadOnly private void updateArcFeatureStatus(int portId, boolean isConnected) { assertRunOnServiceThread(); + HdmiPortInfo portInfo = mService.getPortInfo(portId); + if (!portInfo.isArcSupported()) { + return; + } HdmiDeviceInfo avr = getAvrDeviceInfo(); if (avr == null) { + if (isConnected) { + // Update the status (since TV may not have seen AVR yet) so + // that ARC can be initiated after discovery. + mArcFeatureEnabled.put(portId, isConnected); + } return; } // HEAC 2.4, HEACT 5-15 // Should not activate ARC if +5V status is false. - HdmiPortInfo portInfo = mService.getPortInfo(portId); - if (avr.getPortId() == portId && portInfo.isArcSupported()) { + if (avr.getPortId() == portId) { changeArcFeatureEnabled(portId, isConnected); } } diff --git a/services/core/java/com/android/server/notification/CalendarTracker.java b/services/core/java/com/android/server/notification/CalendarTracker.java index 28da73c..71d7f19 100644 --- a/services/core/java/com/android/server/notification/CalendarTracker.java +++ b/services/core/java/com/android/server/notification/CalendarTracker.java @@ -16,6 +16,8 @@ package com.android.server.notification; +import static android.service.notification.ZenModeConfig.EventInfo.ANY_CALENDAR; + import android.content.ContentResolver; import android.content.ContentUris; import android.content.Context; @@ -150,7 +152,7 @@ public class CalendarTracker { eventId, owner, calendarId)); final boolean meetsTime = time >= begin && time < end; final boolean meetsCalendar = visible - && (filter.calendar == 0 || filter.calendar == calendarId) + && (filter.calendar == ANY_CALENDAR || filter.calendar == calendarId) && availability != Instances.AVAILABILITY_FREE; if (meetsCalendar) { if (DEBUG) Log.d(TAG, " MEETS CALENDAR"); diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index b92c734..6f8e3ca 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -189,6 +189,10 @@ abstract public class ManagedServices { } } + public boolean isComponentEnabledForPackage(String pkg) { + return mEnabledServicesPackageNames.contains(pkg); + } + public void onPackagesChanged(boolean queryReplace, String[] pkgList) { if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList)) diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 25998da..791c1de 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -37,7 +37,6 @@ import android.app.NotificationManager.Policy; import android.app.PendingIntent; import android.app.StatusBarManager; import android.app.usage.UsageEvents; -import android.app.usage.UsageStats; import android.app.usage.UsageStatsManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; @@ -233,7 +232,7 @@ public class NotificationManagerService extends SystemService { new ArrayMap<String, NotificationRecord>(); final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>(); final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>(); - private final ArrayMap<String, Policy.Token> mPolicyTokens = new ArrayMap<>(); + private final ArrayMap<String, Boolean> mPolicyAccess = new ArrayMap<>(); // The last key in this list owns the hardware. @@ -899,6 +898,7 @@ public class NotificationManagerService extends SystemService { @Override void onZenModeChanged() { + sendRegisteredOnlyBroadcast(NotificationManager.ACTION_INTERRUPTION_FILTER_CHANGED); synchronized(mNotificationList) { updateInterruptionFilterLocked(); } @@ -906,9 +906,12 @@ public class NotificationManagerService extends SystemService { @Override void onPolicyChanged() { - getContext().sendBroadcast( - new Intent(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED) - .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)); + sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED); + } + + private void sendRegisteredOnlyBroadcast(String action) { + getContext().sendBroadcast(new Intent(action) + .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY)); } }); final File systemDir = new File(Environment.getDataDirectory(), "system"); @@ -1607,6 +1610,19 @@ public class NotificationManagerService extends SystemService { } @Override + public void setInterruptionFilter(String pkg, int filter) throws RemoteException { + enforcePolicyAccess(pkg, "setInterruptionFilter"); + final int zen = NotificationManager.zenModeFromInterruptionFilter(filter, -1); + if (zen == -1) throw new IllegalArgumentException("Invalid filter: " + filter); + final long identity = Binder.clearCallingIdentity(); + try { + mZenModeHelper.setManualZenMode(zen, null, "setInterruptionFilter"); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + + @Override public void notifyConditions(String pkg, IConditionProvider provider, Condition[] conditions) { final ManagedServiceInfo info = mConditionProviders.checkServiceToken(provider); @@ -1641,16 +1657,19 @@ public class NotificationManagerService extends SystemService { message); } - private void enforcePolicyToken(Policy.Token token, String method) { - if (!checkPolicyToken(token)) { - Slog.w(TAG, "Invalid notification policy token calling " + method); - throw new SecurityException("Invalid notification policy token"); + private void enforcePolicyAccess(String pkg, String method) { + if (!checkPolicyAccess(pkg)) { + Slog.w(TAG, "Notification policy access denied calling " + method); + throw new SecurityException("Notification policy access denied"); } } - private boolean checkPolicyToken(Policy.Token token) { - return mPolicyTokens.containsValue(token) - || mListeners.mPolicyTokens.containsValue(token); + private boolean checkPackagePolicyAccess(String pkg) { + return Boolean.TRUE.equals(mPolicyAccess.get(pkg)); + } + + private boolean checkPolicyAccess(String pkg) { + return checkPackagePolicyAccess(pkg) || mListeners.isComponentEnabledForPackage(pkg); } @Override @@ -1702,52 +1721,76 @@ public class NotificationManagerService extends SystemService { } @Override - public Policy.Token getPolicyTokenFromListener(INotificationListener listener) { + public void requestNotificationPolicyAccess(String pkg, + INotificationManagerCallback callback) throws RemoteException { + if (callback == null) { + Slog.w(TAG, "requestNotificationPolicyAccess: no callback specified"); + return; + } + if (pkg == null) { + Slog.w(TAG, "requestNotificationPolicyAccess denied: no package specified"); + callback.onPolicyRequestResult(false); + return; + } final long identity = Binder.clearCallingIdentity(); try { - return mListeners.getPolicyToken(listener); + synchronized (mNotificationList) { + // immediately grant for now + mPolicyAccess.put(pkg, true); + if (DBG) Slog.w(TAG, "requestNotificationPolicyAccess granted for " + pkg); + } } finally { Binder.restoreCallingIdentity(identity); } + callback.onPolicyRequestResult(true); } @Override - public void requestNotificationPolicyToken(String pkg, - INotificationManagerCallback callback) throws RemoteException { - if (callback == null) { - Slog.w(TAG, "requestNotificationPolicyToken: no callback specified"); - return; - } - if (pkg == null) { - Slog.w(TAG, "requestNotificationPolicyToken denied: no package specified"); - callback.onPolicyToken(null); - return; - } - Policy.Token token = null; + public boolean isNotificationPolicyAccessGranted(String pkg) { + return checkPolicyAccess(pkg); + } + + @Override + public boolean isNotificationPolicyAccessGrantedForPackage(String pkg) { + enforceSystemOrSystemUI("request policy access status for another package"); + return checkPackagePolicyAccess(pkg); + } + + @Override + public String[] getPackagesRequestingNotificationPolicyAccess() + throws RemoteException { + enforceSystemOrSystemUI("request policy access packages"); final long identity = Binder.clearCallingIdentity(); try { synchronized (mNotificationList) { - token = mPolicyTokens.get(pkg); - if (token == null) { - token = new Policy.Token(new Binder()); - mPolicyTokens.put(pkg, token); + final String[] rt = new String[mPolicyAccess.size()]; + for (int i = 0; i < mPolicyAccess.size(); i++) { + rt[i] = mPolicyAccess.keyAt(i); } - if (DBG) Slog.w(TAG, "requestNotificationPolicyToken granted for " + pkg); + return rt; } } finally { Binder.restoreCallingIdentity(identity); } - callback.onPolicyToken(token); } @Override - public boolean isNotificationPolicyTokenValid(String pkg, Policy.Token token) { - return checkPolicyToken(token); + public void setNotificationPolicyAccessGranted(String pkg, boolean granted) + throws RemoteException { + enforceSystemOrSystemUI("grant notification policy access"); + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mNotificationList) { + mPolicyAccess.put(pkg, granted); + } + } finally { + Binder.restoreCallingIdentity(identity); + } } @Override - public Policy getNotificationPolicy(Policy.Token token) { - enforcePolicyToken(token, "getNotificationPolicy"); + public Policy getNotificationPolicy(String pkg) { + enforcePolicyAccess(pkg, "getNotificationPolicy"); final long identity = Binder.clearCallingIdentity(); try { return mZenModeHelper.getNotificationPolicy(); @@ -1757,8 +1800,8 @@ public class NotificationManagerService extends SystemService { } @Override - public void setNotificationPolicy(Policy.Token token, Policy policy) { - enforcePolicyToken(token, "setNotificationPolicy"); + public void setNotificationPolicy(String pkg, Policy policy) { + enforcePolicyAccess(pkg, "setNotificationPolicy"); final long identity = Binder.clearCallingIdentity(); try { mZenModeHelper.setNotificationPolicy(policy); @@ -1881,11 +1924,9 @@ public class NotificationManagerService extends SystemService { pw.print(listener.component); } pw.println(')'); - pw.print(" mPolicyTokens.keys: "); - pw.println(TextUtils.join(",", mPolicyTokens.keySet())); - pw.print(" mListeners.mPolicyTokens.keys: "); - pw.println(TextUtils.join(",", mListeners.mPolicyTokens.keySet())); } + pw.println("\n Policy access:"); + pw.print(" mPolicyAccess: "); pw.println(mPolicyAccess); pw.println("\n Condition providers:"); mConditionProviders.dump(pw, filter); @@ -3138,18 +3179,12 @@ public class NotificationManagerService extends SystemService { public class NotificationListeners extends ManagedServices { private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>(); - private final ArrayMap<ComponentName, Policy.Token> mPolicyTokens = new ArrayMap<>(); private boolean mNotificationGroupsDesired; public NotificationListeners() { super(getContext(), mHandler, mNotificationList, mUserProfiles); } - public Policy.Token getPolicyToken(INotificationListener listener) { - final ManagedServiceInfo info = checkServiceTokenLocked(listener); - return info == null ? null : mPolicyTokens.get(info.component); - } - @Override protected Config getConfig() { Config c = new Config(); @@ -3174,7 +3209,6 @@ public class NotificationManagerService extends SystemService { synchronized (mNotificationList) { updateNotificationGroupsDesiredLocked(); update = makeRankingUpdateLocked(info); - mPolicyTokens.put(info.component, new Policy.Token(new Binder())); } try { listener.onListenerConnected(update); @@ -3191,7 +3225,6 @@ public class NotificationManagerService extends SystemService { } mLightTrimListeners.remove(removed); updateNotificationGroupsDesiredLocked(); - mPolicyTokens.remove(removed.component); } public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) { diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index e97def8..aeb6b78 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -22,6 +22,7 @@ import static android.media.AudioAttributes.USAGE_NOTIFICATION; import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE; import android.app.AppOpsManager; +import android.app.NotificationManager; import android.app.NotificationManager.Policy; import android.content.ComponentName; import android.content.ContentResolver; @@ -42,6 +43,7 @@ import android.provider.Settings.Global; import android.service.notification.IConditionListener; import android.service.notification.NotificationListenerService; import android.service.notification.ZenModeConfig; +import android.service.notification.ZenModeConfig.EventInfo; import android.service.notification.ZenModeConfig.ScheduleInfo; import android.service.notification.ZenModeConfig.ZenRule; import android.util.ArraySet; @@ -90,6 +92,7 @@ public class ZenModeHelper { mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); mDefaultConfig = readDefaultConfig(context.getResources()); appendDefaultScheduleRules(mDefaultConfig); + appendDefaultEventRules(mDefaultConfig); mConfig = mDefaultConfig; mSettingsObserver = new SettingsObserver(mHandler); mSettingsObserver.observe(); @@ -142,11 +145,11 @@ public class ZenModeHelper { } public int getZenModeListenerInterruptionFilter() { - return getZenModeListenerInterruptionFilter(mZenMode); + return NotificationManager.zenModeToInterruptionFilter(mZenMode); } - public void requestFromListener(ComponentName name, int interruptionFilter) { - final int newZen = zenModeFromListenerInterruptionFilter(interruptionFilter, -1); + public void requestFromListener(ComponentName name, int filter) { + final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1); if (newZen != -1) { setManualZenMode(newZen, null, "listener:" + (name != null ? name.flattenToShortString() : null)); @@ -393,37 +396,6 @@ public class ZenModeHelper { } } - private static int getZenModeListenerInterruptionFilter(int zen) { - switch (zen) { - case Global.ZEN_MODE_OFF: - return NotificationListenerService.INTERRUPTION_FILTER_ALL; - case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: - return NotificationListenerService.INTERRUPTION_FILTER_PRIORITY; - case Global.ZEN_MODE_ALARMS: - return NotificationListenerService.INTERRUPTION_FILTER_ALARMS; - case Global.ZEN_MODE_NO_INTERRUPTIONS: - return NotificationListenerService.INTERRUPTION_FILTER_NONE; - default: - return 0; - } - } - - private static int zenModeFromListenerInterruptionFilter(int listenerInterruptionFilter, - int defValue) { - switch (listenerInterruptionFilter) { - case NotificationListenerService.INTERRUPTION_FILTER_ALL: - return Global.ZEN_MODE_OFF; - case NotificationListenerService.INTERRUPTION_FILTER_PRIORITY: - return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; - case NotificationListenerService.INTERRUPTION_FILTER_ALARMS: - return Global.ZEN_MODE_ALARMS; - case NotificationListenerService.INTERRUPTION_FILTER_NONE: - return Global.ZEN_MODE_NO_INTERRUPTIONS; - default: - return defValue; - } - } - private ZenModeConfig readDefaultConfig(Resources resources) { XmlResourceParser parser = null; try { @@ -469,6 +441,20 @@ public class ZenModeHelper { config.automaticRules.put(config.newRuleId(), rule2); } + private void appendDefaultEventRules(ZenModeConfig config) { + if (config == null) return; + + final EventInfo events = new EventInfo(); + events.calendar = EventInfo.ANY_CALENDAR; + events.reply = EventInfo.REPLY_YES_OR_MAYBE; + final ZenRule rule = new ZenRule(); + rule.enabled = false; + rule.name = mContext.getResources().getString(R.string.zen_mode_default_events_name); + rule.conditionId = ZenModeConfig.toEventConditionId(events); + rule.zenMode = Global.ZEN_MODE_ALARMS; + config.automaticRules.put(config.newRuleId(), rule); + } + private static int zenSeverity(int zen) { switch (zen) { case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1; @@ -511,6 +497,7 @@ public class ZenModeHelper { Log.i(TAG, "No existing V1 downtime found, generating default schedules"); appendDefaultScheduleRules(rt); } + appendDefaultEventRules(rt); return rt; } }; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index f30a5674..a120c1f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -11853,6 +11853,7 @@ public class PackageManagerService extends IPackageManager.Stub { synchronized (mPackages) { if (deletedPs != null) { if ((flags&PackageManager.DELETE_KEEP_DATA) == 0) { + clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL); if (outInfo != null) { mSettings.mKeySetManagerService.removeAppKeySetDataLPw(packageName); outInfo.removedAppId = mSettings.removePackageLPw(packageName); @@ -11883,7 +11884,6 @@ public class PackageManagerService extends IPackageManager.Stub { } } clearPackagePreferredActivitiesLPw(deletedPs.name, UserHandle.USER_ALL); - clearIntentFilterVerificationsLPw(deletedPs.name, UserHandle.USER_ALL); } // make sure to preserve per-user disabled state if this removal was just // a downgrade of a system app to the factory package @@ -12744,13 +12744,16 @@ public class PackageManagerService extends IPackageManager.Stub { /** This method takes a specific user id as well as UserHandle.USER_ALL. */ void clearIntentFilterVerificationsLPw(String packageName, int userId) { if (userId == UserHandle.USER_ALL) { - mSettings.removeIntentFilterVerificationLPw(packageName, sUserManager.getUserIds()); - for (int oneUserId : sUserManager.getUserIds()) { - scheduleWritePackageRestrictionsLocked(oneUserId); + if (mSettings.removeIntentFilterVerificationLPw(packageName, + sUserManager.getUserIds())) { + for (int oneUserId : sUserManager.getUserIds()) { + scheduleWritePackageRestrictionsLocked(oneUserId); + } } } else { - mSettings.removeIntentFilterVerificationLPw(packageName, userId); - scheduleWritePackageRestrictionsLocked(userId); + if (mSettings.removeIntentFilterVerificationLPw(packageName, userId)) { + scheduleWritePackageRestrictionsLocked(userId); + } } } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index d476bfde..fd70ce1 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -1067,19 +1067,22 @@ final class Settings { return result; } - void removeIntentFilterVerificationLPw(String packageName, int userId) { + boolean removeIntentFilterVerificationLPw(String packageName, int userId) { PackageSetting ps = mPackages.get(packageName); if (ps == null) { Slog.w(PackageManagerService.TAG, "No package known for name: " + packageName); - return; + return false; } ps.clearDomainVerificationStatusForUser(userId); + return true; } - void removeIntentFilterVerificationLPw(String packageName, int[] userIds) { + boolean removeIntentFilterVerificationLPw(String packageName, int[] userIds) { + boolean result = false; for (int userId : userIds) { - removeIntentFilterVerificationLPw(packageName, userId); + result |= removeIntentFilterVerificationLPw(packageName, userId); } + return result; } boolean setDefaultBrowserPackageNameLPr(String packageName, int userId) { diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index e79a206..8dccfdf 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -50,6 +50,8 @@ import android.util.SparseBooleanArray; import android.util.TimeUtils; import android.util.Xml; +import com.google.android.collect.Sets; + import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.IAppOpsService; import com.android.internal.util.ArrayUtils; @@ -68,11 +70,9 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; +import java.util.Set; import libcore.io.IoUtils; @@ -88,10 +88,6 @@ public class UserManagerService extends IUserManager.Stub { private static final String ATTR_ID = "id"; private static final String ATTR_CREATION_TIME = "created"; private static final String ATTR_LAST_LOGGED_IN_TIME = "lastLoggedIn"; - private static final String ATTR_SALT = "salt"; - private static final String ATTR_PIN_HASH = "pinHash"; - private static final String ATTR_FAILED_ATTEMPTS = "failedAttempts"; - private static final String ATTR_LAST_RETRY_MS = "lastAttemptMs"; private static final String ATTR_SERIAL_NO = "serialNumber"; private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber"; private static final String ATTR_PARTIAL = "partial"; @@ -129,16 +125,13 @@ public class UserManagerService extends IUserManager.Stub { private static final long EPOCH_PLUS_30_YEARS = 30L * 365 * 24 * 60 * 60 * 1000L; // ms - // Number of attempts before jumping to the next BACKOFF_TIMES slot - private static final int BACKOFF_INC_INTERVAL = 5; - // Maximum number of managed profiles permitted is 1. This cannot be increased // without first making sure that the rest of the framework is prepared for it. private static final int MAX_MANAGED_PROFILES = 1; - // Amount of time to force the user to wait before entering the PIN again, after failing - // BACKOFF_INC_INTERVAL times. - private static final int[] BACKOFF_TIMES = { 0, 30*1000, 60*1000, 5*60*1000, 30*60*1000 }; + // Set of user restrictions, which can only be enforced by the system + private static final Set<String> SYSTEM_CONTROLLED_RESTRICTIONS = Sets.newArraySet( + UserManager.DISALLOW_RECORD_AUDIO); static final int WRITE_USER_MSG = 1; static final int WRITE_USER_DELAY = 2*1000; // 2 seconds @@ -158,16 +151,6 @@ public class UserManagerService extends IUserManager.Stub { private final SparseArray<Bundle> mUserRestrictions = new SparseArray<Bundle>(); private final Bundle mGuestRestrictions = new Bundle(); - class RestrictionsPinState { - long salt; - String pinHash; - int failedAttempts; - long lastAttemptTime; - } - - private final SparseArray<RestrictionsPinState> mRestrictionsPinStates = - new SparseArray<RestrictionsPinState>(); - /** * Set of user IDs being actively removed. Removed IDs linger in this set * for several seconds to work around a VFS caching issue. @@ -234,6 +217,14 @@ public class UserManagerService extends IUserManager.Stub { mUserListFile = new File(mUsersDir, USER_LIST_FILENAME); initDefaultGuestRestrictions(); readUserListLocked(); + sInstance = this; + } + } + } + + void systemReady() { + synchronized (mInstallLock) { + synchronized (mPackagesLock) { // Prune out any partially created/partially removed users. ArrayList<UserInfo> partials = new ArrayList<UserInfo>(); for (int i = 0; i < mUsers.size(); i++) { @@ -248,12 +239,8 @@ public class UserManagerService extends IUserManager.Stub { + " (name=" + ui.name + ")"); removeUserStateLocked(ui.id); } - sInstance = this; } } - } - - void systemReady() { userForeground(UserHandle.USER_OWNER); mAppOpsService = IAppOpsService.Stub.asInterface( ServiceManager.getService(Context.APP_OPS_SERVICE)); @@ -520,7 +507,7 @@ public class UserManagerService extends IUserManager.Stub { public boolean hasUserRestriction(String restrictionKey, int userId) { synchronized (mPackagesLock) { Bundle restrictions = mUserRestrictions.get(userId); - return restrictions != null ? restrictions.getBoolean(restrictionKey) : false; + return restrictions != null && restrictions.getBoolean(restrictionKey); } } @@ -535,23 +522,57 @@ public class UserManagerService extends IUserManager.Stub { } @Override + public void setUserRestriction(String key, boolean value, int userId) { + synchronized (mPackagesLock) { + if (!SYSTEM_CONTROLLED_RESTRICTIONS.contains(key)) { + Bundle restrictions = getUserRestrictions(userId); + restrictions.putBoolean(key, value); + setUserRestrictionsInternalLocked(restrictions, userId); + } + } + } + + @Override + public void setSystemControlledUserRestriction(String key, boolean value, int userId) { + checkSystemOrRoot("setSystemControlledUserRestriction"); + synchronized (mPackagesLock) { + Bundle restrictions = getUserRestrictions(userId); + restrictions.putBoolean(key, value); + setUserRestrictionsInternalLocked(restrictions, userId); + } + } + + @Override public void setUserRestrictions(Bundle restrictions, int userId) { checkManageUsersPermission("setUserRestrictions"); if (restrictions == null) return; synchronized (mPackagesLock) { - mUserRestrictions.get(userId).clear(); - mUserRestrictions.get(userId).putAll(restrictions); - long token = Binder.clearCallingIdentity(); - try { - mAppOpsService.setUserRestrictions(mUserRestrictions.get(userId), userId); - } catch (RemoteException e) { - Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions"); - } finally { - Binder.restoreCallingIdentity(token); + final Bundle oldUserRestrictions = mUserRestrictions.get(userId); + // Restore the original state of system controlled restrictions from oldUserRestrictions + for (String key : SYSTEM_CONTROLLED_RESTRICTIONS) { + restrictions.remove(key); + if (oldUserRestrictions.containsKey(key)) { + restrictions.putBoolean(key, oldUserRestrictions.getBoolean(key)); + } } - scheduleWriteUserLocked(mUsers.get(userId)); + setUserRestrictionsInternalLocked(restrictions, userId); + } + } + + private void setUserRestrictionsInternalLocked(Bundle restrictions, int userId) { + final Bundle userRestrictions = mUserRestrictions.get(userId); + userRestrictions.clear(); + userRestrictions.putAll(restrictions); + long token = Binder.clearCallingIdentity(); + try { + mAppOpsService.setUserRestrictions(userRestrictions, userId); + } catch (RemoteException e) { + Log.w(LOG_TAG, "Unable to notify AppOpsService of UserRestrictions"); + } finally { + Binder.restoreCallingIdentity(token); } + scheduleWriteUserLocked(mUsers.get(userId)); } /** @@ -589,6 +610,13 @@ public class UserManagerService extends IUserManager.Stub { } } + private static void checkSystemOrRoot(String message) { + final int uid = Binder.getCallingUid(); + if (uid != Process.SYSTEM_UID && uid != 0) { + throw new SecurityException("Only system may call: " + message); + } + } + private void writeBitmapLocked(UserInfo info, Bitmap bitmap) { try { File dir = new File(mUsersDir, Integer.toString(info.id)); @@ -806,21 +834,6 @@ public class UserManagerService extends IUserManager.Stub { serializer.attribute(null, ATTR_CREATION_TIME, Long.toString(userInfo.creationTime)); serializer.attribute(null, ATTR_LAST_LOGGED_IN_TIME, Long.toString(userInfo.lastLoggedInTime)); - RestrictionsPinState pinState = mRestrictionsPinStates.get(userInfo.id); - if (pinState != null) { - if (pinState.salt != 0) { - serializer.attribute(null, ATTR_SALT, Long.toString(pinState.salt)); - } - if (pinState.pinHash != null) { - serializer.attribute(null, ATTR_PIN_HASH, pinState.pinHash); - } - if (pinState.failedAttempts != 0) { - serializer.attribute(null, ATTR_FAILED_ATTEMPTS, - Integer.toString(pinState.failedAttempts)); - serializer.attribute(null, ATTR_LAST_RETRY_MS, - Long.toString(pinState.lastAttemptTime)); - } - } if (userInfo.iconPath != null) { serializer.attribute(null, ATTR_ICON_PATH, userInfo.iconPath); } @@ -940,11 +953,7 @@ public class UserManagerService extends IUserManager.Stub { String iconPath = null; long creationTime = 0L; long lastLoggedInTime = 0L; - long salt = 0L; - String pinHash = null; - int failedAttempts = 0; int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID; - long lastAttemptTime = 0L; boolean partial = false; boolean guestToRemove = false; Bundle restrictions = new Bundle(); @@ -978,10 +987,6 @@ public class UserManagerService extends IUserManager.Stub { iconPath = parser.getAttributeValue(null, ATTR_ICON_PATH); creationTime = readLongAttribute(parser, ATTR_CREATION_TIME, 0); lastLoggedInTime = readLongAttribute(parser, ATTR_LAST_LOGGED_IN_TIME, 0); - salt = readLongAttribute(parser, ATTR_SALT, 0L); - pinHash = parser.getAttributeValue(null, ATTR_PIN_HASH); - failedAttempts = readIntAttribute(parser, ATTR_FAILED_ATTEMPTS, 0); - lastAttemptTime = readLongAttribute(parser, ATTR_LAST_RETRY_MS, 0L); profileGroupId = readIntAttribute(parser, ATTR_PROFILE_GROUP_ID, UserInfo.NO_PROFILE_GROUP_ID); String valueString = parser.getAttributeValue(null, ATTR_PARTIAL); @@ -1019,17 +1024,6 @@ public class UserManagerService extends IUserManager.Stub { userInfo.guestToRemove = guestToRemove; userInfo.profileGroupId = profileGroupId; mUserRestrictions.append(id, restrictions); - if (salt != 0L) { - RestrictionsPinState pinState = mRestrictionsPinStates.get(id); - if (pinState == null) { - pinState = new RestrictionsPinState(); - mRestrictionsPinStates.put(id, pinState); - } - pinState.salt = salt; - pinState.pinHash = pinHash; - pinState.failedAttempts = failedAttempts; - pinState.lastAttemptTime = lastAttemptTime; - } return userInfo; } catch (IOException ioe) { @@ -1431,8 +1425,6 @@ public class UserManagerService extends IUserManager.Stub { // Remove this user from the list mUsers.remove(userHandle); - - mRestrictionsPinStates.remove(userHandle); // Remove user file AtomicFile userFile = new AtomicFile(new File(mUsersDir, userHandle + XML_SUFFIX)); userFile.delete(); @@ -1504,92 +1496,6 @@ public class UserManagerService extends IUserManager.Stub { } @Override - public boolean setRestrictionsChallenge(String newPin) { - checkManageUsersPermission("Only system can modify the restrictions pin"); - int userId = UserHandle.getCallingUserId(); - synchronized (mPackagesLock) { - RestrictionsPinState pinState = mRestrictionsPinStates.get(userId); - if (pinState == null) { - pinState = new RestrictionsPinState(); - } - if (newPin == null) { - pinState.salt = 0; - pinState.pinHash = null; - } else { - try { - pinState.salt = SecureRandom.getInstance("SHA1PRNG").nextLong(); - } catch (NoSuchAlgorithmException e) { - pinState.salt = (long) (Math.random() * Long.MAX_VALUE); - } - pinState.pinHash = passwordToHash(newPin, pinState.salt); - pinState.failedAttempts = 0; - } - mRestrictionsPinStates.put(userId, pinState); - writeUserLocked(mUsers.get(userId)); - } - return true; - } - - @Override - public int checkRestrictionsChallenge(String pin) { - checkManageUsersPermission("Only system can verify the restrictions pin"); - int userId = UserHandle.getCallingUserId(); - synchronized (mPackagesLock) { - RestrictionsPinState pinState = mRestrictionsPinStates.get(userId); - // If there's no pin set, return error code - if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) { - return UserManager.PIN_VERIFICATION_FAILED_NOT_SET; - } else if (pin == null) { - // If just checking if user can be prompted, return remaining time - int waitTime = getRemainingTimeForPinAttempt(pinState); - Slog.d(LOG_TAG, "Remaining waittime peek=" + waitTime); - return waitTime; - } else { - int waitTime = getRemainingTimeForPinAttempt(pinState); - Slog.d(LOG_TAG, "Remaining waittime=" + waitTime); - if (waitTime > 0) { - return waitTime; - } - if (passwordToHash(pin, pinState.salt).equals(pinState.pinHash)) { - pinState.failedAttempts = 0; - scheduleWriteUserLocked(mUsers.get(userId)); - return UserManager.PIN_VERIFICATION_SUCCESS; - } else { - pinState.failedAttempts++; - pinState.lastAttemptTime = System.currentTimeMillis(); - scheduleWriteUserLocked(mUsers.get(userId)); - return waitTime; - } - } - } - } - - private int getRemainingTimeForPinAttempt(RestrictionsPinState pinState) { - int backoffIndex = Math.min(pinState.failedAttempts / BACKOFF_INC_INTERVAL, - BACKOFF_TIMES.length - 1); - int backoffTime = (pinState.failedAttempts % BACKOFF_INC_INTERVAL) == 0 ? - BACKOFF_TIMES[backoffIndex] : 0; - return (int) Math.max(backoffTime + pinState.lastAttemptTime - System.currentTimeMillis(), - 0); - } - - @Override - public boolean hasRestrictionsChallenge() { - int userId = UserHandle.getCallingUserId(); - synchronized (mPackagesLock) { - return hasRestrictionsPinLocked(userId); - } - } - - private boolean hasRestrictionsPinLocked(int userId) { - RestrictionsPinState pinState = mRestrictionsPinStates.get(userId); - if (pinState == null || pinState.salt == 0 || pinState.pinHash == null) { - return false; - } - return true; - } - - @Override public void removeRestrictions() { checkManageUsersPermission("Only system can remove restrictions"); final int userHandle = UserHandle.getCallingUserId(); @@ -1600,8 +1506,6 @@ public class UserManagerService extends IUserManager.Stub { synchronized (mPackagesLock) { // Remove all user restrictions setUserRestrictions(new Bundle(), userHandle); - // Remove restrictions pin - setRestrictionsChallenge(null); // Remove any app restrictions cleanAppRestrictions(userHandle); } @@ -1633,42 +1537,6 @@ public class UserManagerService extends IUserManager.Stub { } }); } - - /* - * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash. - * Not the most secure, but it is at least a second level of protection. First level is that - * the file is in a location only readable by the system process. - * @param password the password. - * @param salt the randomly generated salt - * @return the hash of the pattern in a String. - */ - private String passwordToHash(String password, long salt) { - if (password == null) { - return null; - } - String algo = null; - String hashed = salt + password; - try { - byte[] saltedPassword = (password + salt).getBytes(); - byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword); - byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword); - hashed = toHex(sha1) + toHex(md5); - } catch (NoSuchAlgorithmException e) { - Log.w(LOG_TAG, "Failed to encode string because of missing algorithm: " + algo); - } - return hashed; - } - - private static String toHex(byte[] ary) { - final String hex = "0123456789ABCDEF"; - String ret = ""; - for (int i = 0; i < ary.length; i++) { - ret += hex.charAt((ary[i] >> 4) & 0xf); - ret += hex.charAt(ary[i] & 0xf); - } - return ret; - } - private int getUidForPackage(String packageName) { long ident = Binder.clearCallingIdentity(); try { @@ -1954,11 +1822,6 @@ public class UserManagerService extends IUserManager.Stub { return RESTRICTIONS_FILE_PREFIX + packageName + XML_SUFFIX; } - private String restrictionsFileNameToPackage(String fileName) { - return fileName.substring(RESTRICTIONS_FILE_PREFIX.length(), - (int) (fileName.length() - XML_SUFFIX.length())); - } - @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) diff --git a/services/core/java/com/android/server/policy/BarController.java b/services/core/java/com/android/server/policy/BarController.java index e972ec7..5877b3e 100644 --- a/services/core/java/com/android/server/policy/BarController.java +++ b/services/core/java/com/android/server/policy/BarController.java @@ -58,6 +58,9 @@ public class BarController { private int mTransientBarState; private boolean mPendingShow; private long mLastTranslucent; + private boolean mShowTransparent; + private boolean mSetUnHideFlagWhenNextTransparent; + private boolean mNoAnimationOnNextShow; public BarController(String tag, int transientFlag, int unhideFlag, int translucentFlag, int statusBarManagerId, int translucentWmFlag) { @@ -74,6 +77,14 @@ public class BarController { mWin = win; } + public void setShowTransparent(boolean transparent) { + if (transparent != mShowTransparent) { + mShowTransparent = transparent; + mSetUnHideFlagWhenNextTransparent = transparent; + mNoAnimationOnNextShow = true; + } + } + public void showTransient() { if (mWin != null) { setTransientBarState(TRANSIENT_BAR_SHOW_REQUESTED); @@ -135,7 +146,9 @@ public class BarController { } final boolean wasVis = mWin.isVisibleLw(); final boolean wasAnim = mWin.isAnimatingLw(); - final boolean change = show ? mWin.showLw(true) : mWin.hideLw(true); + final boolean change = show ? mWin.showLw(!mNoAnimationOnNextShow) + : mWin.hideLw(!mNoAnimationOnNextShow); + mNoAnimationOnNextShow = false; final int state = computeStateLw(wasVis, wasAnim, mWin, change); final boolean stateChanged = updateStateLw(state); return change || stateChanged; @@ -233,6 +246,13 @@ public class BarController { setTransientBarState(TRANSIENT_BAR_NONE); // request denied } } + if (mShowTransparent) { + vis |= View.SYSTEM_UI_TRANSPARENT; + if (mSetUnHideFlagWhenNextTransparent) { + vis |= mUnhideFlag; + mSetUnHideFlagWhenNextTransparent = false; + } + } if (mTransientBarState != TRANSIENT_BAR_NONE) { vis |= mTransientFlag; // ignore clear requests until transition completes vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE; // never show transient bars in low profile diff --git a/services/core/java/com/android/server/policy/GlobalActions.java b/services/core/java/com/android/server/policy/GlobalActions.java index b431b33..3cee927 100644 --- a/services/core/java/com/android/server/policy/GlobalActions.java +++ b/services/core/java/com/android/server/policy/GlobalActions.java @@ -1138,7 +1138,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac public GlobalActionsDialog(Context context, AlertParams params) { super(context, getDialogTheme(context)); - mContext = context; + mContext = getContext(); mAlert = new AlertController(mContext, this, getWindow()); mAdapter = (MyAdapter) params.mAdapter; mWindowTouchSlop = ViewConfiguration.get(context).getScaledWindowTouchSlop(); diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index dbd3676..185ef03 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -476,6 +476,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { boolean mTopIsFullscreen; boolean mForceStatusBar; boolean mForceStatusBarFromKeyguard; + private boolean mForceStatusBarTransparent; boolean mHideLockScreen; boolean mForcingShowNavBar; int mForcingShowNavBarLayer; @@ -4129,6 +4130,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mAppsThatDismissKeyguard.clear(); mForceStatusBar = false; mForceStatusBarFromKeyguard = false; + mForceStatusBarTransparent = false; mForcingShowNavBar = false; mForcingShowNavBarLayer = -1; @@ -4154,8 +4156,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { mForcingShowNavBar = true; mForcingShowNavBarLayer = win.getSurfaceLayer(); } - if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { - mForceStatusBarFromKeyguard = true; + if (attrs.type == TYPE_STATUS_BAR) { + if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) { + mForceStatusBarFromKeyguard = true; + } + if ((attrs.privateFlags & PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT) != 0) { + mForceStatusBarTransparent = true; + } } boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW @@ -4302,7 +4309,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (DEBUG_LAYOUT) Slog.i(TAG, "force=" + mForceStatusBar + " forcefkg=" + mForceStatusBarFromKeyguard + " top=" + mTopFullscreenOpaqueWindowState); - if (mForceStatusBar || mForceStatusBarFromKeyguard) { + boolean shouldBeTransparent = mForceStatusBarTransparent + && !mForceStatusBar + && !mForceStatusBarFromKeyguard; + if (!shouldBeTransparent) { + mStatusBarController.setShowTransparent(false /* transparent */); + } else if (!mStatusBar.isVisibleLw()) { + mStatusBarController.setShowTransparent(true /* transparent */); + } + if (mForceStatusBar || mForceStatusBarFromKeyguard || mForceStatusBarTransparent) { if (DEBUG_LAYOUT) Slog.v(TAG, "Showing status bar: forced"); if (mStatusBarController.setBarShowingLw(true)) { changes |= FINISH_LAYOUT_REDO_LAYOUT; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 6f01ca0..67c198f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -2897,7 +2897,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { boolean callerIsDeviceOwnerAdmin = isCallerDeviceOwnerOrInitializer(callingUid); boolean doNotAskCredentialsOnBoot = - (flags & DevicePolicyManager.DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0; + (flags & DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0; if (callerIsDeviceOwnerAdmin && doNotAskCredentialsOnBoot) { setDoNotAskCredentialsOnBoot(); } diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 2d265e2..925a609 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.Configuration; +import android.content.res.Resources.Theme; import android.os.Build; import android.os.Environment; import android.os.FactoryTest; @@ -291,7 +292,7 @@ public final class SystemServer { private void createSystemContext() { ActivityThread activityThread = ActivityThread.systemMain(); mSystemContext = activityThread.getSystemContext(); - mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar); + mSystemContext.setTheme(android.R.style.Theme_Material_DayNight_DarkActionBar); } /** @@ -1026,6 +1027,12 @@ public final class SystemServer { w.getDefaultDisplay().getMetrics(metrics); context.getResources().updateConfiguration(config, metrics); + // The system context's theme may be configuration-dependent. + final Theme systemTheme = context.getTheme(); + if (systemTheme.getChangingConfigurations() != 0) { + systemTheme.rebase(); + } + try { // TODO: use boot phase mPowerManagerService.systemReady(mActivityManagerService.getAppOpsService()); diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java index c1c5c56..176f54b 100644 --- a/services/midi/java/com/android/server/midi/MidiService.java +++ b/services/midi/java/com/android/server/midi/MidiService.java @@ -294,8 +294,10 @@ public class MidiService extends IMidiManager.Stub { @Override public String toString() { - StringBuilder sb = new StringBuilder("Device: "); + StringBuilder sb = new StringBuilder("Device Info: "); sb.append(mDeviceInfo); + sb.append(" Status: "); + sb.append(mDeviceStatus); sb.append(" UID: "); sb.append(mUid); return sb.toString(); diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 6adb8be..f84beb6 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -78,8 +78,6 @@ public class UsbDeviceManager { "/sys/class/android_usb/android0/functions"; private static final String STATE_PATH = "/sys/class/android_usb/android0/state"; - private static final String MASS_STORAGE_FILE_PATH = - "/sys/class/android_usb/android0/f_mass_storage/lun/file"; private static final String RNDIS_ETH_ADDR_PATH = "/sys/class/android_usb/android0/f_rndis/ethaddr"; private static final String AUDIO_SOURCE_PCM_PATH = @@ -832,8 +830,6 @@ public class UsbDeviceManager { + FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim()); pw.println(" Kernel function list: " + FileUtils.readTextFile(new File(FUNCTIONS_PATH), 0, null).trim()); - pw.println(" Mass storage backing file: " - + FileUtils.readTextFile(new File(MASS_STORAGE_FILE_PATH), 0, null).trim()); } catch (IOException e) { pw.println("IOException: " + e); } @@ -866,15 +862,6 @@ public class UsbDeviceManager { mHandler.sendMessage(MSG_SET_CURRENT_FUNCTIONS, functions, makeDefault); } - public void setMassStorageBackingFile(String path) { - if (path == null) path = ""; - try { - FileUtils.stringToFile(MASS_STORAGE_FILE_PATH, path); - } catch (IOException e) { - Slog.e(TAG, "failed to write to " + MASS_STORAGE_FILE_PATH); - } - } - private void readOemUsbOverrideConfig() { String[] configList = mContext.getResources().getStringArray( com.android.internal.R.array.config_oemUsbModeOverride); diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index fda8076..e03884f 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -271,16 +271,6 @@ public class UsbService extends IUsbManager.Stub { } @Override - public void setMassStorageBackingFile(String path) { - mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); - if (mDeviceManager != null) { - mDeviceManager.setMassStorageBackingFile(path); - } else { - throw new IllegalStateException("USB device mode not supported"); - } - } - - @Override public void allowUsbDebugging(boolean alwaysAllow, String publicKey) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); mDeviceManager.allowUsbDebugging(alwaysAllow, publicKey); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 2897c61..fcdb6d6 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -754,7 +754,7 @@ public class VoiceInteractionManagerService extends SystemService { public boolean activeServiceSupportsAssist() { enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE); synchronized (this) { - return mImpl != null && mImpl.mInfo.getSupportsAssist(); + return mImpl != null && mImpl.mInfo != null && mImpl.mInfo.getSupportsAssist(); } } @@ -762,7 +762,8 @@ public class VoiceInteractionManagerService extends SystemService { public boolean activeServiceSupportsLaunchFromKeyguard() throws RemoteException { enforceCallingPermission(Manifest.permission.ACCESS_VOICE_INTERACTION_SERVICE); synchronized (this) { - return mImpl != null && mImpl.mInfo.getSupportsLaunchFromKeyguard(); + return mImpl != null && mImpl.mInfo != null + && mImpl.mInfo.getSupportsLaunchFromKeyguard(); } } |