Merge "NetworkNotificationManager: correctly handle existing notifications" into oc-dr1-dev
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index acceed0..7fc9a69 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -285,7 +285,8 @@
public PermissionInfo getPermissionInfo(String name, int flags)
throws NameNotFoundException {
try {
- PermissionInfo pi = mPM.getPermissionInfo(name, flags);
+ PermissionInfo pi = mPM.getPermissionInfo(name,
+ mContext.getOpPackageName(), flags);
if (pi != null) {
return pi;
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index e800e88..4b44a17 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -72,7 +72,7 @@
String[] currentToCanonicalPackageNames(in String[] names);
String[] canonicalToCurrentPackageNames(in String[] names);
- PermissionInfo getPermissionInfo(String name, int flags);
+ PermissionInfo getPermissionInfo(String name, String packageName, int flags);
ParceledListSlice queryPermissionsByGroup(String group, int flags);
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java
index 477285e63..727412b 100644
--- a/core/java/com/android/internal/colorextraction/ColorExtractor.java
+++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java
@@ -45,12 +45,12 @@
private static final String TAG = "ColorExtractor";
- private final SparseArray<GradientColors[]> mGradientColors;
+ protected final SparseArray<GradientColors[]> mGradientColors;
private final ArrayList<WeakReference<OnColorsChangedListener>> mOnColorsChangedListeners;
private final Context mContext;
private final ExtractionType mExtractionType;
- private WallpaperColors mSystemColors;
- private WallpaperColors mLockColors;
+ protected WallpaperColors mSystemColors;
+ protected WallpaperColors mLockColors;
public ColorExtractor(Context context) {
this(context, new Tonal(context));
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7819f30..7bbed29 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -568,10 +568,6 @@
during voice calls -->
<bool translatable="false" name="config_wifi_framework_enable_voice_call_sar_tx_power_limit">false</bool>
- <!-- Integer indicating the value that framework needs to set the tx power to for meeting SAR requirements
- during voice calls -->
- <integer translatable="false" name="config_wifi_framework_voice_call_sar_tx_power_limit_in_dbm">0</integer>
-
<!-- Wifi driver supports batched scan -->
<bool translatable="false" name="config_wifi_batched_scan_supported">false</bool>
@@ -1854,9 +1850,8 @@
states. -->
<bool name="config_dozeAlwaysOnDisplayAvailable">false</bool>
- <!-- Whether the display hardware requires we go to the off state before transitioning
- out of any doze states. -->
- <bool name="config_displayTransitionOffAfterDoze">false</bool>
+ <!-- Whether the display blanks itself when transitioning from a doze to a non-doze state -->
+ <bool name="config_displayBlanksAfterDoze">false</bool>
<!-- Power Management: Specifies whether to decouple the auto-suspend state of the
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index decf42d..115dc9f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -313,7 +313,6 @@
<java-symbol type="bool" name="config_wifi_framework_enable_associated_network_selection" />
<java-symbol type="bool" name="config_wifi_only_link_same_credential_configurations" />
<java-symbol type="bool" name="config_wifi_framework_enable_voice_call_sar_tx_power_limit" />
- <java-symbol type="integer" name="config_wifi_framework_voice_call_sar_tx_power_limit_in_dbm" />
<java-symbol type="bool" name="config_wifi_enable_disconnection_debounce" />
<java-symbol type="bool" name="config_wifi_revert_country_code_on_cellular_loss" />
<java-symbol type="bool" name="config_wifi_enable_wifi_firmware_debugging" />
@@ -3051,7 +3050,7 @@
<java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
<java-symbol type="integer" name="config_inCallNotificationVolumeRelative" />
<java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" />
- <java-symbol type="bool" name="config_displayTransitionOffAfterDoze" />
+ <java-symbol type="bool" name="config_displayBlanksAfterDoze" />
<java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" />
<java-symbol type="string" name="config_headlineFontFamily" />
<java-symbol type="string" name="config_headlineFontFamilyLight" />
diff --git a/libs/androidfw/include/androidfw/StringPiece.h b/libs/androidfw/include/androidfw/StringPiece.h
index a873d66..99b4245 100644
--- a/libs/androidfw/include/androidfw/StringPiece.h
+++ b/libs/androidfw/include/androidfw/StringPiece.h
@@ -37,6 +37,7 @@
public:
using const_iterator = const TChar*;
using difference_type = size_t;
+ using size_type = size_t;
// End of string marker.
constexpr static const size_t npos = static_cast<size_t>(-1);
diff --git a/packages/SystemUI/res/layout/zen_mode_condition.xml b/packages/SystemUI/res/layout/zen_mode_condition.xml
index 2b4a0f5..ab52465 100644
--- a/packages/SystemUI/res/layout/zen_mode_condition.xml
+++ b/packages/SystemUI/res/layout/zen_mode_condition.xml
@@ -27,6 +27,8 @@
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:minHeight="48dp"
+ android:gravity="center_vertical"
android:layout_centerVertical="true"
android:orientation="vertical"
android:layout_toEndOf="@android:id/checkbox"
@@ -79,4 +81,4 @@
android:tint="?android:attr/textColorPrimary"
android:src="@drawable/ic_qs_plus" />
-</RelativeLayout>
\ No newline at end of file
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 4261641..5516983 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -93,7 +93,7 @@
</RelativeLayout>
- <LinearLayout
+ <com.android.systemui.volume.ZenRadioLayout
android:id="@+id/zen_conditions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -111,7 +111,7 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"/>
- </LinearLayout>
+ </com.android.systemui.volume.ZenRadioLayout>
<TextView
android:id="@+id/zen_alarm_warning"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 34aa6d0..3c86c87 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -267,14 +267,15 @@
<!-- Doze: alpha to apply to small icons when dozing -->
<integer name="doze_small_icon_alpha">222</integer><!-- 87% of 0xff -->
- <!-- Doze: the brightness value to use for the lower brightness AOD mode -->
- <integer name="config_doze_aod_brightness_low">5</integer>
-
- <!-- Doze: the brightness value to use for the higher brightness AOD mode -->
- <integer name="config_doze_aod_brightness_high">27</integer>
-
- <!-- Doze: the brightness value to use for the sunlight AOD mode -->
- <integer name="config_doze_aod_brightness_sunlight">28</integer>
+ <!-- Doze: Table that translates sensor values from the doze_brightness_sensor_type sensor
+ to brightness values; -1 means keeping the current brightness. -->
+ <integer-array name="config_doze_brightness_sensor_to_brightness">
+ <item>-1</item> <!-- 0: OFF -->
+ <item>2</item> <!-- 1: NIGHT -->
+ <item>5</item> <!-- 2: LOW -->
+ <item>27</item> <!-- 3: HIGH -->
+ <item>28</item> <!-- 4: SUN -->
+ </integer-array>
<!-- Doze: whether the double tap sensor reports 2D touch coordinates -->
<bool name="doze_double_tap_reports_touch_coordinates">false</bool>
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 61cbc98..9ba7be8 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -31,11 +31,16 @@
import com.android.internal.colorextraction.ColorExtractor;
import com.android.internal.colorextraction.types.ExtractionType;
import com.android.internal.colorextraction.types.Tonal;
+import com.android.systemui.Dumpable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
/**
* ColorExtractor aware of wallpaper visibility
*/
-public class SysuiColorExtractor extends ColorExtractor {
+public class SysuiColorExtractor extends ColorExtractor implements Dumpable {
private static final String TAG = "SysuiColorExtractor";
private boolean mWallpaperVisible;
// Colors to return when the wallpaper isn't visible
@@ -154,4 +159,20 @@
}
}
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.println("SysuiColorExtractor:");
+
+ pw.println(" Current wallpaper colors:");
+ pw.println(" system: " + mSystemColors);
+ pw.println(" lock: " + mLockColors);
+
+ GradientColors[] system = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
+ GradientColors[] lock = mGradientColors.get(WallpaperManager.FLAG_LOCK);
+ pw.println(" Gradients:");
+ pw.println(" system: " + Arrays.toString(system));
+ pw.println(" lock: " + Arrays.toString(lock));
+ pw.println(" Default scrim: " + mWpHiddenColors);
+
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index ed4b131..32baf94 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -35,12 +35,9 @@
private final Handler mHandler;
private final SensorManager mSensorManager;
private final Sensor mLightSensor;
+ private final int[] mSensorToBrightness;
private boolean mRegistered;
- private final int mHighBrightness;
- private final int mLowBrightness;
- private final int mSunlightBrightness;
-
public DozeScreenBrightness(Context context, DozeMachine.Service service,
SensorManager sensorManager, Sensor lightSensor, Handler handler) {
mContext = context;
@@ -49,12 +46,8 @@
mLightSensor = lightSensor;
mHandler = handler;
- mLowBrightness = context.getResources().getInteger(
- R.integer.config_doze_aod_brightness_low);
- mHighBrightness = context.getResources().getInteger(
- R.integer.config_doze_aod_brightness_high);
- mSunlightBrightness = context.getResources().getInteger(
- R.integer.config_doze_aod_brightness_sunlight);
+ mSensorToBrightness = context.getResources().getIntArray(
+ R.array.config_doze_brightness_sensor_to_brightness);
}
@Override
@@ -81,21 +74,18 @@
@Override
public void onSensorChanged(SensorEvent event) {
if (mRegistered) {
- mDozeService.setDozeScreenBrightness(computeBrightness((int) event.values[0]));
+ int brightness = computeBrightness((int) event.values[0]);
+ if (brightness > 0) {
+ mDozeService.setDozeScreenBrightness(brightness);
+ }
}
}
private int computeBrightness(int sensorValue) {
- // The sensor reports 0 for off, 1 for low brightness, 2 for high brightness, and 3 for
- // sunlight. We currently use DozeScreenState for screen off, so we treat off as low
- // brightness.
- if (sensorValue >= 3) {
- return mSunlightBrightness;
- } else if (sensorValue == 2) {
- return mHighBrightness;
- } else {
- return mLowBrightness;
+ if (sensorValue < 0 || sensorValue >= mSensorToBrightness.length) {
+ return -1;
}
+ return mSensorToBrightness[sensorValue];
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 1dc37cd..8847452 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -100,7 +100,6 @@
private boolean shouldAnimateWakeup(DozeMachine.State state) {
switch (state) {
- case DOZE_AOD:
case DOZE_REQUEST_PULSE:
case DOZE_PULSING:
case DOZE_PULSE_DONE:
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
index 3f39dfe..b6fce44 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
@@ -16,6 +16,8 @@
package com.android.systemui.keyguard;
+import android.os.Trace;
+
import com.android.systemui.Dumpable;
import java.io.FileDescriptor;
@@ -38,22 +40,22 @@
}
public void dispatchScreenTurningOn() {
- mScreenState = SCREEN_TURNING_ON;
+ setScreenState(SCREEN_TURNING_ON);
dispatch(Observer::onScreenTurningOn);
}
public void dispatchScreenTurnedOn() {
- mScreenState = SCREEN_ON;
+ setScreenState(SCREEN_ON);
dispatch(Observer::onScreenTurnedOn);
}
public void dispatchScreenTurningOff() {
- mScreenState = SCREEN_TURNING_OFF;
+ setScreenState(SCREEN_TURNING_OFF);
dispatch(Observer::onScreenTurningOff);
}
public void dispatchScreenTurnedOff() {
- mScreenState = SCREEN_OFF;
+ setScreenState(SCREEN_OFF);
dispatch(Observer::onScreenTurnedOff);
}
@@ -63,6 +65,11 @@
pw.println(" mScreenState=" + mScreenState);
}
+ private void setScreenState(int screenState) {
+ mScreenState = screenState;
+ Trace.traceCounter(Trace.TRACE_TAG_APP, "screenState", screenState);
+ }
+
public interface Observer {
default void onScreenTurningOn() {}
default void onScreenTurnedOn() {}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
index 578e6fb..951c0ea 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
@@ -16,6 +16,8 @@
package com.android.systemui.keyguard;
+import android.os.Trace;
+
import com.android.systemui.Dumpable;
import java.io.FileDescriptor;
@@ -39,22 +41,22 @@
}
public void dispatchStartedWakingUp() {
- mWakefulness = WAKEFULNESS_WAKING;
+ setWakefulness(WAKEFULNESS_WAKING);
dispatch(Observer::onStartedWakingUp);
}
public void dispatchFinishedWakingUp() {
- mWakefulness = WAKEFULNESS_AWAKE;
+ setWakefulness(WAKEFULNESS_AWAKE);
dispatch(Observer::onFinishedWakingUp);
}
public void dispatchStartedGoingToSleep() {
- mWakefulness = WAKEFULNESS_GOING_TO_SLEEP;
+ setWakefulness(WAKEFULNESS_GOING_TO_SLEEP);
dispatch(Observer::onStartedGoingToSleep);
}
public void dispatchFinishedGoingToSleep() {
- mWakefulness = WAKEFULNESS_ASLEEP;
+ setWakefulness(WAKEFULNESS_ASLEEP);
dispatch(Observer::onFinishedGoingToSleep);
}
@@ -64,6 +66,11 @@
pw.println(" mWakefulness=" + mWakefulness);
}
+ private void setWakefulness(int wakefulness) {
+ mWakefulness = wakefulness;
+ Trace.traceCounter(Trace.TRACE_TAG_APP, "wakefulness", wakefulness);
+ }
+
public interface Observer {
default void onStartedWakingUp() {}
default void onFinishedWakingUp() {}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index 14afbfa..c691498 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -269,7 +269,7 @@
item.icon = R.drawable.ic_qs_bluetooth_on;
item.line1 = device.getName();
item.tag = device;
- int state = mController.getMaxConnectionState(device);
+ int state = device.getMaxConnectionState();
if (state == BluetoothProfile.STATE_CONNECTED) {
item.icon = R.drawable.ic_qs_bluetooth_connected;
int batteryLevel = device.getBatteryLevel();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 7391509..d9984f7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -324,12 +324,30 @@
@Override
public void onAccessPointsChanged(final List<AccessPoint> accessPoints) {
mAccessPoints = accessPoints.toArray(new AccessPoint[accessPoints.size()]);
+ filterUnreachableAPs();
+
updateItems();
if (accessPoints != null && accessPoints.size() > 0) {
fireScanStateChanged(false);
}
}
+ /** Filter unreachable APs from mAccessPoints */
+ private void filterUnreachableAPs() {
+ int numReachable = 0;
+ for (AccessPoint ap : mAccessPoints) {
+ if (ap.isReachable()) numReachable++;
+ }
+ if (numReachable != mAccessPoints.length) {
+ AccessPoint[] unfiltered = mAccessPoints;
+ mAccessPoints = new AccessPoint[numReachable];
+ int i = 0;
+ for (AccessPoint ap : unfiltered) {
+ if (ap.isReachable()) mAccessPoints[i++] = ap;
+ }
+ }
+ }
+
@Override
public void onSettingsActivityTriggered(Intent settingsIntent) {
mActivityStarter.postStartActivityDismissingKeyguard(settingsIntent, 0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index 2dc467f..2283c13 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -322,7 +322,7 @@
mHandler.removeCallbacks(mPulseOutExtended);
if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
if (!mDozing) return;
- startScrimAnimation(true /* inFront */, mDozeParameters.getAlwaysOn() ? 0 : 1,
+ startScrimAnimation(true /* inFront */, 1,
mDozeParameters.getPulseOutDuration(),
Interpolators.ALPHA_IN, mPulseOutFinished);
}
@@ -336,6 +336,9 @@
// Signal that the pulse is all finished so we can turn the screen off now.
pulseFinished();
+ if (mDozeParameters.getAlwaysOn()) {
+ mScrimController.setDozeInFrontAlpha(0);
+ }
}
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 95f32bb..49bac99 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -249,6 +249,7 @@
mKeyguardView.setViewMediatorCallback(mCallback);
mContainer.addView(mRoot, mContainer.getChildCount());
mRoot.setVisibility(View.INVISIBLE);
+ mRoot.dispatchApplyWindowInsets(mRoot.getRootWindowInsets());
}
protected void removeView() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 0c62096..cca6ae0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -232,6 +232,7 @@
private int mAmbientIndicationBottomPadding;
private boolean mIsFullWidth;
private float mDarkAmount;
+ private float mDarkAmountTarget;
private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
private boolean mNoVisibleNotifications = true;
private ValueAnimator mDarkAnimator;
@@ -2590,8 +2591,13 @@
return;
}
if (mDarkAnimator != null && mDarkAnimator.isRunning()) {
- mDarkAnimator.cancel();
+ if (animate && mDarkAmountTarget == darkAmount) {
+ return;
+ } else {
+ mDarkAnimator.cancel();
+ }
}
+ mDarkAmountTarget = darkAmount;
if (animate) {
mDarkAnimator = ObjectAnimator.ofFloat(this, SET_DARK_AMOUNT_PROPERTY, darkAmount);
mDarkAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 61f9109..136c158 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -3509,6 +3509,14 @@
pw.print (" ");
mStackScroller.dump(fd, pw, args);
}
+ pw.println(" Theme:");
+ if (mOverlayManager == null) {
+ pw.println(" overlay manager not initialized!");
+ } else {
+ pw.println(" dark overlay on: " + isUsingDarkTheme());
+ }
+ final boolean lightWpTheme = mContext.getThemeResId() == R.style.Theme_SystemUI_Light;
+ pw.println(" light wallpaper theme: " + lightWpTheme);
DozeLog.dump(pw);
@@ -3712,7 +3720,6 @@
}
}
else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
- notifyHeadsUpScreenOff();
finishBarAnimations();
resetUserExpandedStates();
}
@@ -4612,6 +4619,7 @@
}
private void updateDozingState() {
+ Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0);
Trace.beginSection("StatusBar#updateDozingState");
boolean animate = !mDozing && mDozeServiceHost.shouldAnimateWakeup();
mNotificationPanel.setDozing(mDozing, animate);
@@ -4715,6 +4723,7 @@
// Make our window larger and the panel expanded.
makeExpandedVisible(true);
mNotificationPanel.expand(false /* animate */);
+ recomputeDisableFlags(false /* animate */);
}
private void instantCollapseNotificationPanel() {
@@ -5152,6 +5161,7 @@
@Override
public void onStartedGoingToSleep() {
+ notifyHeadsUpGoingToSleep();
dismissVolumeDialog();
}
@@ -5493,6 +5503,11 @@
@Override
public void setAnimateWakeup(boolean animateWakeup) {
+ if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_AWAKE
+ || mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_WAKING) {
+ // Too late to change the wakeup animation.
+ return;
+ }
mAnimateWakeup = animateWakeup;
}
@@ -7239,7 +7254,7 @@
setAreThereNotifications();
}
- protected void notifyHeadsUpScreenOff() {
+ protected void notifyHeadsUpGoingToSleep() {
maybeEscalateHeadsUp();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 73ec0a4..ad47411 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -913,11 +913,7 @@
@Override
public void onRemoteUpdate(Token token, String name, PlaybackInfo pi) {
- if (!mRemoteStreams.containsKey(token)) {
- mRemoteStreams.put(token, mNextStream);
- if (D.BUG) Log.d(TAG, "onRemoteUpdate: " + name + " is stream " + mNextStream);
- mNextStream++;
- }
+ addStream(token, "onRemoteUpdate");
final int stream = mRemoteStreams.get(token);
boolean changed = mState.states.indexOfKey(stream) < 0;
final StreamState ss = streamStateW(stream);
@@ -942,6 +938,7 @@
@Override
public void onRemoteVolumeChanged(Token token, int flags) {
+ addStream(token, "onRemoteVolumeChanged");
final int stream = mRemoteStreams.get(token);
final boolean showUI = shouldShowUI(flags);
boolean changed = updateActiveStreamW(stream);
@@ -958,6 +955,11 @@
@Override
public void onRemoteRemoved(Token token) {
+ if (!mRemoteStreams.containsKey(token)) {
+ if (D.BUG) Log.d(TAG, "onRemoteRemoved: stream doesn't exist, "
+ + "aborting remote removed for token:" + token.toString());
+ return;
+ }
final int stream = mRemoteStreams.get(token);
mState.states.remove(stream);
if (mState.activeStream == stream) {
@@ -983,6 +985,15 @@
}
return null;
}
+
+ private void addStream(Token token, String triggeringMethod) {
+ if (!mRemoteStreams.containsKey(token)) {
+ mRemoteStreams.put(token, mNextStream);
+ if (D.BUG) Log.d(TAG, triggeringMethod + ": added stream " + mNextStream
+ + " from token + "+ token.toString());
+ mNextStream++;
+ }
+ }
}
public interface UserActivityListener {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java b/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java
new file mode 100644
index 0000000..5dbcd8a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 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.systemui.volume;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
+
+/**
+ * Specialized layout for zen mode that allows the radio buttons to reside within
+ * a RadioGroup, but also makes sure that all the heights off the radio buttons align
+ * with the corresponding content in the second child of this view.
+ */
+public class ZenRadioLayout extends LinearLayout {
+
+ public ZenRadioLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ /**
+ * Run 2 measurement passes, 1 that figures out the size of the content, and another
+ * that sets the size of the radio buttons to the heights of the corresponding content.
+ */
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ ViewGroup radioGroup = (ViewGroup) getChildAt(0);
+ ViewGroup radioContent = (ViewGroup) getChildAt(1);
+ int size = radioGroup.getChildCount();
+ if (size != radioContent.getChildCount()) {
+ throw new IllegalStateException("Expected matching children");
+ }
+ boolean hasChanges = false;
+ for (int i = 0; i < size; i++) {
+ View radio = radioGroup.getChildAt(i);
+ View content = radioContent.getChildAt(i);
+ if (radio.getLayoutParams().height != content.getMeasuredHeight()) {
+ hasChanges = true;
+ radio.getLayoutParams().height = content.getMeasuredHeight();
+ }
+ }
+ // Measure again if any heights changed.
+ if (hasChanges) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index 064ca58..da196e2 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -802,7 +802,7 @@
IPackageManager pm = AppGlobals.getPackageManager();
for (int i = perms.length-1; i >= 0; i--) {
try {
- PermissionInfo pi = pm.getPermissionInfo(perms[i], 0);
+ PermissionInfo pi = pm.getPermissionInfo(perms[i], "android", 0);
if ((pi.protectionLevel & (PermissionInfo.PROTECTION_MASK_BASE
| PermissionInfo.PROTECTION_FLAG_PRIVILEGED))
!= PermissionInfo.PROTECTION_SIGNATURE) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index cbd02ac..e858edb 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -165,11 +165,11 @@
// a stylish color fade animation instead.
private boolean mColorFadeFadesConfig;
- // True if we need to transition to the off state when coming out of a doze state.
- // Some display hardware will show artifacts (flickers, etc) when transitioning from a doze
- // to a fully on state. In order to hide these, we first transition to off to let the system
- // animate the screen on as it normally would, which is a much smoother experience.
- private boolean mTransitionOffAfterDozeConfig;
+ // True if we need to fake a transition to off when coming out of a doze state.
+ // Some display hardware will blank itself when coming out of doze in order to hide
+ // artifacts. For these displays we fake a transition into OFF so that policy can appropriately
+ // blank itself and begin an appropriate power on animation.
+ private boolean mDisplayBlanksAfterDozeConfig;
// The pending power request.
// Initially null until the first call to requestPowerState.
@@ -416,8 +416,8 @@
mColorFadeFadesConfig = resources.getBoolean(
com.android.internal.R.bool.config_animateScreenLights);
- mTransitionOffAfterDozeConfig = resources.getBoolean(
- com.android.internal.R.bool.config_displayTransitionOffAfterDoze);
+ mDisplayBlanksAfterDozeConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_displayBlanksAfterDoze);
if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
@@ -803,7 +803,7 @@
// Notify policy about screen turned on.
if (ready && state != Display.STATE_OFF
&& mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_TURNING_ON) {
- mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_ON;
+ setReportedScreenState(REPORTED_TO_POLICY_SCREEN_ON);
mWindowManagerPolicy.screenTurnedOn();
}
@@ -886,10 +886,10 @@
}
private boolean setScreenState(int state) {
- return setScreenState(state, false /*force*/);
+ return setScreenState(state, false /*reportOnly*/);
}
- private boolean setScreenState(int state, boolean force) {
+ private boolean setScreenState(int state, boolean reportOnly) {
final boolean isOff = (state == Display.STATE_OFF);
if (mPowerState.getScreenState() != state) {
@@ -897,32 +897,24 @@
// actually turn the screen off.
if (isOff && !mScreenOffBecauseOfProximity) {
if (mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_ON) {
- mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_OFF;
+ setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_OFF);
blockScreenOff();
mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
- if (force) {
- // If we're forcing the power state transition then immediately
- // unblock the screen off event. This keeps the lifecycle consistent,
- // so WindowManagerPolicy will always see screenTurningOff before
- // screenTurnedOff, but we don't actually block on them for the state
- // change.
- unblockScreenOff();
- } else {
- return false;
- }
+ unblockScreenOff();
} else if (mPendingScreenOffUnblocker != null) {
// Abort doing the state change until screen off is unblocked.
return false;
}
}
- mPowerState.setScreenState(state);
-
- // Tell battery stats about the transition.
- try {
- mBatteryStats.noteScreenState(state);
- } catch (RemoteException ex) {
- // same process
+ if (!reportOnly) {
+ mPowerState.setScreenState(state);
+ // Tell battery stats about the transition.
+ try {
+ mBatteryStats.noteScreenState(state);
+ } catch (RemoteException ex) {
+ // same process
+ }
}
}
@@ -934,7 +926,7 @@
// finished drawing underneath.
if (isOff && mReportedScreenStateToPolicy != REPORTED_TO_POLICY_SCREEN_OFF
&& !mScreenOffBecauseOfProximity) {
- mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
+ setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
unblockScreenOn();
mWindowManagerPolicy.screenTurnedOff();
} else if (!isOff
@@ -944,10 +936,10 @@
// Complete the full state transition on -> turningOff -> off.
unblockScreenOff();
mWindowManagerPolicy.screenTurnedOff();
- mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_OFF;
+ setReportedScreenState(REPORTED_TO_POLICY_SCREEN_OFF);
}
if (!isOff && mReportedScreenStateToPolicy == REPORTED_TO_POLICY_SCREEN_OFF) {
- mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_ON;
+ setReportedScreenState(REPORTED_TO_POLICY_SCREEN_TURNING_ON);
if (mPowerState.getColorFadeLevel() == 0.0f) {
blockScreenOn();
} else {
@@ -960,6 +952,11 @@
return mPendingScreenOnUnblocker == null;
}
+ private void setReportedScreenState(int state) {
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, "ReportedScreenStateToPolicy", state);
+ mReportedScreenStateToPolicy = state;
+ }
+
private int clampScreenBrightness(int value) {
return MathUtils.constrain(
value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
@@ -989,15 +986,20 @@
mPendingScreenOff = false;
}
- if (mTransitionOffAfterDozeConfig &&
- Display.isDozeState(mPowerState.getScreenState())
+ if (mDisplayBlanksAfterDozeConfig
+ && Display.isDozeState(mPowerState.getScreenState())
&& !Display.isDozeState(target)) {
- setScreenState(Display.STATE_OFF, true /*force*/);
// Skip the screen off animation and add a black surface to hide the
- // contents of the screen. This will also trigger another power state update so that we
- // end up converging on the target state.
+ // contents of the screen.
+ mPowerState.prepareColorFade(mContext,
+ mColorFadeFadesConfig ? ColorFade.MODE_FADE : ColorFade.MODE_WARM_UP);
mColorFadeOffAnimator.end();
- return;
+ // Some display hardware will blank itself on the transition between doze and non-doze
+ // but still on display states. In this case we want to report to policy that the
+ // display has turned off so it can prepare the appropriate power on animation, but we
+ // don't want to actually transition to the fully off state since that takes
+ // significantly longer to transition from.
+ setScreenState(Display.STATE_OFF, target != Display.STATE_OFF /*reportOnly*/);
}
// If we were in the process of turning off the screen but didn't quite
@@ -1295,7 +1297,8 @@
pw.println(" mAppliedLowPower=" + mAppliedLowPower);
pw.println(" mPendingScreenOnUnblocker=" + mPendingScreenOnUnblocker);
pw.println(" mPendingScreenOff=" + mPendingScreenOff);
- pw.println(" mReportedToPolicy=" + reportedToPolicyToString(mReportedScreenStateToPolicy));
+ pw.println(" mReportedToPolicy=" +
+ reportedToPolicyToString(mReportedScreenStateToPolicy));
pw.println(" mScreenBrightnessRampAnimator.isAnimating()=" +
mScreenBrightnessRampAnimator.isAnimating());
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index e2fd0ac..7b55ec1 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -20,6 +20,7 @@
import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
+import android.os.Trace;
import android.util.FloatProperty;
import android.util.IntProperty;
import android.util.Slog;
@@ -49,6 +50,7 @@
private static final String TAG = "DisplayPowerState";
private static boolean DEBUG = false;
+ private static String COUNTER_COLOR_FADE = "ColorFadeLevel";
private final Handler mHandler;
private final Choreographer mChoreographer;
@@ -190,6 +192,7 @@
* Dismisses the color fade surface.
*/
public void dismissColorFade() {
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, COUNTER_COLOR_FADE, 100);
mColorFade.dismiss();
mColorFadePrepared = false;
mColorFadeReady = true;
@@ -328,6 +331,8 @@
if (mColorFadePrepared) {
mColorFade.draw(mColorFadeLevel);
+ Trace.traceCounter(Trace.TRACE_TAG_POWER,
+ COUNTER_COLOR_FADE, Math.round(mColorFadeLevel* 100));
}
mColorFadeReady = true;
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index cdc973b..ce5f430 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -515,6 +515,7 @@
try {
final int mode = getPowerModeForState(state);
SurfaceControl.setDisplayPowerMode(token, mode);
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, "DisplayPowerMode", mode);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
@@ -530,6 +531,8 @@
+ "id=" + displayId + ", brightness=" + brightness + ")");
try {
mBacklight.setBrightness(brightness);
+ Trace.traceCounter(Trace.TRACE_TAG_POWER,
+ "DisplayBrightness", brightness);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java
index b124a39..026921d 100644
--- a/services/core/java/com/android/server/display/NightDisplayService.java
+++ b/services/core/java/com/android/server/display/NightDisplayService.java
@@ -119,9 +119,9 @@
* </table>
*/
private static final float[] mColorTempCoefficients = new float[] {
- 0.0f, -0.0000000871377221f, -0.0000000753960646f,
- 0.0f, 0.000750142586f, .000725567598f,
- 1.0f, -.830130222f, -1.15546312f
+ 0.0f, -0.000000014365268757f, -0.000000000910931179f,
+ 0.0f, 0.000255092801250106f, 0.000207598323269139f,
+ 1.0f, -0.064156942434907716f, -0.349361641294833436f
};
private int mCurrentUser = UserHandle.USER_NULL;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1242daa..5b24d8b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -3997,20 +3997,64 @@
}
@Override
- public PermissionInfo getPermissionInfo(String name, int flags) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ public PermissionInfo getPermissionInfo(String name, String packageName, int flags) {
+ final int callingUid = Binder.getCallingUid();
+ if (getInstantAppPackageName(callingUid) != null) {
return null;
}
// reader
synchronized (mPackages) {
final BasePermission p = mSettings.mPermissions.get(name);
- if (p != null) {
- return generatePermissionInfo(p, flags);
- }
- return null;
+ // If the caller is an app that targets pre 26 SDK drop protection flags.
+ final PermissionInfo permissionInfo = generatePermissionInfo(p, flags);
+ permissionInfo.protectionLevel = adjustPermissionProtectionFlagsLPr(
+ permissionInfo.protectionLevel, packageName, callingUid);
+ return permissionInfo;
}
}
+ private int adjustPermissionProtectionFlagsLPr(int protectionLevel,
+ String packageName, int uid) {
+ // Signature permission flags area always reported
+ final int protectionLevelMasked = protectionLevel
+ & (PermissionInfo.PROTECTION_NORMAL
+ | PermissionInfo.PROTECTION_DANGEROUS
+ | PermissionInfo.PROTECTION_SIGNATURE);
+ if (protectionLevelMasked == PermissionInfo.PROTECTION_SIGNATURE) {
+ return protectionLevel;
+ }
+
+ // System sees all flags.
+ final int appId = UserHandle.getAppId(uid);
+ if (appId == Process.SYSTEM_UID || appId == Process.ROOT_UID
+ || appId == Process.SHELL_UID) {
+ return protectionLevel;
+ }
+
+ // Normalize package name to handle renamed packages and static libs
+ packageName = resolveInternalPackageNameLPr(packageName,
+ PackageManager.VERSION_CODE_HIGHEST);
+
+ // Apps that target O see flags for all protection levels.
+ final PackageSetting ps = mSettings.mPackages.get(packageName);
+ if (ps == null) {
+ return protectionLevel;
+ }
+ if (ps.appId != appId) {
+ return protectionLevel;
+ }
+
+ final PackageParser.Package pkg = mPackages.get(packageName);
+ if (pkg == null) {
+ return protectionLevel;
+ }
+ if (pkg.applicationInfo.targetSdkVersion < Build.VERSION_CODES.O) {
+ return protectionLevelMasked;
+ }
+
+ return protectionLevel;
+ }
+
@Override
public @Nullable ParceledListSlice<PermissionInfo> queryPermissionsByGroup(String group,
int flags) {
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
index 831ab12..748092d 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -29,7 +29,7 @@
* by having one of the methods called on the {@link IImsCallSessionListener}.
* {@hide}
*/
-interface IImsCallSessionListener {
+oneway interface IImsCallSessionListener {
/**
* Notifies the result of the basic session operation (setup / terminate).
*/
diff --git a/telephony/java/com/android/ims/internal/IImsEcbmListener.aidl b/telephony/java/com/android/ims/internal/IImsEcbmListener.aidl
index d866ecb..6066f49 100644
--- a/telephony/java/com/android/ims/internal/IImsEcbmListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsEcbmListener.aidl
@@ -35,7 +35,7 @@
*
* {@hide}
*/
-interface IImsEcbmListener {
+oneway interface IImsEcbmListener {
/**
* Notifies the application when the device enters Emergency Callback Mode.
*/
diff --git a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
index 27b8fa1..1621967 100644
--- a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
@@ -23,7 +23,7 @@
*
* {@hide}
*/
-interface IImsExternalCallStateListener {
+oneway interface IImsExternalCallStateListener {
/**
* Notifies client when Dialog Event Package update is received
diff --git a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
index 98f8e0a..15f8726 100644
--- a/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl
@@ -26,7 +26,7 @@
*
* {@hide}
*/
-interface IImsRegistrationListener {
+oneway interface IImsRegistrationListener {
/**
* Notifies the application when the device is connected to the IMS network.
*
diff --git a/telephony/java/com/android/ims/internal/IImsUtListener.aidl b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
index 6416631..300273a 100644
--- a/telephony/java/com/android/ims/internal/IImsUtListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsUtListener.aidl
@@ -26,7 +26,7 @@
/**
* {@hide}
*/
-interface IImsUtListener {
+oneway interface IImsUtListener {
/**
* Notifies the result of the supplementary service configuration udpate.
*/
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 0711749..bfebedef 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -257,9 +257,11 @@
// Process plain strings to make sure they get properly escaped.
StringPiece raw_value = xml_attr->value;
- util::StringBuilder str_builder;
+
+ util::StringBuilder str_builder(true /*preserve_spaces*/);
+ str_builder.Append(xml_attr->value);
+
if (!options_.keep_raw_values) {
- str_builder.Append(xml_attr->value);
raw_value = str_builder.ToString();
}
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index f1e903f..a57e317 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -23,7 +23,13 @@
#include "util/BigBuffer.h"
#include "util/Util.h"
-using android::StringPiece16;
+using ::aapt::test::StrEq;
+using ::android::StringPiece16;
+using ::testing::Eq;
+using ::testing::Ge;
+using ::testing::IsNull;
+using ::testing::Ne;
+using ::testing::NotNull;
namespace aapt {
@@ -72,163 +78,138 @@
};
TEST_F(XmlFlattenerTest, FlattenXmlWithNoCompiledAttributes) {
- std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
- <View xmlns:test="http://com.test"
- attr="hey">
- <Layout test:hello="hi" />
- <Layout>Some text\\</Layout>
- </View>)EOF");
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
+ <View xmlns:test="http://com.test" attr="hey">
+ <Layout test:hello="hi" />
+ <Layout>Some text\\</Layout>
+ </View>)");
android::ResXMLTree tree;
ASSERT_TRUE(Flatten(doc.get(), &tree));
-
- ASSERT_EQ(android::ResXMLTree::START_NAMESPACE, tree.next());
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_NAMESPACE));
size_t len;
- const char16_t* namespace_prefix = tree.getNamespacePrefix(&len);
- EXPECT_EQ(StringPiece16(u"test"), StringPiece16(namespace_prefix, len));
+ EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"test"));
+ EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://com.test"));
- const char16_t* namespace_uri = tree.getNamespaceUri(&len);
- ASSERT_EQ(StringPiece16(u"http://com.test"), StringPiece16(namespace_uri, len));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"View"));
- ASSERT_EQ(android::ResXMLTree::START_TAG, tree.next());
+ ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
+ EXPECT_THAT(tree.getAttributeNamespace(0, &len), IsNull());
+ EXPECT_THAT(tree.getAttributeName(0, &len), StrEq(u"attr"));
- ASSERT_EQ(nullptr, tree.getElementNamespace(&len));
- const char16_t* tag_name = tree.getElementName(&len);
- EXPECT_EQ(StringPiece16(u"View"), StringPiece16(tag_name, len));
+ const StringPiece16 kAttr(u"attr");
+ EXPECT_THAT(tree.indexOfAttribute(nullptr, 0, kAttr.data(), kAttr.size()), Eq(0));
- ASSERT_EQ(1u, tree.getAttributeCount());
- ASSERT_EQ(nullptr, tree.getAttributeNamespace(0, &len));
- const char16_t* attr_name = tree.getAttributeName(0, &len);
- EXPECT_EQ(StringPiece16(u"attr"), StringPiece16(attr_name, len));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
+ EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
- EXPECT_EQ(0, tree.indexOfAttribute(nullptr, 0, u"attr", StringPiece16(u"attr").size()));
+ ASSERT_THAT(tree.getAttributeCount(), Eq(1u));
+ EXPECT_THAT(tree.getAttributeNamespace(0, &len), StrEq(u"http://com.test"));
+ EXPECT_THAT(tree.getAttributeName(0, &len), StrEq(u"hello"));
- ASSERT_EQ(android::ResXMLTree::START_TAG, tree.next());
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
- ASSERT_EQ(nullptr, tree.getElementNamespace(&len));
- tag_name = tree.getElementName(&len);
- EXPECT_EQ(StringPiece16(u"Layout"), StringPiece16(tag_name, len));
+ EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
+ ASSERT_THAT(tree.getAttributeCount(), Eq(0u));
- ASSERT_EQ(1u, tree.getAttributeCount());
- const char16_t* attr_namespace = tree.getAttributeNamespace(0, &len);
- EXPECT_EQ(StringPiece16(u"http://com.test"), StringPiece16(attr_namespace, len));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"Some text\\"));
- attr_name = tree.getAttributeName(0, &len);
- EXPECT_EQ(StringPiece16(u"hello"), StringPiece16(attr_name, len));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+ EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"Layout"));
- ASSERT_EQ(android::ResXMLTree::END_TAG, tree.next());
- ASSERT_EQ(android::ResXMLTree::START_TAG, tree.next());
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_TAG));
+ EXPECT_THAT(tree.getElementNamespace(&len), IsNull());
+ EXPECT_THAT(tree.getElementName(&len), StrEq(u"View"));
- ASSERT_EQ(nullptr, tree.getElementNamespace(&len));
- tag_name = tree.getElementName(&len);
- EXPECT_EQ(StringPiece16(u"Layout"), StringPiece16(tag_name, len));
- ASSERT_EQ(0u, tree.getAttributeCount());
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_NAMESPACE));
+ EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"test"));
+ EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://com.test"));
- ASSERT_EQ(android::ResXMLTree::TEXT, tree.next());
- const char16_t* text = tree.getText(&len);
- EXPECT_EQ(StringPiece16(u"Some text\\"), StringPiece16(text, len));
-
- ASSERT_EQ(android::ResXMLTree::END_TAG, tree.next());
- ASSERT_EQ(nullptr, tree.getElementNamespace(&len));
- tag_name = tree.getElementName(&len);
- EXPECT_EQ(StringPiece16(u"Layout"), StringPiece16(tag_name, len));
-
- ASSERT_EQ(android::ResXMLTree::END_TAG, tree.next());
- ASSERT_EQ(nullptr, tree.getElementNamespace(&len));
- tag_name = tree.getElementName(&len);
- EXPECT_EQ(StringPiece16(u"View"), StringPiece16(tag_name, len));
-
- ASSERT_EQ(android::ResXMLTree::END_NAMESPACE, tree.next());
- namespace_prefix = tree.getNamespacePrefix(&len);
- EXPECT_EQ(StringPiece16(u"test"), StringPiece16(namespace_prefix, len));
-
- namespace_uri = tree.getNamespaceUri(&len);
- ASSERT_EQ(StringPiece16(u"http://com.test"), StringPiece16(namespace_uri, len));
-
- ASSERT_EQ(android::ResXMLTree::END_DOCUMENT, tree.next());
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::END_DOCUMENT));
}
TEST_F(XmlFlattenerTest, FlattenCompiledXmlAndStripOnlyTools) {
- std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
- <View xmlns:tools="http://schemas.android.com/tools"
- xmlns:foo="http://schemas.android.com/foo"
- foo:bar="Foo"
- tools:ignore="MissingTranslation"/>)EOF");
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
+ <View xmlns:tools="http://schemas.android.com/tools"
+ xmlns:foo="http://schemas.android.com/foo"
+ foo:bar="Foo"
+ tools:ignore="MissingTranslation"/>)");
android::ResXMLTree tree;
ASSERT_TRUE(Flatten(doc.get(), &tree));
-
- ASSERT_EQ(tree.next(), android::ResXMLTree::START_NAMESPACE);
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_NAMESPACE));
size_t len;
- const char16_t* namespace_prefix = tree.getNamespacePrefix(&len);
- EXPECT_EQ(StringPiece16(namespace_prefix, len), u"foo");
+ EXPECT_THAT(tree.getNamespacePrefix(&len), StrEq(u"foo"));
+ EXPECT_THAT(tree.getNamespaceUri(&len), StrEq(u"http://schemas.android.com/foo"));
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::START_TAG));
- const char16_t* namespace_uri = tree.getNamespaceUri(&len);
- ASSERT_EQ(StringPiece16(namespace_uri, len),
- u"http://schemas.android.com/foo");
-
- ASSERT_EQ(tree.next(), android::ResXMLTree::START_TAG);
-
- EXPECT_EQ(tree.indexOfAttribute("http://schemas.android.com/tools", "ignore"),
- android::NAME_NOT_FOUND);
- EXPECT_GE(tree.indexOfAttribute("http://schemas.android.com/foo", "bar"), 0);
+ EXPECT_THAT(tree.indexOfAttribute("http://schemas.android.com/tools", "ignore"),
+ Eq(android::NAME_NOT_FOUND));
+ EXPECT_THAT(tree.indexOfAttribute("http://schemas.android.com/foo", "bar"), Ge(0));
}
TEST_F(XmlFlattenerTest, AssignSpecialAttributeIndices) {
- std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
- <View xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@id/id"
- class="str"
- style="@id/id"/>)EOF");
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
+ <View xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@id/id"
+ class="str"
+ style="@id/id"/>)");
android::ResXMLTree tree;
ASSERT_TRUE(Flatten(doc.get(), &tree));
while (tree.next() != android::ResXMLTree::START_TAG) {
- ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
- ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
}
- EXPECT_EQ(tree.indexOfClass(), 0);
- EXPECT_EQ(tree.indexOfStyle(), 1);
+ EXPECT_THAT(tree.indexOfClass(), Eq(0));
+ EXPECT_THAT(tree.indexOfStyle(), Eq(1));
}
// The device ResXMLParser in libandroidfw differentiates between empty namespace and null
// namespace.
TEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) {
- std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom("<View package=\"android\"/>");
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<View package="android"/>)");
android::ResXMLTree tree;
ASSERT_TRUE(Flatten(doc.get(), &tree));
while (tree.next() != android::ResXMLTree::START_TAG) {
- ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
- ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
}
const StringPiece16 kPackage = u"package";
- EXPECT_GE(tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size()), 0);
+ EXPECT_THAT(tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size()), Ge(0));
}
TEST_F(XmlFlattenerTest, EmptyStringValueInAttributeIsNotNull) {
- std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom("<View package=\"\"/>");
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<View package=""/>)");
android::ResXMLTree tree;
ASSERT_TRUE(Flatten(doc.get(), &tree));
while (tree.next() != android::ResXMLTree::START_TAG) {
- ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
- ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
}
const StringPiece16 kPackage = u"package";
ssize_t idx = tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size());
- ASSERT_GE(idx, 0);
+ ASSERT_THAT(idx, Ge(0));
size_t len;
- EXPECT_NE(nullptr, tree.getAttributeStringValue(idx, &len));
+ EXPECT_THAT(tree.getAttributeStringValue(idx, &len), NotNull());
}
TEST_F(XmlFlattenerTest, FlattenNonStandardPackageId) {
@@ -236,11 +217,11 @@
context_->SetPackageId(0x80);
context_->SetNameManglerPolicy({"com.app.test.feature"});
- std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"EOF(
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDomForPackageName(context_.get(), R"(
<View xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@id/foo"
- app:foo="@id/foo" />)EOF");
+ app:foo="@id/foo" />)");
XmlReferenceLinker linker;
ASSERT_TRUE(linker.Consume(context_.get(), doc.get()));
@@ -253,59 +234,57 @@
ASSERT_TRUE(Flatten(doc.get(), &tree));
while (tree.next() != android::ResXMLTree::START_TAG) {
- ASSERT_NE(android::ResXMLTree::BAD_DOCUMENT, tree.getEventType());
- ASSERT_NE(android::ResXMLTree::END_DOCUMENT, tree.getEventType());
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
}
ssize_t idx;
idx = tree.indexOfAttribute(xml::kSchemaAndroid, "id");
- ASSERT_GE(idx, 0);
- EXPECT_EQ(idx, tree.indexOfID());
- EXPECT_EQ(ResourceId(0x010100d0), ResourceId(tree.getAttributeNameResID(idx)));
+ ASSERT_THAT(idx, Ge(0));
+ EXPECT_THAT(tree.indexOfID(), Eq(idx));
+ EXPECT_THAT(tree.getAttributeNameResID(idx), Eq(0x010100d0u));
idx = tree.indexOfAttribute(xml::kSchemaAuto, "foo");
- ASSERT_GE(idx, 0);
- EXPECT_EQ(ResourceId(0x80010000), ResourceId(tree.getAttributeNameResID(idx)));
- EXPECT_EQ(android::Res_value::TYPE_REFERENCE, tree.getAttributeDataType(idx));
- EXPECT_EQ(ResourceId(0x80020000), tree.getAttributeData(idx));
+ ASSERT_THAT(idx, Ge(0));
+ EXPECT_THAT(tree.getAttributeNameResID(idx), Eq(0x80010000u));
+ EXPECT_THAT(tree.getAttributeDataType(idx), Eq(android::Res_value::TYPE_REFERENCE));
+ EXPECT_THAT(tree.getAttributeData(idx), Eq(int32_t(0x80020000)));
}
TEST_F(XmlFlattenerTest, ProcessEscapedStrings) {
std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(
- R"EOF(<element value="\?hello" pattern="\\d{5}">\\d{5}</element>)EOF");
+ R"(<element value="\?hello" pattern="\\d{5}" other=""">\\d{5}</element>)");
android::ResXMLTree tree;
ASSERT_TRUE(Flatten(doc.get(), &tree));
while (tree.next() != android::ResXMLTree::START_TAG) {
- ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
- ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::BAD_DOCUMENT));
+ ASSERT_THAT(tree.getEventType(), Ne(android::ResXMLTree::END_DOCUMENT));
}
const StringPiece16 kValue = u"value";
const StringPiece16 kPattern = u"pattern";
+ const StringPiece16 kOther = u"other";
size_t len;
ssize_t idx;
- const char16_t* str16;
idx = tree.indexOfAttribute(nullptr, 0, kValue.data(), kValue.size());
- ASSERT_GE(idx, 0);
- str16 = tree.getAttributeStringValue(idx, &len);
- ASSERT_NE(nullptr, str16);
- EXPECT_EQ(StringPiece16(u"?hello"), StringPiece16(str16, len));
+ ASSERT_THAT(idx, Ge(0));
+ EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"?hello"));
idx = tree.indexOfAttribute(nullptr, 0, kPattern.data(), kPattern.size());
- ASSERT_GE(idx, 0);
- str16 = tree.getAttributeStringValue(idx, &len);
- ASSERT_NE(nullptr, str16);
- EXPECT_EQ(StringPiece16(u"\\d{5}"), StringPiece16(str16, len));
+ ASSERT_THAT(idx, Ge(0));
+ EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"\\d{5}"));
- ASSERT_EQ(android::ResXMLTree::TEXT, tree.next());
- str16 = tree.getText(&len);
- ASSERT_NE(nullptr, str16);
- EXPECT_EQ(StringPiece16(u"\\d{5}"), StringPiece16(str16, len));
+ idx = tree.indexOfAttribute(nullptr, 0, kOther.data(), kOther.size());
+ ASSERT_THAT(idx, Ge(0));
+ EXPECT_THAT(tree.getAttributeStringValue(idx, &len), StrEq(u"\""));
+
+ ASSERT_THAT(tree.next(), Eq(android::ResXMLTree::TEXT));
+ EXPECT_THAT(tree.getText(&len), StrEq(u"\\d{5}"));
}
} // namespace aapt
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index 0585148..01b2d14 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -145,6 +145,12 @@
namespace test {
+MATCHER_P(StrEq, a,
+ std::string(negation ? "isn't" : "is") + " equal to " +
+ ::testing::PrintToString(android::StringPiece16(a))) {
+ return android::StringPiece16(arg) == a;
+}
+
MATCHER_P(ValueEq, a,
std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
return arg.Equals(&a);
diff --git a/tools/aapt2/util/Maybe.h b/tools/aapt2/util/Maybe.h
index b43f8e8..9a82418 100644
--- a/tools/aapt2/util/Maybe.h
+++ b/tools/aapt2/util/Maybe.h
@@ -281,16 +281,12 @@
return Maybe<T>();
}
-/**
- * Define the == operator between Maybe<T> and Maybe<U> only if the operator T
- * == U is defined.
- * That way the compiler will show an error at the callsite when comparing two
- * Maybe<> objects
- * whose inner types can't be compared.
- */
+// Define the == operator between Maybe<T> and Maybe<U> only if the operator T == U is defined.
+// That way the compiler will show an error at the callsite when comparing two Maybe<> objects
+// whose inner types can't be compared.
template <typename T, typename U>
-typename std::enable_if<has_eq_op<T, U>::value, bool>::type operator==(
- const Maybe<T>& a, const Maybe<U>& b) {
+typename std::enable_if<has_eq_op<T, U>::value, bool>::type operator==(const Maybe<T>& a,
+ const Maybe<U>& b) {
if (a && b) {
return a.value() == b.value();
} else if (!a && !b) {
@@ -299,18 +295,22 @@
return false;
}
-/**
- * Same as operator== but negated.
- */
template <typename T, typename U>
-typename std::enable_if<has_eq_op<T, U>::value, bool>::type operator!=(
- const Maybe<T>& a, const Maybe<U>& b) {
+typename std::enable_if<has_eq_op<T, U>::value, bool>::type operator==(const Maybe<T>& a,
+ const U& b) {
+ return a ? a.value() == b : false;
+}
+
+// Same as operator== but negated.
+template <typename T, typename U>
+typename std::enable_if<has_eq_op<T, U>::value, bool>::type operator!=(const Maybe<T>& a,
+ const Maybe<U>& b) {
return !(a == b);
}
template <typename T, typename U>
-typename std::enable_if<has_lt_op<T, U>::value, bool>::type operator<(
- const Maybe<T>& a, const Maybe<U>& b) {
+typename std::enable_if<has_lt_op<T, U>::value, bool>::type operator<(const Maybe<T>& a,
+ const Maybe<U>& b) {
if (a && b) {
return a.value() < b.value();
} else if (!a && !b) {
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index 28e952e..8a8be85 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -312,6 +312,9 @@
return result_utf8;
}
+StringBuilder::StringBuilder(bool preserve_spaces) : preserve_spaces_(preserve_spaces) {
+}
+
StringBuilder& StringBuilder::Append(const StringPiece& str) {
if (!error_.empty()) {
return *this;
@@ -368,14 +371,12 @@
}
last_char_was_escape_ = false;
start = current + 1;
- } else if (*current == '"') {
+ } else if (!preserve_spaces_ && *current == '"') {
if (!quote_ && trailing_space_) {
- // We found an opening quote, and we have
- // trailing space, so we should append that
+ // We found an opening quote, and we have trailing space, so we should append that
// space now.
if (trailing_space_) {
- // We had trailing whitespace, so
- // replace with a single space.
+ // We had trailing whitespace, so replace with a single space.
if (!str_.empty()) {
str_ += ' ';
}
@@ -385,7 +386,7 @@
quote_ = !quote_;
str_.append(start, current - start);
start = current + 1;
- } else if (*current == '\'' && !quote_) {
+ } else if (!preserve_spaces_ && *current == '\'' && !quote_) {
// This should be escaped.
error_ = "unescaped apostrophe";
return *this;
@@ -402,7 +403,7 @@
str_.append(start, current - start);
start = current + 1;
last_char_was_escape_ = true;
- } else if (!quote_) {
+ } else if (!preserve_spaces_ && !quote_) {
// This is not quoted text, so look for whitespace.
if (isspace(*current)) {
// We found whitespace, see if we have seen some
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 386f74b..b9ada77 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -166,6 +166,8 @@
class StringBuilder {
public:
+ explicit StringBuilder(bool preserve_spaces = false);
+
StringBuilder& Append(const android::StringPiece& str);
const std::string& ToString() const;
const std::string& Error() const;
@@ -179,6 +181,7 @@
explicit operator bool() const;
private:
+ bool preserve_spaces_;
std::string str_;
size_t utf16_len_ = 0;
bool quote_ = false;
diff --git a/tools/aapt2/util/Util_test.cpp b/tools/aapt2/util/Util_test.cpp
index e49aee5..5cced3e 100644
--- a/tools/aapt2/util/Util_test.cpp
+++ b/tools/aapt2/util/Util_test.cpp
@@ -20,16 +20,17 @@
#include "test/Test.h"
-using android::StringPiece;
+using ::android::StringPiece;
+using ::testing::Eq;
+using ::testing::Ne;
+using ::testing::SizeIs;
namespace aapt {
TEST(UtilTest, TrimOnlyWhitespace) {
- const std::string full = "\n ";
-
- StringPiece trimmed = util::TrimWhitespace(full);
+ const StringPiece trimmed = util::TrimWhitespace("\n ");
EXPECT_TRUE(trimmed.empty());
- EXPECT_EQ(0u, trimmed.size());
+ EXPECT_THAT(trimmed, SizeIs(0u));
}
TEST(UtilTest, StringEndsWith) {
@@ -41,85 +42,74 @@
}
TEST(UtilTest, StringBuilderSplitEscapeSequence) {
- EXPECT_EQ(StringPiece("this is a new\nline."), util::StringBuilder()
- .Append("this is a new\\")
- .Append("nline.")
- .ToString());
+ EXPECT_THAT(util::StringBuilder().Append("this is a new\\").Append("nline.").ToString(),
+ Eq("this is a new\nline."));
}
TEST(UtilTest, StringBuilderWhitespaceRemoval) {
- EXPECT_EQ(StringPiece("hey guys this is so cool"),
- util::StringBuilder()
- .Append(" hey guys ")
- .Append(" this is so cool ")
- .ToString());
-
- EXPECT_EQ(StringPiece(" wow, so many \t spaces. what?"),
- util::StringBuilder()
- .Append(" \" wow, so many \t ")
- .Append("spaces. \"what? ")
- .ToString());
-
- EXPECT_EQ(StringPiece("where is the pie?"), util::StringBuilder()
- .Append(" where \t ")
- .Append(" \nis the "
- " pie?")
- .ToString());
+ EXPECT_THAT(util::StringBuilder().Append(" hey guys ").Append(" this is so cool ").ToString(),
+ Eq("hey guys this is so cool"));
+ EXPECT_THAT(
+ util::StringBuilder().Append(" \" wow, so many \t ").Append("spaces. \"what? ").ToString(),
+ Eq(" wow, so many \t spaces. what?"));
+ EXPECT_THAT(util::StringBuilder().Append(" where \t ").Append(" \nis the pie?").ToString(),
+ Eq("where is the pie?"));
}
TEST(UtilTest, StringBuilderEscaping) {
- EXPECT_EQ(StringPiece("hey guys\n this \t is so\\ cool"),
- util::StringBuilder()
- .Append(" hey guys\\n ")
- .Append(" this \\t is so\\\\ cool ")
- .ToString());
-
- EXPECT_EQ(StringPiece("@?#\\\'"),
- util::StringBuilder().Append("\\@\\?\\#\\\\\\'").ToString());
+ EXPECT_THAT(util::StringBuilder()
+ .Append(" hey guys\\n ")
+ .Append(" this \\t is so\\\\ cool ")
+ .ToString(),
+ Eq("hey guys\n this \t is so\\ cool"));
+ EXPECT_THAT(util::StringBuilder().Append("\\@\\?\\#\\\\\\'").ToString(), Eq("@?#\\\'"));
}
TEST(UtilTest, StringBuilderMisplacedQuote) {
- util::StringBuilder builder{};
+ util::StringBuilder builder;
EXPECT_FALSE(builder.Append("they're coming!"));
}
TEST(UtilTest, StringBuilderUnicodeCodes) {
- EXPECT_EQ(std::string("\u00AF\u0AF0 woah"),
- util::StringBuilder().Append("\\u00AF\\u0AF0 woah").ToString());
-
+ EXPECT_THAT(util::StringBuilder().Append("\\u00AF\\u0AF0 woah").ToString(),
+ Eq("\u00AF\u0AF0 woah"));
EXPECT_FALSE(util::StringBuilder().Append("\\u00 yo"));
}
+TEST(UtilTest, StringBuilderPreserveSpaces) {
+ EXPECT_THAT(util::StringBuilder(true /*preserve_spaces*/).Append("\"").ToString(), Eq("\""));
+}
+
TEST(UtilTest, TokenizeInput) {
auto tokenizer = util::Tokenize(StringPiece("this| is|the|end"), '|');
auto iter = tokenizer.begin();
- ASSERT_EQ(*iter, StringPiece("this"));
+ ASSERT_THAT(*iter, Eq("this"));
++iter;
- ASSERT_EQ(*iter, StringPiece(" is"));
+ ASSERT_THAT(*iter, Eq(" is"));
++iter;
- ASSERT_EQ(*iter, StringPiece("the"));
+ ASSERT_THAT(*iter, Eq("the"));
++iter;
- ASSERT_EQ(*iter, StringPiece("end"));
+ ASSERT_THAT(*iter, Eq("end"));
++iter;
- ASSERT_EQ(tokenizer.end(), iter);
+ ASSERT_THAT(iter, Eq(tokenizer.end()));
}
TEST(UtilTest, TokenizeEmptyString) {
auto tokenizer = util::Tokenize(StringPiece(""), '|');
auto iter = tokenizer.begin();
- ASSERT_NE(tokenizer.end(), iter);
- ASSERT_EQ(StringPiece(), *iter);
+ ASSERT_THAT(iter, Ne(tokenizer.end()));
+ ASSERT_THAT(*iter, Eq(StringPiece()));
++iter;
- ASSERT_EQ(tokenizer.end(), iter);
+ ASSERT_THAT(iter, Eq(tokenizer.end()));
}
TEST(UtilTest, TokenizeAtEnd) {
auto tokenizer = util::Tokenize(StringPiece("one."), '.');
auto iter = tokenizer.begin();
- ASSERT_EQ(*iter, StringPiece("one"));
+ ASSERT_THAT(*iter, Eq("one"));
++iter;
- ASSERT_NE(iter, tokenizer.end());
- ASSERT_EQ(*iter, StringPiece());
+ ASSERT_THAT(iter, Ne(tokenizer.end()));
+ ASSERT_THAT(*iter, Eq(StringPiece()));
}
TEST(UtilTest, IsJavaClassName) {
diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp
index fb18ea3..031801e 100644
--- a/tools/aapt2/xml/XmlDom_test.cpp
+++ b/tools/aapt2/xml/XmlDom_test.cpp
@@ -28,17 +28,16 @@
TEST(XmlDomTest, Inflate) {
std::stringstream in(kXmlPreamble);
- in << R"EOF(
- <Layout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content">
- <TextView android:id="@+id/id"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
- </Layout>
- )EOF";
+ in << R"(
+ <Layout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+ <TextView android:id="@+id/id"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ </Layout>)";
- const Source source = {"test.xml"};
+ const Source source("test.xml");
StdErrDiagnostics diag;
std::unique_ptr<xml::XmlResource> doc = xml::Inflate(&in, &diag, source);
ASSERT_NE(doc, nullptr);
@@ -51,8 +50,8 @@
// Escaping is handled after parsing of the values for resource-specific values.
TEST(XmlDomTest, ForwardEscapes) {
- std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"EOF(
- <element value="\?hello" pattern="\\d{5}">\\d{5}</element>)EOF");
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(
+ <element value="\?hello" pattern="\\d{5}">\\d{5}</element>)");
xml::Element* el = xml::FindRootElement(doc->root.get());
ASSERT_NE(nullptr, el);
@@ -65,10 +64,20 @@
ASSERT_NE(nullptr, attr);
EXPECT_EQ("\\?hello", attr->value);
- ASSERT_EQ(1u, el->children.size());
xml::Text* text = xml::NodeCast<xml::Text>(el->children[0].get());
ASSERT_NE(nullptr, text);
EXPECT_EQ("\\\\d{5}", text->text);
}
+TEST(XmlDomTest, XmlEscapeSequencesAreParsed) {
+ std::unique_ptr<xml::XmlResource> doc = test::BuildXmlDom(R"(<element value=""" />)");
+
+ xml::Element* el = xml::FindRootElement(doc.get());
+ ASSERT_NE(nullptr, el);
+
+ xml::Attribute* attr = el->FindAttribute({}, "value");
+ ASSERT_NE(nullptr, attr);
+ EXPECT_EQ("\"", attr->value);
+}
+
} // namespace aapt