diff options
70 files changed, 1104 insertions, 427 deletions
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/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/provider/Settings.java b/core/java/android/provider/Settings.java index b1bf355363e3..d98e2177058a 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6869,14 +6869,6 @@ public final class Settings { "hdmi_control_auto_device_off_enabled"; /** - * Whether to use the DHCP client from Lollipop and earlier instead of the newer Android DHCP - * client. - * (0 = false, 1 = true) - * @hide - */ - public static final String LEGACY_DHCP_CLIENT = "legacy_dhcp_client"; - - /** * Whether TV will switch to MHL port when a mobile device is plugged in. * (0 = false, 1 = true) * @hide 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/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java index 4737e9be3f99..2d3b6abbd08a 100644 --- a/core/java/android/webkit/WebChromeClient.java +++ b/core/java/android/webkit/WebChromeClient.java @@ -284,6 +284,13 @@ public class WebChromeClient { * currently set for that origin. The host application should invoke the * specified callback with the desired permission state. See * {@link GeolocationPermissions} for details. + * + * <p>Note that for applications targeting Android N and later SDKs + * (API level > {@link android.os.Build.VERSION_CODES#M}) + * this method is only called for requests originating from secure + * origins such as https. On non-secure origins geolocation requests + * are automatically denied.</p> + * * @param origin The origin of the web content attempting to use the * Geolocation API. * @param callback The callback to use to set the permission state for the diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index ada77318f297..f54edf14bbe1 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -255,6 +255,16 @@ import java.util.Map; * is loading. * </p> * + * <h3>HTML5 Geolocation API support</h3> + * + * <p>For applications targeting Android N and later releases + * (API level > {@link android.os.Build.VERSION_CODES#M}) the geolocation api is only supported on + * secure origins such as https. For such applications requests to geolocation api on non-secure + * origins are automatically denied without invoking the corresponding + * {@link WebChromeClient#onGeolocationPermissionsShowPrompt(String, GeolocationPermissions.Callback)} + * method. + * </p> + * * <h3>Layout size</h3> * <p> * It is recommended to set the WebView layout height to a fixed value or to diff --git a/core/java/android/widget/TimePickerClockDelegate.java b/core/java/android/widget/TimePickerClockDelegate.java index b6200a14abca..c21f1dfe0ed1 100644 --- a/core/java/android/widget/TimePickerClockDelegate.java +++ b/core/java/android/widget/TimePickerClockDelegate.java @@ -38,6 +38,7 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import android.widget.RadialTimePickerView.OnValueSelectedListener; import com.android.internal.R; import com.android.internal.widget.NumericTextView; @@ -48,8 +49,7 @@ import java.util.Calendar; /** * A delegate implementing the radial clock-based TimePicker. */ -class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate implements - RadialTimePickerView.OnValueSelectedListener { +class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate { /** * Delay in milliseconds before valid but potentially incomplete, for * example "1" but not "12", keyboard edits are propagated from the @@ -88,8 +88,8 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl private boolean mIsEnabled = true; private boolean mAllowAutoAdvance; - private int mInitialHourOfDay; - private int mInitialMinute; + private int mCurrentHour; + private int mCurrentMinute; private boolean mIs24Hour; private boolean mIsAmPmAtStart; @@ -189,8 +189,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl mRadialTimePickerView = (RadialTimePickerView) mainView.findViewById(R.id.radial_picker); mRadialTimePickerView.applyAttributes(attrs, defStyleAttr, defStyleRes); - - setupListeners(); + mRadialTimePickerView.setOnValueSelectedListener(mOnValueSelectedListener); mAllowAutoAdvance = true; @@ -324,28 +323,24 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl } private void initialize(int hourOfDay, int minute, boolean is24HourView, int index) { - mInitialHourOfDay = hourOfDay; - mInitialMinute = minute; + mCurrentHour = hourOfDay; + mCurrentMinute = minute; mIs24Hour = is24HourView; updateUI(index); } - private void setupListeners() { - mRadialTimePickerView.setOnValueSelectedListener(this); - } - private void updateUI(int index) { updateHeaderAmPm(); - updateHeaderHour(mInitialHourOfDay, false); + updateHeaderHour(mCurrentHour, false); updateHeaderSeparator(); - updateHeaderMinute(mInitialMinute, false); + updateHeaderMinute(mCurrentMinute, false); updateRadialPicker(index); mDelegator.invalidate(); } private void updateRadialPicker(int index) { - mRadialTimePickerView.initialize(mInitialHourOfDay, mInitialMinute, mIs24Hour); + mRadialTimePickerView.initialize(mCurrentHour, mCurrentMinute, mIs24Hour); setCurrentItemShowing(index, false, true); } @@ -358,7 +353,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl final boolean isAmPmAtStart = dateTimePattern.startsWith("a"); setAmPmAtStart(isAmPmAtStart); - updateAmPmLabelStates(mInitialHourOfDay < 12 ? AM : PM); + updateAmPmLabelStates(mCurrentHour < 12 ? AM : PM); } } @@ -388,15 +383,25 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl */ @Override public void setHour(int hour) { - if (mInitialHourOfDay != hour) { - mInitialHourOfDay = hour; - updateHeaderHour(hour, true); - updateHeaderAmPm(); + setHourInternal(hour, false, true); + } + + private void setHourInternal(int hour, boolean isFromPicker, boolean announce) { + if (mCurrentHour == hour) { + return; + } + + mCurrentHour = hour; + updateHeaderHour(hour, announce); + updateHeaderAmPm(); + + if (!isFromPicker) { mRadialTimePickerView.setCurrentHour(hour); - mRadialTimePickerView.setAmOrPm(mInitialHourOfDay < 12 ? AM : PM); - mDelegator.invalidate(); - onTimeChanged(); + mRadialTimePickerView.setAmOrPm(hour < 12 ? AM : PM); } + + mDelegator.invalidate(); + onTimeChanged(); } /** @@ -421,13 +426,23 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl */ @Override public void setMinute(int minute) { - if (mInitialMinute != minute) { - mInitialMinute = minute; - updateHeaderMinute(minute, true); + setMinuteInternal(minute, false); + } + + private void setMinuteInternal(int minute, boolean isFromPicker) { + if (mCurrentMinute == minute) { + return; + } + + mCurrentMinute = minute; + updateHeaderMinute(minute, true); + + if (!isFromPicker) { mRadialTimePickerView.setCurrentMinute(minute); - mDelegator.invalidate(); - onTimeChanged(); } + + mDelegator.invalidate(); + onTimeChanged(); } /** @@ -448,7 +463,7 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl public void setIs24Hour(boolean is24Hour) { if (mIs24Hour != is24Hour) { mIs24Hour = is24Hour; - mInitialHourOfDay = getHour(); + mCurrentHour = getHour(); updateHourFormat(); updateUI(mRadialTimePickerView.getCurrentItemShowing()); @@ -563,34 +578,6 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl } /** - * Called by the picker for updating the header display. - */ - @Override - public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) { - switch (pickerIndex) { - case HOUR_INDEX: - if (mAllowAutoAdvance && autoAdvance) { - updateHeaderHour(newValue, false); - setCurrentItemShowing(MINUTE_INDEX, true, false); - mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes); - } else { - updateHeaderHour(newValue, true); - } - break; - case MINUTE_INDEX: - updateHeaderMinute(newValue, true); - break; - case AMPM_INDEX: - updateAmPmLabelStates(newValue); - break; - } - - if (mOnTimeChangedListener != null) { - mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute()); - } - } - - /** * Converts hour-of-day (0-23) time into a localized hour number. * <p> * The localized value may be in the range (0-23), (1-24), (0-11), or @@ -702,11 +689,43 @@ class TimePickerClockDelegate extends TimePicker.AbstractTimePickerDelegate impl private void setAmOrPm(int amOrPm) { updateAmPmLabelStates(amOrPm); - if (mRadialTimePickerView.setAmOrPm(amOrPm) && mOnTimeChangedListener != null) { - mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute()); + if (mRadialTimePickerView.setAmOrPm(amOrPm)) { + mCurrentHour = getHour(); + + if (mOnTimeChangedListener != null) { + mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute()); + } } } + /** Listener for RadialTimePickerView interaction. */ + private final OnValueSelectedListener mOnValueSelectedListener = new OnValueSelectedListener() { + @Override + public void onValueSelected(int pickerIndex, int newValue, boolean autoAdvance) { + switch (pickerIndex) { + case HOUR_INDEX: + final boolean isTransition = mAllowAutoAdvance && autoAdvance; + setHourInternal(newValue, true, !isTransition); + if (isTransition) { + setCurrentItemShowing(MINUTE_INDEX, true, false); + mDelegator.announceForAccessibility(newValue + ". " + mSelectMinutes); + } + break; + case MINUTE_INDEX: + setMinuteInternal(newValue, true); + break; + case AMPM_INDEX: + updateAmPmLabelStates(newValue); + break; + } + + if (mOnTimeChangedListener != null) { + mOnTimeChangedListener.onTimeChanged(mDelegator, getHour(), getMinute()); + } + } + }; + + /** Listener for keyboard interaction. */ private final OnValueChangedListener mDigitEnteredListener = new OnValueChangedListener() { @Override public void onValueChanged(NumericTextView view, int value, 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/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java index 1848fe88dea9..bc12391a2f79 100644 --- a/core/java/com/android/internal/widget/FloatingToolbar.java +++ b/core/java/com/android/internal/widget/FloatingToolbar.java @@ -592,9 +592,11 @@ public final class FloatingToolbar { private void refreshCoordinatesAndOverflowDirection(Rect contentRectOnScreen) { refreshViewPort(); - int x = contentRectOnScreen.centerX() - mPopupWindow.getWidth() / 2; - // Update x so that the toolbar isn't rendered behind the nav bar in landscape. - x = Math.max(0, Math.min(x, mViewPortOnScreen.right - mPopupWindow.getWidth())); + // Initialize x ensuring that the toolbar isn't rendered behind the nav bar in + // landscape. + final int x = Math.min( + contentRectOnScreen.centerX() - mPopupWindow.getWidth() / 2, + mViewPortOnScreen.right - mPopupWindow.getWidth()); final int y; @@ -684,7 +686,8 @@ public final class FloatingToolbar { int rootViewTopOnWindow = mTmpCoords[1]; int windowLeftOnScreen = rootViewLeftOnScreen - rootViewLeftOnWindow; int windowTopOnScreen = rootViewTopOnScreen - rootViewTopOnWindow; - mCoordsOnWindow.set(x - windowLeftOnScreen, y - windowTopOnScreen); + mCoordsOnWindow.set( + Math.max(0, x - windowLeftOnScreen), Math.max(0, y - windowTopOnScreen)); } /** 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/layout-sw600dp/date_picker_dialog.xml b/core/res/res/layout-sw600dp/date_picker_dialog.xml index f18485f756ee..5e3ca14dd96c 100644 --- a/core/res/res/layout-sw600dp/date_picker_dialog.xml +++ b/core/res/res/layout-sw600dp/date_picker_dialog.xml @@ -21,4 +21,5 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:spinnersShown="true" - android:calendarViewShown="true" /> + android:calendarViewShown="true" + android:datePickerMode="@integer/date_picker_mode" /> diff --git a/core/res/res/layout/date_picker_dialog.xml b/core/res/res/layout/date_picker_dialog.xml index 64ac1b954e3e..8f36e95a15c6 100644 --- a/core/res/res/layout/date_picker_dialog.xml +++ b/core/res/res/layout/date_picker_dialog.xml @@ -21,4 +21,5 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:spinnersShown="true" - android:calendarViewShown="false" /> + android:calendarViewShown="false" + android:datePickerMode="@integer/date_picker_mode" /> diff --git a/core/res/res/layout/time_picker_dialog.xml b/core/res/res/layout/time_picker_dialog.xml index 30fe91093c46..d1f3902bd2d2 100644 --- a/core/res/res/layout/time_picker_dialog.xml +++ b/core/res/res/layout/time_picker_dialog.xml @@ -21,4 +21,5 @@ android:id="@+id/timePicker" android:layout_gravity="center_horizontal" android:layout_width="wrap_content" - android:layout_height="wrap_content" /> + android:layout_height="wrap_content" + android:timePickerMode="@integer/time_picker_mode" /> 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/styles_material.xml b/core/res/res/values/styles_material.xml index 8a33406eeaa7..6752e3c900b0 100644 --- a/core/res/res/values/styles_material.xml +++ b/core/res/res/values/styles_material.xml @@ -660,7 +660,7 @@ please see styles_device_defaults.xml. </style> <style name="Widget.Material.TimePicker"> - <item name="timePickerMode">@integer/time_picker_mode</item> + <item name="timePickerMode">clock</item> <item name="legacyLayout">@layout/time_picker_legacy_material</item> <!-- Attributes for new-style TimePicker. --> <item name="internalLayout">@layout/time_picker_material</item> @@ -674,7 +674,7 @@ please see styles_device_defaults.xml. </style> <style name="Widget.Material.DatePicker"> - <item name="datePickerMode">@integer/date_picker_mode</item> + <item name="datePickerMode">calendar</item> <item name="legacyLayout">@layout/date_picker_legacy_holo</item> <item name="calendarViewShown">true</item> <!-- Attributes for new-style DatePicker. --> diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd index 94b7e559f866..1e7761b6d779 100644 --- a/docs/html/sdk/index.jd +++ b/docs/html/sdk/index.jd @@ -55,7 +55,7 @@ system all allow you to focus on building unique and high quality apps.</p> <!-- start studio download modal --> -<div data-modal="studio_tos" class="dac-modal" id="langform"> +<div data-modal="studio_tos" class="dac-modal" id="studio_tos"> <div class="dac-modal-container"> <div class="dac-modal-window"> <header class="dac-modal-header"> @@ -534,4 +534,3 @@ or AMD processor with support for AMD Virtualizationâ„¢ (AMD-Vâ„¢)</li> </div> </section> - diff --git a/graphics/java/android/view/PixelCopy.java b/graphics/java/android/view/PixelCopy.java index 95c930c5264d..29bf963842da 100644 --- a/graphics/java/android/view/PixelCopy.java +++ b/graphics/java/android/view/PixelCopy.java @@ -123,6 +123,9 @@ public final class PixelCopy { public static void request(@NonNull Surface source, @NonNull Bitmap dest, @NonNull OnPixelCopyFinishedListener listener, @NonNull Handler listenerThread) { validateBitmapDest(dest); + if (!source.isValid()) { + throw new IllegalArgumentException("Surface isn't valid, source.isValid() == false"); + } // TODO: Make this actually async and fast and cool and stuff int result = ThreadedRenderer.copySurfaceInto(source, dest); listenerThread.post(new Runnable() { diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index fdbe76a5e459..0a8e3f3b4db3 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -471,18 +471,19 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) { return *this; } -GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture) { +GlopBuilder& GlopBuilder::setFillExternalTexture(Texture& texture, Matrix4& textureTransform) { TRIGGER_STAGE(kFillStage); REQUIRE_STAGES(kMeshStage | kRoundRectClipStage); mOutGlop->fill.texture = { &texture, GL_TEXTURE_EXTERNAL_OES, GL_LINEAR, GL_CLAMP_TO_EDGE, - nullptr }; + &textureTransform }; setFill(SK_ColorWHITE, 1.0f, SkXfermode::kSrc_Mode, Blend::ModeOrderSwap::NoSwap, nullptr, nullptr); mDescription.modulate = mOutGlop->fill.color.a < 1.0f; + mDescription.hasTextureTransform = true; return *this; } diff --git a/libs/hwui/GlopBuilder.h b/libs/hwui/GlopBuilder.h index b6c186d85e76..a9dd56f385b1 100644 --- a/libs/hwui/GlopBuilder.h +++ b/libs/hwui/GlopBuilder.h @@ -73,7 +73,7 @@ public: // TODO: Texture should probably know and own its target. // setFillLayer() forces it to GL_TEXTURE which isn't always correct. // Similarly setFillLayer normally forces its own wrap & filter mode - GlopBuilder& setFillExternalTexture(Texture& texture); + GlopBuilder& setFillExternalTexture(Texture& texture, Matrix4& textureTransform); GlopBuilder& setTransform(const Snapshot& snapshot, const int transformFlags) { return setTransform(*snapshot.transform, transformFlags); diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index 36007cd5dc0e..9cde5d6aa04e 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -236,6 +236,8 @@ public: static const Matrix4& identity(); + void invalidateType() { mType = kTypeUnknown; } + private: mutable uint8_t mType; diff --git a/libs/hwui/Readback.cpp b/libs/hwui/Readback.cpp index 49596e143ebf..55f823dfe226 100644 --- a/libs/hwui/Readback.cpp +++ b/libs/hwui/Readback.cpp @@ -101,7 +101,10 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread, // Setup the source sp<GraphicBuffer> sourceBuffer; sp<Fence> sourceFence; - status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence); + Matrix4 texTransform; + status_t err = surface.getLastQueuedBuffer(&sourceBuffer, &sourceFence, + texTransform.data); + texTransform.invalidateType(); if (err != NO_ERROR) { ALOGW("Failed to get last queued buffer, error = %d", err); return CopyResult::UnknownError; @@ -163,8 +166,8 @@ CopyResult Readback::copySurfaceInto(renderthread::RenderThread& renderThread, Glop glop; GlopBuilder(renderState, caches, &glop) .setRoundRectClipState(nullptr) - .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO - .setFillExternalTexture(sourceTexture) + .setMeshTexturedUnitQuad(nullptr) + .setFillExternalTexture(sourceTexture, texTransform) .setTransform(Matrix4::identity(), TransformFlags::None) .setModelViewMapUnitToRect(destRect) .build(); 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/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index 346f083f696b..93c595f1ca2b 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -46,7 +46,8 @@ import java.util.Map; * <tr><td>{@link #KEY_HEIGHT}</td><td>Integer</td><td></td></tr> * <tr><td>{@link #KEY_COLOR_FORMAT}</td><td>Integer</td><td>set by the user * for encoders, readable in the output format of decoders</b></td></tr> - * <tr><td>{@link #KEY_FRAME_RATE}</td><td>Integer or Float</td><td><b>encoder-only</b></td></tr> + * <tr><td>{@link #KEY_FRAME_RATE}</td><td>Integer or Float</td><td>required for <b>encoders</b>, + * optional for <b>decoders</b></td></tr> * <tr><td>{@link #KEY_CAPTURE_RATE}</td><td>Integer</td><td></td></tr> * <tr><td>{@link #KEY_I_FRAME_INTERVAL}</td><td>Integer</td><td><b>encoder-only</b></td></tr> * <tr><td>{@link #KEY_INTRA_REFRESH_PERIOD}</td><td>Integer</td><td><b>encoder-only</b>, optional</td></tr> @@ -197,7 +198,19 @@ public final class MediaFormat { /** * A key describing the frame rate of a video format in frames/sec. - * The associated value is an integer or a float. + * The associated value is normally an integer when the value is used by the platform, + * but video codecs also accept float configuration values. + * Specifically, {@link MediaExtractor#getTrackFormat MediaExtractor} provides an integer + * value corresponding to the frame rate information of the track if specified and non-zero. + * Otherwise, this key is not present. {@link MediaCodec#configure MediaCodec} accepts both + * float and integer values. This represents the desired operating frame rate if the + * {@link #KEY_OPERATING_RATE} is not present and {@link #KEY_PRIORITY} is {@code 0} + * (realtime). For video encoders this value corresponds to the intended frame rate, + * although encoders are expected + * to support variable frame rate based on {@link MediaCodec.BufferInfo#presentationTimeUs + * buffer timestamp}. This key is not used in the {@code MediaCodec} + * {@link MediaCodec#getInputFormat input}/{@link MediaCodec#getOutputFormat output} formats, + * nor by {@link MediaMuxer#addTrack MediaMuxer}. */ public static final String KEY_FRAME_RATE = "frame-rate"; diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index 74c98e4f5988..efa34ff8ec08 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -421,8 +421,6 @@ <string name="wifi_aggressive_handover">Aggressive Wi\u2011Fi to Cellular handover</string> <!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] --> <string name="wifi_allow_scan_with_traffic">Always allow Wi\u2011Fi Roam Scans</string> - <!-- Setting Checkbox title whether to enable WiFi Scanning in the presence of traffic. [CHAR LIMIT=80] --> - <string name="legacy_dhcp_client">Use legacy DHCP client</string> <!-- Setting Checkbox title whether to always keep cellular data active. [CHAR LIMIT=80] --> <string name="mobile_data_always_on">Cellular data always active</string> <!-- Setting Checkbox title for disabling Bluetooth absolute volume --> diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java index bcbc6ac28f0a..bf750467d991 100644 --- a/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java +++ b/packages/SettingsLib/src/com/android/settingslib/drawer/SettingsDrawerActivity.java @@ -52,7 +52,7 @@ public class SettingsDrawerActivity extends Activity { protected static final boolean DEBUG_TIMING = false; private static final String TAG = "SettingsDrawerActivity"; - static final String EXTRA_SHOW_MENU = "show_drawer_menu"; + public static final String EXTRA_SHOW_MENU = "show_drawer_menu"; private static List<DashboardCategory> sDashboardCategories; private static HashMap<Pair<String, String>, Tile> sTileCache; 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/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java index 6d76763edc84..ce0163e66eaf 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java @@ -327,7 +327,14 @@ public class StatusBarIconView extends AnimatedImageView { public static String contentDescForNotification(Context c, Notification n) { Notification.Builder builder = Notification.Builder.recoverBuilder(c, n); String appName = builder.loadHeaderAppName(); + + CharSequence title = n.extras.getString(Notification.EXTRA_TITLE); CharSequence ticker = n.tickerText; - return c.getString(R.string.accessibility_desc_notification_icon, appName, ticker); + + CharSequence desc = !TextUtils.isEmpty(ticker) ? ticker + : !TextUtils.isEmpty(title) ? title : ""; + + return c.getString(R.string.accessibility_desc_notification_icon, appName, desc); } + } 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/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto index f49235c0b756..c417fe8ae5cc 100644 --- a/proto/src/metrics_constants.proto +++ b/proto/src/metrics_constants.proto @@ -2187,6 +2187,10 @@ message MetricsEvent { // reinflation. ACTION_REMOTE_INPUT_CLOSE = 400; + // OPEN: Settings > Accounts > Work profile settings + // CATEGORY: SETTINGS + ACCOUNTS_WORK_PROFILE_SETTINGS = 401; + // Add new aosp constants above this line. // END OF AOSP CONSTANTS } 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..f5e9d1968eb8 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); } diff --git a/services/core/java/com/android/server/LockSettingsService.java b/services/core/java/com/android/server/LockSettingsService.java index c912b11250dd..cbf7e8038b5b 100644 --- a/services/core/java/com/android/server/LockSettingsService.java +++ b/services/core/java/com/android/server/LockSettingsService.java @@ -1281,8 +1281,14 @@ public class LockSettingsService extends ILockSettings.Stub { // service can't connect to vold, it restarts, and then the new instance // does successfully connect. final IMountService service = getMountService(); - String password = service.getPassword(); - service.clearPassword(); + String password; + long identity = Binder.clearCallingIdentity(); + try { + password = service.getPassword(); + service.clearPassword(); + } finally { + Binder.restoreCallingIdentity(identity); + } if (password == null) { return false; } diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java index b0581aa331fb..7253870d2f12 100644 --- a/services/core/java/com/android/server/MountService.java +++ b/services/core/java/com/android/server/MountService.java @@ -2648,6 +2648,8 @@ class MountService extends IMountService.Stub */ @Override public int getPasswordType() { + mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL, + "no permission to access the crypt keeper"); waitForReady(); @@ -2672,6 +2674,8 @@ class MountService extends IMountService.Stub */ @Override public void setField(String field, String contents) throws RemoteException { + mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL, + "no permission to access the crypt keeper"); waitForReady(); @@ -2690,6 +2694,8 @@ class MountService extends IMountService.Stub */ @Override public String getField(String field) throws RemoteException { + mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL, + "no permission to access the crypt keeper"); waitForReady(); @@ -2714,6 +2720,8 @@ class MountService extends IMountService.Stub */ @Override public boolean isConvertibleToFBE() throws RemoteException { + mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL, + "no permission to access the crypt keeper"); waitForReady(); @@ -2728,8 +2736,9 @@ class MountService extends IMountService.Stub @Override public String getPassword() throws RemoteException { - mContext.enforceCallingOrSelfPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE, + mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL, "only keyguard can retrieve password"); + if (!isReady()) { return new String(); } @@ -2752,6 +2761,9 @@ class MountService extends IMountService.Stub @Override public void clearPassword() throws RemoteException { + mContext.enforceCallingOrSelfPermission(Manifest.permission.STORAGE_INTERNAL, + "only keyguard can clear password"); + if (!isReady()) { return; } 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/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..64581e8fd881 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -437,6 +437,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 +9727,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 +9777,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); } 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/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index b9e9ac856185..3785cdc44b0c 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -383,6 +383,15 @@ </activity> <activity + android:name="VideoViewCaptureActivity" + android:label="SurfaceView/GetBitmap with Video source"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="com.android.test.hwui.TEST" /> + </intent-filter> + </activity> + + <activity android:name="GLTextureViewActivity" android:label="TextureView/OpenGL"> <intent-filter> diff --git a/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 b/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 Binary files differnew file mode 100644 index 000000000000..1be8bee39fd4 --- /dev/null +++ b/tests/HwAccelerationTest/res/raw/colorgrid_video.mp4 diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java index f658b7c05e66..6fe2cb472a97 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GetBitmapSurfaceViewActivity.java @@ -23,6 +23,7 @@ import android.os.Bundle; import android.os.Environment; import android.view.Gravity; import android.view.PixelCopy; +import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; @@ -87,9 +88,42 @@ public class GetBitmapSurfaceViewActivity extends Activity implements SurfaceHol android.util.Log.e("TextureView", "Cannot set preview texture target!", t); } + setCameraDisplayOrientation(this, 0, mCamera); mCamera.startPreview(); } + public static void setCameraDisplayOrientation(Activity activity, + int cameraId, android.hardware.Camera camera) { + android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo(); + android.hardware.Camera.getCameraInfo(cameraId, info); + int rotation = activity.getWindowManager().getDefaultDisplay() + .getRotation(); + int degrees = 0; + switch (rotation) { + case Surface.ROTATION_0: + degrees = 0; + break; + case Surface.ROTATION_90: + degrees = 90; + break; + case Surface.ROTATION_180: + degrees = 180; + break; + case Surface.ROTATION_270: + degrees = 270; + break; + } + + int result; + if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + result = (info.orientation + degrees) % 360; + result = (360 - result) % 360; // compensate the mirror + } else { // back-facing + result = (info.orientation - degrees + 360) % 360; + } + camera.setDisplayOrientation(result); + } + @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java new file mode 100644 index 000000000000..b87be8058d81 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/VideoViewCaptureActivity.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.hwui; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Bundle; +import android.os.Environment; +import android.view.PixelCopy; +import android.view.View; +import android.widget.Button; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.Toast; +import android.widget.VideoView; + +import java.io.FileOutputStream; + +public class VideoViewCaptureActivity extends Activity { + private VideoView mVideoView; + private int mVideoWidth, mVideoHeight; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mVideoView = new VideoView(this); + mVideoView.setOnPreparedListener(mp -> { + mp.setLooping(true); + mVideoWidth = mp.getVideoWidth(); + mVideoHeight = mp.getVideoHeight(); + mVideoView.start(); + }); + + Uri uri = Uri.parse("android.resource://com.android.test.hwui/" + R.raw.colorgrid_video); + mVideoView.setVideoURI(uri); + + Button button = new Button(this); + button.setText("Copy bitmap to /sdcard/surfaceview.png"); + button.setOnClickListener((View v) -> { + final Bitmap b = Bitmap.createBitmap( + mVideoWidth, mVideoHeight, + Bitmap.Config.ARGB_8888); + PixelCopy.request(mVideoView, b, + (int result) -> { + if (result != PixelCopy.SUCCESS) { + Toast.makeText(VideoViewCaptureActivity.this, + "Failed to copy", Toast.LENGTH_SHORT).show(); + return; + } + try { + try (FileOutputStream out = new FileOutputStream( + Environment.getExternalStorageDirectory() + "/surfaceview.png");) { + b.compress(Bitmap.CompressFormat.PNG, 100, out); + } + } catch (Exception e) { + // Ignore + } + }, mVideoView.getHandler()); + }); + + FrameLayout content = new FrameLayout(this); + LinearLayout layout = new LinearLayout(this); + layout.setOrientation(LinearLayout.VERTICAL); + layout.addView(button, LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + layout.addView(mVideoView, LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT); + + content.addView(layout, new FrameLayout.LayoutParams( + FrameLayout.LayoutParams.MATCH_PARENT, + FrameLayout.LayoutParams.MATCH_PARENT)); + setContentView(content); + } +} 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) |