Merge changes from topic "revert_save_info" into pi-dev
* changes:
Document compatibility mode limitations.
Revert "Always set FLAG_SAVE_ON_ALL_VIEWS_INVISIBLE on SaveInfo when on compat mode."
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index ee667c2..1b6b5a0 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -80,8 +80,7 @@
* {@link #getBondedDevices()}; start device discovery with
* {@link #startDiscovery()}; or create a {@link BluetoothServerSocket} to
* listen for incoming RFComm connection requests with {@link
- * #listenUsingRfcommWithServiceRecord(String, UUID)}; listen for incoming L2CAP Connection-oriented
- * Channels (CoC) connection requests with listenUsingL2capCoc(int)}; or start a scan for
+ * #listenUsingRfcommWithServiceRecord(String, UUID)}; or start a scan for
* Bluetooth LE devices with {@link #startLeScan(LeScanCallback callback)}.
* </p>
* <p>This class is thread safe.</p>
diff --git a/core/java/android/bluetooth/BluetoothGattServer.java b/core/java/android/bluetooth/BluetoothGattServer.java
index 4ed2500..ef1b0bd 100644
--- a/core/java/android/bluetooth/BluetoothGattServer.java
+++ b/core/java/android/bluetooth/BluetoothGattServer.java
@@ -701,10 +701,14 @@
* <p>If the local device has already exposed services when this function
* is called, a service update notification will be sent to all clients.
*
+ * <p>The {@link BluetoothGattServerCallback#onServiceAdded} callback will indicate
+ * whether this service has been added successfully. Do not add another service
+ * before this callback.
+ *
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
* @param service Service to be added to the list of services provided by this device.
- * @return true, if the service has been added successfully
+ * @return true, if the request to add service has been initiated
*/
public boolean addService(BluetoothGattService service) {
if (DBG) Log.d(TAG, "addService() - service: " + service.getUuid());
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 1d232bf..0b4b921 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -4447,8 +4447,7 @@
pw.println(sb.toString());
}
- final long dischargeScreenOnCount =
- dischargeCount - dischargeScreenOffCount - dischargeScreenDozeCount;
+ final long dischargeScreenOnCount = dischargeCount - dischargeScreenOffCount;
if (dischargeScreenOnCount >= 0) {
sb.setLength(0);
sb.append(prefix);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 71b6084..6b16d42 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20700,7 +20700,7 @@
if (canTakeFocus()) {
// We have a robust focus, so parents should no longer be wanting focus.
clearParentsWantFocus();
- } else if (!getViewRootImpl().isInLayout()) {
+ } else if (getViewRootImpl() == null || !getViewRootImpl().isInLayout()) {
// This is a weird case. Most-likely the user, rather than ViewRootImpl, called
// layout. In this case, there's no guarantee that parent layouts will be evaluated
// and thus the safest action is to clear focus here.
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index 96016b4..ad50dc0 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -277,12 +277,12 @@
*/
@Nullable
public static PendingIntent createPendingIntent(
- @NonNull final Context context, @NonNull final Intent intent) {
+ @NonNull final Context context, @NonNull final Intent intent, int requestCode) {
switch (getIntentType(intent, context)) {
case IntentType.ACTIVITY:
- return PendingIntent.getActivity(context, 0, intent, 0);
+ return PendingIntent.getActivity(context, requestCode, intent, 0);
case IntentType.SERVICE:
- return PendingIntent.getService(context, 0, intent, 0);
+ return PendingIntent.getService(context, requestCode, intent, 0);
default:
return null;
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 2213355..910fcaa 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -412,7 +412,7 @@
boolean isPrimaryAction = true;
for (LabeledIntent labeledIntent : IntentFactory.create(
mContext, referenceTime, highestScoringResult, classifiedText)) {
- RemoteAction action = labeledIntent.asRemoteAction(mContext);
+ final RemoteAction action = labeledIntent.asRemoteAction(mContext);
if (isPrimaryAction) {
// For O backwards compatibility, the first RemoteAction is also written to the
// legacy API fields.
@@ -421,7 +421,7 @@
builder.setIntent(labeledIntent.getIntent());
builder.setOnClickListener(TextClassification.createIntentOnClickListener(
TextClassification.createPendingIntent(mContext,
- labeledIntent.getIntent())));
+ labeledIntent.getIntent(), labeledIntent.getRequestCode())));
isPrimaryAction = false;
}
builder.addAction(action);
@@ -559,14 +559,30 @@
* Helper class to store the information from which RemoteActions are built.
*/
private static final class LabeledIntent {
- private String mTitle;
- private String mDescription;
- private Intent mIntent;
- LabeledIntent(String title, String description, Intent intent) {
+ static final int DEFAULT_REQUEST_CODE = 0;
+
+ private final String mTitle;
+ private final String mDescription;
+ private final Intent mIntent;
+ private final int mRequestCode;
+
+ /**
+ * Initializes a LabeledIntent.
+ *
+ * <p>NOTE: {@code reqestCode} is required to not be {@link #DEFAULT_REQUEST_CODE}
+ * if distinguishing info (e.g. the classified text) is represented in intent extras only.
+ * In such circumstances, the request code should represent the distinguishing info
+ * (e.g. by generating a hashcode) so that the generated PendingIntent is (somewhat)
+ * unique. To be correct, the PendingIntent should be definitely unique but we try a
+ * best effort approach that avoids spamming the system with PendingIntents.
+ */
+ // TODO: Fix the issue mentioned above so the behaviour is correct.
+ LabeledIntent(String title, String description, Intent intent, int requestCode) {
mTitle = title;
mDescription = description;
mIntent = intent;
+ mRequestCode = requestCode;
}
String getTitle() {
@@ -581,6 +597,10 @@
return mIntent;
}
+ int getRequestCode() {
+ return mRequestCode;
+ }
+
RemoteAction asRemoteAction(Context context) {
final PackageManager pm = context.getPackageManager();
final ResolveInfo resolveInfo = pm.resolveActivity(mIntent, 0);
@@ -602,8 +622,8 @@
icon = Icon.createWithResource("android",
com.android.internal.R.drawable.ic_more_items);
}
- RemoteAction action = new RemoteAction(icon, mTitle, mDescription,
- TextClassification.createPendingIntent(context, mIntent));
+ final RemoteAction action = new RemoteAction(icon, mTitle, mDescription,
+ TextClassification.createPendingIntent(context, mIntent, mRequestCode));
action.setShouldShowIcon(shouldShowIcon);
return action;
}
@@ -659,13 +679,15 @@
context.getString(com.android.internal.R.string.email),
context.getString(com.android.internal.R.string.email_desc),
new Intent(Intent.ACTION_SENDTO)
- .setData(Uri.parse(String.format("mailto:%s", text)))),
+ .setData(Uri.parse(String.format("mailto:%s", text))),
+ LabeledIntent.DEFAULT_REQUEST_CODE),
new LabeledIntent(
context.getString(com.android.internal.R.string.add_contact),
context.getString(com.android.internal.R.string.add_contact_desc),
new Intent(Intent.ACTION_INSERT_OR_EDIT)
.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
- .putExtra(ContactsContract.Intents.Insert.EMAIL, text)));
+ .putExtra(ContactsContract.Intents.Insert.EMAIL, text),
+ text.hashCode()));
}
@NonNull
@@ -679,20 +701,23 @@
context.getString(com.android.internal.R.string.dial),
context.getString(com.android.internal.R.string.dial_desc),
new Intent(Intent.ACTION_DIAL).setData(
- Uri.parse(String.format("tel:%s", text)))));
+ Uri.parse(String.format("tel:%s", text))),
+ LabeledIntent.DEFAULT_REQUEST_CODE));
}
actions.add(new LabeledIntent(
context.getString(com.android.internal.R.string.add_contact),
context.getString(com.android.internal.R.string.add_contact_desc),
new Intent(Intent.ACTION_INSERT_OR_EDIT)
.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE)
- .putExtra(ContactsContract.Intents.Insert.PHONE, text)));
+ .putExtra(ContactsContract.Intents.Insert.PHONE, text),
+ text.hashCode()));
if (!userRestrictions.getBoolean(UserManager.DISALLOW_SMS, false)) {
actions.add(new LabeledIntent(
context.getString(com.android.internal.R.string.sms),
context.getString(com.android.internal.R.string.sms_desc),
new Intent(Intent.ACTION_SENDTO)
- .setData(Uri.parse(String.format("smsto:%s", text)))));
+ .setData(Uri.parse(String.format("smsto:%s", text))),
+ LabeledIntent.DEFAULT_REQUEST_CODE));
}
return actions;
}
@@ -706,7 +731,8 @@
context.getString(com.android.internal.R.string.map),
context.getString(com.android.internal.R.string.map_desc),
new Intent(Intent.ACTION_VIEW)
- .setData(Uri.parse(String.format("geo:0,0?q=%s", encText)))));
+ .setData(Uri.parse(String.format("geo:0,0?q=%s", encText))),
+ LabeledIntent.DEFAULT_REQUEST_CODE));
} catch (UnsupportedEncodingException e) {
Log.e(LOG_TAG, "Could not encode address", e);
}
@@ -728,7 +754,8 @@
context.getString(com.android.internal.R.string.browse),
context.getString(com.android.internal.R.string.browse_desc),
new Intent(Intent.ACTION_VIEW, Uri.parse(text))
- .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName())));
+ .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()),
+ LabeledIntent.DEFAULT_REQUEST_CODE));
}
@NonNull
@@ -754,7 +781,8 @@
context.getString(com.android.internal.R.string.view_flight),
context.getString(com.android.internal.R.string.view_flight_desc),
new Intent(Intent.ACTION_WEB_SEARCH)
- .putExtra(SearchManager.QUERY, text)));
+ .putExtra(SearchManager.QUERY, text),
+ text.hashCode()));
}
@NonNull
@@ -765,7 +793,8 @@
return new LabeledIntent(
context.getString(com.android.internal.R.string.view_calendar),
context.getString(com.android.internal.R.string.view_calendar_desc),
- new Intent(Intent.ACTION_VIEW).setData(builder.build()));
+ new Intent(Intent.ACTION_VIEW).setData(builder.build()),
+ LabeledIntent.DEFAULT_REQUEST_CODE);
}
@NonNull
@@ -781,7 +810,8 @@
.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME,
parsedTime.toEpochMilli())
.putExtra(CalendarContract.EXTRA_EVENT_END_TIME,
- parsedTime.toEpochMilli() + DEFAULT_EVENT_DURATION));
+ parsedTime.toEpochMilli() + DEFAULT_EVENT_DURATION),
+ parsedTime.hashCode());
}
}
}
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index dac100a..f6ac1cc 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -4063,7 +4063,8 @@
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
mAssistClickHandlers.put(item, TextClassification.createIntentOnClickListener(
TextClassification.createPendingIntent(mTextView.getContext(),
- textClassification.getIntent())));
+ textClassification.getIntent(),
+ createAssistMenuItemPendingIntentRequestCode())));
}
final int count = textClassification.getActions().size();
for (int i = 1; i < count; i++) {
@@ -4121,7 +4122,9 @@
final Intent intent = assistMenuItem.getIntent();
if (intent != null) {
onClickListener = TextClassification.createIntentOnClickListener(
- TextClassification.createPendingIntent(mTextView.getContext(), intent));
+ TextClassification.createPendingIntent(
+ mTextView.getContext(), intent,
+ createAssistMenuItemPendingIntentRequestCode()));
}
}
if (onClickListener != null) {
@@ -4132,6 +4135,14 @@
return true;
}
+ private int createAssistMenuItemPendingIntentRequestCode() {
+ return mTextView.hasSelection()
+ ? mTextView.getText().subSequence(
+ mTextView.getSelectionStart(), mTextView.getSelectionEnd())
+ .hashCode()
+ : 0;
+ }
+
private boolean shouldEnableAssistMenuItems() {
return mTextView.isDeviceProvisioned()
&& TextClassificationManager.getSettings(mTextView.getContext())
diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp
index 3118009..f1cc569 100644
--- a/libs/androidfw/tests/AssetManager2_test.cpp
+++ b/libs/androidfw/tests/AssetManager2_test.cpp
@@ -386,6 +386,38 @@
EXPECT_EQ(basic::R::array::integerArray1, last_ref);
}
+TEST_F(AssetManager2Test, ResolveDeepIdReference) {
+ AssetManager2 assetmanager;
+ assetmanager.SetApkAssets({basic_assets_.get()});
+
+ // Set up the resource ids
+ const uint32_t high_ref = assetmanager
+ .GetResourceId("@id/high_ref", "values", "com.android.basic");
+ ASSERT_NE(high_ref, 0u);
+ const uint32_t middle_ref = assetmanager
+ .GetResourceId("@id/middle_ref", "values", "com.android.basic");
+ ASSERT_NE(middle_ref, 0u);
+ const uint32_t low_ref = assetmanager
+ .GetResourceId("@id/low_ref", "values", "com.android.basic");
+ ASSERT_NE(low_ref, 0u);
+
+ // Retrieve the most shallow resource
+ Res_value value;
+ ResTable_config config;
+ uint32_t flags;
+ ApkAssetsCookie cookie = assetmanager.GetResource(high_ref, false /*may_be_bag*/,
+ 0 /*density_override*/,
+ &value, &config, &flags);
+ ASSERT_NE(kInvalidCookie, cookie);
+ EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType);
+ EXPECT_EQ(middle_ref, value.data);
+
+ // Check that resolving the reference resolves to the deepest id
+ uint32_t last_ref = high_ref;
+ assetmanager.ResolveReference(cookie, &value, &config, &flags, &last_ref);
+ EXPECT_EQ(last_ref, low_ref);
+}
+
TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) {
AssetManager2 assetmanager;
assetmanager.SetApkAssets({basic_assets_.get()});
diff --git a/libs/androidfw/tests/data/basic/basic.apk b/libs/androidfw/tests/data/basic/basic.apk
index 1733b6a..b721ebf 100644
--- a/libs/androidfw/tests/data/basic/basic.apk
+++ b/libs/androidfw/tests/data/basic/basic.apk
Binary files differ
diff --git a/libs/androidfw/tests/data/basic/res/values/values.xml b/libs/androidfw/tests/data/basic/res/values/values.xml
index b343562..d4b2683 100644
--- a/libs/androidfw/tests/data/basic/res/values/values.xml
+++ b/libs/androidfw/tests/data/basic/res/values/values.xml
@@ -78,4 +78,8 @@
<item type="string" name="test2" />
<item type="array" name="integerArray1" />
</overlayable>
+
+ <item name="high_ref" type="id">@id/middle_ref</item>
+ <item name="middle_ref" type="id">@id/low_ref</item>
+ <item name="low_ref" type="id"/>
</resources>
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
index a5f0f24..1ca3c1d 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/DeviceDiscoveryService.java
@@ -65,9 +65,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.CollectionUtils;
import com.android.internal.util.Preconditions;
-import com.android.internal.util.function.pooled.PooledLambda;
-import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
@@ -219,7 +217,7 @@
stopScan();
mDevicesFound.clear();
mSelectedDevice = null;
- mDevicesAdapter.notifyDataSetChanged();
+ notifyDataSetChanged();
}
@Override
@@ -265,7 +263,12 @@
onReadyToShowUI();
}
mDevicesFound.add(device);
- mDevicesAdapter.notifyDataSetChanged();
+ notifyDataSetChanged();
+ }
+
+ private void notifyDataSetChanged() {
+ Handler.getMain().sendMessage(obtainMessage(
+ DevicesAdapter::notifyDataSetChanged, mDevicesAdapter));
}
//TODO also, on timeout -> call onFailure
@@ -283,7 +286,7 @@
private void onDeviceLost(@Nullable DeviceFilterPair device) {
mDevicesFound.remove(device);
- mDevicesAdapter.notifyDataSetChanged();
+ notifyDataSetChanged();
if (DEBUG) Log.i(LOG_TAG, "Lost device " + device.getDisplayName());
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index 547cd9a..fe0b35b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -103,10 +103,9 @@
public void handleBroadcast(Intent intent) {
String action = intent.getAction();
if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- state = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN);
- enabled = state == WifiManager.WIFI_STATE_ENABLED;
+ updateWifiState();
} else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
+ updateWifiState();
final NetworkInfo networkInfo =
intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
connected = networkInfo != null && networkInfo.isConnected();
@@ -128,6 +127,11 @@
}
}
+ private void updateWifiState() {
+ state = mWifiManager.getWifiState();
+ enabled = state == WifiManager.WIFI_STATE_ENABLED;
+ }
+
private void updateRssi(int newRssi) {
rssi = newRssi;
level = WifiManager.calculateSignalLevel(rssi, WifiManager.RSSI_LEVELS);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 6c7eda7..5ae43c6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -65,10 +65,9 @@
void setKeyguardShowing(boolean keyguardShowing);
/**
- * Returns the {@link View} that should expand the quick settings when clicked.
+ * Sets the {@link android.view.View.OnClickListener to be used on elements that expend QS.
*/
- @Nullable
- View getExpandView();
+ void setExpandClickListener(View.OnClickListener onClickListener);
default void disable(int state1, int state2, boolean animate) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index abe819b..fd9ddb0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -17,7 +17,6 @@
package com.android.systemui.qs;
import static android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS;
-import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import android.content.Context;
import android.content.Intent;
@@ -27,6 +26,7 @@
import android.graphics.PorterDuff.Mode;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
+import android.os.Bundle;
import android.os.UserManager;
import android.support.annotation.Nullable;
import android.support.annotation.VisibleForTesting;
@@ -34,6 +34,7 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -96,6 +97,7 @@
private ImageView mMobileRoaming;
private final int mColorForeground;
private final CellSignalState mInfo = new CellSignalState();
+ private OnClickListener mExpandClickListener;
public QSFooterImpl(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -140,6 +142,7 @@
mActivityStarter = Dependency.get(ActivityStarter.class);
addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight,
oldBottom) -> updateAnimator(right - left));
+ setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
}
private void updateAnimator(int width) {
@@ -205,6 +208,11 @@
}
@Override
+ public void setExpandClickListener(OnClickListener onClickListener) {
+ mExpandClickListener = onClickListener;
+ }
+
+ @Override
public void setExpanded(boolean expanded) {
if (mExpanded == expanded) return;
mExpanded = expanded;
@@ -238,8 +246,20 @@
}
@Override
- public View getExpandView() {
- return findViewById(R.id.expand_indicator);
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ if (action == AccessibilityNodeInfo.ACTION_EXPAND) {
+ if (mExpandClickListener != null) {
+ mExpandClickListener.onClick(null);
+ return true;
+ }
+ }
+ return super.performAccessibilityAction(action, arguments);
+ }
+
+ @Override
+ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(info);
+ info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_EXPAND);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index b82e355..cbd1ca1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -240,11 +240,6 @@
@Override
public void setHeaderClickable(boolean clickable) {
if (DEBUG) Log.d(TAG, "setHeaderClickable " + clickable);
-
- View expandView = mFooter.getExpandView();
- if (expandView != null) {
- expandView.setClickable(clickable);
- }
}
@Override
@@ -369,11 +364,7 @@
@Override
public void setExpandClickListener(OnClickListener onClickListener) {
- View expandView = mFooter.getExpandView();
-
- if (expandView != null) {
- expandView.setOnClickListener(onClickListener);
- }
+ mFooter.setExpandClickListener(onClickListener);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index 24b5a34..2ea21c6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -114,11 +114,9 @@
}
}
- @Nullable
@Override
- public View getExpandView() {
+ public void setExpandClickListener(OnClickListener onClickListener) {
// No view that should expand/collapse the quick settings.
- return null;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 04bfcdd..66176b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -544,7 +544,12 @@
// Set visibility, may fail if a11y service is active.
// If invisible, call will stop animation.
- mNavigationBarView.setRotateButtonVisibility(true);
+ int appliedVisibility = mNavigationBarView.setRotateButtonVisibility(true);
+ if (appliedVisibility == View.VISIBLE) {
+ // If the button will actually become visible and the navbar is about to hide,
+ // tell the statusbar to keep it around for longer
+ mStatusBar.touchAutoHide();
+ }
} else { // Hide
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index c2053b6..6dbe9f8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -766,13 +766,13 @@
if (setIcon) getRotateSuggestionButton().setImageDrawable(mRotateSuggestionIcon);
}
- public void setRotateButtonVisibility(final boolean visible) {
+ public int setRotateButtonVisibility(final boolean visible) {
// Never show if a11y is visible
final boolean adjVisible = visible && !mShowAccessibilityButton;
final int vis = adjVisible ? View.VISIBLE : View.INVISIBLE;
// No need to do anything if the request matches the current state
- if (vis == getRotateSuggestionButton().getVisibility()) return;
+ if (vis == getRotateSuggestionButton().getVisibility()) return vis;
getRotateSuggestionButton().setVisibility(vis);
mShowRotateButton = visible;
@@ -789,6 +789,9 @@
// Hide/restore other button visibility, if necessary
updateNavButtonIcons();
+
+ // Return applied visibility
+ return vis;
}
public boolean isRotateButtonVisible() { return mShowRotateButton; }
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 351633b..ca459a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1965,14 +1965,12 @@
@Override
public void onClick(View v) {
- if (v.getId() == R.id.expand_indicator) {
- onQsExpansionStarted();
- if (mQsExpanded) {
- flingSettings(0 /* vel */, false /* expand */, null, true /* isClick */);
- } else if (mQsExpansionEnabled) {
- mLockscreenGestureLogger.write(MetricsEvent.ACTION_SHADE_QS_TAP, 0, 0);
- flingSettings(0 /* vel */, true /* expand */, null, true /* isClick */);
- }
+ onQsExpansionStarted();
+ if (mQsExpanded) {
+ flingSettings(0 /* vel */, false /* expand */, null, true /* isClick */);
+ } else if (mQsExpansionEnabled) {
+ mLockscreenGestureLogger.write(MetricsEvent.ACTION_SHADE_QS_TAP, 0, 0);
+ flingSettings(0 /* vel */, true /* expand */, null, true /* isClick */);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
index d30e777..6591715 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java
@@ -136,10 +136,9 @@
}
protected void setWifiEnabled(boolean enabled) {
- Intent i = new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION);
- i.putExtra(WifiManager.EXTRA_WIFI_STATE,
+ when(mMockWm.getWifiState()).thenReturn(
enabled ? WifiManager.WIFI_STATE_ENABLED : WifiManager.WIFI_STATE_DISABLED);
- mNetworkController.onReceive(mContext, i);
+ mNetworkController.onReceive(mContext, new Intent(WifiManager.WIFI_STATE_CHANGED_ACTION));
}
protected void setWifiState(boolean connected, String ssid) {
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index 0c444cb..febce31 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -1284,12 +1284,16 @@
if (r.showBadge != DEFAULT_SHOW_BADGE) {
record.put("showBadge", Boolean.valueOf(r.showBadge));
}
+ JSONArray channels = new JSONArray();
for (NotificationChannel channel : r.channels.values()) {
- record.put("channel", channel.toJson());
+ channels.put(channel.toJson());
}
+ record.put("channels", channels);
+ JSONArray groups = new JSONArray();
for (NotificationChannelGroup group : r.groups.values()) {
- record.put("group", group.toJson());
+ groups.put(group.toJson());
}
+ record.put("groups", groups);
} catch (JSONException e) {
// pass
}
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 1b6f882..19c6c31 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -586,7 +586,29 @@
out_resource->name.type = ResourceType::kId;
out_resource->name.entry = maybe_name.value().to_string();
- out_resource->value = util::make_unique<Id>();
+
+ // Ids either represent a unique resource id or reference another resource id
+ auto item = ParseItem(parser, out_resource, resource_format);
+ if (!item) {
+ return false;
+ }
+
+ String* empty = ValueCast<String>(out_resource->value.get());
+ if (empty && *empty->value == "") {
+ // If no inner element exists, represent a unique identifier
+ out_resource->value = util::make_unique<Id>();
+ } else {
+ // If an inner element exists, the inner element must be a reference to
+ // another resource id
+ Reference* ref = ValueCast<Reference>(out_resource->value.get());
+ if (!ref || ref->name.value().type != ResourceType::kId) {
+ diag_->Error(DiagMessage(out_resource->source)
+ << "<" << parser->element_name()
+ << "> inner element must either be a resource reference or empty");
+ return false;
+ }
+ }
+
return true;
}
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index fc1aeaa..c12b9fa 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -933,4 +933,32 @@
EXPECT_FALSE(TestParse(input));
}
+TEST_F(ResourceParserTest, ParseIdItem) {
+ std::string input = R"(
+ <item name="foo" type="id">@id/bar</item>
+ <item name="bar" type="id"/>
+ <item name="baz" type="id"></item>)";
+ ASSERT_TRUE(TestParse(input));
+
+ ASSERT_THAT(test::GetValue<Reference>(&table_, "id/foo"), NotNull());
+ ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar"), NotNull());
+ ASSERT_THAT(test::GetValue<Id>(&table_, "id/baz"), NotNull());
+
+ // Reject attribute references
+ input = R"(<item name="foo2" type="id">?attr/bar"</item>)";
+ ASSERT_FALSE(TestParse(input));
+
+ // Reject non-references
+ input = R"(<item name="foo3" type="id">0x7f010001</item>)";
+ ASSERT_FALSE(TestParse(input));
+ input = R"(<item name="foo4" type="id">@drawable/my_image</item>)";
+ ASSERT_FALSE(TestParse(input));
+ input = R"(<item name="foo5" type="id"><string name="biz"></string></item>)";
+ ASSERT_FALSE(TestParse(input));
+
+ // Ids that reference other resource ids cannot be public
+ input = R"(<public name="foo6" type="id">@id/bar6</item>)";
+ ASSERT_FALSE(TestParse(input));
+}
+
} // namespace aapt