diff options
58 files changed, 1011 insertions, 353 deletions
diff --git a/api/current.txt b/api/current.txt index 5e4b2d4eb958..b7b65f1402c7 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5241,6 +5241,7 @@ package android.app { method public boolean getContentIntentAvailableOffline(); method public int getCustomContentHeight(); method public int getCustomSizePreset(); + method public java.lang.String getDismissalId(); method public android.app.PendingIntent getDisplayIntent(); method public int getGravity(); method public boolean getHintAmbientBigPicture(); @@ -5258,6 +5259,7 @@ package android.app { method public android.app.Notification.WearableExtender setContentIntentAvailableOffline(boolean); method public android.app.Notification.WearableExtender setCustomContentHeight(int); method public android.app.Notification.WearableExtender setCustomSizePreset(int); + method public android.app.Notification.WearableExtender setDismissalId(java.lang.String); method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent); method public android.app.Notification.WearableExtender setGravity(int); method public android.app.Notification.WearableExtender setHintAmbientBigPicture(boolean); diff --git a/api/system-current.txt b/api/system-current.txt index bde3a8cd7bb1..6b5f1e992d3d 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -5386,6 +5386,7 @@ package android.app { method public boolean getContentIntentAvailableOffline(); method public int getCustomContentHeight(); method public int getCustomSizePreset(); + method public java.lang.String getDismissalId(); method public android.app.PendingIntent getDisplayIntent(); method public int getGravity(); method public boolean getHintAmbientBigPicture(); @@ -5403,6 +5404,7 @@ package android.app { method public android.app.Notification.WearableExtender setContentIntentAvailableOffline(boolean); method public android.app.Notification.WearableExtender setCustomContentHeight(int); method public android.app.Notification.WearableExtender setCustomSizePreset(int); + method public android.app.Notification.WearableExtender setDismissalId(java.lang.String); method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent); method public android.app.Notification.WearableExtender setGravity(int); method public android.app.Notification.WearableExtender setHintAmbientBigPicture(boolean); diff --git a/api/test-current.txt b/api/test-current.txt index 91415066a3df..ae58f3685f16 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -5241,6 +5241,7 @@ package android.app { method public boolean getContentIntentAvailableOffline(); method public int getCustomContentHeight(); method public int getCustomSizePreset(); + method public java.lang.String getDismissalId(); method public android.app.PendingIntent getDisplayIntent(); method public int getGravity(); method public boolean getHintAmbientBigPicture(); @@ -5258,6 +5259,7 @@ package android.app { method public android.app.Notification.WearableExtender setContentIntentAvailableOffline(boolean); method public android.app.Notification.WearableExtender setCustomContentHeight(int); method public android.app.Notification.WearableExtender setCustomSizePreset(int); + method public android.app.Notification.WearableExtender setDismissalId(java.lang.String); method public android.app.Notification.WearableExtender setDisplayIntent(android.app.PendingIntent); method public android.app.Notification.WearableExtender setGravity(int); method public android.app.Notification.WearableExtender setHintAmbientBigPicture(boolean); diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java index 20037ce30cdb..0c2e3c189aae 100644 --- a/core/java/android/app/Notification.java +++ b/core/java/android/app/Notification.java @@ -5486,6 +5486,7 @@ public class Notification implements Parcelable private static final String KEY_CUSTOM_CONTENT_HEIGHT = "customContentHeight"; private static final String KEY_GRAVITY = "gravity"; private static final String KEY_HINT_SCREEN_TIMEOUT = "hintScreenTimeout"; + private static final String KEY_DISMISSAL_ID = "dismissalId"; // Flags bitwise-ored to mFlags private static final int FLAG_CONTENT_INTENT_AVAILABLE_OFFLINE = 0x1; @@ -5514,6 +5515,7 @@ public class Notification implements Parcelable private int mCustomContentHeight; private int mGravity = DEFAULT_GRAVITY; private int mHintScreenTimeout; + private String mDismissalId; /** * Create a {@link android.app.Notification.WearableExtender} with default @@ -5550,6 +5552,7 @@ public class Notification implements Parcelable mCustomContentHeight = wearableBundle.getInt(KEY_CUSTOM_CONTENT_HEIGHT); mGravity = wearableBundle.getInt(KEY_GRAVITY, DEFAULT_GRAVITY); mHintScreenTimeout = wearableBundle.getInt(KEY_HINT_SCREEN_TIMEOUT); + mDismissalId = wearableBundle.getString(KEY_DISMISSAL_ID); } } @@ -5600,6 +5603,9 @@ public class Notification implements Parcelable if (mHintScreenTimeout != 0) { wearableBundle.putInt(KEY_HINT_SCREEN_TIMEOUT, mHintScreenTimeout); } + if (mDismissalId != null) { + wearableBundle.putString(KEY_DISMISSAL_ID, mDismissalId); + } builder.getExtras().putBundle(EXTRA_WEARABLE_EXTENSIONS, wearableBundle); return builder; @@ -5620,6 +5626,7 @@ public class Notification implements Parcelable that.mCustomContentHeight = this.mCustomContentHeight; that.mGravity = this.mGravity; that.mHintScreenTimeout = this.mHintScreenTimeout; + that.mDismissalId = this.mDismissalId; return that; } @@ -6107,6 +6114,29 @@ public class Notification implements Parcelable return (mFlags & FLAG_HINT_CONTENT_INTENT_LAUNCHES_ACTIVITY) != 0; } + /** + * When you post a notification, if you set the dismissal id field, then when that + * notification is canceled, notifications on other wearables and the paired Android phone + * having that same dismissal id will also be canceled. Note that this only works if you + * have notification bridge mode set to NO_BRIDGING in your Wear app manifest. See + * <a href="{@docRoot}wear/notifications/index.html">Adding Wearable Features to + * Notifications</a> for more information on how to use the bridge mode feature. + * @param dismissalId the dismissal id of the notification. + * @return this object for method chaining + */ + public WearableExtender setDismissalId(String dismissalId) { + mDismissalId = dismissalId; + return this; + } + + /** + * Returns the dismissal id of the notification. + * @return the dismissal id of the notification or null if it has not been set. + */ + public String getDismissalId() { + return mDismissalId; + } + private void setFlag(int mask, boolean value) { if (value) { mFlags |= mask; diff --git a/core/java/android/app/job/JobInfo.java b/core/java/android/app/job/JobInfo.java index ecfc527cb7f3..c47557501b64 100644 --- a/core/java/android/app/job/JobInfo.java +++ b/core/java/android/app/job/JobInfo.java @@ -16,6 +16,8 @@ package android.app.job; +import static android.util.TimeUtils.formatDuration; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; @@ -24,7 +26,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; import android.util.Log; -import static android.util.TimeUtils.formatDuration; import java.util.ArrayList; @@ -154,6 +155,20 @@ public class JobInfo implements Parcelable { */ public static final int PRIORITY_ADJ_ALWAYS_RUNNING = -80; + /** + * Indicates that the implementation of this job will be using + * {@link JobService#startForeground(int, android.app.Notification)} to run + * in the foreground. + * <p> + * When set, the internal scheduling of this job will ignore any background + * network restrictions for the requesting app. Note that this flag alone + * doesn't actually place your {@link JobService} in the foreground; you + * still need to post the notification yourself. + * + * @hide + */ + public static final int FLAG_WILL_BE_FOREGROUND = 1 << 0; + private final int jobId; private final PersistableBundle extras; private final ComponentName service; @@ -174,6 +189,7 @@ public class JobInfo implements Parcelable { private final long initialBackoffMillis; private final int backoffPolicy; private final int priority; + private final int flags; /** * Unique job id associated with this class. This is assigned to your job by the scheduler. @@ -201,6 +217,11 @@ public class JobInfo implements Parcelable { return priority; } + /** @hide */ + public int getFlags() { + return flags; + } + /** * Whether this job needs the device to be plugged in. */ @@ -356,6 +377,7 @@ public class JobInfo implements Parcelable { hasEarlyConstraint = in.readInt() == 1; hasLateConstraint = in.readInt() == 1; priority = in.readInt(); + flags = in.readInt(); } private JobInfo(JobInfo.Builder b) { @@ -381,6 +403,7 @@ public class JobInfo implements Parcelable { hasEarlyConstraint = b.mHasEarlyConstraint; hasLateConstraint = b.mHasLateConstraint; priority = b.mPriority; + flags = b.mFlags; } @Override @@ -410,6 +433,7 @@ public class JobInfo implements Parcelable { out.writeInt(hasEarlyConstraint ? 1 : 0); out.writeInt(hasLateConstraint ? 1 : 0); out.writeInt(priority); + out.writeInt(this.flags); } public static final Creator<JobInfo> CREATOR = new Creator<JobInfo>() { @@ -504,6 +528,7 @@ public class JobInfo implements Parcelable { private PersistableBundle mExtras = PersistableBundle.EMPTY; private ComponentName mJobService; private int mPriority = PRIORITY_DEFAULT; + private int mFlags; // Requirements. private boolean mRequiresCharging; private boolean mRequiresDeviceIdle; @@ -539,14 +564,18 @@ public class JobInfo implements Parcelable { mJobId = jobId; } - /** - * @hide - */ + /** @hide */ public Builder setPriority(int priority) { mPriority = priority; return this; } + /** @hide */ + public Builder setFlags(int flags) { + mFlags = flags; + return this; + } + /** * Set optional extras. This is persisted, so we only allow primitive types. * @param extras Bundle containing extras you want the scheduler to hold on to for you. diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java index 167befc089dd..bdea1e009eb0 100644 --- a/core/java/android/content/pm/ActivityInfo.java +++ b/core/java/android/content/pm/ActivityInfo.java @@ -188,7 +188,7 @@ public class ActivityInfo extends ComponentInfo * See {@link android.R.attr#resizeableActivity}. * @hide */ - public int resizeMode; + public int resizeMode = RESIZE_MODE_RESIZEABLE; /** * Name of the VrListenerService component to run for this activity. diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 66c500063861..6534f5b32456 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -159,6 +159,7 @@ public class PackageParser { private static final String TAG_SUPPORTS_INPUT = "supports-input"; private static final String TAG_EAT_COMMENT = "eat-comment"; private static final String TAG_PACKAGE = "package"; + private static final String TAG_RESTRICT_UPDATE = "restrict-update"; // These are the tags supported by child packages private static final Set<String> CHILD_PACKAGE_TAGS = new ArraySet<>(); @@ -1639,9 +1640,9 @@ public class PackageParser { /** * This is the common parsing routing for handling parent and child * packages in a base APK. The difference between parent and child - * parsing is that some targs are not supported by child packages as + * parsing is that some tags are not supported by child packages as * well as some manifest attributes are ignored. The implementation - * assumes the calling code already handled the manifest tag if needed + * assumes the calling code has already handled the manifest tag if needed * (this applies to the parent only). * * @param pkg The package which to populate @@ -2089,6 +2090,29 @@ public class PackageParser { // If parsing a child failed the error is already set return null; } + + } else if (tagName.equals(TAG_RESTRICT_UPDATE)) { + if ((flags & PARSE_IS_SYSTEM_DIR) != 0) { + sa = res.obtainAttributes(parser, + com.android.internal.R.styleable.AndroidManifestRestrictUpdate); + final String hash = sa.getNonConfigurationString( + com.android.internal.R.styleable.AndroidManifestRestrictUpdate_hash, 0); + sa.recycle(); + + pkg.restrictUpdateHash = null; + if (hash != null) { + final int hashLength = hash.length(); + final byte[] hashBytes = new byte[hashLength / 2]; + for (int i = 0; i < hashLength; i += 2){ + hashBytes[i/2] = (byte) ((Character.digit(hash.charAt(i), 16) << 4) + + Character.digit(hash.charAt(i + 1), 16)); + } + pkg.restrictUpdateHash = hashBytes; + } + } + + XmlUtils.skipCurrentTag(parser); + } else if (RIGID_PARSER) { outError[0] = "Bad element under <manifest>: " + parser.getName(); @@ -4822,6 +4846,8 @@ public class PackageParser { */ public boolean use32bitAbi; + public byte[] restrictUpdateHash; + public Package(String packageName) { this.packageName = packageName; applicationInfo.packageName = packageName; diff --git a/core/java/android/hardware/location/ContextHubInfo.java b/core/java/android/hardware/location/ContextHubInfo.java index 194b9ee58780..aaf6c57b9abe 100644 --- a/core/java/android/hardware/location/ContextHubInfo.java +++ b/core/java/android/hardware/location/ContextHubInfo.java @@ -357,6 +357,7 @@ public class ContextHubInfo { retVal += "\n\tPeakMips : " + mPeakMips; retVal += ", StoppedPowerDraw : " + mStoppedPowerDrawMw + " mW"; retVal += ", PeakPowerDraw : " + mPeakPowerDrawMw + " mW"; + retVal += ", MaxPacketLength : " + mMaxPacketLengthBytes + " Bytes"; retVal += "\n\tSupported sensors : " + Arrays.toString(mSupportedSensors); retVal += "\n\tMemory Regions : " + Arrays.toString(mMemoryRegions); @@ -375,6 +376,7 @@ public class ContextHubInfo { mStoppedPowerDrawMw = in.readFloat(); mSleepPowerDrawMw = in.readFloat(); mPeakPowerDrawMw = in.readFloat(); + mMaxPacketLengthBytes = in.readInt(); int numSupportedSensors = in.readInt(); mSupportedSensors = new int[numSupportedSensors]; @@ -398,6 +400,7 @@ public class ContextHubInfo { out.writeFloat(mStoppedPowerDrawMw); out.writeFloat(mSleepPowerDrawMw); out.writeFloat(mPeakPowerDrawMw); + out.writeInt(mMaxPacketLengthBytes); out.writeInt(mSupportedSensors.length); out.writeIntArray(mSupportedSensors); @@ -414,4 +417,4 @@ public class ContextHubInfo { return new ContextHubInfo[size]; } }; -}
\ No newline at end of file +} diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index faf5c64e5a00..933dddf4a948 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -774,8 +774,13 @@ public class ConnectivityManager { * @hide */ public Network getActiveNetworkForUid(int uid) { + return getActiveNetworkForUid(uid, false); + } + + /** {@hide} */ + public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) { try { - return mService.getActiveNetworkForUid(uid); + return mService.getActiveNetworkForUid(uid, ignoreBlocked); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -836,8 +841,13 @@ public class ConnectivityManager { * {@hide} */ public NetworkInfo getActiveNetworkInfoForUid(int uid) { + return getActiveNetworkInfoForUid(uid, false); + } + + /** {@hide} */ + public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { try { - return mService.getActiveNetworkInfoForUid(uid); + return mService.getActiveNetworkInfoForUid(uid, ignoreBlocked); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -880,8 +890,13 @@ public class ConnectivityManager { * is not valid. */ public NetworkInfo getNetworkInfo(Network network) { + return getNetworkInfoForUid(network, Process.myUid(), false); + } + + /** {@hide} */ + public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) { try { - return mService.getNetworkInfoForNetwork(network); + return mService.getNetworkInfoForUid(network, uid, ignoreBlocked); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index c897c4506c1f..aec6b3ec23fe 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -44,11 +44,11 @@ import com.android.internal.net.VpnProfile; interface IConnectivityManager { Network getActiveNetwork(); - Network getActiveNetworkForUid(int uid); + Network getActiveNetworkForUid(int uid, boolean ignoreBlocked); NetworkInfo getActiveNetworkInfo(); - NetworkInfo getActiveNetworkInfoForUid(int uid); + NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked); NetworkInfo getNetworkInfo(int networkType); - NetworkInfo getNetworkInfoForNetwork(in Network network); + NetworkInfo getNetworkInfoForUid(in Network network, int uid, boolean ignoreBlocked); NetworkInfo[] getAllNetworkInfo(); Network getNetworkForType(int networkType); Network[] getAllNetworks(); diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index 2b8b28d91bd0..224ff5b395c7 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -38,6 +38,9 @@ interface INetworkPolicyManager { boolean isUidForeground(int uid); + /** Higher priority listener before general event dispatch */ + void setConnectivityListener(INetworkPolicyListener listener); + void registerListener(INetworkPolicyListener listener); void unregisterListener(INetworkPolicyListener listener); diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 2c63be255c0b..959b30946c8a 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -1157,6 +1157,8 @@ public abstract class BatteryStats implements Parcelable { public short batteryTemperature; public char batteryVoltage; + + public int batteryChargeCoulombs; // Constants from SCREEN_BRIGHTNESS_* public static final int STATE_BRIGHTNESS_SHIFT = 0; @@ -1181,6 +1183,8 @@ public abstract class BatteryStats implements Parcelable { public static final int STATE_WIFI_SCAN_FLAG = 1<<27; public static final int STATE_WIFI_RADIO_ACTIVE_FLAG = 1<<26; public static final int STATE_MOBILE_RADIO_ACTIVE_FLAG = 1<<25; + // Do not use, this is used for coulomb delta count. + private static final int STATE_RESERVED_0 = 1<<24; // These are on the lower bits used for the command; if they change // we need to write another int of data. public static final int STATE_SENSOR_ON_FLAG = 1<<23; @@ -1352,6 +1356,7 @@ public abstract class BatteryStats implements Parcelable { bat = (((int)batteryTemperature)&0xffff) | ((((int)batteryVoltage)<<16)&0xffff0000); dest.writeInt(bat); + dest.writeInt(batteryChargeCoulombs); dest.writeInt(states); dest.writeInt(states2); if (wakelockTag != null) { @@ -1380,6 +1385,7 @@ public abstract class BatteryStats implements Parcelable { int bat2 = src.readInt(); batteryTemperature = (short)(bat2&0xffff); batteryVoltage = (char)((bat2>>16)&0xffff); + batteryChargeCoulombs = src.readInt(); states = src.readInt(); states2 = src.readInt(); if ((bat&0x10000000) != 0) { @@ -1419,6 +1425,7 @@ public abstract class BatteryStats implements Parcelable { batteryPlugType = 0; batteryTemperature = 0; batteryVoltage = 0; + batteryChargeCoulombs = 0; states = 0; states2 = 0; wakelockTag = null; @@ -1446,6 +1453,7 @@ public abstract class BatteryStats implements Parcelable { batteryPlugType = o.batteryPlugType; batteryTemperature = o.batteryTemperature; batteryVoltage = o.batteryVoltage; + batteryChargeCoulombs = o.batteryChargeCoulombs; states = o.states; states2 = o.states2; if (o.wakelockTag != null) { @@ -1477,6 +1485,7 @@ public abstract class BatteryStats implements Parcelable { && batteryPlugType == o.batteryPlugType && batteryTemperature == o.batteryTemperature && batteryVoltage == o.batteryVoltage + && batteryChargeCoulombs == o.batteryChargeCoulombs && states == o.states && states2 == o.states2 && currentTime == o.currentTime; @@ -4527,6 +4536,7 @@ public abstract class BatteryStats implements Parcelable { int oldPlug = -1; int oldTemp = -1; int oldVolt = -1; + int oldCharge = -1; long lastTime = -1; void reset() { @@ -4537,6 +4547,7 @@ public abstract class BatteryStats implements Parcelable { oldPlug = -1; oldTemp = -1; oldVolt = -1; + oldCharge = -1; } public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin, @@ -4698,6 +4709,11 @@ public abstract class BatteryStats implements Parcelable { pw.print(checkin ? ",Bv=" : " volt="); pw.print(oldVolt); } + if (oldCharge != rec.batteryChargeCoulombs) { + oldCharge = rec.batteryChargeCoulombs; + pw.print(checkin ? ",Bcc=" : " charge="); + pw.print(oldCharge); + } printBitDescriptions(pw, oldState, rec.states, rec.wakelockTag, HISTORY_STATE_DESCRIPTIONS, !checkin); printBitDescriptions(pw, oldState2, rec.states2, null, diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 68b0a9fb2969..b546da021e18 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -324,6 +324,11 @@ interface INetworkManagementService void removeIdleTimer(String iface); /** + * Configure name servers, search paths, and resolver parameters for the given network. + */ + void setDnsConfigurationForNetwork(int netId, in String[] servers, String domains); + + /** * Bind name servers to a network in the DNS resolver. */ void setDnsServersForNetwork(int netId, in String[] servers, String domains); diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index d98e2177058a..700c2d28b3dd 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6974,6 +6974,33 @@ public final class Settings { public static final String STORAGE_BENCHMARK_INTERVAL = "storage_benchmark_interval"; /** + * Sample validity in seconds to configure for the system DNS resolver. + * {@hide} + */ + public static final String DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS = + "dns_resolver_sample_validity_seconds"; + + /** + * Success threshold in percent for use with the system DNS resolver. + * {@hide} + */ + public static final String DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT = + "dns_resolver_success_threshold_percent"; + + /** + * Minimum number of samples needed for statistics to be considered meaningful in the + * system DNS resolver. + * {@hide} + */ + public static final String DNS_RESOLVER_MIN_SAMPLES = "dns_resolver_min_samples"; + + /** + * Maximum number taken into account for statistics purposes in the system DNS resolver. + * {@hide} + */ + public static final String DNS_RESOLVER_MAX_SAMPLES = "dns_resolver_max_samples"; + + /** * Whether to disable the automatic scheduling of system updates. * 1 = system updates won't be automatically scheduled (will always * present notification instead). diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index e708b0ad5aff..cf783d25251e 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -764,9 +764,9 @@ public abstract class NotificationListenerService extends Service { } mSystemContext = context; INotificationManager noMan = getNotificationInterface(); - noMan.registerListener(mWrapper, componentName, currentUser); - mCurrentUser = currentUser; mHandler = new MyHandler(context.getMainLooper()); + mCurrentUser = currentUser; + noMan.registerListener(mWrapper, componentName, currentUser); } /** diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index a0384f2601d3..edf05ba5fc33 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -389,6 +389,8 @@ public final class ViewRootImpl implements ViewParent, /** Set to true once doDie() has been called. */ private boolean mRemoved; + private boolean mNeedsHwRendererSetup; + /** * Consistency verifier for debugging purposes. */ @@ -915,6 +917,11 @@ public final class ViewRootImpl implements ViewParent, mWindowAttributes.surfaceInsets.set( oldInsetLeft, oldInsetTop, oldInsetRight, oldInsetBottom); mWindowAttributes.hasManualSurfaceInsets = oldHasManualSurfaceInsets; + } else if (mWindowAttributes.surfaceInsets.left != oldInsetLeft + || mWindowAttributes.surfaceInsets.top != oldInsetTop + || mWindowAttributes.surfaceInsets.right != oldInsetRight + || mWindowAttributes.surfaceInsets.bottom != oldInsetBottom) { + mNeedsHwRendererSetup = true; } applyKeepScreenOnFlag(mWindowAttributes); @@ -1959,9 +1966,11 @@ public final class ViewRootImpl implements ViewParent, if (hardwareRenderer != null && hardwareRenderer.isEnabled()) { if (hwInitialized || mWidth != hardwareRenderer.getWidth() - || mHeight != hardwareRenderer.getHeight()) { + || mHeight != hardwareRenderer.getHeight() + || mNeedsHwRendererSetup) { hardwareRenderer.setup(mWidth, mHeight, mAttachInfo, mWindowAttributes.surfaceInsets); + mNeedsHwRendererSetup = false; } } diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index a2a135b59a73..42b89d53c9b6 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -122,7 +122,8 @@ interface IBatteryStats { void noteNetworkInterfaceType(String iface, int type); void noteNetworkStatsEnabled(); void noteDeviceIdleMode(int mode, String activeReason, int activeUid); - void setBatteryState(int status, int health, int plugType, int level, int temp, int volt); + void setBatteryState(int status, int health, int plugType, int level, int temp, int volt, + int chargeCount); long getAwakeTimeBattery(); long getAwakeTimePlugged(); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 5358d78e1b02..654a4f19e0dc 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -108,7 +108,7 @@ public class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 143 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 144 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -2089,27 +2089,111 @@ public class BatteryStatsImpl extends BatteryStats { tag.poolIdx = index; } + /* + The history delta format uses flags to denote further data in subsequent ints in the parcel. + + There is always the first token, which may contain the delta time, or an indicator of + the length of the time (int or long) following this token. + + First token: always present, + 31 23 15 7 0 + █M|L|K|J|I|H|G|F█E|D|C|B|A|T|T|T█T|T|T|T|T|T|T|T█T|T|T|T|T|T|T|T█ + + T: the delta time if it is <= 0x7fffd. Otherwise 0x7fffe indicates an int immediately + follows containing the time, and 0x7ffff indicates a long immediately follows with the + delta time. + A: battery level changed and an int follows with battery data. + B: state changed and an int follows with state change data. + C: state2 has changed and an int follows with state2 change data. + D: wakelock/wakereason has changed and an wakelock/wakereason struct follows. + E: event data has changed and an event struct follows. + F: battery charge in coulombs has changed and an int with the charge follows. + G: state flag denoting that the mobile radio was active. + H: state flag denoting that the wifi radio was active. + I: state flag denoting that a wifi scan occurred. + J: state flag denoting that a wifi full lock was held. + K: state flag denoting that the gps was on. + L: state flag denoting that a wakelock was held. + M: state flag denoting that the cpu was running. + + Time int/long: if T in the first token is 0x7ffff or 0x7fffe, then an int or long follows + with the time delta. + + Battery level int: if A in the first token is set, + 31 23 15 7 0 + █L|L|L|L|L|L|L|T█T|T|T|T|T|T|T|T█T|V|V|V|V|V|V|V█V|V|V|V|V|V|V|D█ + + D: indicates that extra history details follow. + V: the battery voltage. + T: the battery temperature. + L: the battery level (out of 100). + + State change int: if B in the first token is set, + 31 23 15 7 0 + █S|S|S|H|H|H|P|P█F|E|D|C|B| | |A█ | | | | | | | █ | | | | | | | █ + + A: wifi multicast was on. + B: battery was plugged in. + C: screen was on. + D: phone was scanning for signal. + E: audio was on. + F: a sensor was active. + + State2 change int: if C in the first token is set, + 31 23 15 7 0 + █M|L|K|J|I|H|H|G█F|E|D|C| | | | █ | | | | | | | █ |B|B|B|A|A|A|A█ + + A: 4 bits indicating the wifi supplicant state: {@link BatteryStats#WIFI_SUPPL_STATE_NAMES}. + B: 3 bits indicating the wifi signal strength: 0, 1, 2, 3, 4. + C: a bluetooth scan was active. + D: the camera was active. + E: bluetooth was on. + F: a phone call was active. + G: the device was charging. + H: 2 bits indicating the device-idle (doze) state: off, light, full + I: the flashlight was on. + J: wifi was on. + K: wifi was running. + L: video was playing. + M: power save mode was on. + + Wakelock/wakereason struct: if D in the first token is set, + TODO(adamlesinski): describe wakelock/wakereason struct. + + Event struct: if E in the first token is set, + TODO(adamlesinski): describe the event struct. + + History step details struct: if D in the battery level int is set, + TODO(adamlesinski): describe the history step details struct. + + Battery charge int: if F in the first token is set, an int representing the battery charge + in coulombs follows. + */ + // Part of initial delta int that specifies the time delta. static final int DELTA_TIME_MASK = 0x7ffff; static final int DELTA_TIME_LONG = 0x7ffff; // The delta is a following long static final int DELTA_TIME_INT = 0x7fffe; // The delta is a following int static final int DELTA_TIME_ABS = 0x7fffd; // Following is an entire abs update. // Flag in delta int: a new battery level int follows. - static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000; + static final int DELTA_BATTERY_LEVEL_FLAG = 0x00080000; // Flag in delta int: a new full state and battery status int follows. - static final int DELTA_STATE_FLAG = 0x00100000; + static final int DELTA_STATE_FLAG = 0x00100000; // Flag in delta int: a new full state2 int follows. - static final int DELTA_STATE2_FLAG = 0x00200000; + static final int DELTA_STATE2_FLAG = 0x00200000; // Flag in delta int: contains a wakelock or wakeReason tag. - static final int DELTA_WAKELOCK_FLAG = 0x00400000; + static final int DELTA_WAKELOCK_FLAG = 0x00400000; // Flag in delta int: contains an event description. - static final int DELTA_EVENT_FLAG = 0x00800000; + static final int DELTA_EVENT_FLAG = 0x00800000; + // Flag in delta int: contains a coulomb charge count. + static final int DELTA_BATTERY_CHARGE_COULOMBS_FLAG = 0x01000000; // These upper bits are the frequently changing state bits. - static final int DELTA_STATE_MASK = 0xff000000; + static final int DELTA_STATE_MASK = 0xfe000000; // These are the pieces of battery state that are packed in to the upper bits of // the state int that have been packed in to the first delta int. They must fit - // in DELTA_STATE_MASK. + // in STATE_BATTERY_MASK. + static final int STATE_BATTERY_MASK = 0xff000000; static final int STATE_BATTERY_STATUS_MASK = 0x00000007; static final int STATE_BATTERY_STATUS_SHIFT = 29; static final int STATE_BATTERY_HEALTH_MASK = 0x00000007; @@ -2165,6 +2249,12 @@ public class BatteryStatsImpl extends BatteryStats { if (cur.eventCode != HistoryItem.EVENT_NONE) { firstToken |= DELTA_EVENT_FLAG; } + + final boolean batteryChargeCoulombsChanged = cur.batteryChargeCoulombs + != last.batteryChargeCoulombs; + if (batteryChargeCoulombsChanged) { + firstToken |= DELTA_BATTERY_CHARGE_COULOMBS_FLAG; + } dest.writeInt(firstToken); if (DEBUG) Slog.i(TAG, "WRITE DELTA: firstToken=0x" + Integer.toHexString(firstToken) + " deltaTime=" + deltaTime); @@ -2247,6 +2337,12 @@ public class BatteryStatsImpl extends BatteryStats { mLastHistoryStepDetails = null; } mLastHistoryStepLevel = cur.batteryLevel; + + if (batteryChargeCoulombsChanged) { + if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeCoulombs=" + + cur.batteryChargeCoulombs); + dest.writeInt(cur.batteryChargeCoulombs); + } } private int buildBatteryLevelInt(HistoryItem h) { @@ -2273,7 +2369,7 @@ public class BatteryStatsImpl extends BatteryStats { return ((h.batteryStatus&STATE_BATTERY_STATUS_MASK)<<STATE_BATTERY_STATUS_SHIFT) | ((h.batteryHealth&STATE_BATTERY_HEALTH_MASK)<<STATE_BATTERY_HEALTH_SHIFT) | ((plugType&STATE_BATTERY_PLUG_MASK)<<STATE_BATTERY_PLUG_SHIFT) - | (h.states&(~DELTA_STATE_MASK)); + | (h.states&(~STATE_BATTERY_MASK)); } private void computeHistoryStepDetails(final HistoryStepDetails out, @@ -2412,7 +2508,7 @@ public class BatteryStatsImpl extends BatteryStats { if ((firstToken&DELTA_STATE_FLAG) != 0) { int stateInt = src.readInt(); - cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~DELTA_STATE_MASK)); + cur.states = (firstToken&DELTA_STATE_MASK) | (stateInt&(~STATE_BATTERY_MASK)); cur.batteryStatus = (byte)((stateInt>>STATE_BATTERY_STATUS_SHIFT) & STATE_BATTERY_STATUS_MASK); cur.batteryHealth = (byte)((stateInt>>STATE_BATTERY_HEALTH_SHIFT) @@ -2438,7 +2534,7 @@ public class BatteryStatsImpl extends BatteryStats { + " batteryPlugType=" + cur.batteryPlugType + " states=0x" + Integer.toHexString(cur.states)); } else { - cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~DELTA_STATE_MASK)); + cur.states = (firstToken&DELTA_STATE_MASK) | (cur.states&(~STATE_BATTERY_MASK)); } if ((firstToken&DELTA_STATE2_FLAG) != 0) { @@ -2493,6 +2589,10 @@ public class BatteryStatsImpl extends BatteryStats { } else { cur.stepDetails = null; } + + if ((firstToken&DELTA_BATTERY_CHARGE_COULOMBS_FLAG) != 0) { + cur.batteryChargeCoulombs = src.readInt(); + } } @Override @@ -5611,12 +5711,12 @@ public class BatteryStatsImpl extends BatteryStats { mWifiControllerActivity.reset(false); } - if (mBsi.mBluetoothActivity != null) { - mBsi.mBluetoothActivity.reset(false); + if (mBluetoothControllerActivity != null) { + mBluetoothControllerActivity.reset(false); } - if (mBsi.mModemActivity != null) { - mBsi.mModemActivity.reset(false); + if (mModemControllerActivity != null) { + mModemControllerActivity.reset(false); } mUserCpuTime.reset(false); @@ -9210,7 +9310,7 @@ public class BatteryStatsImpl extends BatteryStats { public static final int BATTERY_PLUGGED_NONE = 0; public void setBatteryStateLocked(int status, int health, int plugType, int level, - int temp, int volt) { + int temp, int volt, int chargeCount) { final boolean onBattery = plugType == BATTERY_PLUGGED_NONE; final long uptime = mClocks.uptimeMillis(); final long elapsedRealtime = mClocks.elapsedRealtime(); @@ -9254,6 +9354,7 @@ public class BatteryStatsImpl extends BatteryStats { if (mDischargePlugLevel < 0) { mDischargePlugLevel = level; } + if (onBattery != mOnBattery) { mHistoryCur.batteryLevel = (byte)level; mHistoryCur.batteryStatus = (byte)status; @@ -9261,6 +9362,7 @@ public class BatteryStatsImpl extends BatteryStats { mHistoryCur.batteryPlugType = (byte)plugType; mHistoryCur.batteryTemperature = (short)temp; mHistoryCur.batteryVoltage = (char)volt; + mHistoryCur.batteryChargeCoulombs = chargeCount; setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level); } else { boolean changed = false; @@ -9294,6 +9396,11 @@ public class BatteryStatsImpl extends BatteryStats { mHistoryCur.batteryVoltage = (char)volt; changed = true; } + if (chargeCount >= (mHistoryCur.batteryChargeCoulombs+10) + || chargeCount <= (mHistoryCur.batteryChargeCoulombs-10)) { + mHistoryCur.batteryChargeCoulombs = chargeCount; + changed = true; + } long modeBits = (((long)mInitStepMode) << STEP_LEVEL_INITIAL_MODE_SHIFT) | (((long)mModStepMode) << STEP_LEVEL_MODIFIED_MODE_SHIFT) | (((long)(level&0xff)) << STEP_LEVEL_LEVEL_SHIFT); diff --git a/core/jni/android_hardware_location_ContextHubService.cpp b/core/jni/android_hardware_location_ContextHubService.cpp index 5c961d96cf56..98d6b247429c 100644 --- a/core/jni/android_hardware_location_ContextHubService.cpp +++ b/core/jni/android_hardware_location_ContextHubService.cpp @@ -44,7 +44,6 @@ static constexpr int HEADER_FIELD_MSG_TYPE=0; static constexpr int HEADER_FIELD_HUB_HANDLE=2; static constexpr int HEADER_FIELD_APP_INSTANCE=3; - namespace android { namespace { @@ -164,9 +163,20 @@ static int get_hub_id_for_app_instance(int id) { return db.hubInfo.hubs[hubHandle].hub_id; } +static int get_app_instance_for_app_id(uint64_t app_id) { + auto end = db.appInstances.end(); + for (auto current = db.appInstances.begin(); current != end; ++current) { + if (current->second.appInfo.app_name.id == app_id) { + return current->first; + } + } + ALOGD("Cannot find app for app instance %" PRIu64 ".", app_id); + return -1; +} + static int set_dest_app(hub_message_t *msg, int id) { if (!db.appInstances.count(id)) { - ALOGD("%s: Cannod find app for app instance %d", __FUNCTION__, id); + ALOGD("%s: Cannot find app for app instance %d", __FUNCTION__, id); return -1; } @@ -301,7 +311,7 @@ static void initContextHubService() { } } -static int onMessageReceipt(int *header, int headerLen, char *msg, int msgLen) { +static int onMessageReceipt(uint32_t *header, size_t headerLen, char *msg, size_t msgLen) { JNIEnv *env; if ((db.jniInfo.vm)->AttachCurrentThread(&env, nullptr) != JNI_OK) { @@ -396,14 +406,9 @@ static bool sanity_check_cookie(void *cookie, uint32_t hub_id) { int context_hub_callback(uint32_t hubId, const struct hub_message_t *msg, void *cookie) { - int msgHeader[MSG_HEADER_SIZE]; - if (!msg) { return -1; } - - msgHeader[HEADER_FIELD_MSG_TYPE] = msg->message_type; - if (!sanity_check_cookie(cookie, hubId)) { ALOGW("Incorrect cookie %" PRId32 " for cookie %p! Bailing", hubId, cookie); @@ -411,17 +416,22 @@ int context_hub_callback(uint32_t hubId, return -1; } - msgHeader[HEADER_FIELD_HUB_HANDLE] = *(uint32_t*)cookie; + uint32_t messageType = msg->message_type; + uint32_t hubHandle = *(uint32_t*) cookie; - if (msgHeader[HEADER_FIELD_MSG_TYPE] < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE && - msgHeader[HEADER_FIELD_MSG_TYPE] != 0 ) { - handle_os_message(msgHeader[HEADER_FIELD_MSG_TYPE], - msgHeader[HEADER_FIELD_HUB_HANDLE], - (char *)msg->message, - msg->message_len); + if (messageType < CONTEXT_HUB_TYPE_PRIVATE_MSG_BASE) { + handle_os_message(messageType, hubHandle, (char*) msg->message, msg->message_len); } else { - onMessageReceipt(msgHeader, sizeof(msgHeader), - (char *)msg->message, msg->message_len); + int appHandle = get_app_instance_for_app_id(msg->app_name.id); + if (appHandle < 0) { + ALOGE("Filtering out message due to invalid App Instance."); + } else { + uint32_t msgHeader[MSG_HEADER_SIZE] = {}; + msgHeader[HEADER_FIELD_MSG_TYPE] = messageType; + msgHeader[HEADER_FIELD_HUB_HANDLE] = hubHandle; + msgHeader[HEADER_FIELD_APP_INSTANCE] = appHandle; + onMessageReceipt(msgHeader, MSG_HEADER_SIZE, (char*) msg->message, msg->message_len); + } } return 0; diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 3fd75f70c089..191afe5fd521 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -2291,4 +2291,14 @@ <attr name="minimalHeight" format="dimension" /> </declare-styleable> + <!-- <code>restrict-update</code> tag restricts system apps from being updated unless the + SHA-512 hash equals the specified value. + @hide --> + <declare-styleable name="AndroidManifestRestrictUpdate" parent="AndroidManifest"> + <!-- The SHA-512 hash of the only APK that can be used to update a package. + <p>NOTE: This is only applicable to system packages. + @hide --> + <attr name="hash" format="string" /> + </declare-styleable> + </resources> diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 11df8e5fa589..c91e09fd39d0 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2715,6 +2715,7 @@ <public type="attr" name="contentInsetEndWithActions" /> <public type="attr" name="numberPickerStyle" /> <public type="attr" name="enableVrMode" /> + <public type="attr" name="hash" /> <public type="style" name="Theme.Material.Light.DialogWhenLarge.DarkActionBar" /> <public type="style" name="Widget.Material.SeekBar.Discrete" /> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index fb7a19f9487d..dffab2c9c59b 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -626,7 +626,7 @@ <!-- Title for the capability of an accessibility service to request touch exploration. --> <string name="capability_title_canRequestTouchExploration">Turn on Explore by Touch</string> <!-- Description for the capability of an accessibility service to request touch exploration. --> - <string name="capability_desc_canRequestTouchExploration">Touched items will be spoken aloud + <string name="capability_desc_canRequestTouchExploration">Tapped items will be spoken aloud and the screen can be explored using gestures.</string> <!-- Title for the capability of an accessibility service to request enhanced web accessibility. --> @@ -1708,7 +1708,7 @@ <string name="keyguard_password_enter_pin_prompt">New PIN code</string> <!-- Displayed as hint in passwordEntry EditText on PasswordUnlockScreen [CHAR LIMIT=30]--> - <string name="keyguard_password_entry_touch_hint"><font size="17">Touch to type password</font></string> + <string name="keyguard_password_entry_touch_hint"><font size="17">Tap to type password</font></string> <!-- Instructions telling the user to enter their text password to unlock the keyguard. Displayed in one line in a large font. --> @@ -2577,7 +2577,7 @@ is running</string> <!-- [CHAR LIMIT=NONE] Stub notification text for an app running a service that has provided a bad bad notification for itself. --> - <string name="app_running_notification_text">Touch for more information + <string name="app_running_notification_text">Tap for more information or to stop the app.</string> <!-- Preference framework strings. --> @@ -2761,7 +2761,7 @@ <string name="heavy_weight_notification"><xliff:g id="app">%1$s</xliff:g> running</string> <!-- Notification details to tell the user that a heavy-weight application is running. --> - <string name="heavy_weight_notification_detail">Touch to switch to app</string> + <string name="heavy_weight_notification_detail">Tap to switch to app</string> <!-- Title of dialog prompting whether user wants to switch between heavy-weight apps. --> <string name="heavy_weight_switcher_title">Switch apps?</string> @@ -2782,7 +2782,7 @@ <!-- Notification details to tell the user that a process has exceeded its memory limit. --> <string name="dump_heap_notification_detail">Heap dump has been collected; - touch to share</string> + tap to share</string> <!-- Title of dialog prompting the user to share a heap dump. --> <string name="dump_heap_title">Share heap dump?</string> @@ -2865,7 +2865,7 @@ <string name="wifi_no_internet">Wi-Fi has no Internet access</string> <!-- A notification is shown when the user connects to a Wi-Fi network and the system detects that that network has no Internet access. This is the notification's message. --> - <string name="wifi_no_internet_detailed">Touch for options</string> + <string name="wifi_no_internet_detailed">Tap for options</string> <!-- A notification is shown when a user's selected SSID is later disabled due to connectivity problems. This is the notification's title / ticker. --> <string name="wifi_watchdog_network_disabled">Couldn\'t connect to Wi-Fi</string> @@ -2887,7 +2887,7 @@ <string name="wifi_p2p_turnon_message">Start Wi-Fi Direct. This will turn off Wi-Fi client/hotspot.</string> <string name="wifi_p2p_failed_message">Couldn\'t start Wi-Fi Direct.</string> <string name="wifi_p2p_enabled_notification_title">Wi-Fi Direct is on</string> - <string name="wifi_p2p_enabled_notification_message">Touch for settings</string> + <string name="wifi_p2p_enabled_notification_message">Tap for settings</string> <string name="accept">Accept</string> <string name="decline">Decline</string> @@ -2995,12 +2995,12 @@ <!-- USB_PREFERENCES: Notification for when a USB accessory is attached. This is the title --> <string name="usb_accessory_notification_title">Connected to a USB accessory</string> <!-- See USB_PREFERENCES. This is the message. --> - <string name="usb_notification_message">Touch for more options.</string> + <string name="usb_notification_message">Tap for more options.</string> <!-- Title of notification shown when ADB is actively connected to the phone. --> <string name="adb_active_notification_title">USB debugging connected</string> <!-- Message of notification shown when ADB is actively connected to the phone. --> - <string name="adb_active_notification_message">Touch to disable USB debugging.</string> + <string name="adb_active_notification_message">Tap to disable USB debugging.</string> <!-- Title of notification shown to indicate that bug report is being collected. --> <string name="taking_remote_bugreport_notification_title">Taking bug report\u2026</string> @@ -3057,12 +3057,12 @@ <!-- Notification title when external media is unmountable (corrupt) [CHAR LIMIT=30] --> <string name="ext_media_unmountable_notification_title">Corrupted <xliff:g id="name" example="SD card">%s</xliff:g></string> <!-- Notification body when external media is unmountable (corrupt) [CHAR LIMIT=NONE] --> - <string name="ext_media_unmountable_notification_message"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Touch to fix.</string> + <string name="ext_media_unmountable_notification_message"><xliff:g id="name" example="SD card">%s</xliff:g> is corrupt. Tap to fix.</string> <!-- Notification title when external media is unsupported [CHAR LIMIT=30] --> <string name="ext_media_unsupported_notification_title">Unsupported <xliff:g id="name" example="SD card">%s</xliff:g></string> <!-- Notification body when external media is unsupported [CHAR LIMIT=NONE] --> - <string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Touch to set up in a supported format.</string> + <string name="ext_media_unsupported_notification_message">This device doesn\u2019t support this <xliff:g id="name" example="SD card">%s</xliff:g>. Tap to set up in a supported format.</string> <!-- Notification title when external media is unsafely removed [CHAR LIMIT=30] --> <string name="ext_media_badremoval_notification_title"><xliff:g id="name" example="SD card">%s</xliff:g> unexpectedly removed</string> @@ -3148,7 +3148,7 @@ <string name="permdesc_requestInstallPackages">Allows an application to request installation of packages.</string> <!-- Shown in the tutorial for tap twice for zoom control. --> - <string name="tutorial_double_tap_to_zoom_message_short">Touch twice for zoom control</string> + <string name="tutorial_double_tap_to_zoom_message_short">Tap twice for zoom control</string> <!-- Shown in gadget hosts (e.g. the home screen) when there was an error inflating @@ -3235,9 +3235,9 @@ <!-- The title of the notification when VPN is active with an application name. --> <string name="vpn_title_long">VPN is activated by <xliff:g id="app" example="FooVPN client">%s</xliff:g></string> <!-- The text of the notification when VPN is active. --> - <string name="vpn_text">Touch to manage the network.</string> + <string name="vpn_text">Tap to manage the network.</string> <!-- The text of the notification when VPN is active with a session name. --> - <string name="vpn_text_long">Connected to <xliff:g id="session" example="office">%s</xliff:g>. Touch to manage the network.</string> + <string name="vpn_text_long">Connected to <xliff:g id="session" example="office">%s</xliff:g>. Tap to manage the network.</string> <!-- Notification title when connecting to lockdown VPN. --> <string name="vpn_lockdown_connecting">Always-on VPN connecting\u2026</string> @@ -3246,7 +3246,7 @@ <!-- Notification title when error connecting to lockdown VPN. --> <string name="vpn_lockdown_error">Always-on VPN error</string> <!-- Notification body that indicates user can touch to configure lockdown VPN connection. --> - <string name="vpn_lockdown_config">Touch to configure</string> + <string name="vpn_lockdown_config">Tap to configure</string> <!-- Localized strings for WebView --> <!-- Label for button in a WebView that will open a chooser to choose a file to upload --> @@ -3261,12 +3261,12 @@ <!-- Strings for car mode notification --> <!-- Shown when car mode is enabled --> <string name="car_mode_disable_notification_title">Car mode enabled</string> - <string name="car_mode_disable_notification_message">Touch to exit car mode.</string> + <string name="car_mode_disable_notification_message">Tap to exit car mode.</string> <!-- Strings for tethered notification --> <!-- Shown when the device is tethered --> <string name="tethered_notification_title">Tethering or hotspot active</string> - <string name="tethered_notification_message">Touch to set up.</string> + <string name="tethered_notification_message">Tap to set up.</string> <!-- Strings for possible PreferenceActivity Back/Next buttons --> <string name="back_button_label">Back</string> @@ -3352,7 +3352,7 @@ <!-- Description of the button to decrease the NumberPicker value. [CHAR LIMIT=NONE] --> <string name="number_picker_decrement_button">Decrease</string> <!-- Description of the tap and hold action to get into scroll mode in NumberPicker. [CHAR LIMIT=NONE] --> - <string name="number_picker_increment_scroll_mode"><xliff:g id="value" example="3">%s</xliff:g> touch and hold.</string> + <string name="number_picker_increment_scroll_mode"><xliff:g id="value" example="3">%s</xliff:g> touch & hold.</string> <!-- Description of the scrolling action in NumberPicker. [CHAR LIMIT=NONE] --> <string name="number_picker_increment_scroll_action">Slide up to increase and down to decrease.</string> @@ -3470,7 +3470,7 @@ <!-- Notification title when data usage has exceeded warning threshold. [CHAR LIMIT=32] --> <string name="data_usage_warning_title">Data usage warning</string> <!-- Notification body when data usage has exceeded warning threshold. [CHAR LIMIT=32] --> - <string name="data_usage_warning_body">Touch to view usage and settings.</string> + <string name="data_usage_warning_body">Tap to view usage and settings.</string> <!-- Notification title when 2G-3G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] --> <string name="data_usage_3g_limit_title">2G-3G data limit reached</string> @@ -3497,7 +3497,7 @@ <!-- Notification title when background data usage is limited. [CHAR LIMIT=32] --> <string name="data_usage_restricted_title">Background data restricted</string> <!-- Notification body when background data usage is limited. [CHAR LIMIT=32] --> - <string name="data_usage_restricted_body">Touch to remove restriction.</string> + <string name="data_usage_restricted_body">Tap to remove restriction.</string> <!-- SSL Certificate dialogs --> <!-- Title for an SSL Certificate dialog --> @@ -4080,9 +4080,9 @@ <string name="date_picker_day_typeface">sans-serif-medium</string> <!-- Notify use that they are in Lock-to-app --> - <string name="lock_to_app_toast">To unpin this screen, touch and hold Back.</string> + <string name="lock_to_app_toast">To unpin this screen, touch & hold Back.</string> <!-- Notify use that they are in Lock-to-app in accessibility mode --> - <string name="lock_to_app_toast_accessible">To unpin this screen, touch and hold Overview.</string> + <string name="lock_to_app_toast_accessible">To unpin this screen, touch & hold Overview.</string> <!-- Notify user that they are locked in lock-to-app mode --> <string name="lock_to_app_toast_locked">App is pinned: Unpinning isn\'t allowed on this device.</string> <!-- Starting lock-to-app indication. --> diff --git a/core/res/res/values/themes_holo.xml b/core/res/res/values/themes_holo.xml index 34c89fc662ec..677051aa0dd5 100644 --- a/core/res/res/values/themes_holo.xml +++ b/core/res/res/values/themes_holo.xml @@ -466,6 +466,9 @@ please see themes_device_defaults.xml. <item name="editTextColor">?attr/textColorPrimary</item> <item name="editTextBackground">@drawable/edit_text_holo_light</item> + <item name="textEditSuggestionItemLayout">@layout/text_edit_suggestion_item</item> + <item name="textEditSuggestionContainerLayout">@layout/text_edit_suggestion_container</item> + <item name="textEditSuggestionHighlightStyle">@style/TextAppearance.Holo.SuggestionHighlight</item> <item name="candidatesTextStyleSpans">@string/candidates_style</item> diff --git a/docs/html/preview/behavior-changes.jd b/docs/html/preview/behavior-changes.jd index 0cf5bc9de6f2..7c8bfe8ba29e 100644 --- a/docs/html/preview/behavior-changes.jd +++ b/docs/html/preview/behavior-changes.jd @@ -215,11 +215,17 @@ page.image=images/cards/card-n-changes_2x.png <ul> <li> - Private files’ file permissions can no longer be relaxed by the owner, and - an attempt to do so using + Private files’ file permissions should no longer be relaxed by the owner, + and an attempt to do so using {@link android.content.Context#MODE_WORLD_READABLE} and/or {@link android.content.Context#MODE_WORLD_WRITEABLE}, will trigger a {@link java.lang.SecurityException}. + <p class="note"> + <strong>Note:</strong> As of yet, this restriction is not fully enforced. + Apps may still modify permissions to their private directory using + native APIs or the {@link java.io.File File} API. However, we strongly + discourage relaxing the permissions to the private directory. + </p> </li> <li> Passing <code>file://</code> URIs outside the package domain may leave the diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index a8c26522f419..625723857a17 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -1247,7 +1247,8 @@ public final class MediaCodecInfo { private Range<Double> estimateFrameRatesFor(int width, int height) { Size size = findClosestSize(width, height); Range<Long> range = mMeasuredFrameRates.get(size); - Double ratio = (double)(size.getWidth() * size.getHeight()) / (width * height); + Double ratio = getBlockCount(size.getWidth(), size.getHeight()) + / (double)Math.max(getBlockCount(width, height), 1); return Range.create(range.getLower() * ratio, range.getUpper() * ratio); } diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java index f72c7ac7c08f..74bd01689874 100644 --- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java +++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java @@ -288,12 +288,8 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat // the first batch of results which will be delivered // after reading historical data. This should be pretty // fast, so just wait before showing the UI. - mPrinterRegistry = new PrinterRegistry(PrintActivity.this, - new Runnable() { - @Override - public void run() { - onPrinterRegistryReady(documentAdapter); - } + mPrinterRegistry = new PrinterRegistry(PrintActivity.this, () -> { + (new Handler(getMainLooper())).post(() -> onPrinterRegistryReady(documentAdapter)); }, LOADER_ID_PRINT_REGISTRY, LOADER_ID_PRINT_REGISTRY_INT); } diff --git a/packages/SystemUI/res/layout/volume_dialog_row.xml b/packages/SystemUI/res/layout/volume_dialog_row.xml index f0ae1c997efc..be05a3ac259c 100644 --- a/packages/SystemUI/res/layout/volume_dialog_row.xml +++ b/packages/SystemUI/res/layout/volume_dialog_row.xml @@ -18,6 +18,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:clipChildren="false" + android:clipToPadding="false" android:id="@+id/volume_dialog_row" android:paddingEnd="@dimen/volume_button_size" > diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index 716185f343b5..b2aa966c7449 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -106,6 +106,7 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene public void setHost(QSTileHost host) { mHost = host; mPhoneStatusBar = host.getPhoneStatusBar(); + mTileAdapter.setHost(host); } public void setContainer(NotificationsQuickSettingsContainer notificationsQsContainer) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java index 41b49d824a99..ec0eefb6e662 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java @@ -81,6 +81,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta private Holder mCurrentDrag; private boolean mAccessibilityMoving; private int mAccessibilityFromIndex; + private QSTileHost mHost; public TileAdapter(Context context) { mContext = context; @@ -88,6 +89,10 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta mItemTouchHelper = new ItemTouchHelper(mCallbacks); } + public void setHost(QSTileHost host) { + mHost = host; + } + @Override public long getItemId(int position) { return mTiles.get(position) != null ? mAllTiles.indexOf(mTiles.get(position)) @@ -108,7 +113,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta newSpecs.add(mTiles.get(i).spec); } host.changeTiles(mCurrentSpecs, newSpecs); - setTileSpecs(newSpecs); + mCurrentSpecs = newSpecs; } public void setTileSpecs(List<String> currentSpecs) { @@ -285,6 +290,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta move(mAccessibilityFromIndex, position, v); notifyItemChanged(mAccessibilityFromIndex); notifyItemMoved(mAccessibilityFromIndex, position); + saveSpecs(mHost); } private void showAccessibilityDialog(final int position, final View v) { @@ -373,6 +379,7 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta fromLabel, (to + 1)); } v.announceForAccessibility(announcement); + saveSpecs(mHost); return true; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java index f7ecd61e1568..6fc32de100e2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -409,6 +409,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (mKeyguardBottomArea != null) { mKeyguardBottomArea.setUserSetupComplete(mUserSetup); } + if (mNetworkController != null) { + mNetworkController.setUserSetupComplete(mUserSetup); + } } if (mIconPolicy != null) { mIconPolicy.setCurrentUserSetup(mUserSetup); @@ -838,6 +841,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } }); mNetworkController = new NetworkControllerImpl(mContext, mHandlerThread.getLooper()); + mNetworkController.setUserSetupComplete(mUserSetup); mHotspotController = new HotspotControllerImpl(mContext); mBluetoothController = new BluetoothControllerImpl(mContext, mHandlerThread.getLooper()); mSecurityController = new SecurityControllerImpl(mContext); @@ -1437,7 +1441,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, public void removeNotification(String key, RankingMap ranking) { boolean deferRemoval = false; if (mHeadsUpManager.isHeadsUp(key)) { - deferRemoval = !mHeadsUpManager.removeNotification(key); + // A cancel() in repsonse to a remote input shouldn't be delayed, as it makes the + // sending look longer than it takes. + boolean ignoreEarliestRemovalTime = mRemoteInputController.isSpinning(key) + && !FORCE_REMOTE_INPUT_HISTORY; + deferRemoval = !mHeadsUpManager.removeNotification(key, ignoreEarliestRemovalTime); } if (key.equals(mMediaNotificationKey)) { clearCurrentMediaNotification(); @@ -2364,7 +2372,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, if (wasHeadsUp) { if (!shouldPeek) { // We don't want this to be interrupting anymore, lets remove it - mHeadsUpManager.removeNotification(key); + mHeadsUpManager.removeNotification(key, false /* ignoreEarliestRemovalTime */); } else { mHeadsUpManager.updateNotification(entry, alertAgain); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java index 52fb47022275..d3ae54984e99 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java @@ -264,9 +264,9 @@ public class HeadsUpManager implements ViewTreeObserver.OnComputeInternalInsetsL * @return true if the notification was removed and false if it still needs to be kept around * for a bit since it wasn't shown long enough */ - public boolean removeNotification(String key) { + public boolean removeNotification(String key, boolean ignoreEarliestRemovalTime) { if (DEBUG) Log.v(TAG, "remove"); - if (wasShownLongEnough(key)) { + if (wasShownLongEnough(key) || ignoreEarliestRemovalTime) { releaseImmediately(key); return true; } else { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java index 80dcfb6dfe2c..83e25ebd7497 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java @@ -114,6 +114,11 @@ public class MobileSignalController extends SignalController< notifyListenersIfNecessary(); } + public void setUserSetupComplete(boolean userSetup) { + mCurrentState.userSetup = userSetup; + notifyListenersIfNecessary(); + } + @Override public void updateConnectivity(BitSet connectedTransports, BitSet validatedTransports) { boolean isValidated = validatedTransports.get(mTransportType); @@ -204,11 +209,13 @@ public class MobileSignalController extends SignalController< String contentDescription = getStringIfExists(getContentDescription()); String dataContentDescription = getStringIfExists(icons.mDataContentDescription); + final boolean dataDisabled = mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED + && mCurrentState.userSetup; - // Show icon in QS when we are connected or need to show roaming. + // Show icon in QS when we are connected or need to show roaming or data is disabled. boolean showDataIcon = mCurrentState.dataConnected || mCurrentState.iconGroup == TelephonyIcons.ROAMING - || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED; + || dataDisabled; IconState statusIcon = new IconState(mCurrentState.enabled && !mCurrentState.airplaneMode, getCurrentIconId(), contentDescription); @@ -230,7 +237,7 @@ public class MobileSignalController extends SignalController< && mCurrentState.activityOut; showDataIcon &= mCurrentState.isDefault || mCurrentState.iconGroup == TelephonyIcons.ROAMING - || mCurrentState.iconGroup == TelephonyIcons.DATA_DISABLED; + || dataDisabled; int typeIcon = showDataIcon ? icons.mDataType : 0; callback.setMobileDataIndicators(statusIcon, qsIcon, typeIcon, qsTypeIcon, activityIn, activityOut, dataContentDescription, description, icons.mIsWide, @@ -511,6 +518,7 @@ public class MobileSignalController extends SignalController< boolean airplaneMode; boolean carrierNetworkChangeMode; boolean isDefault; + boolean userSetup; @Override public void copyFrom(State s) { @@ -524,6 +532,7 @@ public class MobileSignalController extends SignalController< isEmergency = state.isEmergency; airplaneMode = state.airplaneMode; carrierNetworkChangeMode = state.carrierNetworkChangeMode; + userSetup = state.userSetup; } @Override @@ -537,7 +546,9 @@ public class MobileSignalController extends SignalController< builder.append("isDefault=").append(isDefault).append(','); builder.append("isEmergency=").append(isEmergency).append(','); builder.append("airplaneMode=").append(airplaneMode).append(','); - builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode); + builder.append("carrierNetworkChangeMode=").append(carrierNetworkChangeMode) + .append(','); + builder.append("userSetup=").append(userSetup); } @Override @@ -550,6 +561,7 @@ public class MobileSignalController extends SignalController< && ((MobileState) o).isEmergency == isEmergency && ((MobileState) o).airplaneMode == airplaneMode && ((MobileState) o).carrierNetworkChangeMode == carrierNetworkChangeMode + && ((MobileState) o).userSetup == userSetup && ((MobileState) o).isDefault == isDefault; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java index 40dacd3b991d..a63324134512 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java @@ -130,6 +130,7 @@ public class NetworkControllerImpl extends BroadcastReceiver @VisibleForTesting ServiceState mLastServiceState; + private boolean mUserSetup; /** * Construct this controller object and register for updates. @@ -490,6 +491,7 @@ public class NetworkControllerImpl extends BroadcastReceiver MobileSignalController controller = new MobileSignalController(mContext, mConfig, mHasMobileDataFeature, mPhone, mCallbackHandler, this, subscriptions.get(i), mSubDefaults, mReceiverHandler.getLooper()); + controller.setUserSetupComplete(mUserSetup); mMobileSignalControllers.put(subId, controller); if (subscriptions.get(i).getSimSlotIndex() == 0) { mDefaultSignalController = controller; @@ -516,6 +518,23 @@ public class NetworkControllerImpl extends BroadcastReceiver updateAirplaneMode(true /* force */); } + public void setUserSetupComplete(final boolean userSetup) { + mReceiverHandler.post(new Runnable() { + @Override + public void run() { + handleSetUserSetupComplete(userSetup); + } + }); + } + + @VisibleForTesting + void handleSetUserSetupComplete(boolean userSetup) { + mUserSetup = userSetup; + for (MobileSignalController controller : mMobileSignalControllers.values()) { + controller.setUserSetupComplete(mUserSetup); + } + } + @VisibleForTesting boolean hasCorrectMobileControllers(List<SubscriptionInfo> allSubscriptions) { if (allSubscriptions.size() != mMobileSignalControllers.size()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java index f3033cd89cf8..a855aed88694 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java @@ -91,8 +91,6 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene mEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - - // Check if this was the result of hitting the enter key final boolean isSoftImeEvent = event == null && (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_ACTION_NEXT @@ -102,7 +100,10 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene && event.getAction() == KeyEvent.ACTION_DOWN; if (isSoftImeEvent || isKeyboardEnterKey) { - sendRemoteInput(); + if (mEditText.length() > 0) { + sendRemoteInput(); + } + // Consume action to prevent IME from closing. return true; } return false; diff --git a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java index 2c53e2962049..36dd72793428 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java +++ b/packages/SystemUI/src/com/android/systemui/usb/StorageNotification.java @@ -654,8 +654,9 @@ public class StorageNotification extends SystemUI { intent.putExtra(PackageManager.EXTRA_MOVE_ID, move.moveId); final VolumeInfo vol = mStorageManager.findVolumeByQualifiedUuid(move.volumeUuid); - intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId()); - + if (vol != null) { + intent.putExtra(VolumeInfo.EXTRA_VOLUME_ID, vol.getId()); + } return PendingIntent.getActivityAsUser(mContext, move.moveId, intent, PendingIntent.FLAG_CANCEL_CURRENT, null, UserHandle.CURRENT); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java index 60d33fa0f191..38cac1e74031 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java @@ -111,6 +111,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase { when(mMockTm.getDataEnabled(mSubId)).thenReturn(true); setDefaultSubId(mSubId); setSubscriptions(mSubId); + mNetworkController.handleSetUserSetupComplete(true); mMobileSignalController = mNetworkController.mMobileSignalControllers.get(mSubId); mPhoneStateListener = mMobileSignalController.mPhoneStateListener; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java index d5eca95e2cbf..542c39021ee9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java @@ -1,9 +1,9 @@ package com.android.systemui.statusbar.policy; +import android.net.NetworkCapabilities; import android.os.Looper; import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; - import com.android.settingslib.net.DataUsageController; import org.mockito.Mockito; @@ -99,6 +99,29 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { TelephonyIcons.QS_DATA_4G); } + public void testDataDisabledIcon() { + setupNetworkController(); + Mockito.when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); + setupDefaultSignal(); + updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0); + setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); + + verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED, + TelephonyIcons.QS_ICON_DATA_DISABLED); + } + + public void testDataDisabledIcon_UserNotSetup() { + setupNetworkController(); + Mockito.when(mMockTm.getDataEnabled(mSubId)).thenReturn(false); + setupDefaultSignal(); + updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0); + setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false); + mNetworkController.handleSetUserSetupComplete(false); + + // Don't show the X until the device is setup. + verifyDataIndicators(0, 0); + } + public void test4gDataIconConfigChange() { setupDefaultSignal(); updateDataConnectionState(TelephonyManager.DATA_CONNECTED, @@ -145,7 +168,6 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest { verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, DEFAULT_ICON); verifyLastQsMobileDataIndicators(true, DEFAULT_QS_SIGNAL_STRENGTH, DEFAULT_QS_ICON, in, out); - } private void verifyDataIndicators(int dataIcon, int qsDataIcon) { diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java index 95f9e2dc0935..1b63cd4958dc 100644 --- a/services/backup/java/com/android/server/backup/BackupManagerService.java +++ b/services/backup/java/com/android/server/backup/BackupManagerService.java @@ -3706,7 +3706,7 @@ public class BackupManagerService { result = BackupTransport.TRANSPORT_OK; } } catch (IOException e) { - Slog.e(TAG, "Error backing up " + mPkg.packageName, e); + Slog.e(TAG, "Error backing up " + mPkg.packageName + ": " + e.getMessage()); result = BackupTransport.AGENT_ERROR; } finally { try { @@ -4466,7 +4466,6 @@ public class BackupManagerService { } } - // If we've lost our running criteria, tell the transport to cancel // and roll back this (partial) backup payload; otherwise tell it // that we've reached the clean finish state. @@ -4484,14 +4483,16 @@ public class BackupManagerService { } } - // TRANSPORT_ERROR here means that we've hit an error that the runner - // doesn't know about, so it's still moving data but we're pulling the + // A transport-originated error here means that we've hit an error that the + // runner doesn't know about, so it's still moving data but we're pulling the // rug out from under it. Don't ask for its result: we already know better // and we'll hang if we block waiting for it, since it relies on us to // read back the data it's writing into the engine. Just proceed with // a graceful failure. The runner/engine mechanism will tear itself - // down cleanly when we close the pipes from this end. - if (backupPackageStatus != BackupTransport.TRANSPORT_ERROR) { + // down cleanly when we close the pipes from this end. Transport-level + // errors take precedence over agent/app-specific errors for purposes of + // determining our course of action. + if (backupPackageStatus == BackupTransport.TRANSPORT_OK) { // We still could fail in backup runner thread, getting result from there. int backupRunnerResult = backupRunner.getBackupResultBlocking(); if (backupRunnerResult != BackupTransport.TRANSPORT_OK) { @@ -4499,10 +4500,14 @@ public class BackupManagerService { // not TRANSPORT_ERROR here, overwrite it. backupPackageStatus = backupRunnerResult; } + } else { + if (MORE_DEBUG) { + Slog.i(TAG, "Transport-level failure; cancelling agent work"); + } } if (MORE_DEBUG) { - Slog.i(TAG, "Done trying to send backup data: result=" + Slog.i(TAG, "Done delivering backup data: result=" + backupPackageStatus); } diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java index 87539921be78..6b517210ef31 100644 --- a/services/core/java/com/android/server/BatteryService.java +++ b/services/core/java/com/android/server/BatteryService.java @@ -358,7 +358,7 @@ public final class BatteryService extends SystemService { try { mBatteryStats.setBatteryState(mBatteryProps.batteryStatus, mBatteryProps.batteryHealth, mPlugType, mBatteryProps.batteryLevel, mBatteryProps.batteryTemperature, - mBatteryProps.batteryVoltage); + mBatteryProps.batteryVoltage, mBatteryProps.batteryChargeCounter); } catch (RemoteException e) { // Should never happen. } diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index d85827e99079..00dcdeae3a27 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -29,8 +29,12 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED; import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED; import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED; import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; +import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED; import static android.net.NetworkPolicyManager.RULE_REJECT_ALL; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; +import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED; +import static android.net.NetworkPolicyManager.RULE_UNKNOWN; + import android.annotation.Nullable; import android.app.BroadcastOptions; import android.app.Notification; @@ -96,8 +100,10 @@ import android.security.Credentials; import android.security.KeyStore; import android.telephony.TelephonyManager; import android.text.TextUtils; +import android.util.ArraySet; import android.util.LocalLog; import android.util.LocalLog.ReadOnlyLocalLog; +import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; @@ -121,9 +127,9 @@ import com.android.internal.util.XmlUtils; import com.android.server.am.BatteryStatsService; import com.android.server.connectivity.DataConnectionStats; import com.android.server.connectivity.KeepaliveTracker; -import com.android.server.connectivity.NetworkDiagnostics; import com.android.server.connectivity.Nat464Xlat; import com.android.server.connectivity.NetworkAgentInfo; +import com.android.server.connectivity.NetworkDiagnostics; import com.android.server.connectivity.NetworkMonitor; import com.android.server.connectivity.PacManager; import com.android.server.connectivity.PermissionMonitor; @@ -131,8 +137,8 @@ import com.android.server.connectivity.Tethering; import com.android.server.connectivity.Vpn; import com.android.server.net.BaseNetworkObserver; import com.android.server.net.LockdownVpnTracker; + import com.google.android.collect.Lists; -import com.google.android.collect.Sets; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -152,11 +158,11 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; -import java.util.SortedSet; -import java.util.TreeSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.SortedSet; +import java.util.TreeSet; /** * @hide @@ -202,9 +208,14 @@ public class ConnectivityService extends IConnectivityManager.Stub /** Lock around {@link #mUidRules} and {@link #mMeteredIfaces}. */ private Object mRulesLock = new Object(); /** Currently active network rules by UID. */ + @GuardedBy("mRulesLock") private SparseIntArray mUidRules = new SparseIntArray(); /** Set of ifaces that are costly. */ - private HashSet<String> mMeteredIfaces = Sets.newHashSet(); + @GuardedBy("mRulesLock") + private ArraySet<String> mMeteredIfaces = new ArraySet<>(); + /** Flag indicating if background data is restricted. */ + @GuardedBy("mRulesLock") + private boolean mRestrictBackground; final private Context mContext; private int mNetworkPreference; @@ -651,7 +662,8 @@ public class ConnectivityService extends IConnectivityManager.Stub mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); try { - mPolicyManager.registerListener(mPolicyListener); + mPolicyManager.setConnectivityListener(mPolicyListener); + mRestrictBackground = mPolicyManager.getRestrictBackground(); } catch (RemoteException e) { // ouch, no rules updates means some processes may never get network loge("unable to register INetworkPolicyListener" + e.toString()); @@ -819,7 +831,7 @@ public class ConnectivityService extends IConnectivityManager.Stub throw new IllegalStateException("No free netIds"); } - private NetworkState getFilteredNetworkState(int networkType, int uid) { + private NetworkState getFilteredNetworkState(int networkType, int uid, boolean ignoreBlocked) { if (mLegacyTypeTracker.isTypeSupported(networkType)) { final NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType); final NetworkState state; @@ -834,7 +846,7 @@ public class ConnectivityService extends IConnectivityManager.Stub state = new NetworkState(info, new LinkProperties(), new NetworkCapabilities(), null, null, null); } - filterNetworkStateForUid(state, uid); + filterNetworkStateForUid(state, uid, ignoreBlocked); return state; } else { return NetworkState.EMPTY; @@ -890,22 +902,36 @@ public class ConnectivityService extends IConnectivityManager.Stub /** * Check if UID should be blocked from using the network with the given LinkProperties. */ - private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid) { - final boolean networkCostly; + private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid, + boolean ignoreBlocked) { + // Networks aren't blocked when ignoring blocked status + if (ignoreBlocked) return false; + // Networks are never blocked for system services + if (uid < Process.FIRST_APPLICATION_UID) return false; + + final boolean networkMetered; final int uidRules; final String iface = (lp == null ? "" : lp.getInterfaceName()); synchronized (mRulesLock) { - networkCostly = mMeteredIfaces.contains(iface); - uidRules = mUidRules.get(uid, RULE_ALLOW_ALL); + networkMetered = mMeteredIfaces.contains(iface); + uidRules = mUidRules.get(uid, RULE_UNKNOWN); } - if (uidRules == RULE_REJECT_ALL) { - return true; - } else if ((uidRules == RULE_REJECT_METERED) && networkCostly) { - return true; - } else { - return false; + switch (uidRules) { + case RULE_ALLOW_ALL: + case RULE_ALLOW_METERED: + case RULE_TEMPORARY_ALLOW_METERED: + return false; + case RULE_REJECT_METERED: + return networkMetered; + case RULE_REJECT_ALL: + return true; + case RULE_UNKNOWN: + default: + // When background data is restricted device-wide, the default + // behavior for apps should be like RULE_REJECT_METERED + return mRestrictBackground ? networkMetered : false; } } @@ -930,10 +956,10 @@ public class ConnectivityService extends IConnectivityManager.Stub * on {@link #isNetworkWithLinkPropertiesBlocked}, or * {@link NetworkInfo#isMetered()} based on network policies. */ - private void filterNetworkStateForUid(NetworkState state, int uid) { + private void filterNetworkStateForUid(NetworkState state, int uid, boolean ignoreBlocked) { if (state == null || state.networkInfo == null || state.linkProperties == null) return; - if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid)) { + if (isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, ignoreBlocked)) { state.networkInfo.setDetailedState(DetailedState.BLOCKED, null, null); } if (mLockdownTracker != null) { @@ -962,7 +988,7 @@ public class ConnectivityService extends IConnectivityManager.Stub enforceAccessPermission(); final int uid = Binder.getCallingUid(); final NetworkState state = getUnfilteredActiveNetworkState(uid); - filterNetworkStateForUid(state, uid); + filterNetworkStateForUid(state, uid, false); maybeLogBlockedNetworkInfo(state.networkInfo, uid); return state.networkInfo; } @@ -970,16 +996,16 @@ public class ConnectivityService extends IConnectivityManager.Stub @Override public Network getActiveNetwork() { enforceAccessPermission(); - return getActiveNetworkForUidInternal(Binder.getCallingUid()); + return getActiveNetworkForUidInternal(Binder.getCallingUid(), false); } @Override - public Network getActiveNetworkForUid(int uid) { + public Network getActiveNetworkForUid(int uid, boolean ignoreBlocked) { enforceConnectivityInternalPermission(); - return getActiveNetworkForUidInternal(uid); + return getActiveNetworkForUidInternal(uid, ignoreBlocked); } - private Network getActiveNetworkForUidInternal(final int uid) { + private Network getActiveNetworkForUidInternal(final int uid, boolean ignoreBlocked) { final int user = UserHandle.getUserId(uid); int vpnNetId = NETID_UNSET; synchronized (mVpns) { @@ -994,7 +1020,10 @@ public class ConnectivityService extends IConnectivityManager.Stub if (nai != null) return nai.network; } nai = getDefaultNetwork(); - if (nai != null && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid)) nai = null; + if (nai != null + && isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, ignoreBlocked)) { + nai = null; + } return nai != null ? nai.network : null; } @@ -1006,10 +1035,10 @@ public class ConnectivityService extends IConnectivityManager.Stub } @Override - public NetworkInfo getActiveNetworkInfoForUid(int uid) { + public NetworkInfo getActiveNetworkInfoForUid(int uid, boolean ignoreBlocked) { enforceConnectivityInternalPermission(); final NetworkState state = getUnfilteredActiveNetworkState(uid); - filterNetworkStateForUid(state, uid); + filterNetworkStateForUid(state, uid, ignoreBlocked); return state.networkInfo; } @@ -1023,22 +1052,21 @@ public class ConnectivityService extends IConnectivityManager.Stub // getUnfilteredActiveNetworkState. final NetworkState state = getUnfilteredActiveNetworkState(uid); if (state.networkInfo != null && state.networkInfo.getType() == networkType) { - filterNetworkStateForUid(state, uid); + filterNetworkStateForUid(state, uid, false); return state.networkInfo; } } - final NetworkState state = getFilteredNetworkState(networkType, uid); + final NetworkState state = getFilteredNetworkState(networkType, uid, false); return state.networkInfo; } @Override - public NetworkInfo getNetworkInfoForNetwork(Network network) { + public NetworkInfo getNetworkInfoForUid(Network network, int uid, boolean ignoreBlocked) { enforceAccessPermission(); - final int uid = Binder.getCallingUid(); final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network); if (nai != null) { final NetworkState state = nai.getNetworkState(); - filterNetworkStateForUid(state, uid); + filterNetworkStateForUid(state, uid, ignoreBlocked); return state.networkInfo; } else { return null; @@ -1063,8 +1091,8 @@ public class ConnectivityService extends IConnectivityManager.Stub public Network getNetworkForType(int networkType) { enforceAccessPermission(); final int uid = Binder.getCallingUid(); - NetworkState state = getFilteredNetworkState(networkType, uid); - if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid)) { + NetworkState state = getFilteredNetworkState(networkType, uid, false); + if (!isNetworkWithLinkPropertiesBlocked(state.linkProperties, uid, false)) { return state.network; } return null; @@ -1381,6 +1409,11 @@ public class ConnectivityService extends IConnectivityManager.Stub if (LOGD_RULES) { log("onRestrictBackgroundChanged(restrictBackground=" + restrictBackground + ")"); } + + synchronized (mRulesLock) { + mRestrictBackground = restrictBackground; + } + if (restrictBackground) { log("onRestrictBackgroundChanged(true): disabling tethering"); mTethering.untetherAll(); @@ -1824,6 +1857,10 @@ public class ConnectivityService extends IConnectivityManager.Stub pw.decreaseIndent(); pw.println(); + pw.print("Restrict background: "); + pw.println(mRestrictBackground); + pw.println(); + pw.println("Network Requests:"); pw.increaseIndent(); for (NetworkRequestInfo nri : mNetworkRequests.values()) { @@ -2765,7 +2802,7 @@ public class ConnectivityService extends IConnectivityManager.Stub // which isn't meant to work on uncreated networks. if (!nai.created) return; - if (isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid)) return; + if (isNetworkWithLinkPropertiesBlocked(nai.linkProperties, uid, false)) return; nai.networkMonitor.sendMessage(NetworkMonitor.CMD_FORCE_REEVALUATION, uid); } @@ -4280,10 +4317,10 @@ public class ConnectivityService extends IConnectivityManager.Stub Collection<InetAddress> dnses = newLp.getDnsServers(); if (DBG) log("Setting DNS servers for network " + netId + " to " + dnses); try { - mNetd.setDnsServersForNetwork( + mNetd.setDnsConfigurationForNetwork( netId, NetworkUtils.makeStrings(dnses), newLp.getDomains()); } catch (Exception e) { - loge("Exception in setDnsServersForNetwork: " + e); + loge("Exception in setDnsConfigurationForNetwork: " + e); } final NetworkAgentInfo defaultNai = getDefaultNetwork(); if (defaultNai != null && defaultNai.network.netId == netId) { diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java index 9fc17a2a3a29..2418160255f8 100644 --- a/services/core/java/com/android/server/NetworkManagementService.java +++ b/services/core/java/com/android/server/NetworkManagementService.java @@ -47,6 +47,7 @@ import static com.android.server.NetworkManagementService.NetdResponseCode.TtyLi import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED; import android.annotation.NonNull; import android.app.ActivityManagerNative; +import android.content.ContentResolver; import android.content.Context; import android.net.ConnectivityManager; import android.net.INetd; @@ -76,6 +77,7 @@ import android.os.ServiceSpecificException; import android.os.StrictMode; import android.os.SystemClock; import android.os.SystemProperties; +import android.provider.Settings; import android.telephony.DataConnectionRealTimeInfo; import android.telephony.PhoneStateListener; import android.telephony.SubscriptionManager; @@ -175,6 +177,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub public static final int StrictCleartext = 617; } + /* Defaults for resolver parameters. */ + public static final int DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS = 1800; + public static final int DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT = 25; + public static final int DNS_RESOLVER_DEFAULT_MIN_SAMPLES = 8; + public static final int DNS_RESOLVER_DEFAULT_MAX_SAMPLES = 64; + /** * String indicating a softap command. */ @@ -1927,6 +1935,51 @@ public class NetworkManagementService extends INetworkManagementService.Stub } @Override + public void setDnsConfigurationForNetwork(int netId, String[] servers, String domains) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + + ContentResolver resolver = mContext.getContentResolver(); + + int sampleValidity = Settings.Global.getInt(resolver, + Settings.Global.DNS_RESOLVER_SAMPLE_VALIDITY_SECONDS, + DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); + if (sampleValidity < 0 || sampleValidity > 65535) { + Slog.w(TAG, "Invalid sampleValidity=" + sampleValidity + ", using default=" + + DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS); + sampleValidity = DNS_RESOLVER_DEFAULT_SAMPLE_VALIDITY_SECONDS; + } + + int successThreshold = Settings.Global.getInt(resolver, + Settings.Global.DNS_RESOLVER_SUCCESS_THRESHOLD_PERCENT, + DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); + if (successThreshold < 0 || successThreshold > 100) { + Slog.w(TAG, "Invalid successThreshold=" + successThreshold + ", using default=" + + DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT); + successThreshold = DNS_RESOLVER_DEFAULT_SUCCESS_THRESHOLD_PERCENT; + } + + int minSamples = Settings.Global.getInt(resolver, + Settings.Global.DNS_RESOLVER_MIN_SAMPLES, DNS_RESOLVER_DEFAULT_MIN_SAMPLES); + int maxSamples = Settings.Global.getInt(resolver, + Settings.Global.DNS_RESOLVER_MAX_SAMPLES, DNS_RESOLVER_DEFAULT_MAX_SAMPLES); + if (minSamples < 0 || minSamples > maxSamples || maxSamples > 64) { + Slog.w(TAG, "Invalid sample count (min, max)=(" + minSamples + ", " + maxSamples + + "), using default=(" + DNS_RESOLVER_DEFAULT_MIN_SAMPLES + ", " + + DNS_RESOLVER_DEFAULT_MAX_SAMPLES + ")"); + minSamples = DNS_RESOLVER_DEFAULT_MIN_SAMPLES; + maxSamples = DNS_RESOLVER_DEFAULT_MAX_SAMPLES; + } + + final String[] domainStrs = domains == null ? new String[0] : domains.split(" "); + final int[] params = { sampleValidity, successThreshold, minSamples, maxSamples }; + try { + mNetdService.setResolverConfiguration(netId, servers, domainStrs, params); + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + + @Override public void setDnsServersForNetwork(int netId, String[] servers, String domains) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); @@ -2048,13 +2101,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub } } - private void closeSocketsForFirewallChain(int chain, String chainName) { + private void closeSocketsForFirewallChainLocked(int chain, String chainName) { // UID ranges to close sockets on. UidRange[] ranges; // UID ranges whose sockets we won't touch. int[] exemptUids; - SparseIntArray rules = getUidFirewallRules(chain); + final SparseIntArray rules = getUidFirewallRules(chain); int numUids = 0; if (getFirewallType(chain) == FIREWALL_TYPE_WHITELIST) { @@ -2119,7 +2172,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub mFirewallChainStates.put(chain, enable); final String operation = enable ? "enable_chain" : "disable_chain"; - String chainName; + final String chainName; switch(chain) { case FIREWALL_CHAIN_STANDBY: chainName = FIREWALL_CHAIN_NAME_STANDBY; @@ -2146,7 +2199,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub // whitelist and blacklist chains allow RSTs through. if (enable) { if (DBG) Slog.d(TAG, "Closing sockets after enabling chain " + chainName); - closeSocketsForFirewallChain(chain, chainName); + closeSocketsForFirewallChainLocked(chain, chainName); } } } diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 96214d6b1a08..98b3b088399a 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -409,7 +409,6 @@ public class AccountManagerService */ public void validateAccounts(int userId) { final UserAccounts accounts = getUserAccounts(userId); - // Invalidate user-specific cache to make sure we catch any // removed authenticators. validateAccountsInternal(accounts, true /* invalidateAuthenticatorCache */); @@ -426,15 +425,13 @@ public class AccountManagerService + " isCeDatabaseAttached=" + accounts.openHelper.isCeDatabaseAttached() + " userLocked=" + mLocalUnlockedUsers.get(accounts.userId)); } + if (invalidateAuthenticatorCache) { mAuthenticatorCache.invalidateCache(accounts.userId); } - final HashMap<String, Integer> knownAuth = new HashMap<>(); - for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : - mAuthenticatorCache.getAllServices(accounts.userId)) { - knownAuth.put(service.type.type, service.uid); - } + final HashMap<String, Integer> knownAuth = getAuthenticatorTypeAndUIDForUser( + mAuthenticatorCache, accounts.userId); synchronized (accounts.cacheLock) { final SQLiteDatabase db = accounts.openHelper.getWritableDatabase(); @@ -452,6 +449,7 @@ public class AccountManagerService // Create a list of authenticator type whose previous uid no longer exists HashSet<String> obsoleteAuthType = Sets.newHashSet(); try { + SparseBooleanArray knownUids = null; while (metaCursor.moveToNext()) { String type = TextUtils.split(metaCursor.getString(0), META_KEY_DELIMITER)[1]; String uid = metaCursor.getString(1); @@ -466,23 +464,48 @@ public class AccountManagerService // Remove it from the knownAuth list if it's unchanged. knownAuth.remove(type); } else { - // Only add it to the list if it no longer exists or uid different - obsoleteAuthType.add(type); - // And delete it from the TABLE_META - db.delete( - TABLE_META, - META_KEY + "=? AND " + META_VALUE + "=?", - new String[] { - META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + type, - uid} - ); + /* + * The authenticator is presently not cached and should only be triggered + * when we think an authenticator has been removed (or is being updated). + * But we still want to check if any data with the associated uid is + * around. This is an (imperfect) signal that the package may be updating. + * + * A side effect of this is that an authenticator sharing a uid with + * multiple apps won't get its credentials wiped as long as some app with + * that uid is still on the device. But I suspect that this is a rare case. + * And it isn't clear to me how an attacker could really exploit that + * feature. + * + * The upshot is that we don't have to worry about accounts getting + * uninstalled while the authenticator's package is being updated. + * + */ + if (knownUids == null) { + knownUids = getUidsOfInstalledOrUpdatedPackagesAsUser(accounts.userId); + } + if (!knownUids.get(Integer.parseInt(uid))) { + // The authenticator is not presently available to the cache. And the + // package no longer has a data directory (so we surmise it isn't updating). + // So purge its data from the account databases. + obsoleteAuthType.add(type); + // And delete it from the TABLE_META + db.delete( + TABLE_META, + META_KEY + "=? AND " + META_VALUE + "=?", + new String[] { + META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + type, + uid} + ); + } } } } finally { metaCursor.close(); } - // Add the newly registered authenticator to TABLE_META + // Add the newly registered authenticator to TABLE_META. If old authenticators have + // been renabled (after being updated for example), then we just overwrite the old + // values. Iterator<Entry<String, Integer>> iterator = knownAuth.entrySet().iterator(); while (iterator.hasNext()) { Entry<String, Integer> entry = iterator.next(); @@ -490,7 +513,7 @@ public class AccountManagerService values.put(META_KEY, META_KEY_FOR_AUTHENTICATOR_UID_FOR_TYPE_PREFIX + entry.getKey()); values.put(META_VALUE, entry.getValue()); - db.insert(TABLE_META, null, values); + db.insertWithOnConflict(TABLE_META, null, values, SQLiteDatabase.CONFLICT_REPLACE); } Cursor cursor = db.query(TABLE_ACCOUNTS, @@ -544,10 +567,32 @@ public class AccountManagerService } } + private SparseBooleanArray getUidsOfInstalledOrUpdatedPackagesAsUser(int userId) { + // Get the UIDs of all apps that might have data on the device. We want + // to preserve user data if the app might otherwise be storing data. + List<PackageInfo> pkgsWithData = + mPackageManager.getInstalledPackagesAsUser( + PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); + SparseBooleanArray knownUids = new SparseBooleanArray(pkgsWithData.size()); + for (PackageInfo pkgInfo : pkgsWithData) { + if (pkgInfo.applicationInfo != null + && (pkgInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0) { + knownUids.put(pkgInfo.applicationInfo.uid, true); + } + } + return knownUids; + } + private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser( Context context, int userId) { AccountAuthenticatorCache authCache = new AccountAuthenticatorCache(context); + return getAuthenticatorTypeAndUIDForUser(authCache, userId); + } + + private static HashMap<String, Integer> getAuthenticatorTypeAndUIDForUser( + IAccountAuthenticatorCache authCache, + int userId) { HashMap<String, Integer> knownAuth = new HashMap<>(); for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> service : authCache .getAllServices(userId)) { diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java index 33b87b656fa0..82ec80c6288c 100644 --- a/services/core/java/com/android/server/am/ActivityStarter.java +++ b/services/core/java/com/android/server/am/ActivityStarter.java @@ -1597,9 +1597,6 @@ class ActivityStarter { private void setTaskFromReuseOrCreateNewTask(TaskRecord taskToAffiliate) { mTargetStack = computeStackFocus(mStartActivity, true, mLaunchBounds, mLaunchFlags, mOptions); - if (mDoResume) { - mTargetStack.moveToFront("startingNewTask"); - } if (mReuseTask == null) { final TaskRecord task = mTargetStack.createTaskRecord( diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index e9ed34b18baa..3ed996992e2e 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -304,6 +304,15 @@ class AppErrors { * @param crashInfo describing the failure */ void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { + final long origId = Binder.clearCallingIdentity(); + try { + crashApplicationInner(r, crashInfo); + } finally { + Binder.restoreCallingIdentity(origId); + } + } + + void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { long timeMillis = System.currentTimeMillis(); String shortMsg = crashInfo.exceptionClassName; String longMsg = crashInfo.exceptionMessage; @@ -317,49 +326,20 @@ class AppErrors { AppErrorResult result = new AppErrorResult(); TaskRecord task; synchronized (mService) { - if (mService.mController != null) { - try { - String name = r != null ? r.processName : null; - int pid = r != null ? r.pid : Binder.getCallingPid(); - int uid = r != null ? r.info.uid : Binder.getCallingUid(); - if (!mService.mController.appCrashed(name, pid, - shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { - if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) - && "Native crash".equals(crashInfo.exceptionClassName)) { - Slog.w(TAG, "Skip killing native crashed app " + name - + "(" + pid + ") during testing"); - } else { - Slog.w(TAG, "Force-killing crashed app " + name - + " at watcher's request"); - if (r != null) { - r.kill("crash", true); - } else { - // Huh. - Process.killProcess(pid); - ActivityManagerService.killProcessGroup(uid, pid); - } - } - return; - } - } catch (RemoteException e) { - mService.mController = null; - Watchdog.getInstance().setActivityController(null); - } + /** + * If crash is handled by instance of {@link android.app.IActivityController}, + * finish now and don't show the app error dialog. + */ + if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace, + timeMillis)) { + return; } - final long origId = Binder.clearCallingIdentity(); - - // If this process is running instrumentation, finish it. + /** + * If this process was running instrumentation, finish now - it will be handled in + * {@link ActivityManagerService#handleAppDiedLocked}. + */ if (r != null && r.instrumentationClass != null) { - Slog.w(TAG, "Error in app " + r.processName - + " running instrumentation " + r.instrumentationClass + ":"); - if (shortMsg != null) Slog.w(TAG, " " + shortMsg); - if (longMsg != null) Slog.w(TAG, " " + longMsg); - Bundle info = new Bundle(); - info.putString("shortMsg", shortMsg); - info.putString("longMsg", longMsg); - mService.finishInstrumentationLocked(r, Activity.RESULT_CANCELED, info); - Binder.restoreCallingIdentity(origId); return; } @@ -375,7 +355,6 @@ class AppErrors { // If we can't identify the process or it's already exceeded its crash quota, // quit right away without showing a crash dialog. if (r == null || !makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, data)) { - Binder.restoreCallingIdentity(origId); return; } @@ -385,97 +364,90 @@ class AppErrors { task = data.task; msg.obj = data; mService.mUiHandler.sendMessage(msg); - - Binder.restoreCallingIdentity(origId); } int res = result.get(); Intent appErrorIntent = null; - final long ident = Binder.clearCallingIdentity(); - try { - MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); - if (res == AppErrorDialog.TIMEOUT) { - res = AppErrorDialog.FORCE_QUIT; - } - if (res == AppErrorDialog.RESET) { - String[] packageList = r.getPackageList(); - if (packageList != null) { - PackageManager pm = mContext.getPackageManager(); - final Semaphore s = new Semaphore(0); - for (int i = 0; i < packageList.length; i++) { - if (i < packageList.length - 1) { - pm.deleteApplicationCacheFiles(packageList[i], null); - } else { - pm.deleteApplicationCacheFiles(packageList[i], - new IPackageDataObserver.Stub() { - @Override - public void onRemoveCompleted(String packageName, - boolean succeeded) { - s.release(); - } - }); - - // Wait until cache has been cleared before we restart. - try { - s.acquire(); - } catch (InterruptedException e) { - } - } - } - } - // If there was nothing to reset, just restart; - res = AppErrorDialog.RESTART; - } - synchronized (mService) { - if (res == AppErrorDialog.MUTE) { - stopReportingCrashesLocked(r); - } - if (res == AppErrorDialog.RESTART) { - mService.removeProcessLocked(r, false, true, "crash"); - if (task != null) { + MetricsLogger.action(mContext, MetricsProto.MetricsEvent.ACTION_APP_CRASH, res); + if (res == AppErrorDialog.TIMEOUT) { + res = AppErrorDialog.FORCE_QUIT; + } + if (res == AppErrorDialog.RESET) { + String[] packageList = r.getPackageList(); + if (packageList != null) { + PackageManager pm = mContext.getPackageManager(); + final Semaphore s = new Semaphore(0); + for (int i = 0; i < packageList.length; i++) { + if (i < packageList.length - 1) { + pm.deleteApplicationCacheFiles(packageList[i], null); + } else { + pm.deleteApplicationCacheFiles(packageList[i], + new IPackageDataObserver.Stub() { + @Override + public void onRemoveCompleted(String packageName, + boolean succeeded) { + s.release(); + } + }); + + // Wait until cache has been cleared before we restart. try { - mService.startActivityFromRecents(task.taskId, - ActivityOptions.makeBasic().toBundle()); - } catch (IllegalArgumentException e) { - // Hmm, that didn't work, app might have crashed before creating a - // recents entry. Let's see if we have a safe-to-restart intent. - if (task.intent.getCategories().contains( - Intent.CATEGORY_LAUNCHER)) { - mService.startActivityInPackage(task.mCallingUid, - task.mCallingPackage, task.intent, - null, null, null, 0, 0, - ActivityOptions.makeBasic().toBundle(), - task.userId, null, null); - } + s.acquire(); + } catch (InterruptedException e) { } } } - if (res == AppErrorDialog.FORCE_QUIT) { - long orig = Binder.clearCallingIdentity(); + } + // If there was nothing to reset, just restart; + res = AppErrorDialog.RESTART; + } + synchronized (mService) { + if (res == AppErrorDialog.MUTE) { + stopReportingCrashesLocked(r); + } + if (res == AppErrorDialog.RESTART) { + mService.removeProcessLocked(r, false, true, "crash"); + if (task != null) { try { - // Kill it with fire! - mService.mStackSupervisor.handleAppCrashLocked(r); - if (!r.persistent) { - mService.removeProcessLocked(r, false, false, "crash"); - mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + mService.startActivityFromRecents(task.taskId, + ActivityOptions.makeBasic().toBundle()); + } catch (IllegalArgumentException e) { + // Hmm, that didn't work, app might have crashed before creating a + // recents entry. Let's see if we have a safe-to-restart intent. + if (task.intent.getCategories().contains( + Intent.CATEGORY_LAUNCHER)) { + mService.startActivityInPackage(task.mCallingUid, + task.mCallingPackage, task.intent, + null, null, null, 0, 0, + ActivityOptions.makeBasic().toBundle(), + task.userId, null, null); } - } finally { - Binder.restoreCallingIdentity(orig); } } - if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) { - appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo); - } - if (r != null && !r.isolated && res != AppErrorDialog.RESTART) { - // XXX Can't keep track of crash time for isolated processes, - // since they don't have a persistent identity. - mProcessCrashTimes.put(r.info.processName, r.uid, - SystemClock.uptimeMillis()); + } + if (res == AppErrorDialog.FORCE_QUIT) { + long orig = Binder.clearCallingIdentity(); + try { + // Kill it with fire! + mService.mStackSupervisor.handleAppCrashLocked(r); + if (!r.persistent) { + mService.removeProcessLocked(r, false, false, "crash"); + mService.mStackSupervisor.resumeFocusedStackTopActivityLocked(); + } + } finally { + Binder.restoreCallingIdentity(orig); } } - } finally { - Binder.restoreCallingIdentity(ident); + if (res == AppErrorDialog.FORCE_QUIT_AND_REPORT) { + appErrorIntent = createAppErrorIntentLocked(r, timeMillis, crashInfo); + } + if (r != null && !r.isolated && res != AppErrorDialog.RESTART) { + // XXX Can't keep track of crash time for isolated processes, + // since they don't have a persistent identity. + mProcessCrashTimes.put(r.info.processName, r.uid, + SystemClock.uptimeMillis()); + } } if (appErrorIntent != null) { @@ -487,6 +459,47 @@ class AppErrors { } } + private boolean handleAppCrashInActivityController(ProcessRecord r, + ApplicationErrorReport.CrashInfo crashInfo, + String shortMsg, String longMsg, + String stackTrace, long timeMillis) { + if (mService.mController == null) { + return false; + } + + try { + String name = r != null ? r.processName : null; + int pid = r != null ? r.pid : Binder.getCallingPid(); + int uid = r != null ? r.info.uid : Binder.getCallingUid(); + if (!mService.mController.appCrashed(name, pid, + shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { + if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0")) + && "Native crash".equals(crashInfo.exceptionClassName)) { + Slog.w(TAG, "Skip killing native crashed app " + name + + "(" + pid + ") during testing"); + } else { + Slog.w(TAG, "Force-killing crashed app " + name + + " at watcher's request"); + if (r != null) { + if (!makeAppCrashingLocked(r, shortMsg, longMsg, stackTrace, null)) + { + r.kill("crash", true); + } + } else { + // Huh. + Process.killProcess(pid); + ActivityManagerService.killProcessGroup(uid, pid); + } + } + return true; + } + } catch (RemoteException e) { + mService.mController = null; + Watchdog.getInstance().setActivityController(null); + } + return false; + } + private boolean makeAppCrashingLocked(ProcessRecord app, String shortMsg, String longMsg, String stackTrace, AppErrorDialog.Data data) { app.crashing = true; diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index c6786defd3f9..d34ec868dc1c 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -974,7 +974,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public void setBatteryState(final int status, final int health, final int plugType, - final int level, final int temp, final int volt) { + final int level, final int temp, final int volt, final int chargeCount) { enforceCallingPermission(); // BatteryService calls us here and we may update external state. It would be wrong @@ -987,7 +987,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub if (mStats.isOnBattery() == onBattery) { // The battery state has not changed, so we don't need to sync external // stats immediately. - mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt); + mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt, + chargeCount); return; } } @@ -996,7 +997,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub // immediately here, we may not collect the relevant data later. updateExternalStatsSync("battery-state", BatteryStatsImpl.ExternalStatsSync.UPDATE_ALL); synchronized (mStats) { - mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt); + mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt, + chargeCount); } } }); diff --git a/services/core/java/com/android/server/job/JobStore.java b/services/core/java/com/android/server/job/JobStore.java index 5ad988a42792..1f7d3128d655 100644 --- a/services/core/java/com/android/server/job/JobStore.java +++ b/services/core/java/com/android/server/job/JobStore.java @@ -333,6 +333,7 @@ public class JobStore { out.attribute(null, "sourceUserId", String.valueOf(jobStatus.getSourceUserId())); out.attribute(null, "uid", Integer.toString(jobStatus.getUid())); out.attribute(null, "priority", String.valueOf(jobStatus.getPriority())); + out.attribute(null, "flags", String.valueOf(jobStatus.getFlags())); } private void writeBundleToXml(PersistableBundle extras, XmlSerializer out) @@ -543,6 +544,10 @@ public class JobStore { if (val != null) { jobBuilder.setPriority(Integer.parseInt(val)); } + val = parser.getAttributeValue(null, "flags"); + if (val != null) { + jobBuilder.setFlags(Integer.parseInt(val)); + } val = parser.getAttributeValue(null, "sourceUserId"); sourceUserId = val == null ? -1 : Integer.parseInt(val); } catch (NumberFormatException e) { diff --git a/services/core/java/com/android/server/job/controllers/ConnectivityController.java b/services/core/java/com/android/server/job/controllers/ConnectivityController.java index 88cf322ed913..f5aac087f9b0 100644 --- a/services/core/java/com/android/server/job/controllers/ConnectivityController.java +++ b/services/core/java/com/android/server/job/controllers/ConnectivityController.java @@ -16,6 +16,7 @@ package com.android.server.job.controllers; +import android.app.job.JobInfo; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -97,7 +98,9 @@ public class ConnectivityController extends StateController implements } private boolean updateConstraintsSatisfied(JobStatus jobStatus) { - final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobStatus.getSourceUid()); + final boolean ignoreBlocked = (jobStatus.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0; + final NetworkInfo info = mConnManager.getActiveNetworkInfoForUid(jobStatus.getSourceUid(), + ignoreBlocked); final boolean connected = (info != null) && info.isConnected(); final boolean unmetered = connected && !info.isMetered(); final boolean notRoaming = connected && !info.isRoaming(); diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java index 590d075446cf..19bede97c503 100644 --- a/services/core/java/com/android/server/job/controllers/JobStatus.java +++ b/services/core/java/com/android/server/job/controllers/JobStatus.java @@ -297,6 +297,10 @@ public final class JobStatus { return job.getPriority(); } + public int getFlags() { + return job.getFlags(); + } + public boolean hasConnectivityConstraint() { return (requiredConstraints&CONSTRAINT_CONNECTIVITY) != 0; } @@ -416,12 +420,12 @@ public final class JobStatus { // satisfied). // AppNotIdle implicit constraint must be satisfied // DeviceNotDozing implicit constraint must be satisfied - return (isConstraintsSatisfied() - || (!job.isPeriodic() - && hasDeadlineConstraint() && (satisfiedConstraints&CONSTRAINT_DEADLINE) != 0) - ) - && (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0 - && (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0; + final boolean deadlineSatisfied = (!job.isPeriodic() && hasDeadlineConstraint() + && (satisfiedConstraints & CONSTRAINT_DEADLINE) != 0); + final boolean notIdle = (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0; + final boolean notDozing = (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0 + || (job.getFlags() & JobInfo.FLAG_WILL_BE_FOREGROUND) != 0; + return (isConstraintsSatisfied() || deadlineSatisfied) && notIdle && notDozing; } static final int CONSTRAINTS_OF_INTEREST = @@ -561,6 +565,10 @@ public final class JobStatus { if (job.getPriority() != 0) { pw.print(prefix); pw.print(" Priority: "); pw.println(job.getPriority()); } + if (job.getFlags() != 0) { + pw.print(prefix); pw.print(" Flags: "); + pw.println(Integer.toHexString(job.getFlags())); + } pw.print(prefix); pw.print(" Requires: charging="); pw.print(job.isRequireCharging()); pw.print(" deviceIdle="); pw.println(job.isRequireDeviceIdle()); @@ -613,6 +621,9 @@ public final class JobStatus { pw.print(prefix); pw.print("Satisfied constraints:"); dumpConstraints(pw, satisfiedConstraints); pw.println(); + pw.print(prefix); pw.print("Unsatisfied constraints:"); + dumpConstraints(pw, (requiredConstraints & ~satisfiedConstraints)); + pw.println(); } if (changedAuthorities != null) { pw.print(prefix); pw.println("Changed authorities:"); diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index 30aab8cc5897..50d936853fed 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -48,7 +48,6 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT; import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY; import static android.net.NetworkPolicyManager.POLICY_NONE; import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND; -import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL; import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED; import static android.net.NetworkPolicyManager.RULE_REJECT_METERED; import static android.net.NetworkPolicyManager.RULE_TEMPORARY_ALLOW_METERED; @@ -349,6 +348,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { /** Foreground at UID granularity. */ final SparseIntArray mUidState = new SparseIntArray(); + /** Higher priority listener before general event dispatch */ + private INetworkPolicyListener mConnectivityListener; + private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<>(); @@ -1391,6 +1393,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final String tag = in.getName(); if (type == START_TAG) { if (TAG_POLICY_LIST.equals(tag)) { + final boolean oldValue = mRestrictBackground; version = readIntAttribute(in, ATTR_VERSION); if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) { mRestrictBackground = readBooleanAttribute( @@ -1398,6 +1401,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } else { mRestrictBackground = false; } + if (mRestrictBackground != oldValue) { + // Some early services may have read the default value, + // so notify them that it's changed + mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, + mRestrictBackground ? 1 : 0, 0).sendToTarget(); + } } else if (TAG_NETWORK_POLICY.equals(tag)) { final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE); @@ -1766,20 +1775,25 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } @Override + public void setConnectivityListener(INetworkPolicyListener listener) { + mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); + if (mConnectivityListener != null) { + throw new IllegalStateException("Connectivity listener already registered"); + } + mConnectivityListener = listener; + } + + @Override public void registerListener(INetworkPolicyListener listener) { // TODO: create permission for observing network policy mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - mListeners.register(listener); - - // TODO: consider dispatching existing rules to new listeners } @Override public void unregisterListener(INetworkPolicyListener listener) { // TODO: create permission for observing network policy mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - mListeners.unregister(listener); } @@ -2754,8 +2768,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0; final boolean isWhitelisted = mRestrictBackgroundWhitelistUids.get(uid); - int newRule = RULE_ALLOW_ALL; - final int oldRule = mUidRules.get(uid); + int newRule = RULE_UNKNOWN; + final int oldRule = mUidRules.get(uid, RULE_UNKNOWN); // First step: define the new rule based on user restrictions and foreground state. if (isForeground) { @@ -2777,8 +2791,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { + ", oldRule: " + ruleToString(oldRule)); } - - if (newRule == RULE_ALLOW_ALL) { + if (newRule == RULE_UNKNOWN) { mUidRules.delete(uid); } else { mUidRules.put(uid, newRule); @@ -2858,6 +2871,45 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + private void dispatchUidRulesChanged(INetworkPolicyListener listener, int uid, int uidRules) { + if (listener != null) { + try { + listener.onUidRulesChanged(uid, uidRules); + } catch (RemoteException ignored) { + } + } + } + + private void dispatchMeteredIfacesChanged(INetworkPolicyListener listener, + String[] meteredIfaces) { + if (listener != null) { + try { + listener.onMeteredIfacesChanged(meteredIfaces); + } catch (RemoteException ignored) { + } + } + } + + private void dispatchRestrictBackgroundChanged(INetworkPolicyListener listener, + boolean restrictBackground) { + if (listener != null) { + try { + listener.onRestrictBackgroundChanged(restrictBackground); + } catch (RemoteException ignored) { + } + } + } + + private void dispatchRestrictBackgroundWhitelistChanged(INetworkPolicyListener listener, + int uid, boolean whitelisted) { + if (listener != null) { + try { + listener.onRestrictBackgroundWhitelistChanged(uid, whitelisted); + } catch (RemoteException ignored) { + } + } + } + private Handler.Callback mHandlerCallback = new Handler.Callback() { @Override public boolean handleMessage(Message msg) { @@ -2865,30 +2917,22 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { case MSG_RULES_CHANGED: { final int uid = msg.arg1; final int uidRules = msg.arg2; + dispatchUidRulesChanged(mConnectivityListener, uid, uidRules); final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); - if (listener != null) { - try { - listener.onUidRulesChanged(uid, uidRules); - } catch (RemoteException e) { - } - } + dispatchUidRulesChanged(listener, uid, uidRules); } mListeners.finishBroadcast(); return true; } case MSG_METERED_IFACES_CHANGED: { final String[] meteredIfaces = (String[]) msg.obj; + dispatchMeteredIfacesChanged(mConnectivityListener, meteredIfaces); final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); - if (listener != null) { - try { - listener.onMeteredIfacesChanged(meteredIfaces); - } catch (RemoteException e) { - } - } + dispatchMeteredIfacesChanged(listener, meteredIfaces); } mListeners.finishBroadcast(); return true; @@ -2915,15 +2959,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } case MSG_RESTRICT_BACKGROUND_CHANGED: { final boolean restrictBackground = msg.arg1 != 0; + dispatchRestrictBackgroundChanged(mConnectivityListener, restrictBackground); final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); - if (listener != null) { - try { - listener.onRestrictBackgroundChanged(restrictBackground); - } catch (RemoteException e) { - } - } + dispatchRestrictBackgroundChanged(listener, restrictBackground); } mListeners.finishBroadcast(); final Intent intent = @@ -2947,18 +2987,16 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final boolean changed = msg.arg2 == 1; final Boolean whitelisted = (Boolean) msg.obj; + // First notify internal listeners... if (whitelisted != null) { + final boolean whitelistedBool = whitelisted.booleanValue(); + dispatchRestrictBackgroundWhitelistChanged(mConnectivityListener, uid, + whitelistedBool); final int length = mListeners.beginBroadcast(); for (int i = 0; i < length; i++) { - // First notify internal listeners... final INetworkPolicyListener listener = mListeners.getBroadcastItem(i); - if (listener != null) { - try { - listener.onRestrictBackgroundWhitelistChanged(uid, - whitelisted.booleanValue()); - } catch (RemoteException e) { - } - } + dispatchRestrictBackgroundWhitelistChanged(listener, uid, + whitelistedBool); } mListeners.finishBroadcast(); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index ba651fce1ec9..61e36d964188 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -266,6 +266,7 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileDescriptor; +import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; @@ -274,6 +275,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.nio.charset.StandardCharsets; +import java.security.DigestInputStream; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.PublicKey; @@ -437,6 +439,8 @@ public class PackageManagerService extends IPackageManager.Stub { */ private static final int DEFAULT_VERIFICATION_RESPONSE = PackageManager.VERIFICATION_ALLOW; + static final String PLATFORM_PACKAGE_NAME = "android"; + static final String DEFAULT_CONTAINER_PACKAGE = "com.android.defcontainer"; static final ComponentName DEFAULT_CONTAINER_COMPONENT = new ComponentName( @@ -9725,7 +9729,9 @@ public class PackageManagerService extends IPackageManager.Stub { switch (grant) { case GRANT_INSTALL: { // Revoke this as runtime permission to handle the case of - // a runtime permission being downgraded to an install one. Also in permission review mode we keep dangerous permissions for legacy apps + // a runtime permission being downgraded to an install one. + // Also in permission review mode we keep dangerous permissions + // for legacy apps for (int userId : UserManagerService.getInstance().getUserIds()) { if (origPermissions.getRuntimePermissionState( bp.name, userId) != null) { @@ -9773,10 +9779,21 @@ public class PackageManagerService extends IPackageManager.Stub { && !appSupportsRuntimePermissions) { // For legacy apps that need a permission review, every new // runtime permission is granted but it is pending a review. - if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) { - permissionsState.grantRuntimePermission(bp, userId); - flags |= FLAG_PERMISSION_REVIEW_REQUIRED; - // We changed the permission and flags, hence have to write. + // We also need to review only platform defined runtime + // permissions as these are the only ones the platform knows + // how to disable the API to simulate revocation as legacy + // apps don't expect to run with revoked permissions. + if (PLATFORM_PACKAGE_NAME.equals(bp.sourcePackage)) { + if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0) { + flags |= FLAG_PERMISSION_REVIEW_REQUIRED; + // We changed the flags, hence have to write. + changedRuntimePermissionUserIds = ArrayUtils.appendInt( + changedRuntimePermissionUserIds, userId); + } + } + if (permissionsState.grantRuntimePermission(bp, userId) + != PermissionsState.PERMISSION_OPERATION_FAILURE) { + // We changed the permission, hence have to write. changedRuntimePermissionUserIds = ArrayUtils.appendInt( changedRuntimePermissionUserIds, userId); } @@ -13817,6 +13834,13 @@ public class PackageManagerService extends IPackageManager.Stub { return false; } + private static void updateDigest(MessageDigest digest, File file) throws IOException { + try (DigestInputStream digestStream = + new DigestInputStream(new FileInputStream(file), digest)) { + while (digestStream.read() != -1) {} // nothing to do; just plow through the file + } + } + private void replacePackageLIF(PackageParser.Package pkg, final int policyFlags, int scanFlags, UserHandle user, String installerPackageName, PackageInstalledInfo res) { final boolean isEphemeral = (policyFlags & PackageParser.PARSE_IS_EPHEMERAL) != 0; @@ -13871,6 +13895,32 @@ public class PackageManagerService extends IPackageManager.Stub { } } + // don't allow a system upgrade unless the upgrade hash matches + if (oldPackage.restrictUpdateHash != null && oldPackage.isSystemApp()) { + byte[] digestBytes = null; + try { + final MessageDigest digest = MessageDigest.getInstance("SHA-512"); + updateDigest(digest, new File(pkg.baseCodePath)); + if (!ArrayUtils.isEmpty(pkg.splitCodePaths)) { + for (String path : pkg.splitCodePaths) { + updateDigest(digest, new File(path)); + } + } + digestBytes = digest.digest(); + } catch (NoSuchAlgorithmException | IOException e) { + res.setError(INSTALL_FAILED_INVALID_APK, + "Could not compute hash: " + pkgName); + return; + } + if (!Arrays.equals(oldPackage.restrictUpdateHash, digestBytes)) { + res.setError(INSTALL_FAILED_INVALID_APK, + "New package fails restrict-update check: " + pkgName); + return; + } + // retain upgrade restriction + pkg.restrictUpdateHash = oldPackage.restrictUpdateHash; + } + // Check for shared user id changes String invalidPackageName = getParentOrChildPackageChangedSharedUser(oldPackage, pkg); diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java index 1493bc73a17f..e3194074f792 100644 --- a/services/core/java/com/android/server/wm/WindowStateAnimator.java +++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java @@ -1441,6 +1441,18 @@ class WindowStateAnimator { return; } + // Do not change surface properties of opening apps if we are waiting for the + // transition to be ready. transitionGoodToGo could be not ready even after all + // opening apps are drawn. It's only waiting on isFetchingAppTransitionsSpecs() + // to get the animation spec. (For example, go into Recents and immediately open + // the same app again before the app's surface is destroyed or saved, the surface + // is always ready in the whole process.) If we go ahead here, the opening app + // will be shown with the full size before the correct animation spec arrives. + if (mService.mAppTransition.isReady() && isDummyAnimation() && + mService.mOpeningApps.contains(w.mAppToken)) { + return; + } + boolean displayed = false; computeShownFrameLocked(); diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py index 81ab3ccf3ec5..fe7c3b9b400f 100755 --- a/tools/fonts/fontchain_lint.py +++ b/tools/fonts/fontchain_lint.py @@ -330,7 +330,7 @@ def check_emoji_defaults(default_emoji): 0x2764, # HEAVY BLACK HEART } assert missing_text_chars == set(), ( - 'Text style version of some emoji characters are missing.') + 'Text style version of some emoji characters are missing: ' + repr(missing_text_chars)) # Setting reverse to true returns a dictionary that maps the values to sets of @@ -411,6 +411,20 @@ def parse_ucd(ucd_path): _emoji_zwj_sequences = parse_unicode_datafile( path.join(ucd_path, 'emoji-zwj-sequences.txt')) + # filter modern pentathlon, as it seems likely to be removed from final spec + def is_excluded(n): + return n == 0x1f93b + + def contains_excluded(t): + if type(t) == int: + return is_excluded(t) + return any(is_excluded(cp) for cp in t) + + # filter modern pentathlon, as it seems likely to be removed from final spec + _emoji_properties['Emoji'] = set( + t for t in _emoji_properties['Emoji'] if not contains_excluded(t)) + _emoji_sequences = dict( + (t, v) for (t, v) in _emoji_sequences.items() if not contains_excluded(t)) def flag_sequence(territory_code): return tuple(0x1F1E6 + ord(ch) - ord('A') for ch in territory_code) diff --git a/tools/layoutlib/Android.mk b/tools/layoutlib/Android.mk index 663e1e25e603..f87f6c53c8dc 100644 --- a/tools/layoutlib/Android.mk +++ b/tools/layoutlib/Android.mk @@ -16,8 +16,6 @@ LOCAL_PATH := $(my-dir) include $(CLEAR_VARS) -LOCAL_JAVA_LANGUAGE_VERSION := 1.8 - # # Define rules to build temp_layoutlib.jar, which contains a subset of # the classes in framework.jar. The layoutlib_create tool is used to diff --git a/tools/layoutlib/bridge/Android.mk b/tools/layoutlib/bridge/Android.mk index 16e5913ab81d..3dd8002bcff5 100644 --- a/tools/layoutlib/bridge/Android.mk +++ b/tools/layoutlib/bridge/Android.mk @@ -18,7 +18,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-java-files-under,src) LOCAL_JAVA_RESOURCE_DIRS := resources -LOCAL_JAVA_LANGUAGE_VERSION := 1.8 LOCAL_JAVA_LIBRARIES := \ layoutlib_api-prebuilt \ diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java index 80e230cd8b86..f87269b7c9f7 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java @@ -861,7 +861,9 @@ public final class BridgeContext extends Context { resValue = mRenderResources.resolveResValue(resValue); if (defaultPropMap != null) { - defaultPropMap.put(attrName, + defaultPropMap.put( + frameworkAttr ? SdkConstants.PREFIX_ANDROID + attrName : + attrName, new Property(preResolve, resValue.getValue())); } @@ -932,7 +934,8 @@ public final class BridgeContext extends Context { @Nullable StyleResourceValue style, int[] attrs) throws Resources.NotFoundException { List<Pair<String, Boolean>> attributes = searchAttrs(attrs); - BridgeTypedArray ta = Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false); + BridgeTypedArray ta = + Resources_Delegate.newTypeArray(mSystemResources, attrs.length, false); PropertiesMap defaultPropMap = new PropertiesMap(); // for each attribute, get its name so that we can search it in the style @@ -943,11 +946,11 @@ public final class BridgeContext extends Context { // look for the value in the given style ResourceValue resValue; String attrName = attribute.getFirst(); + boolean frameworkAttr = attribute.getSecond(); if (style != null) { - resValue = mRenderResources.findItemInStyle(style, attrName, - attribute.getSecond()); + resValue = mRenderResources.findItemInStyle(style, attrName, frameworkAttr); } else { - resValue = mRenderResources.findItemInTheme(attrName, attribute.getSecond()); + resValue = mRenderResources.findItemInTheme(attrName, frameworkAttr); } if (resValue != null) { @@ -955,8 +958,10 @@ public final class BridgeContext extends Context { String preResolve = resValue.getValue(); // resolve it to make sure there are no references left. resValue = mRenderResources.resolveResValue(resValue); - ta.bridgeSetValue(i, attrName, attribute.getSecond(), resValue); - defaultPropMap.put(attrName, new Property(preResolve, resValue.getValue())); + ta.bridgeSetValue(i, attrName, frameworkAttr, resValue); + defaultPropMap.put( + frameworkAttr ? SdkConstants.ANDROID_PREFIX + attrName : attrName, + new Property(preResolve, resValue.getValue())); } } } diff --git a/tools/layoutlib/bridge/tests/Android.mk b/tools/layoutlib/bridge/tests/Android.mk index 5c062d0c7042..8a81d0b684db 100644 --- a/tools/layoutlib/bridge/tests/Android.mk +++ b/tools/layoutlib/bridge/tests/Android.mk @@ -16,8 +16,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_JAVA_LANGUAGE_VERSION := 1.8 - # Only compile source java files in this lib. LOCAL_SRC_FILES := $(call all-java-files-under, src) LOCAL_JAVA_RESOURCE_DIRS := res diff --git a/tools/layoutlib/create/Android.mk b/tools/layoutlib/create/Android.mk index 47377ae42d01..c7f2c4137687 100644 --- a/tools/layoutlib/create/Android.mk +++ b/tools/layoutlib/create/Android.mk @@ -16,8 +16,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_JAVA_LANGUAGE_VERSION := 1.8 - LOCAL_SRC_FILES := $(call all-java-files-under,src) LOCAL_JAR_MANIFEST := manifest.txt diff --git a/tools/layoutlib/create/tests/Android.mk b/tools/layoutlib/create/tests/Android.mk index c59528e81ef2..dafb9c6f9402 100644 --- a/tools/layoutlib/create/tests/Android.mk +++ b/tools/layoutlib/create/tests/Android.mk @@ -15,8 +15,6 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) -LOCAL_JAVA_LANGUAGE_VERSION := 1.8 - # Only compile source java files in this lib. LOCAL_SRC_FILES := $(call all-java-files-under, com) |