summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/Activity.java4
-rw-r--r--core/java/android/app/IActivityManager.aidl2
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java5
-rw-r--r--core/java/android/content/pm/PackageParser.java46
-rw-r--r--core/java/android/net/ITetheringStatsProvider.aidl5
-rw-r--r--core/java/android/net/NetworkStats.java5
-rw-r--r--core/java/android/os/INetworkManagementService.aidl2
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp3
-rw-r--r--media/java/android/media/MediaFile.java5
-rw-r--r--media/java/android/mtp/MtpConstants.java2
-rwxr-xr-xmedia/java/android/mtp/MtpDatabase.java2
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp2
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java5
-rw-r--r--proto/src/metrics_constants.proto16
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java22
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java4
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java130
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityMetricsLogger.java31
-rw-r--r--services/core/java/com/android/server/am/ActivityRecord.java12
-rw-r--r--services/core/java/com/android/server/connectivity/tethering/OffloadController.java8
-rw-r--r--services/core/java/com/android/server/content/ContentService.java8
-rw-r--r--services/core/java/com/android/server/content/SyncManager.java110
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerInternal.java5
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java13
-rw-r--r--services/core/java/com/android/server/job/JobStore.java13
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java17
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java284
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java15
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java2
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotSurface.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/AppWindowTokenTests.java18
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java6
-rw-r--r--tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java19
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java39
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 {