diff options
Diffstat (limited to 'services')
42 files changed, 1341 insertions, 795 deletions
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index e9419ad..b04cc19 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -1535,7 +1535,7 @@ class AlarmManagerService extends SystemService { for (int i=0; i<triggerList.size(); i++) { Alarm alarm = triggerList.get(i); try { - if (localLOGV) Slog.v(TAG, "sending alarm " + alarm); + Slog.v(TAG, "sending alarm " + alarm); alarm.operation.send(getContext(), 0, mBackgroundIntent.putExtra( Intent.EXTRA_ALARM_COUNT, alarm.count), diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 3062a92..75090db 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4746,6 +4746,11 @@ public class ConnectivityService extends IConnectivityManager.Stub { private void updateNetworkScore(NetworkAgentInfo nai, int score) { if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score); + if (score < 0) { + loge("updateNetworkScore for " + nai.name() + " got a negative score (" + score + + "). Bumping score to min of 0"); + score = 0; + } nai.currentScore = score; diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index c8718e3..060c8e3 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -106,6 +106,7 @@ import android.view.inputmethod.InputMethod; import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodSubtype; +import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder; import android.widget.ArrayAdapter; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; @@ -3455,9 +3456,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE); final boolean isAuxiliary = "1".equals(String.valueOf( parser.getAttributeValue(null, ATTR_IS_AUXILIARY))); - final InputMethodSubtype subtype = - new InputMethodSubtype(label, icon, imeSubtypeLocale, - imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary); + final InputMethodSubtype subtype = new InputMethodSubtypeBuilder() + .setSubtypeNameResId(label) + .setSubtypeIconResId(icon) + .setSubtypeLocale(imeSubtypeLocale) + .setSubtypeMode(imeSubtypeMode) + .setSubtypeExtraValue(imeSubtypeExtraValue) + .setIsAuxiliary(isAuxiliary) + .build(); tempSubtypesArray.add(subtype); } } diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java index 7624314..37c23bb 100644 --- a/services/core/java/com/android/server/TelephonyRegistry.java +++ b/services/core/java/com/android/server/TelephonyRegistry.java @@ -196,7 +196,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { if (VDBG) log("MSG_USER_SWITCHED userId=" + msg.arg1); int numPhones = TelephonyManager.getDefault().getPhoneCount(); for (int sub = 0; sub < numPhones; sub++) { - TelephonyRegistry.this.notifyCellLocationUsingSubId(sub, + TelephonyRegistry.this.notifyCellLocationForSubscriber(sub, mCellLocation[sub]); } break; @@ -326,7 +326,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } @Override - public void listenUsingSubId(long subId, String pkgForDebug, IPhoneStateListener callback, + public void listenForSubscriber(long subId, String pkgForDebug, IPhoneStateListener callback, int events, boolean notifyNow) { listen(pkgForDebug, callback, events, notifyNow, subId, false); } @@ -542,12 +542,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { broadcastCallStateChanged(state, incomingNumber, mDefaultSubId); } - public void notifyCallStateUsingSubId(long subId, int state, String incomingNumber) { + public void notifyCallStateForSubscriber(long subId, int state, String incomingNumber) { if (!checkNotifyPermission("notifyCallState()")) { return; } if (VDBG) { - log("notifyCallStateUsingSubId: subId=" + subId + log("notifyCallStateForSubscriber: subId=" + subId + " state=" + state + " incomingNumber=" + incomingNumber); } synchronized (mRecords) { @@ -573,38 +573,38 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyServiceState(ServiceState state) { - notifyServiceStateUsingSubId(mDefaultSubId, state); + notifyServiceStateForSubscriber(mDefaultSubId, state); } - public void notifyServiceStateUsingSubId(long subId, ServiceState state) { + public void notifyServiceStateForSubscriber(long subId, ServiceState state) { if (!checkNotifyPermission("notifyServiceState()")){ return; } if (subId == SubscriptionManager.DEFAULT_SUB_ID) { subId = mDefaultSubId; - if (VDBG) log("notifyServiceStateUsingSubId: using mDefaultSubId=" + mDefaultSubId); + if (VDBG) log("notifyServiceStateForSubscriber: using mDefaultSubId=" + mDefaultSubId); } synchronized (mRecords) { int phoneId = SubscriptionManager.getPhoneId(subId); if (VDBG) { - log("notifyServiceStateUsingSubId: subId=" + subId + " phoneId=" + phoneId + log("notifyServiceStateForSubscriber: subId=" + subId + " phoneId=" + phoneId + " state=" + state); } if (validatePhoneId(phoneId)) { mServiceState[phoneId] = state; - logServiceStateChanged("notifyServiceStateUsingSubId", subId, phoneId, state); - if (VDBG) toStringLogSSC("notifyServiceStateUsingSubId"); + logServiceStateChanged("notifyServiceStateForSubscriber", subId, phoneId, state); + if (VDBG) toStringLogSSC("notifyServiceStateForSubscriber"); for (Record r : mRecords) { if (VDBG) { - log("notifyServiceStateUsingSubId: r=" + r + " subId=" + subId + log("notifyServiceStateForSubscriber: r=" + r + " subId=" + subId + " phoneId=" + phoneId + " state=" + state); } if (((r.events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) && (r.phoneId == phoneId)) { try { if (DBG) { - log("notifyServiceStateUsingSubId: callback.onSSC r=" + r + log("notifyServiceStateForSubscriber: callback.onSSC r=" + r + " subId=" + subId + " phoneId=" + phoneId + " state=" + state); } @@ -615,7 +615,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } } else { - log("notifyServiceStateUsingSubId: INVALID phoneId=" + phoneId); + log("notifyServiceStateForSubscriber: INVALID phoneId=" + phoneId); } handleRemoveListLocked(); } @@ -623,33 +623,33 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifySignalStrength(SignalStrength signalStrength) { - notifySignalStrengthUsingSubId(mDefaultSubId, signalStrength); + notifySignalStrengthForSubscriber(mDefaultSubId, signalStrength); } - public void notifySignalStrengthUsingSubId(long subId, SignalStrength signalStrength) { + public void notifySignalStrengthForSubscriber(long subId, SignalStrength signalStrength) { if (!checkNotifyPermission("notifySignalStrength()")) { return; } if (VDBG) { - log("notifySignalStrengthUsingSubId: subId=" + subId + log("notifySignalStrengthForSubscriber: subId=" + subId + " signalStrength=" + signalStrength); - toStringLogSSC("notifySignalStrengthUsingSubId"); + toStringLogSSC("notifySignalStrengthForSubscriber"); } synchronized (mRecords) { int phoneId = SubscriptionManager.getPhoneId(subId); if (validatePhoneId(phoneId)) { - if (VDBG) log("notifySignalStrengthUsingSubId: valid phoneId=" + phoneId); + if (VDBG) log("notifySignalStrengthForSubscriber: valid phoneId=" + phoneId); mSignalStrength[phoneId] = signalStrength; for (Record r : mRecords) { if (VDBG) { - log("notifySignalStrengthUsingSubId: r=" + r + " subId=" + subId + log("notifySignalStrengthForSubscriber: r=" + r + " subId=" + subId + " phoneId=" + phoneId + " ss=" + signalStrength); } if (((r.events & PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) != 0) && (r.phoneId == phoneId)) { try { if (DBG) { - log("notifySignalStrengthUsingSubId: callback.onSsS r=" + r + log("notifySignalStrengthForSubscriber: callback.onSsS r=" + r + " subId=" + subId + " phoneId=" + phoneId + " ss=" + signalStrength); } @@ -664,7 +664,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { int gsmSignalStrength = signalStrength.getGsmSignalStrength(); int ss = (gsmSignalStrength == 99 ? -1 : gsmSignalStrength); if (DBG) { - log("notifySignalStrengthUsingSubId: callback.onSS r=" + r + log("notifySignalStrengthForSubscriber: callback.onSS r=" + r + " subId=" + subId + " phoneId=" + phoneId + " gsmSS=" + gsmSignalStrength + " ss=" + ss); } @@ -675,7 +675,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } } } else { - log("notifySignalStrengthUsingSubId: invalid phoneId=" + phoneId); + log("notifySignalStrengthForSubscriber: invalid phoneId=" + phoneId); } handleRemoveListLocked(); } @@ -683,15 +683,15 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyCellInfo(List<CellInfo> cellInfo) { - notifyCellInfoUsingSubId(mDefaultSubId, cellInfo); + notifyCellInfoForSubscriber(mDefaultSubId, cellInfo); } - public void notifyCellInfoUsingSubId(long subId, List<CellInfo> cellInfo) { + public void notifyCellInfoForSubscriber(long subId, List<CellInfo> cellInfo) { if (!checkNotifyPermission("notifyCellInfo()")) { return; } if (VDBG) { - log("notifyCellInfoUsingSubId: subId=" + subId + log("notifyCellInfoForSubscriber: subId=" + subId + " cellInfo=" + cellInfo); } @@ -743,15 +743,15 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyMessageWaitingChanged(boolean mwi) { - notifyMessageWaitingChangedUsingSubId(mDefaultSubId, mwi); + notifyMessageWaitingChangedForSubscriber(mDefaultSubId, mwi); } - public void notifyMessageWaitingChangedUsingSubId(long subId, boolean mwi) { + public void notifyMessageWaitingChangedForSubscriber(long subId, boolean mwi) { if (!checkNotifyPermission("notifyMessageWaitingChanged()")) { return; } if (VDBG) { - log("notifyMessageWaitingChangedUsingSubId: subId=" + subId + log("notifyMessageWaitingChangedForSubscriber: subId=" + subId + " mwi=" + mwi); } synchronized (mRecords) { @@ -774,15 +774,15 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyCallForwardingChanged(boolean cfi) { - notifyCallForwardingChangedUsingSubId(mDefaultSubId, cfi); + notifyCallForwardingChangedForSubscriber(mDefaultSubId, cfi); } - public void notifyCallForwardingChangedUsingSubId(long subId, boolean cfi) { + public void notifyCallForwardingChangedForSubscriber(long subId, boolean cfi) { if (!checkNotifyPermission("notifyCallForwardingChanged()")) { return; } if (VDBG) { - log("notifyCallForwardingChangedUsingSubId: subId=" + subId + log("notifyCallForwardingChangedForSubscriber: subId=" + subId + " cfi=" + cfi); } synchronized (mRecords) { @@ -805,10 +805,10 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyDataActivity(int state) { - notifyDataActivityUsingSubId(mDefaultSubId, state); + notifyDataActivityForSubscriber(mDefaultSubId, state); } - public void notifyDataActivityUsingSubId(long subId, int state) { + public void notifyDataActivityForSubscriber(long subId, int state) { if (!checkNotifyPermission("notifyDataActivity()" )) { return; } @@ -831,12 +831,12 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { public void notifyDataConnection(int state, boolean isDataConnectivityPossible, String reason, String apn, String apnType, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int networkType, boolean roaming) { - notifyDataConnectionUsingSubId(mDefaultSubId, state, isDataConnectivityPossible, + notifyDataConnectionForSubscriber(mDefaultSubId, state, isDataConnectivityPossible, reason, apn, apnType, linkProperties, networkCapabilities, networkType, roaming); } - public void notifyDataConnectionUsingSubId(long subId, int state, + public void notifyDataConnectionForSubscriber(long subId, int state, boolean isDataConnectivityPossible, String reason, String apn, String apnType, LinkProperties linkProperties, NetworkCapabilities networkCapabilities, int networkType, boolean roaming) { @@ -844,7 +844,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { return; } if (VDBG) { - log("notifyDataConnectionUsingSubId: subId=" + subId + log("notifyDataConnectionForSubscriber: subId=" + subId + " state=" + state + " isDataConnectivityPossible=" + isDataConnectivityPossible + " reason='" + reason + "' apn='" + apn + "' apnType=" + apnType + " networkType=" + networkType @@ -921,16 +921,16 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyDataConnectionFailed(String reason, String apnType) { - notifyDataConnectionFailedUsingSubId(mDefaultSubId, reason, apnType); + notifyDataConnectionFailedForSubscriber(mDefaultSubId, reason, apnType); } - public void notifyDataConnectionFailedUsingSubId(long subId, + public void notifyDataConnectionFailedForSubscriber(long subId, String reason, String apnType) { if (!checkNotifyPermission("notifyDataConnectionFailed()")) { return; } if (VDBG) { - log("notifyDataConnectionFailedUsingSubId: subId=" + subId + log("notifyDataConnectionFailedForSubscriber: subId=" + subId + " reason=" + reason + " apnType=" + apnType); } synchronized (mRecords) { @@ -954,17 +954,17 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub { } public void notifyCellLocation(Bundle cellLocation) { - notifyCellLocationUsingSubId(mDefaultSubId, cellLocation); + notifyCellLocationForSubscriber(mDefaultSubId, cellLocation); } - public void notifyCellLocationUsingSubId(long subId, Bundle cellLocation) { - log("notifyCellLocationUsingSubId: subId=" + subId + public void notifyCellLocationForSubscriber(long subId, Bundle cellLocation) { + log("notifyCellLocationForSubscriber: subId=" + subId + " cellLocation=" + cellLocation); if (!checkNotifyPermission("notifyCellLocation()")) { return; } if (VDBG) { - log("notifyCellLocationUsingSubId: subId=" + subId + log("notifyCellLocationForSubscriber: subId=" + subId + " cellLocation=" + cellLocation); } synchronized (mRecords) { diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java index 0bdb964..599c3b9 100755 --- a/services/core/java/com/android/server/am/ActiveServices.java +++ b/services/core/java/com/android/server/am/ActiveServices.java @@ -308,7 +308,14 @@ public final class ActiveServices { return new ComponentName("!", res.permission != null ? res.permission : "private to package"); } + ServiceRecord r = res.record; + + if (!mAm.getUserManagerLocked().exists(r.userId)) { + Slog.d(TAG, "Trying to start service with non-existent user! " + r.userId); + return null; + } + NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked( callingUid, r.packageName, service, service.getFlags(), null, r.userId); if (unscheduleServiceRestartLocked(r, callingUid, false)) { diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index a9a4732..2885b83 100755 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -180,6 +180,7 @@ import android.os.SystemClock; import android.os.SystemProperties; import android.os.UpdateLock; import android.os.UserHandle; +import android.os.UserManager; import android.provider.Settings; import android.text.format.DateUtils; import android.text.format.Time; @@ -888,6 +889,8 @@ public final class ActivityManagerService extends ActivityManagerNative boolean mProcessesReady = false; boolean mSystemReady = false; boolean mBooting = false; + boolean mCallFinishBooting = false; + boolean mBootAnimationComplete = false; boolean mWaitingUpdate = false; boolean mDidUpdate = false; boolean mOnBattery = false; @@ -1075,13 +1078,16 @@ public final class ActivityManagerService extends ActivityManagerNative /** * Runtime CPU use collection thread. This object's lock is used to - * protect all related state. + * perform synchronization with the thread (notifying it to run). */ final Thread mProcessCpuThread; /** - * Used to collect process stats when showing not responding dialog. - * Protected by mProcessCpuThread. + * Used to collect per-process CPU use for ANRs, battery stats, etc. + * Must acquire this object's lock when accessing it. + * NOTE: this lock will be held while doing long operations (trawling + * through all processes in /proc), so it should never be acquired by + * any critical paths such as when holding the main activity manager lock. */ final ProcessCpuTracker mProcessCpuTracker = new ProcessCpuTracker( MONITOR_THREAD_CPU_USAGE); @@ -1595,7 +1601,7 @@ public final class ActivityManagerService extends ActivityManagerNative infoMap.put(mi.pid, mi); } updateCpuStatsNow(); - synchronized (mProcessCpuThread) { + synchronized (mProcessCpuTracker) { final int N = mProcessCpuTracker.countStats(); for (int i=0; i<N; i++) { ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); @@ -1894,7 +1900,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (memInfo != null) { updateCpuStatsNow(); long nativeTotalPss = 0; - synchronized (mProcessCpuThread) { + synchronized (mProcessCpuTracker) { final int N = mProcessCpuTracker.countStats(); for (int j=0; j<N; j++) { ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(j); @@ -1912,7 +1918,7 @@ public final class ActivityManagerService extends ActivityManagerNative } } memInfo.readMemInfo(); - synchronized (this) { + synchronized (ActivityManagerService.this) { if (DEBUG_PSS) Slog.d(TAG, "Collected native and kernel memory in " + (SystemClock.uptimeMillis()-start) + "ms"); mProcessStats.addSysMemUsageLocked(memInfo.getCachedSizeKb(), @@ -2183,7 +2189,7 @@ public final class ActivityManagerService extends ActivityManagerNative return; } - synchronized (mActivityManagerService.mProcessCpuThread) { + synchronized (mActivityManagerService.mProcessCpuTracker) { pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentLoad()); pw.print(mActivityManagerService.mProcessCpuTracker.printCurrentState( SystemClock.uptimeMillis())); @@ -2379,7 +2385,7 @@ public final class ActivityManagerService extends ActivityManagerNative } void updateCpuStatsNow() { - synchronized (mProcessCpuThread) { + synchronized (mProcessCpuTracker) { mProcessCpuMutexFree.set(false); final long now = SystemClock.uptimeMillis(); boolean haveNewCpuStats = false; @@ -3364,6 +3370,16 @@ public final class ActivityManagerService extends ActivityManagerNative } } + void enforceShellRestriction(String restriction, int userHandle) { + if (Binder.getCallingUid() == Process.SHELL_UID) { + if (userHandle < 0 + || mUserManager.hasUserRestriction(restriction, userHandle)) { + throw new SecurityException("Shell does not have permission to access user " + + userHandle); + } + } + } + @Override public int getFrontActivityScreenCompatMode() { enforceNotIsolatedCaller("getFrontActivityScreenCompatMode"); @@ -5074,7 +5090,7 @@ public final class ActivityManagerService extends ActivityManagerNative String cpuInfo = null; if (MONITOR_CPU_USAGE) { updateCpuStatsNow(); - synchronized (mProcessCpuThread) { + synchronized (mProcessCpuTracker) { cpuInfo = mProcessCpuTracker.printCurrentState(anrTime); } info.append(processCpuTracker.printCurrentLoad()); @@ -6195,6 +6211,14 @@ public final class ActivityManagerService extends ActivityManagerNative } final void finishBooting() { + synchronized (this) { + if (!mBootAnimationComplete) { + mCallFinishBooting = true; + return; + } + mCallFinishBooting = false; + } + // Register receivers to handle package update events mPackageMonitor.register(mContext, Looper.getMainLooper(), false); @@ -6253,6 +6277,18 @@ public final class ActivityManagerService extends ActivityManagerNative } } + @Override + public void bootAnimationComplete() { + final boolean callFinishBooting; + synchronized (this) { + callFinishBooting = mCallFinishBooting; + mBootAnimationComplete = true; + } + if (callFinishBooting) { + finishBooting(); + } + } + final void ensureBootCompleted() { boolean booting; boolean enableScreen; @@ -7446,12 +7482,33 @@ public final class ActivityManagerService extends ActivityManagerNative // Does the caller have this permission on the URI? if (!checkHoldingPermissionsLocked(pm, pi, grantUri, callingUid, modeFlags)) { - // Right now, if you are not the original owner of the permission, - // you are not allowed to revoke it. - //if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) { - throw new SecurityException("Uid " + callingUid - + " does not have permission to uri " + grantUri); - //} + // Have they don't have direct access to the URI, then revoke any URI + // permissions that have been granted to them. + final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid); + if (perms != null) { + boolean persistChanged = false; + for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) { + final UriPermission perm = it.next(); + if (perm.uri.sourceUserId == grantUri.sourceUserId + && perm.uri.uri.isPathPrefixMatch(grantUri.uri)) { + if (DEBUG_URI_PERMISSION) + Slog.v(TAG, + "Revoking " + perm.targetUid + " permission to " + perm.uri); + persistChanged |= perm.revokeModes( + modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION); + if (perm.modeFlags == 0) { + it.remove(); + } + } + } + if (perms.isEmpty()) { + mGrantedUriPermissions.remove(callingUid); + } + if (persistChanged) { + schedulePersistUriGrants(); + } + } + return; } boolean persistChanged = false; @@ -9665,14 +9722,9 @@ public final class ActivityManagerService extends ActivityManagerNative long ident = 0; boolean clearedIdentity = false; userId = unsafeConvertIncomingUser(userId); - if (UserHandle.getUserId(callingUid) != userId) { - if (checkComponentPermission(INTERACT_ACROSS_USERS, callingPid, - callingUid, -1, true) == PackageManager.PERMISSION_GRANTED - || checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid, - callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) { - clearedIdentity = true; - ident = Binder.clearCallingIdentity(); - } + if (canClearIdentity(callingPid, callingUid, userId)) { + clearedIdentity = true; + ident = Binder.clearCallingIdentity(); } ContentProviderHolder holder = null; try { @@ -9700,6 +9752,19 @@ public final class ActivityManagerService extends ActivityManagerNative return null; } + private boolean canClearIdentity(int callingPid, int callingUid, int userId) { + if (UserHandle.getUserId(callingUid) == userId) { + return true; + } + if (checkComponentPermission(INTERACT_ACROSS_USERS, callingPid, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED + || checkComponentPermission(INTERACT_ACROSS_USERS_FULL, callingPid, + callingUid, -1, true) == PackageManager.PERMISSION_GRANTED) { + return true; + } + return false; + } + // ========================================================= // GLOBAL MANAGEMENT // ========================================================= @@ -13700,7 +13765,7 @@ public final class ActivityManagerService extends ActivityManagerNative findPid = Integer.parseInt(args[opti]); } catch (NumberFormatException e) { } - synchronized (mProcessCpuThread) { + synchronized (mProcessCpuTracker) { final int N = mProcessCpuTracker.countStats(); for (int i=0; i<N; i++) { ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); @@ -13862,7 +13927,7 @@ public final class ActivityManagerService extends ActivityManagerNative // If we are showing aggregations, also look for native processes to // include so that our aggregations are more accurate. updateCpuStatsNow(); - synchronized (mProcessCpuThread) { + synchronized (mProcessCpuTracker) { final int N = mProcessCpuTracker.countStats(); for (int i=0; i<N; i++) { ProcessCpuTracker.Stats st = mProcessCpuTracker.getStats(i); @@ -14548,6 +14613,14 @@ public final class ActivityManagerService extends ActivityManagerNative throw new IllegalArgumentException( "Call does not support special user #" + targetUserId); } + // Check shell permission + if (callingUid == Process.SHELL_UID && targetUserId >= UserHandle.USER_OWNER) { + if (mUserManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, + targetUserId)) { + throw new SecurityException("Shell does not have permission to access user " + + targetUserId + "\n " + Debug.getCallers(3)); + } + } return targetUserId; } @@ -14572,13 +14645,10 @@ public final class ActivityManagerService extends ActivityManagerNative } } else if ("system".equals(componentProcessName)) { result = true; - } else if (UserHandle.isSameApp(aInfo.uid, Process.PHONE_UID) - && (flags & ServiceInfo.FLAG_SINGLE_USER) != 0) { - // Phone app is allowed to export singleuser providers. - result = true; - } else { - // App with pre-defined UID, check if it's a persistent app - result = (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0; + } else if ((flags & ServiceInfo.FLAG_SINGLE_USER) != 0) { + // Phone app and persistent apps are allowed to export singleuser providers. + result = UserHandle.isSameApp(aInfo.uid, Process.PHONE_UID) + || (aInfo.flags & ApplicationInfo.FLAG_PERSISTENT) != 0; } if (DEBUG_MU) { Slog.v(TAG, "isSingleton(" + componentProcessName + ", " + aInfo @@ -14606,6 +14676,7 @@ public final class ActivityManagerService extends ActivityManagerNative Intent service, String resolvedType, IServiceConnection connection, int flags, int userId) { enforceNotIsolatedCaller("bindService"); + // Refuse possible leaked file descriptors if (service != null && service.hasFileDescriptors() == true) { throw new IllegalArgumentException("File descriptors passed in Intent"); @@ -15040,12 +15111,18 @@ public final class ActivityManagerService extends ActivityManagerNative } private List<ResolveInfo> collectReceiverComponents(Intent intent, String resolvedType, - int[] users) { + int callingUid, int[] users) { List<ResolveInfo> receivers = null; try { HashSet<ComponentName> singleUserReceivers = null; boolean scannedFirstReceivers = false; for (int user : users) { + // Skip users that have Shell restrictions + if (callingUid == Process.SHELL_UID + && getUserManagerLocked().hasUserRestriction( + UserManager.DISALLOW_DEBUGGING_FEATURES, user)) { + continue; + } List<ResolveInfo> newReceivers = AppGlobals.getPackageManager() .queryIntentReceivers(intent, resolvedType, STOCK_PM_FLAGS, user); if (user != 0 && newReceivers != null) { @@ -15134,7 +15211,6 @@ public final class ActivityManagerService extends ActivityManagerNative // Make sure that the user who is receiving this broadcast is started. // If not, we will just skip it. - if (userId != UserHandle.USER_ALL && mStartedUsers.get(userId) == null) { if (callingUid != Process.SYSTEM_UID || (intent.getFlags() & Intent.FLAG_RECEIVER_BOOT_UPGRADE) == 0) { @@ -15399,11 +15475,30 @@ public final class ActivityManagerService extends ActivityManagerNative // Need to resolve the intent to interested receivers... if ((intent.getFlags()&Intent.FLAG_RECEIVER_REGISTERED_ONLY) == 0) { - receivers = collectReceiverComponents(intent, resolvedType, users); + receivers = collectReceiverComponents(intent, resolvedType, callingUid, users); } if (intent.getComponent() == null) { - registeredReceivers = mReceiverResolver.queryIntent(intent, - resolvedType, false, userId); + if (userId == UserHandle.USER_ALL && callingUid == Process.SHELL_UID) { + // Query one target user at a time, excluding shell-restricted users + UserManagerService ums = getUserManagerLocked(); + for (int i = 0; i < users.length; i++) { + if (ums.hasUserRestriction( + UserManager.DISALLOW_DEBUGGING_FEATURES, users[i])) { + continue; + } + List<BroadcastFilter> registeredReceiversForUser = + mReceiverResolver.queryIntent(intent, + resolvedType, false, users[i]); + if (registeredReceivers == null) { + registeredReceivers = registeredReceiversForUser; + } else if (registeredReceiversForUser != null) { + registeredReceivers.addAll(registeredReceiversForUser); + } + } + } else { + registeredReceivers = mReceiverResolver.queryIntent(intent, + resolvedType, false, userId); + } } final boolean replacePending = @@ -15565,7 +15660,7 @@ public final class ActivityManagerService extends ActivityManagerNative enforceNotIsolatedCaller("broadcastIntent"); synchronized(this) { intent = verifyBroadcastLocked(intent); - + final ProcessRecord callerApp = getRecordForAppLocked(caller); final int callingPid = Binder.getCallingPid(); final int callingUid = Binder.getCallingUid(); @@ -17973,6 +18068,7 @@ public final class ActivityManagerService extends ActivityManagerNative @Override public boolean switchUser(final int userId) { + enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId); String userName; synchronized (this) { UserInfo userInfo = getUserManagerLocked().getUserInfo(userId); @@ -18414,6 +18510,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (userId <= 0) { throw new IllegalArgumentException("Can't stop primary user " + userId); } + enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, userId); synchronized (this) { return stopUserLocked(userId, callback); } diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java index bcf3b17..d71f94e 100755 --- a/services/core/java/com/android/server/am/ActivityStack.java +++ b/services/core/java/com/android/server/am/ActivityStack.java @@ -1042,11 +1042,8 @@ final class ActivityStack { if (prev.app != null && prev.cpuTimeAtResume > 0 && mService.mBatteryStatsService.isOnBattery()) { - long diff; - synchronized (mService.mProcessCpuThread) { - diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid) - - prev.cpuTimeAtResume; - } + long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid) + - prev.cpuTimeAtResume; if (diff > 0) { BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics(); synchronized (bsi) { @@ -1097,9 +1094,7 @@ final class ActivityStack { // TODO: To be more accurate, the mark should be before the onCreate, // not after the onResume. But for subsequent starts, onResume is fine. if (next.app != null) { - synchronized (mService.mProcessCpuThread) { - next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid); - } + next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid); } else { next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process } diff --git a/services/core/java/com/android/server/am/TaskPersister.java b/services/core/java/com/android/server/am/TaskPersister.java index 3cc406b..b21af48 100644 --- a/services/core/java/com/android/server/am/TaskPersister.java +++ b/services/core/java/com/android/server/am/TaskPersister.java @@ -347,6 +347,10 @@ public class TaskPersister { private static void removeObsoleteFiles(ArraySet<Integer> persistentTaskIds, File[] files) { if (DEBUG) Slog.d(TAG, "removeObsoleteFile: persistentTaskIds=" + persistentTaskIds + " files=" + files); + if (files == null) { + Slog.e(TAG, "File error accessing recents directory (too many files open?)."); + return; + } for (int fileNdx = 0; fileNdx < files.length; ++fileNdx) { File file = files[fileNdx]; String filename = file.getName(); diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index f6beb9a..9292d45 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -16,6 +16,7 @@ package com.android.server.content; +import android.Manifest; import android.accounts.Account; import android.accounts.AccountAndUser; import android.accounts.AccountManager; @@ -478,7 +479,7 @@ public class SyncManager { mContext.registerReceiverAsUser(mAccountsUpdatedReceiver, UserHandle.ALL, new IntentFilter(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION), - null, null); + Manifest.permission.ACCOUNT_MANAGER, null); } // Pick a random second in a day to seed all periodic syncs diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java index f6399a3..a6a9a89 100644 --- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java +++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java @@ -69,7 +69,7 @@ final class VirtualDisplayAdapter extends DisplayAdapter { try { if (projection != null) { - projection.addCallback(new MediaProjectionCallback(appToken)); + projection.registerCallback(new MediaProjectionCallback(appToken)); } appToken.linkToDeath(device, 0); } catch (RemoteException ex) { diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java index 38c6fb3..3d0fd3f 100644 --- a/services/core/java/com/android/server/hdmi/HdmiControlService.java +++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java @@ -43,7 +43,7 @@ import android.hardware.hdmi.IHdmiControlService; import android.hardware.hdmi.IHdmiDeviceEventListener; import android.hardware.hdmi.IHdmiHotplugEventListener; import android.hardware.hdmi.IHdmiInputChangeListener; -import android.hardware.hdmi.IHdmiMhlScratchpadCommandListener; +import android.hardware.hdmi.IHdmiMhlVendorCommandListener; import android.hardware.hdmi.IHdmiRecordListener; import android.hardware.hdmi.IHdmiSystemAudioModeChangeListener; import android.hardware.hdmi.IHdmiVendorCommandListener; @@ -247,16 +247,16 @@ public final class HdmiControlService extends SystemService { @GuardedBy("mLock") private boolean mMhlInputChangeEnabled; - // List of records for MHL Scratchpad command listener to handle the caller killed in action. + // List of records for MHL Vendor command listener to handle the caller killed in action. @GuardedBy("mLock") - private final ArrayList<HdmiMhlScratchpadCommandListenerRecord> - mScratchpadCommandListenerRecords = new ArrayList<>(); + private final ArrayList<HdmiMhlVendorCommandListenerRecord> + mMhlVendorCommandListenerRecords = new ArrayList<>(); @GuardedBy("mLock") private List<HdmiDeviceInfo> mMhlDevices; @Nullable - private HdmiMhlController mMhlController; + private HdmiMhlControllerStub mMhlController; // Last input port before switching to the MHL port. Should switch back to this port // when the mobile device sends the request one touch play with off. @@ -305,7 +305,7 @@ public final class HdmiControlService extends SystemService { Slog.i(TAG, "Device does not support HDMI-CEC."); } - mMhlController = HdmiMhlController.create(this); + mMhlController = HdmiMhlControllerStub.create(this); if (!mMhlController.isReady()) { Slog.i(TAG, "Device does not support MHL-control."); } @@ -928,16 +928,16 @@ public final class HdmiControlService extends SystemService { return mMhlDevices; } - private class HdmiMhlScratchpadCommandListenerRecord implements IBinder.DeathRecipient { - private final IHdmiMhlScratchpadCommandListener mListener; + private class HdmiMhlVendorCommandListenerRecord implements IBinder.DeathRecipient { + private final IHdmiMhlVendorCommandListener mListener; - public HdmiMhlScratchpadCommandListenerRecord(IHdmiMhlScratchpadCommandListener listener) { + public HdmiMhlVendorCommandListenerRecord(IHdmiMhlVendorCommandListener listener) { mListener = listener; } @Override public void binderDied() { - mScratchpadCommandListenerRecords.remove(this); + mMhlVendorCommandListenerRecords.remove(this); } } @@ -1403,7 +1403,7 @@ public final class HdmiControlService extends SystemService { } @Override - public void sendScratchpadCommand(final int portId, final int offset, final int length, + public void sendMhlVendorCommand(final int portId, final int offset, final int length, final byte[] data) { enforceAccessPermission(); runOnServiceThread(new Runnable() { @@ -1418,16 +1418,16 @@ public final class HdmiControlService extends SystemService { Slog.w(TAG, "Invalid port id:" + portId); return; } - mMhlController.sendScratchpadCommand(portId, offset, length, data); + mMhlController.sendVendorCommand(portId, offset, length, data); } }); } @Override - public void addHdmiMhlScratchpadCommandListener( - IHdmiMhlScratchpadCommandListener listener) { + public void addHdmiMhlVendorCommandListener( + IHdmiMhlVendorCommandListener listener) { enforceAccessPermission(); - HdmiControlService.this.addHdmiMhlScratchpadCommandListener(listener); + HdmiControlService.this.addHdmiMhlVendorCommandListener(listener); } @Override @@ -1880,9 +1880,9 @@ public final class HdmiControlService extends SystemService { } } - private void addHdmiMhlScratchpadCommandListener(IHdmiMhlScratchpadCommandListener listener) { - HdmiMhlScratchpadCommandListenerRecord record = - new HdmiMhlScratchpadCommandListenerRecord(listener); + private void addHdmiMhlVendorCommandListener(IHdmiMhlVendorCommandListener listener) { + HdmiMhlVendorCommandListenerRecord record = + new HdmiMhlVendorCommandListenerRecord(listener); try { listener.asBinder().linkToDeath(record, 0); } catch (RemoteException e) { @@ -1891,18 +1891,17 @@ public final class HdmiControlService extends SystemService { } synchronized (mLock) { - mScratchpadCommandListenerRecords.add(record); + mMhlVendorCommandListenerRecords.add(record); } } - void invokeScratchpadCommandListeners(int portId, int offest, int length, byte[] data) { + void invokeMhlVendorCommandListeners(int portId, int offest, int length, byte[] data) { synchronized (mLock) { - for (HdmiMhlScratchpadCommandListenerRecord record : - mScratchpadCommandListenerRecords) { + for (HdmiMhlVendorCommandListenerRecord record : mMhlVendorCommandListenerRecords) { try { record.mListener.onReceived(portId, offest, length, data); } catch (RemoteException e) { - Slog.e(TAG, "Failed to notify scratchpad command", e); + Slog.e(TAG, "Failed to notify MHL vendor command", e); } } } diff --git a/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java b/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java new file mode 100644 index 0000000..afe6e3c --- /dev/null +++ b/services/core/java/com/android/server/hdmi/HdmiMhlControllerStub.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.hdmi; + +import android.hardware.hdmi.HdmiPortInfo; +import android.util.SparseArray; + +import com.android.server.hdmi.HdmiControlService.SendMessageCallback; + +/** + * A handler class for MHL control command. It converts user's command into MHL command and pass it + * to MHL HAL layer. + * <p> + * It can be created only by {@link HdmiMhlControllerStub#create}. + */ +final class HdmiMhlControllerStub { + + private static final SparseArray<HdmiMhlLocalDevice> mLocalDevices = new SparseArray<>(); + private static final HdmiPortInfo[] EMPTY_PORT_INFO = new HdmiPortInfo[0]; + private static final int INVALID_MHL_VERSION = 0; + private static final int NO_SUPPORTED_FEATURES = 0; + private static final int INVALID_DEVICE_ROLES = 0; + + // Private constructor. Use HdmiMhlControllerStub.create(). + private HdmiMhlControllerStub(HdmiControlService service) { + } + + // Returns true if MHL controller is initialized and ready to use. + boolean isReady() { + return false; + } + + static HdmiMhlControllerStub create(HdmiControlService service) { + return new HdmiMhlControllerStub(service); + } + + HdmiPortInfo[] getPortInfos() { + return EMPTY_PORT_INFO; + } + + /** + * Return {@link HdmiMhlLocalDevice} matched with the given port id. + * + * @return null if has no matched port id + */ + HdmiMhlLocalDevice getLocalDevice(int portId) { + return null; + } + + /** + * Return {@link HdmiMhlLocalDevice} matched with the given device id. + * + * @return null if has no matched id + */ + HdmiMhlLocalDevice getLocalDeviceById(int deviceId) { + return null; + } + + SparseArray<HdmiMhlLocalDevice> getAllLocalDevices() { + return mLocalDevices; + } + + /** + * Remove a {@link HdmiMhlLocalDevice} matched with the given port id. + * + * @return removed {@link HdmiMhlLocalDevice}. Return null if no matched port id. + */ + HdmiMhlLocalDevice removeLocalDevice(int portId) { + return null; + } + + /** + * Add a new {@link HdmiMhlLocalDevice}. + * + * @return old {@link HdmiMhlLocalDevice} having same port id + */ + HdmiMhlLocalDevice addLocalDevice(HdmiMhlLocalDevice device) { + return null; + } + + void clearAllLocalDevices() { + } + + /** + * Send MHL MSC-Subcommand to the device connected to the given port. + */ + void sendSubcommand(int portId, HdmiMhlSubcommand command) { + } + + void sendSubcommand(final int portId, final HdmiMhlSubcommand command, + SendMessageCallback callback) { + } + + + void sendVendorCommand(int portId, int offset, int length, byte[] data) { + } + + void setOption(int flag, int value) { + } + + /** + * Get the MHL version supported by underlying hardware port of the given {@code portId}. + * MHL specification version 2.0 returns 0x20, 3.0 will return 0x30 respectively. + * The return value is stored in 'version'. Return INVALID_VERSION if MHL hardware layer + * is not ready. + */ + int getMhlVersion(int portId) { + return INVALID_MHL_VERSION; + } + + /** + * Get MHL version of a device which is connected to a port of the given {@code portId}. + * MHL specification version 2.0 returns 0x20, 3.0 will return 0x30 respectively. + * The return value is stored in 'version'. + */ + int getPeerMhlVersion(int portId) { + return INVALID_MHL_VERSION; + } + + /** + * Get the bit flags describing the features supported by the system. Refer to feature support + * flag register info in MHL specification. + */ + int getSupportedFeatures(int portId) { + return NO_SUPPORTED_FEATURES; + } + + /** + * Get the bit flags describing the roles which ECBUS device can play. Refer to the + * ECBUS_DEV_ROLES Register info MHL3.0 specification + */ + int getEcbusDeviceRoles(int portId) { + return INVALID_DEVICE_ROLES; + } +} diff --git a/services/core/java/com/android/server/job/JobServiceContext.java b/services/core/java/com/android/server/job/JobServiceContext.java index 344c57b..d0447bc 100644 --- a/services/core/java/com/android/server/job/JobServiceContext.java +++ b/services/core/java/com/android/server/job/JobServiceContext.java @@ -153,7 +153,8 @@ public class JobServiceContext extends IJobCallback.Stub implements ServiceConne } mRunningJob = job; - mParams = new JobParameters(job.getJobId(), job.getExtras(), this); + mParams = new JobParameters(this, job.getJobId(), job.getExtras(), + !job.isConstraintsSatisfied()); mExecutionStartTimeElapsed = SystemClock.elapsedRealtime(); mVerb = VERB_BINDING; diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index f562721..e3c55b6 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -195,16 +195,23 @@ public class JobStatus { } /** - * @return Whether or not this job is ready to run, based on its requirements. + * @return Whether or not this job is ready to run, based on its requirements. This is true if + * the constraints are satisfied <strong>or</strong> the deadline on the job has expired. */ public synchronized boolean isReady() { + return isConstraintsSatisfied() + || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get()); + } + + /** + * @return Whether the constraints set on this job are satisfied. + */ + public synchronized boolean isConstraintsSatisfied() { return (!hasChargingConstraint() || chargingConstraintSatisfied.get()) && (!hasTimingDelayConstraint() || timeDelayConstraintSatisfied.get()) && (!hasConnectivityConstraint() || connectivityConstraintSatisfied.get()) && (!hasUnmeteredConstraint() || unmeteredConstraintSatisfied.get()) - && (!hasIdleConstraint() || idleConstraintSatisfied.get()) - // Also ready if the deadline has expired - special case. - || (hasDeadlineConstraint() && deadlineConstraintSatisfied.get()); + && (!hasIdleConstraint() || idleConstraintSatisfied.get()); } public boolean matches(int uid, int jobId) { diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java index 8ec9b25..8a1f3ad 100644 --- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java +++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java @@ -389,7 +389,7 @@ public final class MediaProjectionManagerService extends SystemService throw new IllegalStateException( "Cannot start already started MediaProjection"); } - addCallback(callback); + registerCallback(callback); try { mToken = callback.asBinder(); mDeathEater = new IBinder.DeathRecipient() { @@ -424,7 +424,7 @@ public final class MediaProjectionManagerService extends SystemService } @Override - public void addCallback(IMediaProjectionCallback callback) { + public void registerCallback(IMediaProjectionCallback callback) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); } @@ -432,7 +432,7 @@ public final class MediaProjectionManagerService extends SystemService } @Override - public void removeCallback(IMediaProjectionCallback callback) { + public void unregisterCallback(IMediaProjectionCallback callback) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); } diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 9e5fa41..cf19416 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -433,14 +433,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // listen for configured wifi networks to be removed final IntentFilter wifiConfigFilter = new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION); - mContext.registerReceiver( - mWifiConfigReceiver, wifiConfigFilter, CONNECTIVITY_INTERNAL, mHandler); + mContext.registerReceiver(mWifiConfigReceiver, wifiConfigFilter, null, mHandler); // listen for wifi state changes to catch metered hint final IntentFilter wifiStateFilter = new IntentFilter( WifiManager.NETWORK_STATE_CHANGED_ACTION); - mContext.registerReceiver( - mWifiStateReceiver, wifiStateFilter, CONNECTIVITY_INTERNAL, mHandler); + mContext.registerReceiver(mWifiStateReceiver, wifiStateFilter, null, mHandler); } diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index f995dee..b5aa4d8 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -318,7 +318,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { // watch for tethering changes final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED); - mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler); + mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler); // listen for periodic polling events final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index a56f783..c09eff8 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -49,6 +49,7 @@ import android.content.res.Resources; import android.database.ContentObserver; import android.media.AudioAttributes; import android.media.AudioManager; +import android.media.AudioSystem; import android.media.IRingtonePlayer; import android.net.Uri; import android.os.Binder; @@ -1945,14 +1946,19 @@ public class NotificationManagerService extends SystemService { } private static AudioAttributes audioAttributesForNotification(Notification n) { - if (n.audioAttributes != null - && !Notification.AUDIO_ATTRIBUTES_DEFAULT.equals(n.audioAttributes)) { + if (n.audioAttributes != null) { return n.audioAttributes; + } else if (n.audioStreamType >= 0 && n.audioStreamType < AudioSystem.getNumStreamTypes()) { + // the stream type is valid, use it + return new AudioAttributes.Builder() + .setInternalLegacyStreamType(n.audioStreamType) + .build(); + } else if (n.audioStreamType == AudioSystem.STREAM_DEFAULT) { + return Notification.AUDIO_ATTRIBUTES_DEFAULT; + } else { + Log.w(TAG, String.format("Invalid stream type: %d", n.audioStreamType)); + return Notification.AUDIO_ATTRIBUTES_DEFAULT; } - return new AudioAttributes.Builder() - .setLegacyStreamType(n.audioStreamType) - .setUsage(AudioAttributes.usageForLegacyStreamType(n.audioStreamType)) - .build(); } void showNextToastLocked() { @@ -2965,15 +2971,18 @@ public class NotificationManagerService extends SystemService { */ private static final class StatusBarNotificationHolder extends IStatusBarNotificationHolder.Stub { - private final StatusBarNotification mValue; + private StatusBarNotification mValue; public StatusBarNotificationHolder(StatusBarNotification value) { mValue = value; } + /** Get the held value and clear it. This function should only be called once per holder */ @Override public StatusBarNotification get() { - return mValue; + StatusBarNotification value = mValue; + mValue = null; + return value; } } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 5639dad..41d7fa8 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -301,8 +301,8 @@ public class ZenModeHelper { final int ringerMode = mAudioManager.getRingerMode(); int newZen = -1; if (ringerMode == AudioManager.RINGER_MODE_SILENT) { - if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS) { - newZen = Global.ZEN_MODE_NO_INTERRUPTIONS; + if (mZenMode == Global.ZEN_MODE_OFF) { + newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; } } else if ((ringerMode == AudioManager.RINGER_MODE_NORMAL || ringerMode == AudioManager.RINGER_MODE_VIBRATE) diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java index b7b1c23..dcc4f8d 100644 --- a/services/core/java/com/android/server/pm/LauncherAppsService.java +++ b/services/core/java/com/android/server/pm/LauncherAppsService.java @@ -199,8 +199,7 @@ public class LauncherAppsService extends SystemService { mainIntent.setPackage(packageName); long ident = Binder.clearCallingIdentity(); try { - List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, - PackageManager.NO_CROSS_PROFILE, // We only want the apps for this user + List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 0 /* flags */, user.getIdentifier()); return apps; } finally { @@ -288,8 +287,7 @@ public class LauncherAppsService extends SystemService { // as calling startActivityAsUser ignores the category and just // resolves based on the component if present. List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent, - PackageManager.NO_CROSS_PROFILE, // We only want the apps for this user - user.getIdentifier()); + 0 /* flags */, user.getIdentifier()); final int size = apps.size(); for (int i = 0; i < size; ++i) { ActivityInfo activityInfo = apps.get(i).activityInfo; diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 496c136..ed678d2 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -446,7 +446,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { private int createSessionInternal(SessionParams params, String installerPackageName, int userId) throws IOException { final int callingUid = Binder.getCallingUid(); - mPm.enforceCrossUserPermission(callingUid, userId, true, "createSession"); + mPm.enforceCrossUserPermission(callingUid, userId, true, false, "createSession"); if (mPm.isUserRestricted(UserHandle.getUserId(callingUid), UserManager.DISALLOW_INSTALL_APPS)) { @@ -654,7 +654,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { @Override public List<SessionInfo> getAllSessions(int userId) { - mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getAllSessions"); + mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getAllSessions"); final List<SessionInfo> result = new ArrayList<>(); synchronized (mSessions) { @@ -670,7 +670,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { @Override public List<SessionInfo> getMySessions(String installerPackageName, int userId) { - mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "getMySessions"); + mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "getMySessions"); mAppOps.checkPackage(Binder.getCallingUid(), installerPackageName); final List<SessionInfo> result = new ArrayList<>(); @@ -688,7 +688,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { @Override public void uninstall(String packageName, int flags, IntentSender statusReceiver, int userId) { - mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "uninstall"); + mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "uninstall"); final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, statusReceiver, packageName); @@ -717,7 +717,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub { @Override public void registerCallback(IPackageInstallerCallback callback, int userId) { - mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "registerCallback"); + mPm.enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "registerCallback"); mCallbacks.register(callback, userId); } diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index adca46a..06f550d 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -579,8 +579,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { apk = PackageParser.parseApkLite(file, PackageParser.PARSE_COLLECT_CERTIFICATES); } catch (PackageParserException e) { - throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, - "Failed to parse " + file + ": " + e); + throw PackageManagerException.from(e); } if (!stagedSplits.add(apk.splitName)) { @@ -646,8 +645,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { existingBase = PackageParser.parseApkLite(new File(app.getBaseCodePath()), PackageParser.PARSE_COLLECT_CERTIFICATES); } catch (PackageParserException e) { - throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, - "Failed to parse existing package " + app.getCodePath() + ": " + e); + throw PackageManagerException.from(e); } assertApkConsistent("Existing base", existingBase); @@ -699,8 +697,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { try { baseApk = PackageParser.parseApkLite(mResolvedBaseFile, 0); } catch (PackageParserException e) { - throw new PackageManagerException(INSTALL_FAILED_INVALID_APK, - "Failed to parse base package " + mResolvedBaseFile + ": " + e); + throw PackageManagerException.from(e); } final List<String> splitPaths = new ArrayList<>(); diff --git a/services/core/java/com/android/server/pm/PackageManagerException.java b/services/core/java/com/android/server/pm/PackageManagerException.java index 0cbdcdc..a41636e 100644 --- a/services/core/java/com/android/server/pm/PackageManagerException.java +++ b/services/core/java/com/android/server/pm/PackageManagerException.java @@ -16,6 +16,8 @@ package com.android.server.pm; +import android.content.pm.PackageParser.PackageParserException; + /** {@hide} */ public class PackageManagerException extends Exception { public final int error; @@ -29,4 +31,9 @@ public class PackageManagerException extends Exception { super(detailMessage, throwable); this.error = error; } + + public static PackageManagerException from(PackageParserException e) + throws PackageManagerException { + throw new PackageManagerException(e.error, e.getMessage(), e.getCause()); + } } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7b4270b..3e5d514 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -138,6 +138,7 @@ import android.os.Bundle; import android.os.Environment; import android.os.Environment.UserEnvironment; import android.os.storage.StorageManager; +import android.os.Debug; import android.os.FileUtils; import android.os.Handler; import android.os.IBinder; @@ -1845,7 +1846,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public boolean isPackageAvailable(String packageName, int userId) { if (!sUserManager.exists(userId)) return false; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "is package available"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "is package available"); synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); if (p != null) { @@ -1864,7 +1865,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public PackageInfo getPackageInfo(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package info"); // reader synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); @@ -1909,7 +1910,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public int getPackageUid(String packageName, int userId) { if (!sUserManager.exists(userId)) return -1; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get package uid"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get package uid"); // reader synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); @@ -2059,7 +2060,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get application info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get application info"); // writer synchronized (mPackages) { PackageParser.Package p = mPackages.get(packageName); @@ -2150,7 +2151,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get activity info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get activity info"); synchronized (mPackages) { PackageParser.Activity a = mActivities.mActivities.get(component); @@ -2189,7 +2190,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get receiver info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get receiver info"); synchronized (mPackages) { PackageParser.Activity a = mReceivers.mActivities.get(component); if (DEBUG_PACKAGE_INFO) Log.v( @@ -2207,7 +2208,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public ServiceInfo getServiceInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get service info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get service info"); synchronized (mPackages) { PackageParser.Service s = mServices.mServices.get(component); if (DEBUG_PACKAGE_INFO) Log.v( @@ -2225,7 +2226,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public ProviderInfo getProviderInfo(ComponentName component, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get provider info"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "get provider info"); synchronized (mPackages) { PackageParser.Provider p = mProviders.mProviders.get(component); if (DEBUG_PACKAGE_INFO) Log.v( @@ -2329,13 +2330,17 @@ public class PackageManagerService extends IPackageManager.Stub { /** * Checks if the request is from the system or an app that has INTERACT_ACROSS_USERS * or INTERACT_ACROSS_USERS_FULL permissions, if the userid is not for the caller. + * @param checkShell TODO(yamasani): * @param message the message to log on security exception */ void enforceCrossUserPermission(int callingUid, int userId, boolean requireFullPermission, - String message) { + boolean checkShell, String message) { if (userId < 0) { throw new IllegalArgumentException("Invalid userId " + userId); } + if (checkShell) { + enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, userId); + } if (userId == UserHandle.getUserId(callingUid)) return; if (callingUid != Process.SYSTEM_UID && callingUid != 0) { if (requireFullPermission) { @@ -2353,6 +2358,19 @@ public class PackageManagerService extends IPackageManager.Stub { } } + void enforceShellRestriction(String restriction, int callingUid, int userHandle) { + if (callingUid == Process.SHELL_UID) { + if (userHandle >= 0 + && sUserManager.hasUserRestriction(restriction, userHandle)) { + throw new SecurityException("Shell does not have permission to access user " + + userHandle); + } else if (userHandle < 0) { + Slog.e(TAG, "Unable to check shell permission for user " + userHandle + "\n\t" + + Debug.getCallers(3)); + } + } + } + private BasePermission findPermissionTreeLP(String permName) { for(BasePermission bp : mSettings.mPermissionTrees.values()) { if (permName.startsWith(bp.name) && @@ -2876,7 +2894,7 @@ public class PackageManagerService extends IPackageManager.Stub { public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return null; - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "resolve intent"); List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId); return chooseBestActivity(intent, resolvedType, flags, query, userId); } @@ -3183,24 +3201,6 @@ public class PackageManagerService extends IPackageManager.Stub { if (matches.get(i).getTargetUserId() == targetUserId) return true; } } - ArrayList<String> packageNames = null; - SparseArray<ArrayList<String>> fromSource = - mSettings.mCrossProfilePackageInfo.get(sourceUserId); - if (fromSource != null) { - packageNames = fromSource.get(targetUserId); - if (packageNames != null) { - // We need the package name, so we try to resolve with the loosest flags possible - List<ResolveInfo> resolveInfos = mActivities.queryIntent(intent, resolvedType, - PackageManager.GET_UNINSTALLED_PACKAGES, targetUserId); - int count = resolveInfos.size(); - for (int i = 0; i < count; i++) { - ResolveInfo resolveInfo = resolveInfos.get(i); - if (packageNames.contains(resolveInfo.activityInfo.packageName)) { - return true; - } - } - } - } return false; } @@ -3217,7 +3217,7 @@ public class PackageManagerService extends IPackageManager.Stub { public List<ResolveInfo> queryIntentActivities(Intent intent, String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return Collections.emptyList(); - enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "query intent activities"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, false, false, "query intent activities"); ComponentName comp = intent.getComponent(); if (comp == null) { if (intent.getSelector() != null) { @@ -3240,32 +3240,21 @@ public class PackageManagerService extends IPackageManager.Stub { // reader synchronized (mPackages) { final String pkgName = intent.getPackage(); - boolean queryCrossProfile = (flags & PackageManager.NO_CROSS_PROFILE) == 0; if (pkgName == null) { - ResolveInfo resolveInfo = null; - if (queryCrossProfile) { - // Check if the intent needs to be forwarded to another user for this package - ArrayList<ResolveInfo> crossProfileResult = - queryIntentActivitiesCrossProfilePackage( - intent, resolvedType, flags, userId); - if (!crossProfileResult.isEmpty()) { - // Skip the current profile - return crossProfileResult; - } - List<CrossProfileIntentFilter> matchingFilters = - getMatchingCrossProfileIntentFilters(intent, resolvedType, userId); - // Check for results that need to skip the current profile. - resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent, - resolvedType, flags, userId); - if (resolveInfo != null) { - List<ResolveInfo> result = new ArrayList<ResolveInfo>(1); - result.add(resolveInfo); - return result; - } - // Check for cross profile results. - resolveInfo = queryCrossProfileIntents( - matchingFilters, intent, resolvedType, flags, userId); + List<CrossProfileIntentFilter> matchingFilters = + getMatchingCrossProfileIntentFilters(intent, resolvedType, userId); + // Check for results that need to skip the current profile. + ResolveInfo resolveInfo = querySkipCurrentProfileIntents(matchingFilters, intent, + resolvedType, flags, userId); + if (resolveInfo != null) { + List<ResolveInfo> result = new ArrayList<ResolveInfo>(1); + result.add(resolveInfo); + return result; } + // Check for cross profile results. + resolveInfo = queryCrossProfileIntents( + matchingFilters, intent, resolvedType, flags, userId); + // Check for results in the current profile. List<ResolveInfo> result = mActivities.queryIntent( intent, resolvedType, flags, userId); @@ -3277,15 +3266,6 @@ public class PackageManagerService extends IPackageManager.Stub { } final PackageParser.Package pkg = mPackages.get(pkgName); if (pkg != null) { - if (queryCrossProfile) { - ArrayList<ResolveInfo> crossProfileResult = - queryIntentActivitiesCrossProfilePackage( - intent, resolvedType, flags, userId, pkg, pkgName); - if (!crossProfileResult.isEmpty()) { - // Skip the current profile - return crossProfileResult; - } - } return mActivities.queryIntentForPackage(intent, resolvedType, flags, pkg.activities, userId); } @@ -3314,56 +3294,6 @@ public class PackageManagerService extends IPackageManager.Stub { return null; } - private ArrayList<ResolveInfo> queryIntentActivitiesCrossProfilePackage( - Intent intent, String resolvedType, int flags, int userId) { - ArrayList<ResolveInfo> matchingResolveInfos = new ArrayList<ResolveInfo>(); - SparseArray<ArrayList<String>> sourceForwardingInfo = - mSettings.mCrossProfilePackageInfo.get(userId); - if (sourceForwardingInfo != null) { - int NI = sourceForwardingInfo.size(); - for (int i = 0; i < NI; i++) { - int targetUserId = sourceForwardingInfo.keyAt(i); - ArrayList<String> packageNames = sourceForwardingInfo.valueAt(i); - List<ResolveInfo> resolveInfos = mActivities.queryIntent( - intent, resolvedType, flags, targetUserId); - int NJ = resolveInfos.size(); - for (int j = 0; j < NJ; j++) { - ResolveInfo resolveInfo = resolveInfos.get(j); - if (packageNames.contains(resolveInfo.activityInfo.packageName)) { - matchingResolveInfos.add(createForwardingResolveInfo( - resolveInfo.filter, userId, targetUserId)); - } - } - } - } - return matchingResolveInfos; - } - - private ArrayList<ResolveInfo> queryIntentActivitiesCrossProfilePackage( - Intent intent, String resolvedType, int flags, int userId, PackageParser.Package pkg, - String packageName) { - ArrayList<ResolveInfo> matchingResolveInfos = new ArrayList<ResolveInfo>(); - SparseArray<ArrayList<String>> sourceForwardingInfo = - mSettings.mCrossProfilePackageInfo.get(userId); - if (sourceForwardingInfo != null) { - int NI = sourceForwardingInfo.size(); - for (int i = 0; i < NI; i++) { - int targetUserId = sourceForwardingInfo.keyAt(i); - if (sourceForwardingInfo.valueAt(i).contains(packageName)) { - List<ResolveInfo> resolveInfos = mActivities.queryIntentForPackage( - intent, resolvedType, flags, pkg.activities, targetUserId); - int NJ = resolveInfos.size(); - for (int j = 0; j < NJ; j++) { - ResolveInfo resolveInfo = resolveInfos.get(j); - matchingResolveInfos.add(createForwardingResolveInfo( - resolveInfo.filter, userId, targetUserId)); - } - } - } - } - return matchingResolveInfos; - } - // Return matching ResolveInfo if any for skip current profile intent filters. private ResolveInfo queryCrossProfileIntents( List<CrossProfileIntentFilter> matchingFilters, Intent intent, String resolvedType, @@ -3434,7 +3364,7 @@ public class PackageManagerService extends IPackageManager.Stub { String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return Collections.emptyList(); enforceCrossUserPermission(Binder.getCallingUid(), userId, false, - "query intent activity options"); + false, "query intent activity options"); final String resultsAction = intent.getAction(); List<ResolveInfo> results = queryIntentActivities(intent, resolvedType, flags @@ -3730,7 +3660,7 @@ public class PackageManagerService extends IPackageManager.Stub { public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) { final boolean listUninstalled = (flags & PackageManager.GET_UNINSTALLED_PACKAGES) != 0; - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "get installed packages"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "get installed packages"); // writer synchronized (mPackages) { @@ -4165,8 +4095,7 @@ public class PackageManagerService extends IPackageManager.Stub { pp.collectCertificates(pkg, parseFlags); pp.collectManifestDigest(pkg); } catch (PackageParserException e) { - throw new PackageManagerException(e.error, "Failed to collect certificates for " - + pkg.packageName + ": " + e.getMessage()); + throw PackageManagerException.from(e); } } @@ -4191,8 +4120,7 @@ public class PackageManagerService extends IPackageManager.Stub { try { pkg = pp.parsePackage(scanFile, parseFlags); } catch (PackageParserException e) { - throw new PackageManagerException(e.error, - "Failed to scan " + scanFile + ": " + e.getMessage()); + throw PackageManagerException.from(e); } PackageSetting ps = null; @@ -7750,7 +7678,7 @@ public class PackageManagerService extends IPackageManager.Stub { final File originFile = new File(originPath); final int uid = Binder.getCallingUid(); - if (isUserRestricted(UserHandle.getUserId(uid), UserManager.DISALLOW_INSTALL_APPS)) { + if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { try { if (observer != null) { observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null); @@ -7838,11 +7766,8 @@ public class PackageManagerService extends IPackageManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); PackageSetting pkgSetting; final int uid = Binder.getCallingUid(); - if (UserHandle.getUserId(uid) != userId) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, - "setApplicationHiddenSetting for user " + userId); - } + enforceCrossUserPermission(uid, userId, true, true, + "setApplicationHiddenSetting for user " + userId); if (hidden && isPackageDeviceAdmin(packageName, userId)) { Slog.w(TAG, "Not hiding package " + packageName + ": has active device admin"); @@ -7901,7 +7826,7 @@ public class PackageManagerService extends IPackageManager.Stub { public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); enforceCrossUserPermission(Binder.getCallingUid(), userId, true, - "getApplicationHidden for user " + userId); + false, "getApplicationHidden for user " + userId); PackageSetting pkgSetting; long callingId = Binder.clearCallingIdentity(); try { @@ -7927,7 +7852,8 @@ public class PackageManagerService extends IPackageManager.Stub { null); PackageSetting pkgSetting; final int uid = Binder.getCallingUid(); - enforceCrossUserPermission(uid, userId, true, "installExistingPackage for user " + userId); + enforceCrossUserPermission(uid, userId, true, true, "installExistingPackage for user " + + userId); if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) { return PackageManager.INSTALL_FAILED_USER_RESTRICTED; } @@ -11051,7 +10977,7 @@ public class PackageManagerService extends IPackageManager.Stub { final IPackageDataObserver observer, final int userId) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.CLEAR_APP_USER_DATA, null); - enforceCrossUserPermission(Binder.getCallingUid(), userId, true, "clear application data"); + enforceCrossUserPermission(Binder.getCallingUid(), userId, true, false, "clear application data"); // Queue up an async operation since the package deletion may take a little while. mHandler.post(new Runnable() { public void run() { @@ -11351,7 +11277,7 @@ public class PackageManagerService extends IPackageManager.Stub { String opname) { // writer int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, true, "add preferred activity"); + enforceCrossUserPermission(callingUid, userId, true, false, "add preferred activity"); if (filter.countActions() == 0) { Slog.w(TAG, "Cannot set a preferred activity with no filter actions"); return; @@ -11396,7 +11322,7 @@ public class PackageManagerService extends IPackageManager.Stub { } final int callingUid = Binder.getCallingUid(); - enforceCrossUserPermission(callingUid, userId, true, "replace preferred activity"); + enforceCrossUserPermission(callingUid, userId, true, false, "replace preferred activity"); synchronized (mPackages) { if (mContext.checkCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS) @@ -11537,6 +11463,7 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public void resetPreferredActivities(int userId) { + /* TODO: Actually use userId. Why is it being passed in? */ mContext.enforceCallingOrSelfPermission( android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null); // writer @@ -11651,6 +11578,7 @@ public class PackageManagerService extends IPackageManager.Stub { android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); int callingUid = Binder.getCallingUid(); enforceOwnerRights(ownerPackage, ownerUserId, callingUid); + enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId); if (intentFilter.countActions() == 0) { Slog.w(TAG, "Cannot set a crossProfile intent filter with no filter actions"); return; @@ -11664,30 +11592,13 @@ public class PackageManagerService extends IPackageManager.Stub { } @Override - public void addCrossProfileIntentsForPackage(String packageName, - int sourceUserId, int targetUserId) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); - mSettings.addCrossProfilePackage(packageName, sourceUserId, targetUserId); - mSettings.writePackageRestrictionsLPr(sourceUserId); - } - - @Override - public void removeCrossProfileIntentsForPackage(String packageName, - int sourceUserId, int targetUserId) { - mContext.enforceCallingOrSelfPermission( - android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); - mSettings.removeCrossProfilePackage(packageName, sourceUserId, targetUserId); - mSettings.writePackageRestrictionsLPr(sourceUserId); - } - - @Override public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage, int ownerUserId) { mContext.enforceCallingOrSelfPermission( android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null); int callingUid = Binder.getCallingUid(); enforceOwnerRights(ownerPackage, ownerUserId, callingUid); + enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId); int callingUserId = UserHandle.getUserId(callingUid); synchronized (mPackages) { CrossProfileIntentResolver resolver = @@ -11782,7 +11693,7 @@ public class PackageManagerService extends IPackageManager.Stub { final int uid = Binder.getCallingUid(); final int permission = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); - enforceCrossUserPermission(uid, userId, false, "set enabled"); + enforceCrossUserPermission(uid, userId, false, true, "set enabled"); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); boolean sendNow = false; boolean isApp = (className == null); @@ -11916,7 +11827,7 @@ public class PackageManagerService extends IPackageManager.Stub { final int permission = mContext.checkCallingOrSelfPermission( android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE); final boolean allowedByPermission = (permission == PackageManager.PERMISSION_GRANTED); - enforceCrossUserPermission(uid, userId, true, "stop package"); + enforceCrossUserPermission(uid, userId, true, true, "stop package"); // writer synchronized (mPackages) { if (mSettings.setPackageStoppedStateLPw(packageName, stopped, allowedByPermission, @@ -11938,7 +11849,7 @@ public class PackageManagerService extends IPackageManager.Stub { public int getApplicationEnabledSetting(String packageName, int userId) { if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED; int uid = Binder.getCallingUid(); - enforceCrossUserPermission(uid, userId, false, "get enabled"); + enforceCrossUserPermission(uid, userId, false, false, "get enabled"); // reader synchronized (mPackages) { return mSettings.getApplicationEnabledSettingLPr(packageName, userId); @@ -11949,7 +11860,7 @@ public class PackageManagerService extends IPackageManager.Stub { public int getComponentEnabledSetting(ComponentName componentName, int userId) { if (!sUserManager.exists(userId)) return COMPONENT_ENABLED_STATE_DISABLED; int uid = Binder.getCallingUid(); - enforceCrossUserPermission(uid, userId, false, "get component enabled"); + enforceCrossUserPermission(uid, userId, false, false, "get component enabled"); // reader synchronized (mPackages) { return mSettings.getComponentEnabledSettingLPr(componentName, userId); diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index c1caeac..0dadee7 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -138,10 +138,6 @@ final class Settings { "persistent-preferred-activities"; static final String TAG_CROSS_PROFILE_INTENT_FILTERS = "crossProfile-intent-filters"; - private static final String TAG_CROSS_PROFILE_PACKAGE_INFO = "cross-profile-package-info"; - private static final String CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID = "target-user-id"; - private static final String CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME = "package-name"; - private static final String CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME = "value"; private static final String ATTR_NAME = "name"; private static final String ATTR_USER = "user"; @@ -249,23 +245,15 @@ final class Settings { */ private final ArrayList<PendingPackage> mPendingPackages = new ArrayList<PendingPackage>(); - private final Context mContext; - private final File mSystemDir; public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages); - // A mapping of (sourceUserId, targetUserId, packageNames) for forwarding the intents of a - // package. - final SparseArray<SparseArray<ArrayList<String>>> - mCrossProfilePackageInfo = new SparseArray<SparseArray<ArrayList<String>>>(); - Settings(Context context) { this(context, Environment.getDataDirectory()); } Settings(Context context, File dataDir) { - mContext = context; mSystemDir = new File(dataDir, "system"); mSystemDir.mkdirs(); FileUtils.setPermissions(mSystemDir.toString(), @@ -282,47 +270,6 @@ final class Settings { mBackupStoppedPackagesFilename = new File(mSystemDir, "packages-stopped-backup.xml"); } - public void addCrossProfilePackage( - String packageName, int sourceUserId, int targetUserId) { - synchronized(mCrossProfilePackageInfo) { - SparseArray<ArrayList<String>> sourceForwardingInfo = - mCrossProfilePackageInfo.get(sourceUserId); - if (sourceForwardingInfo == null) { - sourceForwardingInfo = new SparseArray<ArrayList<String>>(); - mCrossProfilePackageInfo.put(sourceUserId, sourceForwardingInfo); - } - ArrayList<String> packageNames = sourceForwardingInfo.get(targetUserId); - if (packageNames == null) { - packageNames = new ArrayList<String>(); - sourceForwardingInfo.put(targetUserId, packageNames); - } - if (!packageNames.contains(packageName)) { - packageNames.add(packageName); - } - } - } - - public void removeCrossProfilePackage( - String packageName, int sourceUserId, int targetUserId) { - synchronized(mCrossProfilePackageInfo) { - SparseArray<ArrayList<String>> sourceForwardingInfo = - mCrossProfilePackageInfo.get(sourceUserId); - if (sourceForwardingInfo == null) { - return; - } - ArrayList<String> packageNames = sourceForwardingInfo.get(targetUserId); - if (packageNames != null && packageNames.contains(packageName)) { - packageNames.remove(packageName); - if (packageNames.isEmpty()) { - sourceForwardingInfo.remove(targetUserId); - if (sourceForwardingInfo.size() == 0) { - mCrossProfilePackageInfo.remove(sourceUserId); - } - } - } - } - } - PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage, String realName, SharedUserSetting sharedUser, File codePath, File resourcePath, String legacyNativeLibraryPathString, String primaryCpuAbi, String secondaryCpuAbi, @@ -517,6 +464,7 @@ final class Settings { int vc, int pkgFlags, UserHandle installUser, boolean add, boolean allowInstall) { PackageSetting p = mPackages.get(name); + UserManagerService userManager = UserManagerService.getInstance(); if (p != null) { p.primaryCpuAbiString = primaryCpuAbiString; p.secondaryCpuAbiString = secondaryCpuAbiString; @@ -594,6 +542,7 @@ final class Settings { Slog.i(PackageManagerService.TAG, "Stopping package " + name, e); } List<UserInfo> users = getAllUsers(); + final int installUserId = installUser != null ? installUser.getIdentifier() : 0; if (users != null && allowInstall) { for (UserInfo user : users) { // By default we consider this app to be installed @@ -603,8 +552,9 @@ final class Settings { // asked to install for all users, or this is the // user we are installing for. final boolean installed = installUser == null - || installUser.getIdentifier() == UserHandle.USER_ALL - || installUser.getIdentifier() == user.id; + || (installUserId == UserHandle.USER_ALL + && !isAdbInstallDisallowed(userManager, user.id)) + || installUserId == user.id; p.setUserState(user.id, COMPONENT_ENABLED_STATE_DEFAULT, installed, true, // stopped, @@ -670,7 +620,8 @@ final class Settings { List<UserInfo> users = getAllUsers(); if (users != null) { for (UserInfo user : users) { - if (installUser.getIdentifier() == UserHandle.USER_ALL + if ((installUser.getIdentifier() == UserHandle.USER_ALL + && !isAdbInstallDisallowed(userManager, user.id)) || installUser.getIdentifier() == user.id) { boolean installed = p.getInstalled(user.id); if (!installed) { @@ -685,6 +636,11 @@ final class Settings { return p; } + boolean isAdbInstallDisallowed(UserManagerService userManager, int userId) { + return userManager.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, + userId); + } + void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) { p.pkg = pkg; // pkg.mSetEnabled = p.getEnabled(userId); @@ -1068,68 +1024,6 @@ final class Settings { } } - private void readCrossProfilePackageInfoLPw(XmlPullParser parser, int userId) - throws XmlPullParserException, IOException { - int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - String tagName = parser.getName(); - if (tagName.equals(TAG_ITEM)) { - String targetUserIdString = parser.getAttributeValue(null, - CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID); - if (targetUserIdString == null) { - String msg = "Missing element under " + TAG +": " - + CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID + " at " + - parser.getPositionDescription(); - PackageManagerService.reportSettingsProblem(Log.WARN, msg); - continue; - } - int targetUserId = Integer.parseInt(targetUserIdString); - readCrossProfilePackageInfoForTargetLPw(parser, userId, targetUserId); - } else { - String msg = "Unknown element under " + TAG_CROSS_PROFILE_PACKAGE_INFO + ": " + - parser.getName(); - PackageManagerService.reportSettingsProblem(Log.WARN, msg); - XmlUtils.skipCurrentTag(parser); - } - } - } - - private void readCrossProfilePackageInfoForTargetLPw( - XmlPullParser parser, int sourceUserId, int targetUserId) - throws XmlPullParserException, IOException { - int outerDepth = parser.getDepth(); - int type; - while ((type = parser.next()) != XmlPullParser.END_DOCUMENT - && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) { - if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) { - continue; - } - String tagName = parser.getName(); - if (tagName.equals(CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME)) { - String packageName = parser.getAttributeValue( - null, CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME); - if (packageName == null) { - String msg = "Missing element under " + TAG +": " - + CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME + " at " + - parser.getPositionDescription(); - PackageManagerService.reportSettingsProblem(Log.WARN, msg); - continue; - } - addCrossProfilePackage(packageName, sourceUserId, targetUserId); - } else { - String msg = "Unknown element under " + TAG_ITEM + ": " + - parser.getName(); - PackageManagerService.reportSettingsProblem(Log.WARN, msg); - XmlUtils.skipCurrentTag(parser); - } - } - } - void readPackageRestrictionsLPr(int userId) { if (DEBUG_MU) { Log.i(TAG, "Reading package restrictions for user=" + userId); @@ -1271,8 +1165,6 @@ final class Settings { readPersistentPreferredActivitiesLPw(parser, userId); } else if (tagName.equals(TAG_CROSS_PROFILE_INTENT_FILTERS)) { readCrossProfileIntentFiltersLPw(parser, userId); - } else if (tagName.equals(TAG_CROSS_PROFILE_PACKAGE_INFO)){ - readCrossProfilePackageInfoLPw(parser, userId); } else { Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: " + parser.getName()); @@ -1364,32 +1256,6 @@ final class Settings { serializer.endTag(null, TAG_CROSS_PROFILE_INTENT_FILTERS); } - void writeCrossProfilePackageInfoLPr(XmlSerializer serializer, int userId) - throws IllegalArgumentException, IllegalStateException, IOException { - SparseArray<ArrayList<String>> sourceForwardingInfo = mCrossProfilePackageInfo.get(userId); - if (sourceForwardingInfo == null) { - return; - } - serializer.startTag(null, TAG_CROSS_PROFILE_PACKAGE_INFO); - int NI = sourceForwardingInfo.size(); - for (int i = 0; i < NI; i++) { - int targetUserId = sourceForwardingInfo.keyAt(i); - ArrayList<String> packageNames = sourceForwardingInfo.valueAt(i); - serializer.startTag(null, TAG_ITEM); - serializer.attribute(null, CROSS_PROFILE_PACKAGE_INFO_ATTR_TARGET_USER_ID, - Integer.toString(targetUserId)); - int NJ = packageNames.size(); - for (int j = 0; j < NJ; j++) { - serializer.startTag(null, CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME); - serializer.attribute(null, CROSS_PROFILE_PACKAGE_INFO_ATTR_PACKAGE_NAME, - packageNames.get(j)); - serializer.endTag(null, CROSS_PROFILE_PACKAGE_INFO_TAG_PACKAGE_NAME); - } - serializer.endTag(null, TAG_ITEM); - } - serializer.endTag(null, TAG_CROSS_PROFILE_PACKAGE_INFO); - } - void writePackageRestrictionsLPr(int userId) { if (DEBUG_MU) { Log.i(TAG, "Writing package restrictions for user=" + userId); @@ -1494,8 +1360,6 @@ final class Settings { writeCrossProfileIntentFiltersLPr(serializer, userId); - writeCrossProfilePackageInfoLPr(serializer, userId); - serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS); serializer.endDocument(); @@ -3180,7 +3044,6 @@ final class Settings { file = getUserPackagesStateBackupFile(userId); file.delete(); removeCrossProfileIntentFiltersLPw(userId); - removeCrossProfilePackagesLPw(userId); } void removeCrossProfileIntentFiltersLPw(int userId) { @@ -3211,27 +3074,6 @@ final class Settings { } } - public void removeCrossProfilePackagesLPw(int userId) { - synchronized(mCrossProfilePackageInfo) { - // userId is the source user - if (mCrossProfilePackageInfo.get(userId) != null) { - mCrossProfilePackageInfo.remove(userId); - writePackageRestrictionsLPr(userId); - } - // userId is the target user - int count = mCrossProfilePackageInfo.size(); - for (int i = 0; i < count; i++) { - int sourceUserId = mCrossProfilePackageInfo.keyAt(i); - SparseArray<ArrayList<String>> sourceForwardingInfo = - mCrossProfilePackageInfo.valueAt(i); - if (sourceForwardingInfo.get(userId) != null) { - sourceForwardingInfo.remove(userId); - writePackageRestrictionsLPr(sourceUserId); - } - } - } - } - // This should be called (at least) whenever an application is removed private void setFirstAvailableUid(int uid) { if (uid > mFirstAvailableUid) { diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java index 4a2cece..26e0db3 100644 --- a/services/core/java/com/android/server/pm/UserManagerService.java +++ b/services/core/java/com/android/server/pm/UserManagerService.java @@ -21,7 +21,6 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManagerNative; -import android.app.ActivityThread; import android.app.IStopUserCallback; import android.content.BroadcastReceiver; import android.content.Context; @@ -34,6 +33,7 @@ import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Binder; import android.os.Bundle; +import android.os.Debug; import android.os.Environment; import android.os.FileUtils; import android.os.Handler; @@ -92,6 +92,7 @@ public class UserManagerService extends IUserManager.Stub { private static final String ATTR_SERIAL_NO = "serialNumber"; private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber"; private static final String ATTR_PARTIAL = "partial"; + private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove"; private static final String ATTR_USER_VERSION = "version"; private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId"; private static final String TAG_GUEST_RESTRICTIONS = "guestRestrictions"; @@ -228,7 +229,7 @@ public class UserManagerService extends IUserManager.Stub { ArrayList<UserInfo> partials = new ArrayList<UserInfo>(); for (int i = 0; i < mUsers.size(); i++) { UserInfo ui = mUsers.valueAt(i); - if (ui.partial && i != 0) { + if ((ui.partial || ui.guestToRemove) && i != 0) { partials.add(ui); } } @@ -480,6 +481,14 @@ public class UserManagerService extends IUserManager.Stub { } @Override + public boolean hasUserRestriction(String restrictionKey, int userId) { + synchronized (mPackagesLock) { + Bundle restrictions = mUserRestrictions.get(userId); + return restrictions != null ? restrictions.getBoolean(restrictionKey) : false; + } + } + + @Override public Bundle getUserRestrictions(int userId) { // checkManageUsersPermission("getUserRestrictions"); @@ -759,6 +768,9 @@ public class UserManagerService extends IUserManager.Stub { if (userInfo.partial) { serializer.attribute(null, ATTR_PARTIAL, "true"); } + if (userInfo.guestToRemove) { + serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true"); + } if (userInfo.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID) { serializer.attribute(null, ATTR_PROFILE_GROUP_ID, Integer.toString(userInfo.profileGroupId)); @@ -806,7 +818,7 @@ public class UserManagerService extends IUserManager.Stub { serializer.attribute(null, ATTR_NEXT_SERIAL_NO, Integer.toString(mNextSerialNumber)); serializer.attribute(null, ATTR_USER_VERSION, Integer.toString(mUserVersion)); - serializer.startTag(null, TAG_GUEST_RESTRICTIONS); + serializer.startTag(null, TAG_GUEST_RESTRICTIONS); writeRestrictionsLocked(serializer, mGuestRestrictions); serializer.endTag(null, TAG_GUEST_RESTRICTIONS); for (int i = 0; i < mUsers.size(); i++) { @@ -855,6 +867,8 @@ public class UserManagerService extends IUserManager.Stub { writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_CALLS); writeBoolean(serializer, restrictions, UserManager.DISALLOW_SMS); writeBoolean(serializer, restrictions, UserManager.DISALLOW_CREATE_WINDOWS); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_OUTGOING_BEAM); serializer.endTag(null, TAG_RESTRICTIONS); } @@ -871,6 +885,7 @@ public class UserManagerService extends IUserManager.Stub { int profileGroupId = UserInfo.NO_PROFILE_GROUP_ID; long lastAttemptTime = 0L; boolean partial = false; + boolean guestToRemove = false; Bundle restrictions = new Bundle(); FileInputStream fis = null; @@ -918,6 +933,10 @@ public class UserManagerService extends IUserManager.Stub { if ("true".equals(valueString)) { partial = true; } + valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE); + if ("true".equals(valueString)) { + guestToRemove = true; + } int outerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT @@ -942,6 +961,7 @@ public class UserManagerService extends IUserManager.Stub { userInfo.creationTime = creationTime; userInfo.lastLoggedInTime = lastLoggedInTime; userInfo.partial = partial; + userInfo.guestToRemove = guestToRemove; userInfo.profileGroupId = profileGroupId; mUserRestrictions.append(id, restrictions); if (salt != 0L) { @@ -999,6 +1019,8 @@ public class UserManagerService extends IUserManager.Stub { readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_CALLS); readBoolean(parser, restrictions, UserManager.DISALLOW_SMS); readBoolean(parser, restrictions, UserManager.DISALLOW_CREATE_WINDOWS); + readBoolean(parser, restrictions, UserManager.DISALLOW_CROSS_PROFILE_COPY_PASTE); + readBoolean(parser, restrictions, UserManager.DISALLOW_OUTGOING_BEAM); } private void readBoolean(XmlPullParser parser, Bundle restrictions, @@ -1119,7 +1141,7 @@ public class UserManagerService extends IUserManager.Stub { return null; } // If we're adding a guest and there already exists one, bail. - if (isGuest && numberOfUsersOfTypeLocked(UserInfo.FLAG_GUEST, true) > 0) { + if (isGuest && findCurrentGuestUserLocked() != null) { return null; } // Limit number of managed profiles that can be created @@ -1180,6 +1202,23 @@ public class UserManagerService extends IUserManager.Stub { } /** + * Find the current guest user. If the Guest user is partial, + * then do not include it in the results as it is about to die. + * This is different than {@link #numberOfUsersOfTypeLocked(int, boolean)} due to + * the special handling of Guests being removed. + */ + private UserInfo findCurrentGuestUserLocked() { + final int size = mUsers.size(); + for (int i = 0; i < size; i++) { + final UserInfo user = mUsers.valueAt(i); + if (user.isGuest() && !user.guestToRemove && !mRemovingUserIds.get(user.id)) { + return user; + } + } + return null; + } + + /** * Mark this guest user for deletion to allow us to create another guest * and switch to that user before actually removing this guest. * @param userHandle the userid of the current guest @@ -1204,14 +1243,15 @@ public class UserManagerService extends IUserManager.Stub { if (!user.isGuest()) { return false; } - // Set this to a partially created user, so that the user will be purged - // on next startup, in case the runtime stops now before stopping and - // removing the user completely. - user.partial = true; + // We set this to a guest user that is to be removed. This is a temporary state + // where we are allowed to add new Guest users, even if this one is still not + // removed. This user will still show up in getUserInfo() calls. + // If we don't get around to removing this Guest user, it will be purged on next + // startup. + user.guestToRemove = true; // Mark it as disabled, so that it isn't returned any more when // profiles are queried. user.flags |= UserInfo.FLAG_DISABLED; - user.flags &= ~UserInfo.FLAG_GUEST; writeUserLocked(user); } } finally { diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 5f97a00..0a4b3bc 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -91,8 +91,6 @@ public final class PowerManagerService extends com.android.server.SystemService private static final int MSG_SANDMAN = 2; // Message: Sent when the screen on blocker is released. private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3; - // Message: Sent to poll whether the boot animation has terminated. - private static final int MSG_CHECK_IF_BOOT_ANIMATION_FINISHED = 4; // Dirty bit: mWakeLocks changed private static final int DIRTY_WAKE_LOCKS = 1 << 0; @@ -154,12 +152,6 @@ public final class PowerManagerService extends com.android.server.SystemService // provider populates the actual default value (R.integer.def_screen_off_timeout). private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000; - // The name of the boot animation service in init.rc. - private static final String BOOT_ANIMATION_SERVICE = "bootanim"; - - // Poll interval in milliseconds for watching boot animation finished. - private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; - // Power hints defined in hardware/libhardware/include/hardware/power.h. private static final int POWER_HINT_INTERACTION = 2; private static final int POWER_HINT_LOW_POWER = 5; @@ -478,14 +470,15 @@ public final class PowerManagerService extends com.android.server.SystemService @Override public void onBootPhase(int phase) { - if (phase == PHASE_BOOT_COMPLETED) { - // This is our early signal that the system thinks it has finished booting. - // However, the boot animation may still be running for a few more seconds - // since it is ultimately in charge of when it terminates. - // Defer transitioning into the boot completed state until the animation exits. - // We do this so that the screen does not start to dim prematurely before - // the user has actually had a chance to interact with the device. - startWatchingForBootAnimationFinished(); + synchronized (mLock) { + if (phase == PHASE_BOOT_COMPLETED) { + final long now = SystemClock.uptimeMillis(); + mBootCompleted = true; + mDirty |= DIRTY_BOOT_COMPLETED; + userActivityNoUpdateLocked( + now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID); + updatePowerStateLocked(); + } } } @@ -821,7 +814,7 @@ public final class PowerManagerService extends com.android.server.SystemService + " [" + wakeLock.mTag + "], flags=0x" + Integer.toHexString(flags)); } - if ((flags & PowerManager.WAIT_FOR_DISTANT_PROXIMITY) != 0) { + if ((flags & PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY) != 0) { mRequestWaitForNegativeProximity = true; } @@ -2076,38 +2069,6 @@ public final class PowerManagerService extends com.android.server.SystemService updatePowerStateLocked(); } - private void startWatchingForBootAnimationFinished() { - mHandler.sendEmptyMessage(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED); - } - - private void checkIfBootAnimationFinished() { - if (DEBUG) { - Slog.d(TAG, "Check if boot animation finished..."); - } - - if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { - mHandler.sendEmptyMessageDelayed(MSG_CHECK_IF_BOOT_ANIMATION_FINISHED, - BOOT_ANIMATION_POLL_INTERVAL); - return; - } - - synchronized (mLock) { - if (!mBootCompleted) { - Slog.i(TAG, "Boot animation finished."); - handleBootCompletedLocked(); - } - } - } - - private void handleBootCompletedLocked() { - final long now = SystemClock.uptimeMillis(); - mBootCompleted = true; - mDirty |= DIRTY_BOOT_COMPLETED; - userActivityNoUpdateLocked( - now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID); - updatePowerStateLocked(); - } - private void shutdownOrRebootInternal(final boolean shutdown, final boolean confirm, final String reason, boolean wait) { if (mHandler == null || !mSystemReady) { @@ -2528,9 +2489,6 @@ public final class PowerManagerService extends com.android.server.SystemService case MSG_SCREEN_ON_BLOCKER_RELEASED: handleScreenOnBlockerReleased(); break; - case MSG_CHECK_IF_BOOT_ANIMATION_FINISHED: - checkIfBootAnimationFinished(); - break; } } } diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index c8b5b3e..fefbe0a 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -33,6 +33,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; @@ -48,6 +49,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; import android.os.UserManager; +import android.provider.Settings; import android.service.trust.TrustAgentService; import android.util.ArraySet; import android.util.AttributeSet; @@ -97,6 +99,7 @@ public class TrustManagerService extends SystemService { private final SparseBooleanArray mUserHasAuthenticatedSinceBoot = new SparseBooleanArray(); /* package */ final TrustArchive mArchive = new TrustArchive(); private final Context mContext; + private final LockPatternUtils mLockPatternUtils; private UserManager mUserManager; @@ -104,6 +107,7 @@ public class TrustManagerService extends SystemService { super(context); mContext = context; mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); + mLockPatternUtils = new LockPatternUtils(context); } @Override @@ -116,6 +120,7 @@ public class TrustManagerService extends SystemService { if (phase == SystemService.PHASE_SYSTEM_SERVICES_READY && !isSafeMode()) { mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true); mReceiver.register(mContext); + maybeEnableFactoryTrustAgents(mLockPatternUtils, UserHandle.USER_OWNER); refreshAgentList(UserHandle.USER_ALL); } } @@ -159,6 +164,11 @@ public class TrustManagerService extends SystemService { void refreshAgentList(int userId) { if (DEBUG) Slog.d(TAG, "refreshAgentList()"); + if (userId != UserHandle.USER_ALL && userId < UserHandle.USER_OWNER) { + Log.e(TAG, "refreshAgentList(userId=" + userId + "): Invalid user handle," + + " must be USER_ALL or a specific user.", new Throwable("here")); + userId = UserHandle.USER_ALL; + } PackageManager pm = mContext.getPackageManager(); List<UserInfo> userInfos; @@ -168,12 +178,13 @@ public class TrustManagerService extends SystemService { userInfos = new ArrayList<>(); userInfos.add(mUserManager.getUserInfo(userId)); } - LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext); + LockPatternUtils lockPatternUtils = mLockPatternUtils; ArraySet<AgentInfo> obsoleteAgents = new ArraySet<>(); obsoleteAgents.addAll(mActiveAgents); for (UserInfo userInfo : userInfos) { + if (!userInfo.supportsSwitchTo()) continue; if (lockPatternUtils.getKeyguardStoredPasswordQuality(userInfo.id) == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) continue; if (!mUserHasAuthenticatedSinceBoot.get(userInfo.id)) continue; @@ -186,22 +197,11 @@ public class TrustManagerService extends SystemService { if (enabledAgents == null) { continue; } - List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT, - PackageManager.GET_META_DATA, userInfo.id); + List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userInfo.id); for (ResolveInfo resolveInfo : resolveInfos) { - if (resolveInfo.serviceInfo == null) continue; - - String packageName = resolveInfo.serviceInfo.packageName; - if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName) - != PackageManager.PERMISSION_GRANTED) { - Log.w(TAG, "Skipping agent because package " + packageName - + " does not have permission " + PERMISSION_PROVIDE_AGENT + "."); - continue; - } - ComponentName name = getComponentName(resolveInfo); - if (!enabledAgents.contains(name)) continue; + if (!enabledAgents.contains(name)) continue; if (disableTrustAgents) { List<String> features = dpm.getTrustAgentFeaturesEnabled(null /* admin */, name); @@ -228,11 +228,13 @@ public class TrustManagerService extends SystemService { boolean trustMayHaveChanged = false; for (int i = 0; i < obsoleteAgents.size(); i++) { AgentInfo info = obsoleteAgents.valueAt(i); - if (info.agent.isManagingTrust()) { - trustMayHaveChanged = true; + if (userId == UserHandle.USER_ALL || userId == info.userId) { + if (info.agent.isManagingTrust()) { + trustMayHaveChanged = true; + } + info.agent.unbind(); + mActiveAgents.remove(info); } - info.agent.unbind(); - mActiveAgents.remove(info); } if (trustMayHaveChanged) { @@ -342,6 +344,54 @@ public class TrustManagerService extends SystemService { return new ComponentName(resolveInfo.serviceInfo.packageName, resolveInfo.serviceInfo.name); } + private void maybeEnableFactoryTrustAgents(LockPatternUtils utils, int userId) { + if (0 != Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.TRUST_AGENTS_INITIALIZED, 0, userId)) { + return; + } + PackageManager pm = mContext.getPackageManager(); + List<ResolveInfo> resolveInfos = resolveAllowedTrustAgents(pm, userId); + ArraySet<ComponentName> discoveredAgents = new ArraySet<>(); + for (ResolveInfo resolveInfo : resolveInfos) { + ComponentName componentName = getComponentName(resolveInfo); + int applicationInfoFlags = resolveInfo.serviceInfo.applicationInfo.flags; + if ((applicationInfoFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { + Log.i(TAG, "Leaving agent " + componentName + " disabled because package " + + "is not a system package."); + continue; + } + discoveredAgents.add(componentName); + } + + List<ComponentName> previouslyEnabledAgents = utils.getEnabledTrustAgents(userId); + if (previouslyEnabledAgents != null) { + discoveredAgents.addAll(previouslyEnabledAgents); + } + utils.setEnabledTrustAgents(discoveredAgents, userId); + Settings.Secure.putIntForUser(mContext.getContentResolver(), + Settings.Secure.TRUST_AGENTS_INITIALIZED, 1, userId); + } + + private List<ResolveInfo> resolveAllowedTrustAgents(PackageManager pm, int userId) { + List<ResolveInfo> resolveInfos = pm.queryIntentServicesAsUser(TRUST_AGENT_INTENT, + 0 /* flags */, userId); + ArrayList<ResolveInfo> allowedAgents = new ArrayList<>(resolveInfos.size()); + for (ResolveInfo resolveInfo : resolveInfos) { + if (resolveInfo.serviceInfo == null) continue; + if (resolveInfo.serviceInfo.applicationInfo == null) continue; + String packageName = resolveInfo.serviceInfo.packageName; + if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName) + != PackageManager.PERMISSION_GRANTED) { + ComponentName name = getComponentName(resolveInfo); + Log.w(TAG, "Skipping agent " + name + " because package does not have" + + " permission " + PERMISSION_PROVIDE_AGENT + "."); + continue; + } + allowedAgents.add(resolveInfo); + } + return allowedAgents; + } + // Agent dispatch and aggregation private boolean aggregateIsTrusted(int userId) { @@ -414,6 +464,7 @@ public class TrustManagerService extends SystemService { } } mTrustListeners.add(listener); + updateTrustAll(); } private void removeListener(ITrustListener listener) { @@ -616,12 +667,19 @@ public class TrustManagerService extends SystemService { @Override public void onReceive(Context context, Intent intent) { - if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals( - intent.getAction())) { + String action = intent.getAction(); + if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(action)) { refreshAgentList(getSendingUserId()); updateDevicePolicyFeatures(); - } else if (Intent.ACTION_USER_PRESENT.equals(intent.getAction())) { + } else if (Intent.ACTION_USER_PRESENT.equals(action)) { updateUserHasAuthenticated(getSendingUserId()); + } else if (Intent.ACTION_USER_ADDED.equals(action)) { + int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -100); + if (userId > 0) { + maybeEnableFactoryTrustAgents(mLockPatternUtils, userId); + } else { + Log.wtf(TAG, "EXTRA_USER_HANDLE missing or invalid, value=" + userId); + } } } @@ -629,6 +687,7 @@ public class TrustManagerService extends SystemService { IntentFilter filter = new IntentFilter(); filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); filter.addAction(Intent.ACTION_USER_PRESENT); + filter.addAction(Intent.ACTION_USER_ADDED); context.registerReceiverAsUser(this, UserHandle.ALL, filter, diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java index 3380f71..adae84f 100644 --- a/services/core/java/com/android/server/tv/TvInputManagerService.java +++ b/services/core/java/com/android/server/tv/TvInputManagerService.java @@ -85,6 +85,7 @@ import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -139,7 +140,7 @@ public final class TvInputManagerService extends SystemService { registerBroadcastReceivers(); } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) { synchronized (mLock) { - buildTvInputListLocked(mCurrentUserId); + buildTvInputListLocked(mCurrentUserId, null); buildTvContentRatingSystemListLocked(mCurrentUserId); } } @@ -148,19 +149,64 @@ public final class TvInputManagerService extends SystemService { private void registerBroadcastReceivers() { PackageMonitor monitor = new PackageMonitor() { + private void buildTvInputList(String[] packages) { + synchronized (mLock) { + buildTvInputListLocked(getChangingUserId(), packages); + buildTvContentRatingSystemListLocked(getChangingUserId()); + } + } + + @Override + public void onPackageUpdateFinished(String packageName, int uid) { + if (DEBUG) Slog.d(TAG, "onPackageUpdateFinished(packageName=" + packageName + ")"); + // This callback is invoked when the TV input is reinstalled. + // In this case, isReplacing() always returns true. + buildTvInputList(new String[] { packageName }); + } + + @Override + public void onPackagesAvailable(String[] packages) { + if (DEBUG) { + Slog.d(TAG, "onPackagesAvailable(packages=" + Arrays.toString(packages) + ")"); + } + // This callback is invoked when the media on which some packages exist become + // available. + if (isReplacing()) { + buildTvInputList(packages); + } + } + + @Override + public void onPackagesUnavailable(String[] packages) { + // This callback is invoked when the media on which some packages exist become + // unavailable. + if (DEBUG) { + Slog.d(TAG, "onPackagesUnavailable(packages=" + Arrays.toString(packages) + + ")"); + } + if (isReplacing()) { + buildTvInputList(packages); + } + } + @Override public void onSomePackagesChanged() { + // TODO: Use finer-grained methods(e.g. onPackageAdded, onPackageRemoved) to manage + // the TV inputs. if (DEBUG) Slog.d(TAG, "onSomePackagesChanged()"); - synchronized (mLock) { - buildTvInputListLocked(mCurrentUserId); - buildTvContentRatingSystemListLocked(mCurrentUserId); + if (isReplacing()) { + if (DEBUG) Slog.d(TAG, "Skipped building TV input list due to replacing"); + // When the package is updated, buildTvInputListLocked is called in other + // methods instead. + return; } + buildTvInputList(null); } @Override public void onPackageRemoved(String packageName, int uid) { synchronized (mLock) { - UserState userState = getUserStateLocked(mCurrentUserId); + UserState userState = getUserStateLocked(getChangingUserId()); if (!userState.packageSet.contains(packageName)) { // Not a TV input package. return; @@ -218,13 +264,11 @@ public final class TvInputManagerService extends SystemService { component.getPackageName()) == PackageManager.PERMISSION_GRANTED; } - private void buildTvInputListLocked(int userId) { + private void buildTvInputListLocked(int userId, String[] updatedPackages) { UserState userState = getUserStateLocked(userId); userState.packageSet.clear(); - if (DEBUG) { - Slog.d(TAG, "buildTvInputList"); - } + if (DEBUG) Slog.d(TAG, "buildTvInputList"); PackageManager pm = mContext.getPackageManager(); List<ResolveInfo> services = pm.queryIntentServices( new Intent(TvInputService.SERVICE_INTERFACE), @@ -278,6 +322,15 @@ public final class TvInputManagerService extends SystemService { for (String inputId : inputMap.keySet()) { if (!userState.inputMap.containsKey(inputId)) { notifyInputAddedLocked(userState, inputId); + } else if (updatedPackages != null) { + // Notify the package updates + TvInputState inputState = inputMap.get(inputId); + for (String updatedPackage : updatedPackages) { + if (inputState.info.getComponent().getPackageName().equals(updatedPackage)) { + notifyInputUpdatedLocked(userState, inputId); + break; + } + } } } @@ -337,7 +390,7 @@ public final class TvInputManagerService extends SystemService { userState = new UserState(mContext, userId); } mUserStates.put(userId, userState); - buildTvInputListLocked(userId); + buildTvInputListLocked(userId, null); buildTvContentRatingSystemListLocked(userId); } } @@ -649,6 +702,19 @@ public final class TvInputManagerService extends SystemService { } } + private void notifyInputUpdatedLocked(UserState userState, String inputId) { + if (DEBUG) { + Slog.d(TAG, "notifyInputUpdatedLocked(inputId=" + inputId + ")"); + } + for (ITvInputManagerCallback callback : userState.callbackSet) { + try { + callback.onInputUpdated(inputId); + } catch (RemoteException e) { + Slog.e(TAG, "failed to report updated input to callback", e); + } + } + } + private void notifyInputStateChangedLocked(UserState userState, String inputId, int state, ITvInputManagerCallback targetCallback) { if (DEBUG) { @@ -1813,7 +1879,7 @@ public final class TvInputManagerService extends SystemService { private void addTvInputLocked(TvInputInfo inputInfo) { ServiceState serviceState = getServiceStateLocked(mComponent, mUserId); serviceState.inputList.add(inputInfo); - buildTvInputListLocked(mUserId); + buildTvInputListLocked(mUserId, null); } @Override @@ -1851,7 +1917,7 @@ public final class TvInputManagerService extends SystemService { } } if (removed) { - buildTvInputListLocked(mUserId); + buildTvInputListLocked(mUserId, null); mTvInputHardwareManager.removeTvInput(inputId); } else { Slog.e(TAG, "failed to remove input " + inputId); diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index e1ade63..a8245e7 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -843,7 +843,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub { } File file = new File(dir, WALLPAPER); ParcelFileDescriptor fd = ParcelFileDescriptor.open(file, - MODE_CREATE|MODE_READ_WRITE); + MODE_CREATE|MODE_READ_WRITE|MODE_TRUNCATE); if (!SELinux.restorecon(file)) { return null; } diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java index 64b852b..a7d41fa 100644 --- a/services/core/java/com/android/server/wm/CircularDisplayMask.java +++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java @@ -63,8 +63,14 @@ class CircularDisplayMask { SurfaceControl ctrl = null; try { - ctrl = new SurfaceControl(session, "CircularDisplayMask", - mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); + if (WindowManagerService.DEBUG_SURFACE_TRACE) { + ctrl = new WindowStateAnimator.SurfaceTrace(session, "CircularDisplayMask", + mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT, + SurfaceControl.HIDDEN); + } else { + ctrl = new SurfaceControl(session, "CircularDisplayMask", mScreenSize.x, + mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); + } ctrl.setLayerStack(display.getLayerStack()); ctrl.setLayer(zOrder); ctrl.setPosition(0, 0); diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java new file mode 100644 index 0000000..62f2b48 --- /dev/null +++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm; + + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.graphics.Point; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.Slog; +import android.view.Display; +import android.view.Surface; +import android.view.Surface.OutOfResourcesException; +import android.view.SurfaceControl; +import android.view.SurfaceSession; + +class EmulatorDisplayOverlay { + private static final String TAG = "EmulatorDisplayOverlay"; + + // Display dimensions + private Point mScreenSize; + + private final SurfaceControl mSurfaceControl; + private final Surface mSurface = new Surface(); + private int mLastDW; + private int mLastDH; + private boolean mDrawNeeded; + private Drawable mOverlay; + private int mRotation; + private boolean mVisible; + + public EmulatorDisplayOverlay(Context context, Display display, SurfaceSession session, + int zOrder) { + mScreenSize = new Point(); + display.getSize(mScreenSize); + + SurfaceControl ctrl = null; + try { + if (WindowManagerService.DEBUG_SURFACE_TRACE) { + ctrl = new WindowStateAnimator.SurfaceTrace(session, "EmulatorDisplayOverlay", + mScreenSize.x, mScreenSize.y, PixelFormat.TRANSLUCENT, + SurfaceControl.HIDDEN); + } else { + ctrl = new SurfaceControl(session, "EmulatorDisplayOverlay", mScreenSize.x, + mScreenSize.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN); + } + ctrl.setLayerStack(display.getLayerStack()); + ctrl.setLayer(zOrder); + ctrl.setPosition(0, 0); + ctrl.show(); + mSurface.copyFrom(ctrl); + } catch (OutOfResourcesException e) { + } + mSurfaceControl = ctrl; + mDrawNeeded = true; + mOverlay = context.getDrawable( + com.android.internal.R.drawable.emulator_circular_window_overlay); + } + + private void drawIfNeeded() { + if (!mDrawNeeded || !mVisible) { + return; + } + mDrawNeeded = false; + + Rect dirty = new Rect(0, 0, mScreenSize.x, mScreenSize.y); + Canvas c = null; + try { + c = mSurface.lockCanvas(dirty); + } catch (IllegalArgumentException e) { + } catch (OutOfResourcesException e) { + } + if (c == null) { + return; + } + c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC); + mSurfaceControl.setPosition(0, 0); + mOverlay.setBounds(0, 0, mScreenSize.x, mScreenSize.y); + mOverlay.draw(c); + mSurface.unlockCanvasAndPost(c); + } + + // Note: caller responsible for being inside + // Surface.openTransaction() / closeTransaction() + public void setVisibility(boolean on) { + if (mSurfaceControl == null) { + return; + } + mVisible = on; + drawIfNeeded(); + if (on) { + mSurfaceControl.show(); + } else { + mSurfaceControl.hide(); + } + } + + void positionSurface(int dw, int dh, int rotation) { + if (mLastDW == dw && mLastDH == dh && mRotation == rotation) { + return; + } + mLastDW = dw; + mLastDH = dh; + mDrawNeeded = true; + mRotation = rotation; + drawIfNeeded(); + } + +} diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java index 81cd602..da5cfda 100644 --- a/services/core/java/com/android/server/wm/WindowAnimator.java +++ b/services/core/java/com/android/server/wm/WindowAnimator.java @@ -252,6 +252,10 @@ public class WindowAnimator { final boolean showImeOverKeyguard = imeTarget != null && imeTarget.isVisibleNow() && (imeTarget.getAttrs().flags & FLAG_SHOW_WHEN_LOCKED) != 0; + final WindowState winShowWhenLocked = (WindowState) mPolicy.getWinShowWhenLockedLw(); + final AppWindowToken appShowWhenLocked = winShowWhenLocked == null ? + null : winShowWhenLocked.mAppToken; + for (int i = windows.size() - 1; i >= 0; i--) { WindowState win = windows.get(i); WindowStateAnimator winAnimator = win.mWinAnimator; @@ -316,8 +320,8 @@ public class WindowAnimator { + " hidden=" + win.mRootToken.hidden + " anim=" + win.mWinAnimator.mAnimation); } else if (mPolicy.canBeForceHidden(win, win.mAttrs)) { - final boolean hideWhenLocked = (flags & FLAG_SHOW_WHEN_LOCKED) == 0 && - !(win.mIsImWindow && showImeOverKeyguard); + final boolean hideWhenLocked = !((win.mIsImWindow && showImeOverKeyguard) || + (appShowWhenLocked != null && appShowWhenLocked == win.mAppToken)); final boolean changed; if (((mForceHiding == KEYGUARD_ANIMATING_IN) && (!winAnimator.isAnimating() || hideWhenLocked)) @@ -454,7 +458,10 @@ public class WindowAnimator { } final int color = winAnimator.mAnimation.getBackgroundColor(); if (color != 0) { - win.getStack().setAnimationBackground(winAnimator, color); + final TaskStack stack = win.getStack(); + if (stack != null) { + stack.setAnimationBackground(winAnimator, color); + } } } mAnimating = true; @@ -473,7 +480,10 @@ public class WindowAnimator { final int color = appAnimator.animation.getBackgroundColor(); if (color != 0) { - win.getStack().setAnimationBackground(winAnimator, color); + final TaskStack stack = win.getStack(); + if (stack != null) { + stack.setAnimationBackground(winAnimator, color); + } } } } // end forall windows @@ -568,6 +578,15 @@ public class WindowAnimator { mBulkUpdateParams |= SET_UPDATE_ROTATION; screenRotationAnimation.kill(); displayAnimator.mScreenRotationAnimation = null; + + //TODO (multidisplay): Accessibility supported only for the default display. + if (mService.mAccessibilityController != null + && displayId == Display.DEFAULT_DISPLAY) { + // We just finished rotation animation which means we did not + // anounce the rotation and waited for it to end, announce now. + mService.mAccessibilityController.onRotationChangedLocked( + mService.getDefaultDisplayContentLocked(), mService.mRotation); + } } } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8e45081..9033f30 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -20,6 +20,8 @@ import static android.view.WindowManager.LayoutParams.*; import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; import android.app.AppOpsManager; +import android.os.Build; +import android.os.SystemService; import android.util.ArraySet; import android.util.TimeUtils; import android.view.IWindowId; @@ -271,6 +273,12 @@ public class WindowManagerService extends IWindowManager.Stub // Default input dispatching timeout in nanoseconds. static final long DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS = 5000 * 1000000L; + // Poll interval in milliseconds for watching boot animation finished. + private static final int BOOT_ANIMATION_POLL_INTERVAL = 200; + + // The name of the boot animation service in init.rc. + private static final String BOOT_ANIMATION_SERVICE = "bootanim"; + /** Minimum value for attachStack and resizeStack weight value */ public static final float STACK_WEIGHT_MIN = 0.2f; @@ -295,6 +303,8 @@ public class WindowManagerService extends IWindowManager.Stub private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; + private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular"; + final private KeyguardDisableHandler mKeyguardDisableHandler; final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @@ -441,6 +451,7 @@ public class WindowManagerService extends IWindowManager.Stub Watermark mWatermark; StrictModeFlash mStrictModeFlash; CircularDisplayMask mCircularDisplayMask; + EmulatorDisplayOverlay mEmulatorDisplayOverlay; FocusedStackFrame mFocusedStackFrame; int mFocusedStackLayer; @@ -454,6 +465,7 @@ public class WindowManagerService extends IWindowManager.Stub boolean mSystemBooted = false; boolean mForceDisplayEnabled = false; boolean mShowingBootMessages = false; + boolean mBootAnimationStopped = false; String mLastANRState; @@ -881,6 +893,7 @@ public class WindowManagerService extends IWindowManager.Stub } showCircularDisplayMaskIfNeeded(); + showEmulatorDisplayOverlayIfNeeded(); } public InputMonitor getInputMonitor() { @@ -5602,17 +5615,70 @@ public class WindowManagerService extends IWindowManager.Stub performEnableScreen(); } + private boolean checkWaitingForWindowsLocked() { + + boolean haveBootMsg = false; + boolean haveApp = false; + // if the wallpaper service is disabled on the device, we're never going to have + // wallpaper, don't bother waiting for it + boolean haveWallpaper = false; + boolean wallpaperEnabled = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_enableWallpaperService) + && !mOnlyCore; + boolean haveKeyguard = true; + // TODO(multidisplay): Expand to all displays? + final WindowList windows = getDefaultWindowListLocked(); + final int N = windows.size(); + for (int i=0; i<N; i++) { + WindowState w = windows.get(i); + if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { + return true; + } + if (w.isDrawnLw()) { + if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { + haveBootMsg = true; + } else if (w.mAttrs.type == TYPE_APPLICATION) { + haveApp = true; + } else if (w.mAttrs.type == TYPE_WALLPAPER) { + haveWallpaper = true; + } else if (w.mAttrs.type == TYPE_STATUS_BAR) { + haveKeyguard = mPolicy.isKeyguardDrawnLw(); + } + } + } + + if (DEBUG_SCREEN_ON || DEBUG_BOOT) { + Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages + + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp + + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled + + " haveKeyguard=" + haveKeyguard); + } + + // If we are turning on the screen to show the boot message, + // don't do it until the boot message is actually displayed. + if (!mSystemBooted && !haveBootMsg) { + return true; + } + + // If we are turning on the screen after the boot is completed + // normally, don't do so until we have the application and + // wallpaper. + if (mSystemBooted && ((!haveApp && !haveKeyguard) || + (wallpaperEnabled && !haveWallpaper))) { + return true; + } + + return false; + } + public void performEnableScreen() { synchronized(mWindowMap) { - if (DEBUG_BOOT) { - RuntimeException here = new RuntimeException("here"); - here.fillInStackTrace(); - Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled - + " mForceDisplayEnabled=" + mForceDisplayEnabled - + " mShowingBootMessages=" + mShowingBootMessages - + " mSystemBooted=" + mSystemBooted - + " mOnlyCore=" + mOnlyCore, here); - } + if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: mDisplayEnabled=" + mDisplayEnabled + + " mForceDisplayEnabled=" + mForceDisplayEnabled + + " mShowingBootMessages=" + mShowingBootMessages + + " mSystemBooted=" + mSystemBooted + + " mOnlyCore=" + mOnlyCore, + new RuntimeException("here").fillInStackTrace()); if (mDisplayEnabled) { return; } @@ -5620,94 +5686,64 @@ public class WindowManagerService extends IWindowManager.Stub return; } - if (!mForceDisplayEnabled) { - // Don't enable the screen until all existing windows - // have been drawn. - boolean haveBootMsg = false; - boolean haveApp = false; - // if the wallpaper service is disabled on the device, we're never going to have - // wallpaper, don't bother waiting for it - boolean haveWallpaper = false; - boolean wallpaperEnabled = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_enableWallpaperService) - && !mOnlyCore; - boolean haveKeyguard = true; - // TODO(multidisplay): Expand to all displays? - final WindowList windows = getDefaultWindowListLocked(); - final int N = windows.size(); - for (int i=0; i<N; i++) { - WindowState w = windows.get(i); - if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) { - return; - } - if (w.isDrawnLw()) { - if (w.mAttrs.type == TYPE_BOOT_PROGRESS) { - haveBootMsg = true; - } else if (w.mAttrs.type == TYPE_APPLICATION) { - haveApp = true; - } else if (w.mAttrs.type == TYPE_WALLPAPER) { - haveWallpaper = true; - } else if (w.mAttrs.type == TYPE_STATUS_BAR) { - haveKeyguard = mPolicy.isKeyguardDrawnLw(); - } - } - } - - if (DEBUG_SCREEN_ON || DEBUG_BOOT) { - Slog.i(TAG, "******** booted=" + mSystemBooted + " msg=" + mShowingBootMessages - + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp - + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled - + " haveKeyguard=" + haveKeyguard); - } + // Don't enable the screen until all existing windows have been drawn. + if (!mForceDisplayEnabled && checkWaitingForWindowsLocked()) { + return; + } - // If we are turning on the screen to show the boot message, - // don't do it until the boot message is actually displayed. - if (!mSystemBooted && !haveBootMsg) { - return; + if (!mBootAnimationStopped) { + // Do this one time. + try { + IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); + if (surfaceFlinger != null) { + //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); + Parcel data = Parcel.obtain(); + data.writeInterfaceToken("android.ui.ISurfaceComposer"); + surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED + data, null, 0); + data.recycle(); + } + } catch (RemoteException ex) { + Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); } + mBootAnimationStopped = true; + } - // If we are turning on the screen after the boot is completed - // normally, don't do so until we have the application and - // wallpaper. - if (mSystemBooted && ((!haveApp && !haveKeyguard) || - (wallpaperEnabled && !haveWallpaper))) { - return; - } + if (!mForceDisplayEnabled && !checkBootAnimationCompleteLocked()) { + if (DEBUG_BOOT) Slog.i(TAG, "performEnableScreen: Waiting for anim complete"); + return; } mDisplayEnabled = true; if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG, "******************** ENABLING SCREEN!"); - if (false) { - StringWriter sw = new StringWriter(); - PrintWriter pw = new FastPrintWriter(sw, false, 1024); - this.dump(null, pw, null); - pw.flush(); - Slog.i(TAG, sw.toString()); - } - try { - IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger"); - if (surfaceFlinger != null) { - //Slog.i(TAG, "******* TELLING SURFACE FLINGER WE ARE BOOTED!"); - Parcel data = Parcel.obtain(); - data.writeInterfaceToken("android.ui.ISurfaceComposer"); - surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED - data, null, 0); - data.recycle(); - } - } catch (RemoteException ex) { - Slog.e(TAG, "Boot completed: SurfaceFlinger is dead!"); - } // Enable input dispatch. mInputMonitor.setEventDispatchingLw(mEventDispatchingEnabled); } + try { + mActivityManager.bootAnimationComplete(); + } catch (RemoteException e) { + } + mPolicy.enableScreenAfterBoot(); // Make sure the last requested orientation has been applied. updateRotationUnchecked(false, false); } + private boolean checkBootAnimationCompleteLocked() { + if (SystemService.isRunning(BOOT_ANIMATION_SERVICE)) { + mH.removeMessages(H.CHECK_IF_BOOT_ANIMATION_FINISHED); + mH.sendEmptyMessageDelayed(H.CHECK_IF_BOOT_ANIMATION_FINISHED, + BOOT_ANIMATION_POLL_INTERVAL); + if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Waiting for anim complete"); + return false; + } + if (DEBUG_BOOT) Slog.i(TAG, "checkBootAnimationComplete: Animation complete!"); + return true; + } + public void showBootMessage(final CharSequence msg, final boolean always) { boolean first = false; synchronized(mWindowMap) { @@ -5767,7 +5803,16 @@ public class WindowManagerService extends IWindowManager.Stub com.android.internal.R.bool.config_windowIsRound) && mContext.getResources().getBoolean( com.android.internal.R.bool.config_windowShowCircularMask)) { - mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK)); + mH.sendMessage(mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK)); + } + } + + public void showEmulatorDisplayOverlayIfNeeded() { + if (mContext.getResources().getBoolean( + com.android.internal.R.bool.config_windowEnableCircularEmulatorDisplayOverlay) + && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false) + && Build.HARDWARE.contains("goldfish")) { + mH.sendMessage(mH.obtainMessage(H.SHOW_EMULATOR_DISPLAY_OVERLAY)); } } @@ -5775,12 +5820,12 @@ public class WindowManagerService extends IWindowManager.Stub synchronized(mWindowMap) { if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, - ">>> OPEN TRANSACTION showDisplayMask"); + ">>> OPEN TRANSACTION showCircularMask"); SurfaceControl.openTransaction(); try { // TODO(multi-display): support multiple displays if (mCircularDisplayMask == null) { - int screenOffset = (int) mContext.getResources().getDimensionPixelSize( + int screenOffset = mContext.getResources().getDimensionPixelSize( com.android.internal.R.dimen.circular_display_mask_offset); mCircularDisplayMask = new CircularDisplayMask( @@ -5794,7 +5839,32 @@ public class WindowManagerService extends IWindowManager.Stub } finally { SurfaceControl.closeTransaction(); if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, - "<<< CLOSE TRANSACTION showDisplayMask"); + "<<< CLOSE TRANSACTION showCircularMask"); + } + } + } + + public void showEmulatorDisplayOverlay() { + synchronized(mWindowMap) { + + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, + ">>> OPEN TRANSACTION showEmulatorDisplayOverlay"); + SurfaceControl.openTransaction(); + try { + if (mEmulatorDisplayOverlay == null) { + mEmulatorDisplayOverlay = new EmulatorDisplayOverlay( + mContext, + getDefaultDisplayContentLocked().getDisplay(), + mFxSession, + mPolicy.windowTypeToLayerLw( + WindowManager.LayoutParams.TYPE_POINTER) + * TYPE_LAYER_MULTIPLIER + 10); + } + mEmulatorDisplayOverlay.setVisibility(true); + } finally { + SurfaceControl.closeTransaction(); + if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, + "<<< CLOSE TRANSACTION showEmulatorDisplayOverlay"); } } } @@ -5892,7 +5962,7 @@ public class WindowManagerService extends IWindowManager.Stub @Override public Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height, boolean force565) { - if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER, + if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER, "screenshotApplications()")) { throw new SecurityException("Requires READ_FRAME_BUFFER permission"); } @@ -5912,7 +5982,7 @@ public class WindowManagerService extends IWindowManager.Stub return null; } - Bitmap rawss = null; + Bitmap bm = null; int maxLayer = 0; final Rect frame = new Rect(); @@ -6053,10 +6123,8 @@ public class WindowManagerService extends IWindowManager.Stub // The screenshot API does not apply the current screen rotation. rot = getDefaultDisplayContentLocked().getDisplay().getRotation(); + if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) { - final int tmp = width; - width = height; - height = tmp; rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90; } @@ -6082,9 +6150,9 @@ public class WindowManagerService extends IWindowManager.Stub if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG, "Taking screenshot while rotating"); - rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, - inRotation); - if (rawss == null) { + bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer, + inRotation, rot); + if (bm == null) { Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh + ") to layer " + maxLayer); return null; @@ -6094,17 +6162,6 @@ public class WindowManagerService extends IWindowManager.Stub break; } - Bitmap bm = Bitmap.createBitmap(width, height, force565 ? - Config.RGB_565 : rawss.getConfig()); - if (DEBUG_SCREENSHOT) { - bm.eraseColor(0xFF000000); - } - Matrix matrix = new Matrix(); - ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix); - Canvas canvas = new Canvas(bm); - canvas.drawBitmap(rawss, matrix, null); - canvas.setBitmap(null); - if (DEBUG_SCREENSHOT) { // TEST IF IT's ALL BLACK int[] buffer = new int[bm.getWidth() * bm.getHeight()]; @@ -6125,9 +6182,12 @@ public class WindowManagerService extends IWindowManager.Stub } } - rawss.recycle(); - - return bm; + // Copy the screenshot bitmap to another buffer so that the gralloc backed + // bitmap will not have a long lifetime. Gralloc memory can be pinned or + // duplicated and might have a higher cost than a skia backed buffer. + Bitmap ret = bm.copy(bm.getConfig(),true); + bm.recycle(); + return ret; } /** @@ -6382,9 +6442,12 @@ public class WindowManagerService extends IWindowManager.Stub } //TODO (multidisplay): Magnification is supported only for the default display. - if (mAccessibilityController != null + // Announce rotation only if we will not animate as we already have the + // windows in final state. Otherwise, we make this call at the rotation end. + if (screenRotationAnimation == null && mAccessibilityController != null && displayContent.getDisplayId() == Display.DEFAULT_DISPLAY) { - mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), rotation); + mAccessibilityController.onRotationChangedLocked(getDefaultDisplayContentLocked(), + rotation); } return true; @@ -7425,7 +7488,10 @@ public class WindowManagerService extends IWindowManager.Stub public static final int NEW_ANIMATOR_SCALE = 34; - public static final int SHOW_DISPLAY_MASK = 35; + public static final int SHOW_CIRCULAR_DISPLAY_MASK = 35; + public static final int SHOW_EMULATOR_DISPLAY_OVERLAY = 36; + + public static final int CHECK_IF_BOOT_ANIMATION_FINISHED = 37; @Override public void handleMessage(Message msg) { @@ -7821,11 +7887,16 @@ public class WindowManagerService extends IWindowManager.Stub break; } - case SHOW_DISPLAY_MASK: { + case SHOW_CIRCULAR_DISPLAY_MASK: { showCircularMask(); break; } + case SHOW_EMULATOR_DISPLAY_OVERLAY: { + showEmulatorDisplayOverlay(); + break; + } + case DO_ANIMATION_CALLBACK: { try { ((IRemoteCallback)msg.obj).sendResult(null); @@ -7906,6 +7977,17 @@ public class WindowManagerService extends IWindowManager.Stub } } break; + case CHECK_IF_BOOT_ANIMATION_FINISHED: { + final boolean bootAnimationComplete; + synchronized (mWindowMap) { + if (DEBUG_BOOT) Slog.i(TAG, "CHECK_IF_BOOT_ANIMATION_FINISHED:"); + bootAnimationComplete = checkBootAnimationCompleteLocked(); + } + if (bootAnimationComplete) { + performEnableScreen(); + } + } + break; } if (DEBUG_WINDOW_TRACE) { Slog.v(TAG, "handleMessage: exit"); @@ -8474,7 +8556,8 @@ public class WindowManagerService extends IWindowManager.Stub layerChanged = true; anyLayerChanged = true; } - if (layerChanged && w.getStack().isDimming(winAnimator)) { + final TaskStack stack = w.getStack(); + if (layerChanged && stack != null && stack.isDimming(winAnimator)) { // Force an animation pass just to update the mDimLayer layer. scheduleAnimationLocked(); } @@ -9298,6 +9381,9 @@ public class WindowManagerService extends IWindowManager.Stub && !w.mExiting) { final WindowStateAnimator winAnimator = w.mWinAnimator; final TaskStack stack = w.getStack(); + if (stack == null) { + return; + } stack.setDimmingTag(); if (!stack.isDimming(winAnimator)) { if (localLOGV) Slog.v(TAG, "Win " + w + " start dimming."); @@ -9395,6 +9481,9 @@ public class WindowManagerService extends IWindowManager.Stub if (mCircularDisplayMask != null) { mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation); } + if (mEmulatorDisplayOverlay != null) { + mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, mRotation); + } boolean focusDisplayed = false; diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index dd611ce..da97876 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1368,7 +1368,10 @@ class WindowStateAnimator { mAnimator.setPendingLayoutChanges(w.getDisplayId(), WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER); if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) { - w.getStack().startDimmingIfNeeded(this); + final TaskStack stack = w.getStack(); + if (stack != null) { + stack.startDimmingIfNeeded(this); + } } } catch (RuntimeException e) { // If something goes wrong with the surface (such diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index 1f377c7..d81cdd9 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -11,7 +11,6 @@ LOCAL_SRC_FILES += \ $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \ $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \ $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \ - $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiMhlController.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \ $(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \ diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp index 39b70a8..7b2e408 100644 --- a/services/core/jni/onload.cpp +++ b/services/core/jni/onload.cpp @@ -38,7 +38,6 @@ int register_android_server_location_GpsLocationProvider(JNIEnv* env); int register_android_server_location_FlpHardwareProvider(JNIEnv* env); int register_android_server_connectivity_Vpn(JNIEnv* env); int register_android_server_hdmi_HdmiCecController(JNIEnv* env); -int register_android_server_hdmi_HdmiMhlController(JNIEnv* env); int register_android_server_tv_TvInputHal(JNIEnv* env); int register_android_server_PersistentDataBlockService(JNIEnv* env); int register_android_server_fingerprint_FingerprintService(JNIEnv* env); @@ -76,7 +75,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved) register_android_server_ConsumerIrService(env); register_android_server_BatteryStatsService(env); register_android_server_hdmi_HdmiCecController(env); - register_android_server_hdmi_HdmiMhlController(env); register_android_server_tv_TvInputHal(env); register_android_server_PersistentDataBlockService(env); register_android_server_fingerprint_FingerprintService(env); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 09584f4..8e82e2a 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -44,13 +44,13 @@ import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; +import android.database.ContentObserver; +import android.hardware.usb.UsbManager; import android.media.AudioManager; import android.media.IAudioService; import android.net.ConnectivityManager; -import android.net.Uri; -import android.database.ContentObserver; -import android.hardware.usb.UsbManager; import android.net.ProxyInfo; +import android.net.Uri; import android.os.Binder; import android.os.Bundle; import android.os.Environment; @@ -69,6 +69,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.provider.Settings; import android.security.Credentials; +import android.security.IKeyChainService; import android.security.KeyChain; import android.security.KeyChain.KeyChainConnection; import android.util.Log; @@ -110,6 +111,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintWriter; +import java.security.cert.CertificateEncodingException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -166,12 +168,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } private static final Set<String> SECURE_SETTINGS_WHITELIST; + private static final Set<String> SECURE_SETTINGS_DEVICEOWNER_WHITELIST; private static final Set<String> GLOBAL_SETTINGS_WHITELIST; static { SECURE_SETTINGS_WHITELIST = new HashSet(); SECURE_SETTINGS_WHITELIST.add(Settings.Secure.DEFAULT_INPUT_METHOD); SECURE_SETTINGS_WHITELIST.add(Settings.Secure.SKIP_FIRST_USE_HINTS); + SECURE_SETTINGS_DEVICEOWNER_WHITELIST = new HashSet(); + SECURE_SETTINGS_DEVICEOWNER_WHITELIST.addAll(SECURE_SETTINGS_WHITELIST); + SECURE_SETTINGS_DEVICEOWNER_WHITELIST.add(Settings.Secure.LOCATION_MODE); + GLOBAL_SETTINGS_WHITELIST = new HashSet(); GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED); GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME); @@ -2824,6 +2831,35 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } + @Override + public boolean installKeyPair(ComponentName who, byte[] privKey, byte[] cert, String alias) { + if (who == null) { + throw new NullPointerException("ComponentName is null"); + } + synchronized (this) { + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + } + final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); + final long id = Binder.clearCallingIdentity(); + try { + final KeyChainConnection keyChainConnection = KeyChain.bindAsUser(mContext, userHandle); + try { + IKeyChainService keyChain = keyChainConnection.getService(); + return keyChain.installKeyPair(privKey, cert, alias); + } catch (RemoteException e) { + Log.e(LOG_TAG, "Installing certificate", e); + } finally { + keyChainConnection.close(); + } + } catch (InterruptedException e) { + Log.w(LOG_TAG, "Interrupted while installing certificate", e); + Thread.currentThread().interrupt(); + } finally { + Binder.restoreCallingIdentity(id); + } + return false; + } + void wipeDataLocked(int flags) { // If the SD card is encrypted and non-removable, we have to force a wipe. boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted(); @@ -4608,7 +4644,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { @Override public void setUserRestriction(ComponentName who, String key, boolean enabled) { - final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId()); + final UserHandle user = new UserHandle(UserHandle.getCallingUserId()); + final int userHandle = user.getIdentifier(); synchronized (this) { if (who == null) { throw new NullPointerException("ComponentName is null"); @@ -4619,7 +4656,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (!isDeviceOwner && DEVICE_OWNER_USER_RESTRICTIONS.contains(key)) { throw new SecurityException("Profile owners cannot set user restriction " + key); } - boolean alreadyRestricted = mUserManager.hasUserRestriction(key, userHandle); + boolean alreadyRestricted = mUserManager.hasUserRestriction(key, user); IAudioService iAudioService = null; if (UserManager.DISALLOW_UNMUTE_MICROPHONE.equals(key) @@ -4645,7 +4682,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (UserManager.DISALLOW_CONFIG_WIFI.equals(key)) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0, - userHandle.getIdentifier()); + userHandle); } else if (UserManager.DISALLOW_USB_FILE_TRANSFER.equals(key)) { UsbManager manager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); @@ -4653,27 +4690,30 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } else if (UserManager.DISALLOW_SHARE_LOCATION.equals(key)) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF, - userHandle.getIdentifier()); + userHandle); Settings.Secure.putStringForUser(mContext.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "", - userHandle.getIdentifier()); + userHandle); } else if (UserManager.DISALLOW_DEBUGGING_FEATURES.equals(key)) { - Settings.Global.putStringForUser(mContext.getContentResolver(), - Settings.Global.ADB_ENABLED, "0", userHandle.getIdentifier()); + // Only disable adb if changing for primary user, since it is global + if (userHandle == UserHandle.USER_OWNER) { + Settings.Global.putStringForUser(mContext.getContentResolver(), + Settings.Global.ADB_ENABLED, "0", userHandle); + } } else if (UserManager.ENSURE_VERIFY_APPS.equals(key)) { Settings.Global.putStringForUser(mContext.getContentResolver(), Settings.Global.PACKAGE_VERIFIER_ENABLE, "1", - userHandle.getIdentifier()); + userHandle); Settings.Global.putStringForUser(mContext.getContentResolver(), Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, "1", - userHandle.getIdentifier()); + userHandle); } else if (UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES.equals(key)) { Settings.Secure.putIntForUser(mContext.getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS, 0, - userHandle.getIdentifier()); + userHandle); } } - mUserManager.setUserRestriction(key, enabled, userHandle); + mUserManager.setUserRestriction(key, enabled, user); } finally { restoreCallingIdentity(id); } @@ -5109,11 +5149,17 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (who == null) { throw new NullPointerException("ComponentName is null"); } - getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); + ActiveAdmin activeAdmin = + getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER); - if (!SECURE_SETTINGS_WHITELIST.contains(setting)) { + if (isDeviceOwner(activeAdmin.info.getPackageName())) { + if (!SECURE_SETTINGS_DEVICEOWNER_WHITELIST.contains(setting)) { + throw new SecurityException(String.format( + "Permission denial: Device owners cannot update %1$s", setting)); + } + } else if (!SECURE_SETTINGS_WHITELIST.contains(setting)) { throw new SecurityException(String.format( - "Permission denial: profile/device owners cannot update %1$s", setting)); + "Permission denial: Profile owners cannot update %1$s", setting)); } long id = Binder.clearCallingIdentity(); diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java index 62a7ec0..972c929 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java +++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java @@ -61,7 +61,7 @@ class UsageStatsDatabase { /** * Initialize any directories required and index what stats are available. */ - void init() { + public void init(long currentTimeMillis) { synchronized (mLock) { for (File f : mIntervalDirs) { f.mkdirs(); @@ -72,27 +72,53 @@ class UsageStatsDatabase { } checkVersionLocked(); + indexFilesLocked(); - final FilenameFilter backupFileFilter = new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return !name.endsWith(".bak"); + // Delete files that are in the future. + for (TimeSparseArray<AtomicFile> files : mSortedStatFiles) { + final int startIndex = files.closestIndexOnOrAfter(currentTimeMillis); + if (startIndex < 0) { + continue; } - }; - // Index the available usage stat files on disk. - for (int i = 0; i < mSortedStatFiles.length; i++) { + final int fileCount = files.size(); + for (int i = startIndex; i < fileCount; i++) { + files.valueAt(i).delete(); + } + + // Remove in a separate loop because any accesses (valueAt) + // will cause a gc in the SparseArray and mess up the order. + for (int i = startIndex; i < fileCount; i++) { + files.removeAt(i); + } + } + } + } + + private void indexFilesLocked() { + final FilenameFilter backupFileFilter = new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + return !name.endsWith(".bak"); + } + }; + + // Index the available usage stat files on disk. + for (int i = 0; i < mSortedStatFiles.length; i++) { + if (mSortedStatFiles[i] == null) { mSortedStatFiles[i] = new TimeSparseArray<>(); - File[] files = mIntervalDirs[i].listFiles(backupFileFilter); - if (files != null) { - if (DEBUG) { - Slog.d(TAG, "Found " + files.length + " stat files for interval " + i); - } + } else { + mSortedStatFiles[i].clear(); + } + File[] files = mIntervalDirs[i].listFiles(backupFileFilter); + if (files != null) { + if (DEBUG) { + Slog.d(TAG, "Found " + files.length + " stat files for interval " + i); + } - for (File f : files) { - final AtomicFile af = new AtomicFile(f); - mSortedStatFiles[i].put(UsageStatsXml.parseBeginTime(af), af); - } + for (File f : files) { + final AtomicFile af = new AtomicFile(f); + mSortedStatFiles[i].put(UsageStatsXml.parseBeginTime(af), af); } } } @@ -135,6 +161,38 @@ class UsageStatsDatabase { } } + public void onTimeChanged(long timeDiffMillis) { + synchronized (mLock) { + for (TimeSparseArray<AtomicFile> files : mSortedStatFiles) { + final int fileCount = files.size(); + for (int i = 0; i < fileCount; i++) { + final AtomicFile file = files.valueAt(i); + final long newTime = files.keyAt(i) + timeDiffMillis; + if (newTime < 0) { + Slog.i(TAG, "Deleting file " + file.getBaseFile().getAbsolutePath() + + " for it is in the future now."); + file.delete(); + } else { + try { + file.openRead().close(); + } catch (IOException e) { + // Ignore, this is just to make sure there are no backups. + } + final File newFile = new File(file.getBaseFile().getParentFile(), + Long.toString(newTime)); + Slog.i(TAG, "Moving file " + file.getBaseFile().getAbsolutePath() + " to " + + newFile.getAbsolutePath()); + file.getBaseFile().renameTo(newFile); + } + } + files.clear(); + } + + // Now re-index the new files. + indexFilesLocked(); + } + } + /** * Get the latest stats that exist for this interval type. */ @@ -296,25 +354,24 @@ class UsageStatsDatabase { /** * Remove any usage stat files that are too old. */ - public void prune() { + public void prune(final long currentTimeMillis) { synchronized (mLock) { - long timeNow = System.currentTimeMillis(); - mCal.setTimeInMillis(timeNow); + mCal.setTimeInMillis(currentTimeMillis); mCal.addYears(-3); pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_YEARLY], mCal.getTimeInMillis()); - mCal.setTimeInMillis(timeNow); + mCal.setTimeInMillis(currentTimeMillis); mCal.addMonths(-6); pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_MONTHLY], mCal.getTimeInMillis()); - mCal.setTimeInMillis(timeNow); + mCal.setTimeInMillis(currentTimeMillis); mCal.addWeeks(-4); pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_WEEKLY], mCal.getTimeInMillis()); - mCal.setTimeInMillis(timeNow); + mCal.setTimeInMillis(currentTimeMillis); mCal.addDays(-7); pruneFilesOlderThan(mIntervalDirs[UsageStatsManager.INTERVAL_DAILY], mCal.getTimeInMillis()); diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java index 2dcdcc4..2ed9745 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UsageStatsService.java @@ -33,6 +33,7 @@ import android.content.pm.ParceledListSlice; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.os.Binder; +import android.os.Debug; import android.os.Environment; import android.os.Handler; import android.os.Looper; @@ -64,6 +65,7 @@ public class UsageStatsService extends SystemService implements private static final long TEN_SECONDS = 10 * 1000; private static final long TWENTY_MINUTES = 20 * 60 * 1000; private static final long FLUSH_INTERVAL = DEBUG ? TEN_SECONDS : TWENTY_MINUTES; + private static final long TIME_CHANGE_THRESHOLD_MILLIS = 2 * 1000; // Two seconds. // Handler message types. static final int MSG_REPORT_EVENT = 0; @@ -170,18 +172,47 @@ public class UsageStatsService extends SystemService implements } } - private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId) { + private UserUsageStatsService getUserDataAndInitializeIfNeededLocked(int userId, + long currentTimeMillis) { UserUsageStatsService service = mUserState.get(userId); if (service == null) { service = new UserUsageStatsService(userId, new File(mUsageStatsDir, Integer.toString(userId)), this); - service.init(); + service.init(currentTimeMillis); mUserState.put(userId, service); } return service; } /** + * This should be the only way to get the time from the system. + */ + private long checkAndGetTimeLocked() { + final long actualSystemTime = System.currentTimeMillis(); + final long actualRealtime = SystemClock.elapsedRealtime(); + final long expectedSystemTime = (actualRealtime - mRealTimeSnapshot) + mSystemTimeSnapshot; + if (Math.abs(actualSystemTime - expectedSystemTime) > TIME_CHANGE_THRESHOLD_MILLIS) { + // The time has changed. + final int userCount = mUserState.size(); + for (int i = 0; i < userCount; i++) { + final UserUsageStatsService service = mUserState.valueAt(i); + service.onTimeChanged(expectedSystemTime, actualSystemTime); + } + mRealTimeSnapshot = actualRealtime; + mSystemTimeSnapshot = actualSystemTime; + } + return actualSystemTime; + } + + /** + * Assuming the event's timestamp is measured in milliseconds since boot, + * convert it to a system wall time. + */ + private void convertToSystemTimeLocked(UsageEvents.Event event) { + event.mTimeStamp = Math.max(0, event.mTimeStamp - mRealTimeSnapshot) + mSystemTimeSnapshot; + } + + /** * Called by the Binder stub */ void shutdown() { @@ -196,7 +227,11 @@ public class UsageStatsService extends SystemService implements */ void reportEvent(UsageEvents.Event event, int userId) { synchronized (mLock) { - final UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId); + final long timeNow = checkAndGetTimeLocked(); + convertToSystemTimeLocked(event); + + final UserUsageStatsService service = + getUserDataAndInitializeIfNeededLocked(userId, timeNow); service.reportEvent(event); } } @@ -225,12 +260,14 @@ public class UsageStatsService extends SystemService implements * Called by the Binder stub. */ List<UsageStats> queryUsageStats(int userId, int bucketType, long beginTime, long endTime) { - if (!validRange(beginTime, endTime)) { - return null; - } - synchronized (mLock) { - UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId); + final long timeNow = checkAndGetTimeLocked(); + if (!validRange(timeNow, beginTime, endTime)) { + return null; + } + + final UserUsageStatsService service = + getUserDataAndInitializeIfNeededLocked(userId, timeNow); return service.queryUsageStats(bucketType, beginTime, endTime); } } @@ -240,12 +277,14 @@ public class UsageStatsService extends SystemService implements */ List<ConfigurationStats> queryConfigurationStats(int userId, int bucketType, long beginTime, long endTime) { - if (!validRange(beginTime, endTime)) { - return null; - } - synchronized (mLock) { - UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId); + final long timeNow = checkAndGetTimeLocked(); + if (!validRange(timeNow, beginTime, endTime)) { + return null; + } + + final UserUsageStatsService service = + getUserDataAndInitializeIfNeededLocked(userId, timeNow); return service.queryConfigurationStats(bucketType, beginTime, endTime); } } @@ -254,19 +293,20 @@ public class UsageStatsService extends SystemService implements * Called by the Binder stub. */ UsageEvents queryEvents(int userId, long beginTime, long endTime) { - if (!validRange(beginTime, endTime)) { - return null; - } - synchronized (mLock) { - UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId); + final long timeNow = checkAndGetTimeLocked(); + if (!validRange(timeNow, beginTime, endTime)) { + return null; + } + + final UserUsageStatsService service = + getUserDataAndInitializeIfNeededLocked(userId, timeNow); return service.queryEvents(beginTime, endTime); } } - private static boolean validRange(long beginTime, long endTime) { - final long timeNow = System.currentTimeMillis(); - return beginTime <= timeNow && beginTime < endTime; + private static boolean validRange(long currentTime, long beginTime, long endTime) { + return beginTime <= currentTime && beginTime < endTime; } private void flushToDiskLocked() { @@ -386,14 +426,6 @@ public class UsageStatsService extends SystemService implements */ private class LocalService extends UsageStatsManagerInternal { - /** - * The system may have its time change, so at least make sure the events - * are monotonic in order. - */ - private long computeMonotonicSystemTime(long realTime) { - return (realTime - mRealTimeSnapshot) + mSystemTimeSnapshot; - } - @Override public void reportEvent(ComponentName component, int userId, int eventType) { if (component == null) { @@ -404,7 +436,10 @@ public class UsageStatsService extends SystemService implements UsageEvents.Event event = new UsageEvents.Event(); event.mPackage = component.getPackageName(); event.mClass = component.getClassName(); - event.mTimeStamp = computeMonotonicSystemTime(SystemClock.elapsedRealtime()); + + // This will later be converted to system time. + event.mTimeStamp = SystemClock.elapsedRealtime(); + event.mEventType = eventType; mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); } @@ -418,7 +453,10 @@ public class UsageStatsService extends SystemService implements UsageEvents.Event event = new UsageEvents.Event(); event.mPackage = "android"; - event.mTimeStamp = computeMonotonicSystemTime(SystemClock.elapsedRealtime()); + + // This will later be converted to system time. + event.mTimeStamp = SystemClock.elapsedRealtime(); + event.mEventType = UsageEvents.Event.CONFIGURATION_CHANGE; event.mConfiguration = new Configuration(config); mHandler.obtainMessage(MSG_REPORT_EVENT, userId, 0, event).sendToTarget(); diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index 2769666..4916ec2 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -22,6 +22,7 @@ import android.app.usage.UsageEvents; import android.app.usage.UsageStats; import android.app.usage.UsageStatsManager; import android.content.res.Configuration; +import android.os.SystemClock; import android.util.ArraySet; import android.util.Slog; @@ -62,10 +63,9 @@ class UserUsageStatsService { mLogPrefix = "User[" + Integer.toString(userId) + "] "; } - void init() { - mDatabase.init(); + void init(final long currentTimeMillis) { + mDatabase.init(currentTimeMillis); - final long timeNow = System.currentTimeMillis(); int nullCount = 0; for (int i = 0; i < mCurrentStats.length; i++) { mCurrentStats[i] = mDatabase.getLatestUsageStats(i); @@ -73,11 +73,6 @@ class UserUsageStatsService { // Find out how many intervals we don't have data for. // Ideally it should be all or none. nullCount++; - } else if (mCurrentStats[i].beginTime > timeNow) { - Slog.e(TAG, mLogPrefix + "Interval " + i + " has stat in the future " + - mCurrentStats[i].beginTime); - mCurrentStats[i] = null; - nullCount++; } } @@ -92,7 +87,7 @@ class UserUsageStatsService { // By calling loadActiveStats, we will // generate new stats for each bucket. - loadActiveStats(); + loadActiveStats(currentTimeMillis, false); } else { // Set up the expiry date to be one day from the latest daily stat. // This may actually be today and we will rollover on the first event @@ -123,6 +118,12 @@ class UserUsageStatsService { } } + void onTimeChanged(long oldTime, long newTime) { + persistActiveStats(); + mDatabase.onTimeChanged(newTime - oldTime); + loadActiveStats(newTime, true); + } + void reportEvent(UsageEvents.Event event) { if (DEBUG) { Slog.d(TAG, mLogPrefix + "Got usage event for " + event.mPackage @@ -132,7 +133,7 @@ class UserUsageStatsService { if (event.mTimeStamp >= mDailyExpiryDate.getTimeInMillis()) { // Need to rollover - rolloverStats(); + rolloverStats(event.mTimeStamp); } final IntervalStats currentDailyStats = mCurrentStats[UsageStatsManager.INTERVAL_DAILY]; @@ -330,8 +331,8 @@ class UserUsageStatsService { } } - private void rolloverStats() { - final long startTime = System.currentTimeMillis(); + private void rolloverStats(final long currentTimeMillis) { + final long startTime = SystemClock.elapsedRealtime(); Slog.i(TAG, mLogPrefix + "Rolling over usage stats"); // Finish any ongoing events with an END_OF_DAY event. Make a note of which components @@ -348,7 +349,7 @@ class UserUsageStatsService { continuePreviousDay.add(pkgStats.mPackageName); stat.update(pkgStats.mPackageName, mDailyExpiryDate.getTimeInMillis() - 1, UsageEvents.Event.END_OF_DAY); - mStatsChanged = true; + notifyStatsChanged(); } } @@ -356,8 +357,8 @@ class UserUsageStatsService { } persistActiveStats(); - mDatabase.prune(); - loadActiveStats(); + mDatabase.prune(currentTimeMillis); + loadActiveStats(currentTimeMillis, false); final int continueCount = continuePreviousDay.size(); for (int i = 0; i < continueCount; i++) { @@ -366,12 +367,12 @@ class UserUsageStatsService { for (IntervalStats stat : mCurrentStats) { stat.update(name, beginTime, UsageEvents.Event.CONTINUE_PREVIOUS_DAY); stat.updateConfigurationStats(previousConfig, beginTime); - mStatsChanged = true; + notifyStatsChanged(); } } persistActiveStats(); - final long totalTime = System.currentTimeMillis() - startTime; + final long totalTime = SystemClock.elapsedRealtime() - startTime; Slog.i(TAG, mLogPrefix + "Rolling over usage stats complete. Took " + totalTime + " milliseconds"); } @@ -383,15 +384,16 @@ class UserUsageStatsService { } } - private void loadActiveStats() { - final long timeNow = System.currentTimeMillis(); - + /** + * @param force To force all in-memory stats to be reloaded. + */ + private void loadActiveStats(final long currentTimeMillis, boolean force) { final UnixCalendar tempCal = mDailyExpiryDate; for (int intervalType = 0; intervalType < mCurrentStats.length; intervalType++) { - tempCal.setTimeInMillis(timeNow); + tempCal.setTimeInMillis(currentTimeMillis); UnixCalendar.truncateTo(tempCal, intervalType); - if (mCurrentStats[intervalType] != null && + if (!force && mCurrentStats[intervalType] != null && mCurrentStats[intervalType].beginTime == tempCal.getTimeInMillis()) { // These are the same, no need to load them (in memory stats are always newer // than persisted stats). @@ -399,11 +401,7 @@ class UserUsageStatsService { } final long lastBeginTime = mDatabase.getLatestUsageStatsBeginTime(intervalType); - if (lastBeginTime > timeNow) { - Slog.e(TAG, mLogPrefix + "Latest usage stats for interval " + - intervalType + " begins in the future"); - mCurrentStats[intervalType] = null; - } else if (lastBeginTime >= tempCal.getTimeInMillis()) { + if (lastBeginTime >= tempCal.getTimeInMillis()) { if (DEBUG) { Slog.d(TAG, mLogPrefix + "Loading existing stats @ " + sDateFormat.format(lastBeginTime) + "(" + lastBeginTime + @@ -423,11 +421,11 @@ class UserUsageStatsService { } mCurrentStats[intervalType] = new IntervalStats(); mCurrentStats[intervalType].beginTime = tempCal.getTimeInMillis(); - mCurrentStats[intervalType].endTime = timeNow; + mCurrentStats[intervalType].endTime = currentTimeMillis; } } mStatsChanged = false; - mDailyExpiryDate.setTimeInMillis(timeNow); + mDailyExpiryDate.setTimeInMillis(currentTimeMillis); mDailyExpiryDate.addDays(1); mDailyExpiryDate.truncateToDay(); Slog.i(TAG, mLogPrefix + "Rollover scheduled @ " + diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java index 376230b..ad38b22 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoundTriggerHelper.java @@ -67,7 +67,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { final ModuleProperties moduleProperties; /** The properties for the DSP module */ - private final SoundTriggerModule mModule; + private SoundTriggerModule mModule; private final Object mLock = new Object(); private final Context mContext; private final TelephonyManager mTelephonyManager; @@ -105,7 +105,6 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { } else { // TODO: Figure out how to determine which module corresponds to the DSP hardware. moduleProperties = modules.get(0); - mModule = SoundTrigger.attachModule(moduleProperties.id, this, null); } } @@ -155,10 +154,17 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { mIsPowerSaveMode = mPowerManager.isPowerSaveMode(); } - if (moduleProperties == null || mModule == null) { + if (moduleProperties == null) { Slog.w(TAG, "Attempting startRecognition without the capability"); return STATUS_ERROR; } + if (mModule == null) { + mModule = SoundTrigger.attachModule(moduleProperties.id, this, null); + if (mModule == null) { + Slog.w(TAG, "startRecognition cannot attach to sound trigger module"); + return STATUS_ERROR; + } + } if (mCurrentSoundModelHandle != INVALID_VALUE && !soundModel.uuid.equals(mCurrentSoundModelUuid)) { @@ -446,6 +452,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener { Slog.w(TAG, "RemoteException in onError", e); } finally { internalClearStateLocked(); + if (mModule != null) { + mModule.detach(); + mModule = null; + } } } |