diff options
36 files changed, 639 insertions, 234 deletions
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index b2fd169ff55c..3fa89279e9cc 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -761,6 +761,7 @@ public class Activity extends ContextThemeWrapper boolean mStartedActivity; private boolean mDestroyed; private boolean mDoReportFullyDrawn = true; + private boolean mRestoredFromBundle; /** true if the activity is going through a transient pause */ /*package*/ boolean mTemporaryPause = false; /** true if the activity is being destroyed in order to recreate it with a new configuration */ @@ -1012,6 +1013,7 @@ public class Activity extends ContextThemeWrapper if (mVoiceInteractor != null) { mVoiceInteractor.attachActivity(this); } + mRestoredFromBundle = savedInstanceState != null; mCalled = true; } @@ -1948,7 +1950,7 @@ public class Activity extends ContextThemeWrapper if (mDoReportFullyDrawn) { mDoReportFullyDrawn = false; try { - ActivityManager.getService().reportActivityFullyDrawn(mToken); + ActivityManager.getService().reportActivityFullyDrawn(mToken, mRestoredFromBundle); } catch (RemoteException e) { } } diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index fa9d7ca8ebc5..897e42bc2b22 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -376,7 +376,7 @@ interface IActivityManager { boolean convertFromTranslucent(in IBinder token); boolean convertToTranslucent(in IBinder token, in Bundle options); void notifyActivityDrawn(in IBinder token); - void reportActivityFullyDrawn(in IBinder token); + void reportActivityFullyDrawn(in IBinder token, boolean restoredFromBundle); void restart(); void performIdleMaintenance(); void takePersistableUriPermission(in Uri uri, int modeFlags, int userId); diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index 72075a515e02..2aa3d09dd479 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -1508,6 +1508,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable { return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) != 0; } + /** @hide */ + public boolean isEncryptionAware() { + return isDirectBootAware() || isPartiallyDirectBootAware(); + } + /** * @hide */ diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 9b9499cd602d..7ae85225ef1b 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -1120,12 +1120,12 @@ public class PackageParser { final String cacheKey = getCacheKey(packageFile, flags); final File cacheFile = new File(mCacheDir, cacheKey); - // If the cache is not up to date, return null. - if (!isCacheUpToDate(packageFile, cacheFile)) { - return null; - } - try { + // If the cache is not up to date, return null. + if (!isCacheUpToDate(packageFile, cacheFile)) { + return null; + } + final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath()); Package p = fromCacheEntry(bytes); if (mCallback != null) { @@ -1140,7 +1140,7 @@ public class PackageParser { } } return p; - } catch (Exception e) { + } catch (Throwable e) { Slog.w(TAG, "Error reading package cache: ", e); // If something went wrong while reading the cache entry, delete the cache file @@ -1158,26 +1158,30 @@ public class PackageParser { return; } - final String cacheKey = getCacheKey(packageFile, flags); - final File cacheFile = new File(mCacheDir, cacheKey); + try { + final String cacheKey = getCacheKey(packageFile, flags); + final File cacheFile = new File(mCacheDir, cacheKey); - if (cacheFile.exists()) { - if (!cacheFile.delete()) { - Slog.e(TAG, "Unable to delete cache file: " + cacheFile); + if (cacheFile.exists()) { + if (!cacheFile.delete()) { + Slog.e(TAG, "Unable to delete cache file: " + cacheFile); + } } - } - final byte[] cacheEntry = toCacheEntry(parsed); + final byte[] cacheEntry = toCacheEntry(parsed); - if (cacheEntry == null) { - return; - } + if (cacheEntry == null) { + return; + } - try (FileOutputStream fos = new FileOutputStream(cacheFile)) { - fos.write(cacheEntry); - } catch (IOException ioe) { - Slog.w(TAG, "Error writing cache entry.", ioe); - cacheFile.delete(); + try (FileOutputStream fos = new FileOutputStream(cacheFile)) { + fos.write(cacheEntry); + } catch (IOException ioe) { + Slog.w(TAG, "Error writing cache entry.", ioe); + cacheFile.delete(); + } + } catch (Throwable e) { + Slog.w(TAG, "Error saving package cache.", e); } } diff --git a/core/java/android/net/ITetheringStatsProvider.aidl b/core/java/android/net/ITetheringStatsProvider.aidl index 1aeabc1e62de..da0bf4c47b94 100644 --- a/core/java/android/net/ITetheringStatsProvider.aidl +++ b/core/java/android/net/ITetheringStatsProvider.aidl @@ -30,7 +30,10 @@ import android.net.NetworkStats; */ interface ITetheringStatsProvider { // Returns cumulative statistics for all tethering sessions since boot, on all upstreams. - NetworkStats getTetherStats(); + // @code {how} is one of the NetworkStats.STATS_PER_* constants. If {@code how} is + // {@code STATS_PER_IFACE}, the provider should not include any traffic that is already + // counted by kernel interface counters. + NetworkStats getTetherStats(int how); // Sets the interface quota for the specified upstream interface. This is defined as the number // of bytes, starting from zero and counting from now, after which data should stop being diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java index be9e80973875..171adc054bbe 100644 --- a/core/java/android/net/NetworkStats.java +++ b/core/java/android/net/NetworkStats.java @@ -82,6 +82,11 @@ public class NetworkStats implements Parcelable { /** {@link #roaming} value where roaming data is accounted. */ public static final int ROAMING_YES = 1; + /** Denotes a request for stats at the interface level. */ + public static final int STATS_PER_IFACE = 0; + /** Denotes a request for stats at the interface and UID level. */ + public static final int STATS_PER_UID = 1; + // TODO: move fields to "mVariable" notation /** diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index e6e1da4a71c7..05627160cc3a 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -281,7 +281,7 @@ interface INetworkManagementService /** * Return summary of network statistics all tethering interfaces. */ - NetworkStats getNetworkStatsTethering(); + NetworkStats getNetworkStatsTethering(int how); /** * Set quota for an interface. diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp index 94edde1a2798..325f6d4615d7 100644 --- a/core/jni/android/graphics/BitmapFactory.cpp +++ b/core/jni/android/graphics/BitmapFactory.cpp @@ -75,6 +75,9 @@ jstring encodedFormatToString(JNIEnv* env, SkEncodedImageFormat format) { case SkEncodedImageFormat::kWEBP: mimeType = "image/webp"; break; + case SkEncodedImageFormat::kHEIF: + mimeType = "image/heif"; + break; case SkEncodedImageFormat::kWBMP: mimeType = "image/vnd.wap.wbmp"; break; diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java index 2f48ffbfdb5c..fc4d15fad5ca 100644 --- a/media/java/android/media/MediaFile.java +++ b/media/java/android/media/MediaFile.java @@ -80,8 +80,9 @@ public class MediaFile { public static final int FILE_TYPE_BMP = 34; public static final int FILE_TYPE_WBMP = 35; public static final int FILE_TYPE_WEBP = 36; + public static final int FILE_TYPE_HEIF = 37; private static final int FIRST_IMAGE_FILE_TYPE = FILE_TYPE_JPEG; - private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_WEBP; + private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_HEIF; // Raw image file types public static final int FILE_TYPE_DNG = 300; @@ -239,6 +240,8 @@ public class MediaFile { addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp", MtpConstants.FORMAT_BMP, true); addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp", MtpConstants.FORMAT_DEFINED, false); addFileType("WEBP", FILE_TYPE_WEBP, "image/webp", MtpConstants.FORMAT_DEFINED, false); + addFileType("HEIC", FILE_TYPE_HEIF, "image/heif", MtpConstants.FORMAT_HEIF, true); + addFileType("HEIF", FILE_TYPE_HEIF, "image/heif", MtpConstants.FORMAT_HEIF, false); addFileType("DNG", FILE_TYPE_DNG, "image/x-adobe-dng", MtpConstants.FORMAT_DNG, true); addFileType("CR2", FILE_TYPE_CR2, "image/x-canon-cr2", MtpConstants.FORMAT_TIFF, false); diff --git a/media/java/android/mtp/MtpConstants.java b/media/java/android/mtp/MtpConstants.java index 7d078d7a97cf..88e287e6264f 100644 --- a/media/java/android/mtp/MtpConstants.java +++ b/media/java/android/mtp/MtpConstants.java @@ -211,6 +211,8 @@ public final class MtpConstants { public static final int FORMAT_JPX = 0x3810; /** Format code for DNG files */ public static final int FORMAT_DNG = 0x3811; + /** Format code for HEIF files {@hide} */ + public static final int FORMAT_HEIF = 0x3812; /** Format code for firmware files */ public static final int FORMAT_UNDEFINED_FIRMWARE = 0xB802; /** Format code for Windows image files */ diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index 698c9c96fe01..9847d705adcf 100755 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -595,6 +595,7 @@ public class MtpDatabase implements AutoCloseable { MtpConstants.FORMAT_XML_DOCUMENT, MtpConstants.FORMAT_FLAC, MtpConstants.FORMAT_DNG, + MtpConstants.FORMAT_HEIF, }; } @@ -705,6 +706,7 @@ public class MtpDatabase implements AutoCloseable { case MtpConstants.FORMAT_PNG: case MtpConstants.FORMAT_BMP: case MtpConstants.FORMAT_DNG: + case MtpConstants.FORMAT_HEIF: return IMAGE_PROPERTIES; default: return FILE_PROPERTIES; diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp index cf4458a6fd49..5b874cd82678 100644 --- a/media/jni/android_mtp_MtpDatabase.cpp +++ b/media/jni/android_mtp_MtpDatabase.cpp @@ -849,6 +849,7 @@ MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle, // read EXIF data for thumbnail information switch (info.mFormat) { case MTP_FORMAT_EXIF_JPEG: + case MTP_FORMAT_HEIF: case MTP_FORMAT_JFIF: { ExifData *exifdata = exif_data_new_from_file(path); if (exifdata) { @@ -906,6 +907,7 @@ void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) { switch (format) { case MTP_FORMAT_EXIF_JPEG: + case MTP_FORMAT_HEIF: case MTP_FORMAT_JFIF: { ExifData *exifdata = exif_data_new_from_file(path); if (exifdata) { diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java index e3eaadd2c66c..4b377153e558 100644 --- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java +++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java @@ -439,7 +439,12 @@ public class SwipeHelper implements Gefingerpoken { public void onAnimationEnd(Animator animation) { updateSwipeProgressFromOffset(animView, canBeDismissed); mDismissPendingMap.remove(animView); - if (!mCancelled) { + boolean wasRemoved = false; + if (animView instanceof ExpandableNotificationRow) { + ExpandableNotificationRow row = (ExpandableNotificationRow) animView; + wasRemoved = row.isRemoved(); + } + if (!mCancelled || wasRemoved) { mCallback.onChildDismissed(animView); } if (endAction != null) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java index 188f21600925..c2da72bb666e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java @@ -4539,7 +4539,10 @@ public class NotificationStackScrollLayout extends ViewGroup anim.start(); } } else if (mMenuExposedView instanceof ExpandableNotificationRow) { - ((ExpandableNotificationRow) mMenuExposedView).resetTranslation(); + ExpandableNotificationRow row = (ExpandableNotificationRow) mMenuExposedView; + if (!row.isRemoved()) { + row.resetTranslation(); + } } mMenuExposedView = null; } diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index 8d7afc23c6a8..0c787dbfc316 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -62,6 +62,14 @@ message MetricsEvent { // The action failed TYPE_FAILURE = 11; + + // Type for APP_TRANSITION_REPORTED_DRAWN event: The activity was started without restoring from + // a bundle. + TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE = 12; + + // Type for APP_TRANSITION_REPORTED_DRAWN event: The activity was started with restoring from + // a bundle. + TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE = 13; } // Types of alerts, as bit field values @@ -4265,6 +4273,14 @@ message MetricsEvent { // FIELD: The numeric preference value (of type int) when it is changed in Settings FIELD_SETTINGS_PREFERENCE_CHANGE_INT_VALUE = 1089; + // ACTION: Logged when the app has notified that it has fully drawn. See + // Activity.reportFullyDrawn(). + APP_TRANSITION_REPORTED_DRAWN = 1090; + + // FIELD: The delay of the activity reporting to be fully drawn measured from the beginning of + // the app transition. + APP_TRANSITION_REPORTED_DRAWN_MS = 1091; + // Add new aosp constants above this line. // END OF AOSP CONSTANTS } diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java index be4d1064ec9c..d1cf0255b18c 100644 --- a/services/core/java/com/android/server/AlarmManagerService.java +++ b/services/core/java/com/android/server/AlarmManagerService.java @@ -850,6 +850,7 @@ class AlarmManagerService extends SystemService { static final class InFlight { final PendingIntent mPendingIntent; + final long mWhenElapsed; final IBinder mListener; final WorkSource mWorkSource; final int mUid; @@ -862,6 +863,7 @@ class AlarmManagerService extends SystemService { WorkSource workSource, int uid, String alarmPkg, int alarmType, String tag, long nowELAPSED) { mPendingIntent = pendingIntent; + mWhenElapsed = nowELAPSED; mListener = listener != null ? listener.asBinder() : null; mWorkSource = workSource; mUid = uid; @@ -883,6 +885,7 @@ class AlarmManagerService extends SystemService { public String toString() { return "InFlight{" + "pendingIntent=" + mPendingIntent + + ", when=" + mWhenElapsed + ", workSource=" + mWorkSource + ", uid=" + mUid + ", tag=" + mTag @@ -1567,8 +1570,10 @@ class AlarmManagerService extends SystemService { pw.println(); pw.print(" Broadcast ref count: "); pw.println(mBroadcastRefCount); - pw.print(" PendingIntent send/finish count: "); pw.println(mSendCount); - pw.print(" Listener send/complete count: "); pw.println(mListenerCount); + pw.print(" PendingIntent send count: "); pw.println(mSendCount); + pw.print(" PendingIntent finish count: "); pw.println(mSendFinishCount); + pw.print(" Listener send count: "); pw.println(mListenerCount); + pw.print(" Listener finish count: "); pw.println(mListenerFinishCount); pw.println(); if (mInFlight.size() > 0) { @@ -2949,7 +2954,11 @@ class AlarmManagerService extends SystemService { @GuardedBy("mLock") private int mSendCount = 0; @GuardedBy("mLock") + private int mSendFinishCount = 0; + @GuardedBy("mLock") private int mListenerCount = 0; + @GuardedBy("mLock") + private int mListenerFinishCount = 0; class DeliveryTracker extends IAlarmCompleteListener.Stub implements PendingIntent.OnFinished { @@ -3054,7 +3063,7 @@ class AlarmManagerService extends SystemService { Slog.i(TAG, "alarmComplete() from " + who); } updateTrackingLocked(inflight); - mListenerCount--; + mListenerFinishCount++; } else { // Delivery timed out, and the timeout handling already took care of // updating our tracking here, so we needn't do anything further. @@ -3075,7 +3084,7 @@ class AlarmManagerService extends SystemService { public void onSendFinished(PendingIntent pi, Intent intent, int resultCode, String resultData, Bundle resultExtras) { synchronized (mLock) { - mSendCount--; + mSendFinishCount++; updateTrackingLocked(removeLocked(pi, intent)); } } @@ -3092,7 +3101,7 @@ class AlarmManagerService extends SystemService { Slog.i(TAG, "Alarm listener " + who + " timed out in delivery"); } updateTrackingLocked(inflight); - mListenerCount--; + mListenerFinishCount++; } else { if (DEBUG_LISTENER_CALLBACK) { Slog.i(TAG, "Spurious timeout of listener " + who); @@ -3125,7 +3134,7 @@ class AlarmManagerService extends SystemService { // 'finished' callback won't be invoked. We also don't need // to do any wakelock or stats tracking, so we have nothing // left to do here but go on to the next thing. - mSendCount--; + mSendFinishCount++; return; } } else { @@ -3150,6 +3159,7 @@ class AlarmManagerService extends SystemService { // alarm was not possible, so we have no wakelock or timeout or // stats management to do. It threw before we posted the delayed // timeout message, so we're done here. + mListenerFinishCount++; return; } } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 5110929bb947..ec83a03f8aff 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -4583,8 +4583,8 @@ public class ConnectivityService extends IConnectivityManager.Stub private void updateCapabilities( int oldScore, NetworkAgentInfo nai, NetworkCapabilities networkCapabilities) { // Once a NetworkAgent is connected, complain if some immutable capabilities are removed. - if (nai.everConnected && - !nai.networkCapabilities.satisfiedByNetworkCapabilities(networkCapabilities)) { + if (nai.everConnected && !nai.networkCapabilities.satisfiedByImmutableNetworkCapabilities( + networkCapabilities)) { // TODO: consider not complaining when a network agent degrade its capabilities if this // does not cause any request (that is not a listen) currently matching that agent to // stop being matched by the updated agent. diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 901e1e7c424d..a678cb368186 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -34,6 +34,7 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY; import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST; import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST; import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_ALL; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; @@ -66,6 +67,7 @@ import android.net.NetworkStats; import android.net.NetworkUtils; import android.net.RouteInfo; import android.net.UidRange; +import android.net.util.NetdService; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.os.BatteryStats; @@ -361,7 +363,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub if (DBG) Slog.d(TAG, "Awaiting socket connection"); connectedSignal.await(); if (DBG) Slog.d(TAG, "Connected"); + if (DBG) Slog.d(TAG, "Connecting native netd service"); service.connectNativeNetdService(); + if (DBG) Slog.d(TAG, "Connected"); return service; } @@ -585,14 +589,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub } private void connectNativeNetdService() { - boolean nativeServiceAvailable = false; - try { - mNetdService = INetd.Stub.asInterface(ServiceManager.getService(NETD_SERVICE_NAME)); - nativeServiceAvailable = mNetdService.isAlive(); - } catch (RemoteException e) {} - if (!nativeServiceAvailable) { - Slog.wtf(TAG, "Can't connect to NativeNetdService " + NETD_SERVICE_NAME); - } + mNetdService = NetdService.get(); } /** @@ -605,36 +602,30 @@ public class NetworkManagementService extends INetworkManagementService.Stub // only enable bandwidth control when support exists final boolean hasKernelSupport = new File("/proc/net/xt_qtaguid/ctrl").exists(); - if (hasKernelSupport) { - Slog.d(TAG, "enabling bandwidth control"); - try { - mConnector.execute("bandwidth", "enable"); - mBandwidthControlEnabled = true; - } catch (NativeDaemonConnectorException e) { - Log.wtf(TAG, "problem enabling bandwidth controls", e); - } - } else { - Slog.i(TAG, "not enabling bandwidth control"); - } - SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); + // push any existing quota or UID rules + synchronized (mQuotaLock) { - if (mBandwidthControlEnabled) { - try { - getBatteryStats().noteNetworkStatsEnabled(); - } catch (RemoteException e) { + if (hasKernelSupport) { + Slog.d(TAG, "enabling bandwidth control"); + try { + mConnector.execute("bandwidth", "enable"); + mBandwidthControlEnabled = true; + } catch (NativeDaemonConnectorException e) { + Log.wtf(TAG, "problem enabling bandwidth controls", e); + } + } else { + Slog.i(TAG, "not enabling bandwidth control"); } - } - try { - mConnector.execute("strict", "enable"); - mStrictEnabled = true; - } catch (NativeDaemonConnectorException e) { - Log.wtf(TAG, "Failed strict enable", e); - } + SystemProperties.set(PROP_QTAGUID_ENABLED, mBandwidthControlEnabled ? "1" : "0"); - // push any existing quota or UID rules - synchronized (mQuotaLock) { + try { + mConnector.execute("strict", "enable"); + mStrictEnabled = true; + } catch (NativeDaemonConnectorException e) { + Log.wtf(TAG, "Failed strict enable", e); + } setDataSaverModeEnabled(mDataSaverMode); @@ -713,6 +704,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } } + + if (mBandwidthControlEnabled) { + try { + getBatteryStats().noteNetworkStatsEnabled(); + } catch (RemoteException e) { + } + } + } /** @@ -1791,6 +1790,30 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } + private void applyUidCleartextNetworkPolicy(int uid, int policy) { + final String policyString; + switch (policy) { + case StrictMode.NETWORK_POLICY_ACCEPT: + policyString = "accept"; + break; + case StrictMode.NETWORK_POLICY_LOG: + policyString = "log"; + break; + case StrictMode.NETWORK_POLICY_REJECT: + policyString = "reject"; + break; + default: + throw new IllegalArgumentException("Unknown policy " + policy); + } + + try { + mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString); + mUidCleartextPolicy.put(uid, policy); + } catch (NativeDaemonConnectorException e) { + throw e.rethrowAsParcelableException(); + } + } + @Override public void setUidCleartextNetworkPolicy(int uid, int policy) { if (Binder.getCallingUid() != uid) { @@ -1800,6 +1823,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub synchronized (mQuotaLock) { final int oldPolicy = mUidCleartextPolicy.get(uid, StrictMode.NETWORK_POLICY_ACCEPT); if (oldPolicy == policy) { + // This also ensures we won't needlessly apply an ACCEPT policy if we've just + // enabled strict and the underlying iptables rules are empty. return; } @@ -1810,28 +1835,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub return; } - final String policyString; - switch (policy) { - case StrictMode.NETWORK_POLICY_ACCEPT: - policyString = "accept"; - break; - case StrictMode.NETWORK_POLICY_LOG: - policyString = "log"; - break; - case StrictMode.NETWORK_POLICY_REJECT: - policyString = "reject"; - break; - default: - throw new IllegalArgumentException("Unknown policy " + policy); - } - - try { - mConnector.execute("strict", "set_uid_cleartext_policy", uid, policyString); - mUidCleartextPolicy.put(uid, policy); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); + // netd does not keep state on strict mode policies, and cannot replace a non-accept + // policy without deleting it first. Rather than add state to netd, just always send + // it an accept policy when switching between two non-accept policies. + if (oldPolicy != StrictMode.NETWORK_POLICY_ACCEPT && + policy != StrictMode.NETWORK_POLICY_ACCEPT) { + applyUidCleartextNetworkPolicy(uid, policy); } } + applyUidCleartextNetworkPolicy(uid, policy); } @Override @@ -1852,7 +1864,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub { @Override - public NetworkStats getTetherStats() { + public NetworkStats getTetherStats(int how) { + // We only need to return per-UID stats. Per-device stats are already counted by + // interface counters. + if (how != STATS_PER_UID) { + return new NetworkStats(SystemClock.elapsedRealtime(), 0); + } + final NativeDaemonEvent[] events; try { events = mConnector.executeForList("bandwidth", "gettetherstats"); @@ -1895,14 +1913,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override - public NetworkStats getNetworkStatsTethering() { + public NetworkStats getNetworkStatsTethering(int how) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1); synchronized (mTetheringStatsProviders) { for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) { try { - stats.combineAllValues(provider.getTetherStats()); + stats.combineAllValues(provider.getTetherStats(how)); } catch (RemoteException e) { Log.e(TAG, "Problem reading tethering stats from " + mTetheringStatsProviders.get(provider) + ": " + e); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 30e5a2cdba9d..45387bd4b363 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -4902,13 +4902,13 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public void reportActivityFullyDrawn(IBinder token) { + public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) { synchronized (this) { ActivityRecord r = ActivityRecord.isInStackLocked(token); if (r == null) { return; } - r.reportFullyDrawnLocked(); + r.reportFullyDrawnLocked(restoredFromBundle); } } diff --git a/services/core/java/com/android/server/am/ActivityMetricsLogger.java b/services/core/java/com/android/server/am/ActivityMetricsLogger.java index 98815d7e18c7..f396e9ef44a5 100644 --- a/services/core/java/com/android/server/am/ActivityMetricsLogger.java +++ b/services/core/java/com/android/server/am/ActivityMetricsLogger.java @@ -15,12 +15,17 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TR import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_DEVICE_UPTIME_SECONDS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_IS_EPHEMERAL; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_PROCESS_RUNNING; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_REPORTED_DRAWN_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_STARTING_WINDOW_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.APP_TRANSITION_WINDOWS_DRAWN_DELAY_MS; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_CLASS_NAME; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_INSTANT_APP_LAUNCH_TOKEN; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_COLD_LAUNCH; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_HOT_LAUNCH; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE; +import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE; import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_TRANSITION_WARM_LAUNCH; import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; @@ -67,12 +72,14 @@ class ActivityMetricsLogger { private final MetricsLogger mMetricsLogger = new MetricsLogger(); private long mCurrentTransitionStartTime = INVALID_START_TIME; + private long mLastTransitionStartTime = INVALID_START_TIME; private int mCurrentTransitionDeviceUptime; private int mCurrentTransitionDelayMs; private boolean mLoggedTransitionStarting; private final SparseArray<StackTransitionInfo> mStackTransitionInfo = new SparseArray<>(); + private final SparseArray<StackTransitionInfo> mLastStackTransitionInfo = new SparseArray<>(); private final class StackTransitionInfo { private ActivityRecord launchedActivity; @@ -136,6 +143,7 @@ class ActivityMetricsLogger { void notifyActivityLaunching() { if (!isAnyTransitionActive()) { mCurrentTransitionStartTime = SystemClock.uptimeMillis(); + mLastTransitionStartTime = mCurrentTransitionStartTime; } } @@ -223,7 +231,8 @@ class ActivityMetricsLogger { newInfo.launchedActivity = launchedActivity; newInfo.currentTransitionProcessRunning = processRunning; newInfo.startResult = resultCode; - mStackTransitionInfo.append(stackId, newInfo); + mStackTransitionInfo.put(stackId, newInfo); + mLastStackTransitionInfo.put(stackId, newInfo); mCurrentTransitionDeviceUptime = (int) (SystemClock.uptimeMillis() / 1000); } @@ -361,7 +370,7 @@ class ActivityMetricsLogger { builder.setType(type); builder.addTaggedData(FIELD_CLASS_NAME, info.launchedActivity.info.name); final boolean isInstantApp = info.launchedActivity.info.applicationInfo.isInstantApp(); - if (isInstantApp && info.launchedActivity.launchedFromPackage != null) { + if (info.launchedActivity.launchedFromPackage != null) { builder.addTaggedData(APP_TRANSITION_CALLING_PACKAGE_NAME, info.launchedActivity.launchedFromPackage); } @@ -388,6 +397,24 @@ class ActivityMetricsLogger { } } + void logAppTransitionReportedDrawn(ActivityRecord r, boolean restoredFromBundle) { + final StackTransitionInfo info = mLastStackTransitionInfo.get(r.getStackId()); + if (info == null) { + return; + } + final LogMaker builder = new LogMaker(APP_TRANSITION_REPORTED_DRAWN); + builder.setPackageName(r.packageName); + builder.addTaggedData(FIELD_CLASS_NAME, r.info.name); + builder.addTaggedData(APP_TRANSITION_REPORTED_DRAWN_MS, + SystemClock.uptimeMillis() - mLastTransitionStartTime); + builder.setType(restoredFromBundle + ? TYPE_TRANSITION_REPORTED_DRAWN_WITH_BUNDLE + : TYPE_TRANSITION_REPORTED_DRAWN_NO_BUNDLE); + builder.addTaggedData(APP_TRANSITION_PROCESS_RUNNING, + info.currentTransitionProcessRunning ? 1 : 0); + mMetricsLogger.write(builder); + } + private int getTransitionType(StackTransitionInfo info) { if (info.currentTransitionProcessRunning) { if (info.startResult == START_SUCCESS) { diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java index 74bdf6f3dae4..44727c35132d 100644 --- a/services/core/java/com/android/server/am/ActivityRecord.java +++ b/services/core/java/com/android/server/am/ActivityRecord.java @@ -146,6 +146,7 @@ import android.os.RemoteException; import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; +import android.os.storage.StorageManager; import android.service.voice.IVoiceInteractionSession; import android.util.EventLog; import android.util.Log; @@ -1835,7 +1836,7 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } } - public void reportFullyDrawnLocked() { + public void reportFullyDrawnLocked(boolean restoredFromBundle) { final long curTime = SystemClock.uptimeMillis(); if (displayStartTime != 0) { reportLaunchTimeLocked(curTime); @@ -1868,6 +1869,8 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo } stack.mFullyDrawnStartTime = 0; } + mStackSupervisor.mActivityMetricsLogger.logAppTransitionReportedDrawn(this, + restoredFromBundle); fullyDrawnStartTime = 0; } @@ -2011,6 +2014,13 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo /** Checks whether the activity should be shown for current user. */ public boolean okToShowLocked() { + // We cannot show activities when the device is locked and the application is not + // encryption aware. + if (!StorageManager.isUserKeyUnlocked(userId) + && !info.applicationInfo.isEncryptionAware()) { + return false; + } + return (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0 || (mStackSupervisor.isCurrentProfileLocked(userId) && service.mUserController.isUserRunningLocked(userId, 0 /* flags */)); diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java index ad661d79767d..4393e3527e4d 100644 --- a/services/core/java/com/android/server/connectivity/tethering/OffloadController.java +++ b/services/core/java/com/android/server/connectivity/tethering/OffloadController.java @@ -17,7 +17,9 @@ package com.android.server.connectivity.tethering; import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; +import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_TETHERING; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; @@ -202,16 +204,18 @@ public class OffloadController { private class OffloadTetheringStatsProvider extends ITetheringStatsProvider.Stub { @Override - public NetworkStats getTetherStats() { + public NetworkStats getTetherStats(int how) { NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0); // We can't just post to mHandler because we are mostly (but not always) called by // NetworkStatsService#performPollLocked, which is (currently) on the same thread as us. mHandler.runWithScissors(() -> { + // We have to report both per-interface and per-UID stats, because offloaded traffic + // is not seen by kernel interface counters. NetworkStats.Entry entry = new NetworkStats.Entry(); entry.set = SET_DEFAULT; entry.tag = TAG_NONE; - entry.uid = UID_TETHERING; + entry.uid = (how == STATS_PER_UID) ? UID_TETHERING : UID_ALL; updateStatsForCurrentUpstream(); diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java index ad74ff88e80f..6e1c21eea15a 100644 --- a/services/core/java/com/android/server/content/ContentService.java +++ b/services/core/java/com/android/server/content/ContentService.java @@ -646,6 +646,7 @@ public final class ContentService extends IContentService.Stub { SyncManager syncManager = getSyncManager(); if (syncManager == null) return; int userId = UserHandle.getCallingUserId(); + final int callingUid = Binder.getCallingUid(); long identityToken = clearCallingIdentity(); try { @@ -658,7 +659,8 @@ public final class ContentService extends IContentService.Stub { // Remove periodic sync. mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, "no permission to write the sync settings"); - getSyncManager().removePeriodicSync(info, extras); + getSyncManager().removePeriodicSync(info, extras, + "cancelRequest() by uid=" + callingUid); } // Cancel active syncs and clear pending syncs from the queue. syncManager.cancelScheduledSyncOperation(info, extras); @@ -814,13 +816,15 @@ public final class ContentService extends IContentService.Stub { mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS, "no permission to write the sync settings"); + final int callingUid = Binder.getCallingUid(); + int userId = UserHandle.getCallingUserId(); long identityToken = clearCallingIdentity(); try { getSyncManager() .removePeriodicSync( new SyncStorageEngine.EndPoint(account, authority, userId), - extras); + extras, "removePeriodicSync() by uid=" + callingUid); } finally { restoreCallingIdentity(identityToken); } diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java index a9c0cb0fb661..845561f09145 100644 --- a/services/core/java/com/android/server/content/SyncManager.java +++ b/services/core/java/com/android/server/content/SyncManager.java @@ -59,6 +59,7 @@ import android.net.NetworkInfo; import android.net.TrafficStats; import android.os.BatteryStats; import android.os.Binder; +import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; @@ -141,6 +142,8 @@ public class SyncManager { private static final boolean DEBUG_ACCOUNT_ACCESS = false; + private static final boolean ENABLE_SUSPICIOUS_CHECK = Build.IS_DEBUGGABLE; + /** Delay a sync due to local changes this long. In milliseconds */ private static final long LOCAL_SYNC_DELAY; @@ -463,7 +466,7 @@ public class SyncManager { } if (opx.key.equals(opy.key)) { mLogger.log("Removing duplicate sync: ", opy); - mJobScheduler.cancel(opy.jobId); + cancelJob(opy, "cleanupJobs() x=" + opx + " y=" + opy); } } } @@ -501,15 +504,21 @@ public class SyncManager { } } } - if (mLogger.enabled()) { - mLogger.log("Connected to JobScheduler: " - + numPersistedPeriodicSyncs + " periodic syncs " - + numPersistedOneshotSyncs + " oneshot syncs."); - } + final int totalJobs = (mJobSchedulerInternal == null) + ? -1 : mJobSchedulerInternal.countJobs(); + final String summary = "Loaded persisted syncs: " + + numPersistedPeriodicSyncs + " periodic syncs, " + + numPersistedOneshotSyncs + " oneshot syncs, " + + (pendingJobs.size()) + " total system server jobs, " + + totalJobs + " total jobs."; + Slog.i(TAG, summary); + mLogger.log(summary); + cleanupJobs(); - if ((numPersistedPeriodicSyncs == 0) && likelyHasPeriodicSyncs()) { - Slog.wtf(TAG, "Device booted with no persisted periodic syncs."); + if (ENABLE_SUSPICIOUS_CHECK && + (numPersistedPeriodicSyncs == 0) && likelyHasPeriodicSyncs()) { + Slog.wtf(TAG, "Device booted with no persisted periodic syncs: " + summary); } } finally { Binder.restoreCallingIdentity(token); @@ -520,6 +529,7 @@ public class SyncManager { * @return whether the device most likely has some periodic syncs. */ private boolean likelyHasPeriodicSyncs() { + // STOPSHIP Remove the google specific string. try { return AccountManager.get(mContext).getAccountsByType("com.google").length > 0; } catch (Throwable th) { @@ -566,7 +576,7 @@ public class SyncManager { mSyncStorageEngine.setOnAuthorityRemovedListener(new SyncStorageEngine.OnAuthorityRemovedListener() { @Override public void onAuthorityRemoved(EndPoint removedAuthority) { - removeSyncsForAuthority(removedAuthority); + removeSyncsForAuthority(removedAuthority, "onAuthorityRemoved"); } }); @@ -1118,14 +1128,14 @@ public class SyncManager { } } - private void removeSyncsForAuthority(EndPoint info) { + private void removeSyncsForAuthority(EndPoint info, String why) { mLogger.log("removeSyncsForAuthority: ", info); verifyJobScheduler(); List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.target.matchesSpec(info)) { mLogger.log("canceling: ", op); - getJobScheduler().cancel(op.jobId); + cancelJob(op, why); } } } @@ -1133,8 +1143,9 @@ public class SyncManager { /** * Remove a specific periodic sync identified by its target and extras. */ - public void removePeriodicSync(EndPoint target, Bundle extras) { - Message m = mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_REMOVE_PERIODIC_SYNC, target); + public void removePeriodicSync(EndPoint target, Bundle extras, String why) { + Message m = mSyncHandler.obtainMessage(mSyncHandler.MESSAGE_REMOVE_PERIODIC_SYNC, + Pair.create(target, why)); m.setData(extras); m.sendToTarget(); } @@ -1359,7 +1370,7 @@ public class SyncManager { for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(target)) { count++; - getJobScheduler().cancel(op.jobId); + cancelJob(op, why); postScheduleSyncMessage(op, 0 /* min delay */); } } @@ -1484,7 +1495,7 @@ public class SyncManager { if (isLoggable) { Slog.v(TAG, "Cancelling duplicate sync " + op); } - getJobScheduler().cancel(op.jobId); + cancelJob(op, "scheduleSyncOperationH-duplicate"); } } } @@ -1544,7 +1555,7 @@ public class SyncManager { List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(info)) { - getJobScheduler().cancel(op.jobId); + cancelJob(op, "clearScheduledSyncOperations"); getSyncStorageEngine().markPending(op.target, false); } } @@ -1562,7 +1573,7 @@ public class SyncManager { for (SyncOperation op: ops) { if (!op.isPeriodic && op.target.matchesSpec(info) && syncExtrasEquals(extras, op.extras, false)) { - getJobScheduler().cancel(op.jobId); + cancelJob(op, "cancelScheduledSyncOperation"); } } setAuthorityPendingState(info); @@ -1678,7 +1689,7 @@ public class SyncManager { List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.target.userId == userId) { - getJobScheduler().cancel(op.jobId); + cancelJob(op, "user removed u" + userId); } } } @@ -2710,7 +2721,8 @@ public class SyncManager { data.flex, data.extras); break; case MESSAGE_REMOVE_PERIODIC_SYNC: - removePeriodicSyncH((EndPoint)msg.obj, msg.getData()); + Pair<EndPoint, String> args = (Pair<EndPoint, String>) (msg.obj); + removePeriodicSyncH(args.first, msg.getData(), args.second); break; case SyncHandler.MESSAGE_CANCEL: @@ -2848,7 +2860,7 @@ public class SyncManager { // mSyncJobService.callJobFinished is async, so cancel the job to ensure we don't // find the this job in the pending jobs list while looking for duplicates // before scheduling it at a later time. - getJobScheduler().cancel(op.jobId); + cancelJob(op, "deferSyncH()"); scheduleSyncOperationH(op, delay); } } @@ -2998,7 +3010,7 @@ public class SyncManager { for (SyncOperation op: ops) { if (!containsAccountAndUser(allAccounts, op.target.account, op.target.userId)) { mLogger.log("canceling: ", op); - getJobScheduler().cancel(op.jobId); + cancelJob(op, "updateRunningAccountsH()"); } } @@ -3105,7 +3117,7 @@ public class SyncManager { /** * Remove this periodic sync operation and all one-off operations initiated by it. */ - private void removePeriodicSyncInternalH(SyncOperation syncOperation) { + private void removePeriodicSyncInternalH(SyncOperation syncOperation, String why) { // Remove this periodic sync and all one-off syncs initiated by it. List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { @@ -3117,18 +3129,18 @@ public class SyncManager { runSyncFinishedOrCanceledH(null, asc); } mLogger.log("removePeriodicSyncInternalH-canceling: ", op); - getJobScheduler().cancel(op.jobId); + cancelJob(op, why); } } } - private void removePeriodicSyncH(EndPoint target, Bundle extras) { + private void removePeriodicSyncH(EndPoint target, Bundle extras, String why) { verifyJobScheduler(); List<SyncOperation> ops = getAllPendingSyncs(); for (SyncOperation op: ops) { if (op.isPeriodic && op.target.matchesSpec(target) && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) { - removePeriodicSyncInternalH(op); + removePeriodicSyncInternalH(op, why); } } } @@ -3369,7 +3381,7 @@ public class SyncManager { // Note this part is probably okay to do before closeActiveSyncContext()... // But moved here to restore OC-dev's behavior. See b/64597061. if (!syncOperation.isPeriodic) { - getJobScheduler().cancel(syncOperation.jobId); + cancelJob(syncOperation, "runSyncFinishedOrCanceledH()-finished"); } if (!syncResult.hasError()) { @@ -3410,7 +3422,7 @@ public class SyncManager { } if (!syncOperation.isPeriodic) { - getJobScheduler().cancel(syncOperation.jobId); + cancelJob(syncOperation, "runSyncFinishedOrCanceledH()-canceled"); } if (activeSyncContext.mSyncAdapter != null) { @@ -3747,4 +3759,48 @@ public class SyncManager { return mContext; } } + + private void cancelJob(SyncOperation op, String why) { + if (op == null) { + Slog.wtf(TAG, "Null sync operation detected."); + return; + } + if (op.isPeriodic) { + mLogger.log("Removing periodic sync ", op, " for ", why); + + if (ENABLE_SUSPICIOUS_CHECK && isSuspiciousPeriodicSyncRemoval(op)) { + wtfWithLog("Suspicious removal of " + op + " for " + why); + } + } + getJobScheduler().cancel(op.jobId); + } + + private boolean isSuspiciousPeriodicSyncRemoval(SyncOperation op) { + // STOPSHIP Remove the google specific string. + if (!op.isPeriodic){ + return false; + } + switch (op.target.provider) { + case "gmail-ls": + case "com.android.contacts.metadata": + break; + default: + return false; + } + final Account account = op.target.account; + final Account[] accounts = AccountManager.get(mContext) + .getAccountsByTypeAsUser(account.type, UserHandle.of(op.target.userId)); + for (Account a : accounts) { + if (a.equals(account)) { + return true; // Account still exists. Suspicious! + } + } + // Account no longer exists. Makes sense... + return false; + } + + private void wtfWithLog(String message) { + Slog.wtf(TAG, message); + mLogger.log("WTF: ", message); + } } diff --git a/services/core/java/com/android/server/job/JobSchedulerInternal.java b/services/core/java/com/android/server/job/JobSchedulerInternal.java index bc6bd501176c..d52b3b760c11 100644 --- a/services/core/java/com/android/server/job/JobSchedulerInternal.java +++ b/services/core/java/com/android/server/job/JobSchedulerInternal.java @@ -37,4 +37,9 @@ public interface JobSchedulerInternal { void addBackingUpUid(int uid); void removeBackingUpUid(int uid); void clearAllBackingUpUids(); + + /** + * @return the total number of jobs across all UIDs. + */ + int countJobs(); } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index e25f3e65d3d8..12087b07444e 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -1835,6 +1835,13 @@ public final class JobSchedulerService extends com.android.server.SystemService } } } + + @Override + public int countJobs() { + synchronized (mLock) { + return mJobs.size(); + } + } } /** @@ -2015,6 +2022,12 @@ public final class JobSchedulerService extends com.android.server.SystemService @Override public void cancelAll() throws RemoteException { final int uid = Binder.getCallingUid(); + switch (uid) { + case Process.SYSTEM_UID: + // This really shouldn't happen. + Slog.wtf(TAG, "JobScheduler.cancelAll() called for uid=" + uid); + return; + } long ident = Binder.clearCallingIdentity(); try { diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 62b06d6242ea..5317616ad13a 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -544,6 +544,7 @@ public final class JobStore { @Override public void run() { + int numJobs = 0; try { List<JobStatus> jobs; FileInputStream fis = mJobsFile.openRead(); @@ -557,6 +558,7 @@ public final class JobStore { js.prepareLocked(am); js.enqueueTime = now; this.jobSet.add(js); + numJobs++; } } } @@ -565,15 +567,10 @@ public final class JobStore { if (DEBUG) { Slog.d(TAG, "Could not find jobs file, probably there was nothing to load."); } - } catch (XmlPullParserException e) { - if (DEBUG) { - Slog.d(TAG, "Error parsing xml.", e); - } - } catch (IOException e) { - if (DEBUG) { - Slog.d(TAG, "Error parsing xml.", e); - } + } catch (XmlPullParserException | IOException e) { + Slog.wtf(TAG, "Error jobstore xml.", e); } + Slog.i(TAG, "Read " + numJobs + " jobs"); } private List<JobStatus> readJobMapImpl(FileInputStream fis, boolean rtcIsGood) diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java index 8209adeb8947..b14aa13bfb28 100644 --- a/services/core/java/com/android/server/net/NetworkStatsService.java +++ b/services/core/java/com/android/server/net/NetworkStatsService.java @@ -29,6 +29,8 @@ import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.STATS_PER_IFACE; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkTemplate.buildTemplateMobileWildcard; @@ -1041,6 +1043,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats xtSnapshot = getNetworkStatsXt(); final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); + // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats + // providers that isn't already counted by dev and XT stats. + final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE); + xtSnapshot.combineAllValues(tetherSnapshot); + devSnapshot.combineAllValues(tetherSnapshot); // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic // can't be reattributed to responsible apps. @@ -1371,14 +1378,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); // fold tethering stats and operations into uid snapshot - final NetworkStats tetherSnapshot = getNetworkStatsTethering(); + final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); uidSnapshot.combineAllValues(tetherSnapshot); final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService( Context.TELEPHONY_SERVICE); // fold video calling data usage stats into uid snapshot - final NetworkStats vtStats = telephonyManager.getVtDataUsage(true); + final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID); if (vtStats != null) { uidSnapshot.combineAllValues(vtStats); } @@ -1397,7 +1404,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { Context.TELEPHONY_SERVICE); // Merge video calling data usage into XT - final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(false); + final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(STATS_PER_IFACE); if (vtSnapshot != null) { xtSnapshot.combineAllValues(vtSnapshot); } @@ -1409,9 +1416,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub { * Return snapshot of current tethering statistics. Will return empty * {@link NetworkStats} if any problems are encountered. */ - private NetworkStats getNetworkStatsTethering() throws RemoteException { + private NetworkStats getNetworkStatsTethering(int how) throws RemoteException { try { - return mNetworkManager.getNetworkStatsTethering(); + return mNetworkManager.getNetworkStatsTethering(how); } catch (IllegalStateException e) { Log.wtf(TAG, "problem reading network stats", e); return new NetworkStats(0L, 10); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 43e0affb590a..529fcc400463 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -85,6 +85,8 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED; import static android.content.pm.PackageParser.PARSE_IS_PRIVILEGED; import static android.content.pm.PackageParser.isApkFile; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; +import static android.os.storage.StorageManager.FLAG_STORAGE_CE; +import static android.os.storage.StorageManager.FLAG_STORAGE_DE; import static android.system.OsConstants.O_CREAT; import static android.system.OsConstants.O_RDWR; @@ -3884,8 +3886,7 @@ public class PackageManagerService extends IPackageManager.Stub throw new SecurityException("Package " + packageName + " is currently frozen!"); } - if (!userKeyUnlocked && !(ps.pkg.applicationInfo.isDirectBootAware() - || ps.pkg.applicationInfo.isPartiallyDirectBootAware())) { + if (!userKeyUnlocked && !ps.pkg.applicationInfo.isEncryptionAware()) { throw new SecurityException("Package " + packageName + " is not encryption aware!"); } } @@ -19758,6 +19759,10 @@ public class PackageManagerService extends IPackageManager.Stub // writer synchronized (mPackages) { + // NOTE: The system package always needs to be enabled; even if it's for + // a compressed stub. If we don't, installing the system package fails + // during scan [scanning checks the disabled packages]. We will reverse + // this later, after we've "installed" the stub. // Reinstate the old system package enableSystemPackageLPw(disabledPs.pkg); // Remove any native libraries from the upgraded package. @@ -19766,23 +19771,38 @@ public class PackageManagerService extends IPackageManager.Stub // Install the system package if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs); + try { + installPackageFromSystemLIF(disabledPs.codePath, false /*isPrivileged*/, allUserHandles, + outInfo.origUsers, deletedPs.getPermissionsState(), writeSettings); + } catch (PackageManagerException e) { + Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": " + + e.getMessage()); + return false; + } finally { + if (disabledPs.pkg.isStub) { + mSettings.disableSystemPackageLPw(disabledPs.name, true /*replaced*/); + } + } + return true; + } + + /** + * Installs a package that's already on the system partition. + */ + private PackageParser.Package installPackageFromSystemLIF(@NonNull File codePath, + boolean isPrivileged, @Nullable int[] allUserHandles, @Nullable int[] origUserHandles, + @Nullable PermissionsState origPermissionState, boolean writeSettings) + throws PackageManagerException { int parseFlags = mDefParseFlags | PackageParser.PARSE_MUST_BE_APK | PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM_DIR; - if (locationIsPrivileged(disabledPs.codePath)) { + if (isPrivileged || locationIsPrivileged(codePath)) { parseFlags |= PackageParser.PARSE_IS_PRIVILEGED; } - final PackageParser.Package newPkg; - try { - newPkg = scanPackageTracedLI(disabledPs.codePath, parseFlags, 0 /* scanFlags */, - 0 /* currentTime */, null); - } catch (PackageManagerException e) { - Slog.w(TAG, "Failed to restore system package:" + deletedPkg.packageName + ": " - + e.getMessage()); - return false; - } + final PackageParser.Package newPkg = + scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/, 0 /*currentTime*/, null); try { // update shared libraries for the newly re-installed system package @@ -19800,17 +19820,21 @@ public class PackageManagerService extends IPackageManager.Stub // Propagate the permissions state as we do not want to drop on the floor // runtime permissions. The update permissions method below will take // care of removing obsolete permissions and grant install permissions. - ps.getPermissionsState().copyFrom(deletedPs.getPermissionsState()); + if (origPermissionState != null) { + ps.getPermissionsState().copyFrom(origPermissionState); + } updatePermissionsLPw(newPkg.packageName, newPkg, UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); + final boolean applyUserRestrictions + = (allUserHandles != null) && (origUserHandles != null); if (applyUserRestrictions) { boolean installedStateChanged = false; if (DEBUG_REMOVE) { Slog.d(TAG, "Propagating install state across reinstall"); } for (int userId : allUserHandles) { - final boolean installed = ArrayUtils.contains(outInfo.origUsers, userId); + final boolean installed = ArrayUtils.contains(origUserHandles, userId); if (DEBUG_REMOVE) { Slog.d(TAG, " user " + userId + " => " + installed); } @@ -19833,7 +19857,7 @@ public class PackageManagerService extends IPackageManager.Stub mSettings.writeLPr(); } } - return true; + return newPkg; } private boolean deleteInstalledPackageLIF(PackageSetting ps, @@ -21766,77 +21790,183 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); } } - synchronized (mPackages) { - if (callingUid == Process.SHELL_UID - && (pkgSetting.pkgFlags & ApplicationInfo.FLAG_TEST_ONLY) == 0) { - // Shell can only change whole packages between ENABLED and DISABLED_USER states - // unless it is a test package. - int oldState = pkgSetting.getEnabled(userId); - if (className == null - && - (oldState == COMPONENT_ENABLED_STATE_DISABLED_USER - || oldState == COMPONENT_ENABLED_STATE_DEFAULT - || oldState == COMPONENT_ENABLED_STATE_ENABLED) - && - (newState == COMPONENT_ENABLED_STATE_DISABLED_USER - || newState == COMPONENT_ENABLED_STATE_DEFAULT - || newState == COMPONENT_ENABLED_STATE_ENABLED)) { - // ok - } else { - throw new SecurityException( - "Shell cannot change component state for " + packageName + "/" - + className + " to " + newState); - } + if (callingUid == Process.SHELL_UID + && (pkgSetting.pkgFlags & ApplicationInfo.FLAG_TEST_ONLY) == 0) { + // Shell can only change whole packages between ENABLED and DISABLED_USER states + // unless it is a test package. + int oldState = pkgSetting.getEnabled(userId); + if (className == null + && + (oldState == COMPONENT_ENABLED_STATE_DISABLED_USER + || oldState == COMPONENT_ENABLED_STATE_DEFAULT + || oldState == COMPONENT_ENABLED_STATE_ENABLED) + && + (newState == COMPONENT_ENABLED_STATE_DISABLED_USER + || newState == COMPONENT_ENABLED_STATE_DEFAULT + || newState == COMPONENT_ENABLED_STATE_ENABLED)) { + // ok + } else { + throw new SecurityException( + "Shell cannot change component state for " + packageName + "/" + + className + " to " + newState); } - if (className == null) { - // We're dealing with an application/package level state change - if (pkgSetting.getEnabled(userId) == newState) { - // Nothing to do + } + if (className == null) { + // We're dealing with an application/package level state change + if (pkgSetting.getEnabled(userId) == newState) { + // Nothing to do + return; + } + // If we're enabling a system stub, there's a little more work to do. + // Prior to enabling the package, we need to decompress the APK(s) to the + // data partition and then replace the version on the system partition. + final PackageParser.Package deletedPkg = pkgSetting.pkg; + final boolean isSystemStub = deletedPkg.isStub + && deletedPkg.isSystemApp(); + if (isSystemStub + && (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) { + final File codePath = decompressPackage(deletedPkg); + if (codePath == null) { + Slog.e(TAG, "couldn't decompress pkg: " + pkgSetting.name); return; } - if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT - || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { - // Don't care about who enables an app. - callingPackage = null; - } - pkgSetting.setEnabled(newState, userId, callingPackage); - // pkgSetting.pkg.mSetEnabled = newState; - } else { - // We're dealing with a component level state change - // First, verify that this is a valid class name. - PackageParser.Package pkg = pkgSetting.pkg; - if (pkg == null || !pkg.hasComponentClassName(className)) { - if (pkg != null && - pkg.applicationInfo.targetSdkVersion >= - Build.VERSION_CODES.JELLY_BEAN) { - throw new IllegalArgumentException("Component class " + className - + " does not exist in " + packageName); - } else { - Slog.w(TAG, "Failed setComponentEnabledSetting: component class " - + className + " does not exist in " + packageName); - } + // TODO remove direct parsing of the package object during internal cleanup + // of scan package + // We need to call parse directly here for no other reason than we need + // the new package in order to disable the old one [we use the information + // for some internal optimization to optionally create a new package setting + // object on replace]. However, we can't get the package from the scan + // because the scan modifies live structures and we need to remove the + // old [system] package from the system before a scan can be attempted. + // Once scan is indempotent we can remove this parse and use the package + // object we scanned, prior to adding it to package settings. + final PackageParser pp = new PackageParser(); + pp.setSeparateProcesses(mSeparateProcesses); + pp.setDisplayMetrics(mMetrics); + pp.setCallback(mPackageParserCallback); + final PackageParser.Package tmpPkg; + try { + final int parseFlags = mDefParseFlags + | PackageParser.PARSE_MUST_BE_APK + | PackageParser.PARSE_IS_SYSTEM + | PackageParser.PARSE_IS_SYSTEM_DIR; + tmpPkg = pp.parsePackage(codePath, parseFlags); + } catch (PackageParserException e) { + Slog.w(TAG, "Failed to parse compressed system package:" + pkgSetting.name, e); + return; } - switch (newState) { - case COMPONENT_ENABLED_STATE_ENABLED: - if (!pkgSetting.enableComponentLPw(className, userId)) { - return; - } - break; - case COMPONENT_ENABLED_STATE_DISABLED: - if (!pkgSetting.disableComponentLPw(className, userId)) { - return; - } - break; - case COMPONENT_ENABLED_STATE_DEFAULT: - if (!pkgSetting.restoreComponentLPw(className, userId)) { + synchronized (mInstallLock) { + // Disable the stub and remove any package entries + removePackageLI(deletedPkg, true); + synchronized (mPackages) { + disableSystemPackageLPw(deletedPkg, tmpPkg); + } + final PackageParser.Package newPkg; + try (PackageFreezer freezer = + freezePackage(deletedPkg.packageName, "setEnabledSetting")) { + final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY + | PackageParser.PARSE_ENFORCE_CODE; + newPkg = scanPackageTracedLI(codePath, parseFlags, 0 /*scanFlags*/, + 0 /*currentTime*/, null /*user*/); + prepareAppDataAfterInstallLIF(newPkg); + synchronized (mPackages) { + try { + updateSharedLibrariesLPr(newPkg, null); + } catch (PackageManagerException e) { + Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e); + } + updatePermissionsLPw(newPkg.packageName, newPkg, + UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG); + mSettings.writeLPr(); + } + } catch (PackageManagerException e) { + // Whoops! Something went wrong; try to roll back to the stub + Slog.w(TAG, "Failed to install compressed system package:" + + pkgSetting.name, e); + // Remove the failed install + removeCodePathLI(codePath); + + // Install the system package + try (PackageFreezer freezer = + freezePackage(deletedPkg.packageName, "setEnabledSetting")) { + synchronized (mPackages) { + // NOTE: The system package always needs to be enabled; even + // if it's for a compressed stub. If we don't, installing the + // system package fails during scan [scanning checks the disabled + // packages]. We will reverse this later, after we've "installed" + // the stub. + // This leaves us in a fragile state; the stub should never be + // enabled, so, cross your fingers and hope nothing goes wrong + // until we can disable the package later. + enableSystemPackageLPw(deletedPkg); + } + installPackageFromSystemLIF(new File(deletedPkg.codePath), + false /*isPrivileged*/, null /*allUserHandles*/, + null /*origUserHandles*/, null /*origPermissionsState*/, + true /*writeSettings*/); + } catch (PackageManagerException pme) { + Slog.w(TAG, "Failed to restore system package:" + + deletedPkg.packageName, pme); + } finally { + synchronized (mPackages) { + mSettings.disableSystemPackageLPw( + deletedPkg.packageName, true /*replaced*/); + mSettings.writeLPr(); + } + } return; } - break; - default: - Slog.e(TAG, "Invalid new component state: " + newState); + clearAppDataLIF(newPkg, UserHandle.USER_ALL, FLAG_STORAGE_DE + | FLAG_STORAGE_CE | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); + clearAppProfilesLIF(newPkg, UserHandle.USER_ALL); + mDexManager.notifyPackageUpdated(newPkg.packageName, + newPkg.baseCodePath, newPkg.splitCodePaths); + } + } + if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { + // Don't care about who enables an app. + callingPackage = null; + } + pkgSetting.setEnabled(newState, userId, callingPackage); + } else { + // We're dealing with a component level state change + // First, verify that this is a valid class name. + PackageParser.Package pkg = pkgSetting.pkg; + if (pkg == null || !pkg.hasComponentClassName(className)) { + if (pkg != null && + pkg.applicationInfo.targetSdkVersion >= + Build.VERSION_CODES.JELLY_BEAN) { + throw new IllegalArgumentException("Component class " + className + + " does not exist in " + packageName); + } else { + Slog.w(TAG, "Failed setComponentEnabledSetting: component class " + + className + " does not exist in " + packageName); + } + } + switch (newState) { + case COMPONENT_ENABLED_STATE_ENABLED: + if (!pkgSetting.enableComponentLPw(className, userId)) { return; } + break; + case COMPONENT_ENABLED_STATE_DISABLED: + if (!pkgSetting.disableComponentLPw(className, userId)) { + return; + } + break; + case COMPONENT_ENABLED_STATE_DEFAULT: + if (!pkgSetting.restoreComponentLPw(className, userId)) { + return; + } + break; + default: + Slog.e(TAG, "Invalid new component state: " + newState); + return; } + } + synchronized (mPackages) { scheduleWritePackageRestrictionsLocked(userId); updateSequenceNumberLP(pkgSetting, new int[] { userId }); final long callingId = Binder.clearCallingIdentity(); diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java index 46049f593105..f4ac961af373 100644 --- a/services/core/java/com/android/server/wm/AppWindowToken.java +++ b/services/core/java/com/android/server/wm/AppWindowToken.java @@ -63,6 +63,7 @@ import android.util.Slog; import android.view.IApplicationToken; import android.view.SurfaceControl; import android.view.WindowManager; +import android.view.WindowManager.LayoutParams; import android.view.WindowManagerPolicy.StartingSurface; import com.android.internal.util.ToBooleanFunction; @@ -471,6 +472,20 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree return delayed; } + /** + * @return The to top most child window for which {@link LayoutParams#isFullscreen()} returns + * true. + */ + WindowState getTopFullscreenWindow() { + for (int i = mChildren.size() - 1; i >= 0; i--) { + final WindowState win = mChildren.get(i); + if (win != null && win.mAttrs.isFullscreen()) { + return win; + } + } + return null; + } + WindowState findMainWindow() { WindowState candidate = null; int j = mChildren.size(); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 4e4d42dea0a6..bc7f33021c77 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -211,7 +211,7 @@ class TaskSnapshotController { } final GraphicBuffer buffer = top.mDisplayContent.screenshotApplicationsToBuffer(top.token, -1, -1, false, 1.0f, false, true); - if (buffer == null) { + if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) { return null; } return new TaskSnapshot(buffer, top.getConfiguration().orientation, diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java index 1bece6903eac..0610b945d20e 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java @@ -162,7 +162,7 @@ class TaskSnapshotSurface implements StartingSurface { + task); return null; } - final WindowState topFullscreenWindow = topFullscreenToken.findMainWindow(); + final WindowState topFullscreenWindow = topFullscreenToken.getTopFullscreenWindow(); if (mainWindow == null || topFullscreenWindow == null) { Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token=" + token); diff --git a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java index b09601e698f9..9ad7addab858 100644 --- a/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java +++ b/services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java @@ -97,6 +97,24 @@ public class AppWindowTokenTests extends WindowTestsBase { } @Test + public void testGetTopFullscreenWindow() throws Exception { + final WindowTestUtils.TestAppWindowToken token = + new WindowTestUtils.TestAppWindowToken(mDisplayContent); + + assertNull(token.getTopFullscreenWindow()); + + final WindowState window1 = createWindow(null, TYPE_BASE_APPLICATION, token, "window1"); + final WindowState window11 = createWindow(null, TYPE_APPLICATION, token, "window11"); + final WindowState window12 = createWindow(null, TYPE_APPLICATION, token, "window12"); + assertEquals(window12, token.getTopFullscreenWindow()); + window12.mAttrs.width = 500; + assertEquals(window11, token.getTopFullscreenWindow()); + window11.mAttrs.width = 500; + assertEquals(window1, token.getTopFullscreenWindow()); + token.removeImmediately(); + } + + @Test public void testLandscapeSeascapeRotationByApp() throws Exception { // Some plumbing to get the service ready for rotation updates. sWm.mDisplayReady = true; diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 5f4283f11976..2c02869ed763 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -6737,11 +6737,13 @@ public class TelephonyManager { * Get aggregated video call data usage since boot. * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required. * - * @param perUidStats True if requesting data usage per uid, otherwise overall usage. + * @param how one of the NetworkStats.STATS_PER_* constants depending on whether the request is + * for data usage per uid or overall usage. * @return Snapshot of video call data usage * @hide */ - public NetworkStats getVtDataUsage(boolean perUidStats) { + public NetworkStats getVtDataUsage(int how) { + boolean perUidStats = (how == NetworkStats.STATS_PER_UID); try { ITelephony service = getITelephony(); if (service != null) { diff --git a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java index 983e04d9930d..53a9b5a6befb 100644 --- a/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +++ b/tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java @@ -17,7 +17,10 @@ package com.android.server.connectivity.tethering; import static android.net.NetworkStats.SET_DEFAULT; +import static android.net.NetworkStats.STATS_PER_IFACE; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; +import static android.net.NetworkStats.UID_ALL; import static android.net.TrafficStats.UID_TETHERING; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats; @@ -373,7 +376,6 @@ public class OffloadControllerTest { assertEquals(stats.txBytes, entry.txBytes); assertEquals(SET_DEFAULT, entry.set); assertEquals(TAG_NONE, entry.tag); - assertEquals(UID_TETHERING, entry.uid); } @Test @@ -412,20 +414,33 @@ public class OffloadControllerTest { ethernetStats.txBytes = 100000; offload.setUpstreamLinkProperties(null); - NetworkStats stats = mTetherStatsProviderCaptor.getValue().getTetherStats(); + ITetheringStatsProvider provider = mTetherStatsProviderCaptor.getValue(); + NetworkStats stats = provider.getTetherStats(STATS_PER_IFACE); + NetworkStats perUidStats = provider.getTetherStats(STATS_PER_UID); + assertEquals(2, stats.size()); + assertEquals(2, perUidStats.size()); NetworkStats.Entry entry = null; + for (int i = 0; i < stats.size(); i++) { + assertEquals(UID_ALL, stats.getValues(i, entry).uid); + assertEquals(UID_TETHERING, perUidStats.getValues(i, entry).uid); + } + int ethernetPosition = ethernetIface.equals(stats.getValues(0, entry).iface) ? 0 : 1; int mobilePosition = 1 - ethernetPosition; entry = stats.getValues(mobilePosition, entry); assertNetworkStats(mobileIface, mobileStats, entry); + entry = perUidStats.getValues(mobilePosition, entry); + assertNetworkStats(mobileIface, mobileStats, entry); ethernetStats.rxBytes = 12345 + 100000; ethernetStats.txBytes = 54321 + 100000; entry = stats.getValues(ethernetPosition, entry); assertNetworkStats(ethernetIface, ethernetStats, entry); + entry = perUidStats.getValues(ethernetPosition, entry); + assertNetworkStats(ethernetIface, ethernetStats, entry); } @Test diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java index feb46d39b563..fa997958ba6d 100644 --- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java +++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java @@ -31,6 +31,8 @@ import static android.net.NetworkStats.ROAMING_YES; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; import static android.net.NetworkStats.SET_FOREGROUND; +import static android.net.NetworkStats.STATS_PER_IFACE; +import static android.net.NetworkStats.STATS_PER_UID; import static android.net.NetworkStats.TAG_NONE; import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkStatsHistory.FIELD_ALL; @@ -823,17 +825,24 @@ public class NetworkStatsServiceTest { incrementCurrentTime(HOUR_IN_MILLIS); expectCurrentTime(); expectDefaultSettings(); - expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1) - .addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L)); + // Traffic seen by kernel counters (includes software tethering). + final NetworkStats ifaceStats = new NetworkStats(getElapsedRealtime(), 1) + .addIfaceValues(TEST_IFACE, 1536L, 12L, 384L, 3L); + // Hardware tethering traffic, not seen by kernel counters. + final NetworkStats tetherStatsHardware = new NetworkStats(getElapsedRealtime(), 1) + .addIfaceValues(TEST_IFACE, 512L, 4L, 128L, 1L); + + // Traffic for UID_RED. final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L); - final String[] tetherIfacePairs = new String[] { TEST_IFACE, "wlan0" }; + // All tethering traffic, both hardware and software. final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1) .addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L, 0L); - expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats); + expectNetworkStatsSummary(ifaceStats, tetherStatsHardware); + expectNetworkStatsUidDetail(uidStats, tetherStats); forcePollAndWaitForIdle(); // verify service recorded history @@ -1013,10 +1022,16 @@ public class NetworkStatsServiceTest { } private void expectNetworkStatsSummary(NetworkStats summary) throws Exception { + expectNetworkStatsSummary(summary, new NetworkStats(0L, 0)); + } + + private void expectNetworkStatsSummary(NetworkStats summary, NetworkStats tetherStats) + throws Exception { when(mConnManager.getAllVpnInfo()).thenReturn(new VpnInfo[0]); - expectNetworkStatsSummaryDev(summary); - expectNetworkStatsSummaryXt(summary); + expectNetworkStatsTethering(STATS_PER_IFACE, tetherStats); + expectNetworkStatsSummaryDev(summary.clone()); + expectNetworkStatsSummaryXt(summary.clone()); } private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception { @@ -1027,17 +1042,21 @@ public class NetworkStatsServiceTest { when(mNetManager.getNetworkStatsSummaryXt()).thenReturn(summary); } + private void expectNetworkStatsTethering(int how, NetworkStats stats) + throws Exception { + when(mNetManager.getNetworkStatsTethering(how)).thenReturn(stats); + } + private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception { - expectNetworkStatsUidDetail(detail, new String[0], new NetworkStats(0L, 0)); + expectNetworkStatsUidDetail(detail, new NetworkStats(0L, 0)); } - private void expectNetworkStatsUidDetail( - NetworkStats detail, String[] tetherIfacePairs, NetworkStats tetherStats) + private void expectNetworkStatsUidDetail(NetworkStats detail, NetworkStats tetherStats) throws Exception { when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail); // also include tethering details, since they are folded into UID - when(mNetManager.getNetworkStatsTethering()).thenReturn(tetherStats); + when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)).thenReturn(tetherStats); } private void expectDefaultSettings() throws Exception { |