Merge "BrightnessMirror: When reinflating, notify QSPanel" into oc-dr1-dev
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index 77ce65b..be9e809 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -672,36 +672,33 @@
entry.tag = left.tag[i];
entry.metered = left.metered[i];
entry.roaming = left.roaming[i];
+ entry.rxBytes = left.rxBytes[i];
+ entry.rxPackets = left.rxPackets[i];
+ entry.txBytes = left.txBytes[i];
+ entry.txPackets = left.txPackets[i];
+ entry.operations = left.operations[i];
// find remote row that matches, and subtract
final int j = right.findIndexHinted(entry.iface, entry.uid, entry.set, entry.tag,
entry.metered, entry.roaming, i);
- if (j == -1) {
- // newly appearing row, return entire value
- entry.rxBytes = left.rxBytes[i];
- entry.rxPackets = left.rxPackets[i];
- entry.txBytes = left.txBytes[i];
- entry.txPackets = left.txPackets[i];
- entry.operations = left.operations[i];
- } else {
- // existing row, subtract remote value
- entry.rxBytes = left.rxBytes[i] - right.rxBytes[j];
- entry.rxPackets = left.rxPackets[i] - right.rxPackets[j];
- entry.txBytes = left.txBytes[i] - right.txBytes[j];
- entry.txPackets = left.txPackets[i] - right.txPackets[j];
- entry.operations = left.operations[i] - right.operations[j];
+ if (j != -1) {
+ // Found matching row, subtract remote value.
+ entry.rxBytes -= right.rxBytes[j];
+ entry.rxPackets -= right.rxPackets[j];
+ entry.txBytes -= right.txBytes[j];
+ entry.txPackets -= right.txPackets[j];
+ entry.operations -= right.operations[j];
+ }
- if (entry.rxBytes < 0 || entry.rxPackets < 0 || entry.txBytes < 0
- || entry.txPackets < 0 || entry.operations < 0) {
- if (observer != null) {
- observer.foundNonMonotonic(left, i, right, j, cookie);
- }
- entry.rxBytes = Math.max(entry.rxBytes, 0);
- entry.rxPackets = Math.max(entry.rxPackets, 0);
- entry.txBytes = Math.max(entry.txBytes, 0);
- entry.txPackets = Math.max(entry.txPackets, 0);
- entry.operations = Math.max(entry.operations, 0);
+ if (entry.isNegative()) {
+ if (observer != null) {
+ observer.foundNonMonotonic(left, i, right, j, cookie);
}
+ entry.rxBytes = Math.max(entry.rxBytes, 0);
+ entry.rxPackets = Math.max(entry.rxPackets, 0);
+ entry.txBytes = Math.max(entry.txBytes, 0);
+ entry.txPackets = Math.max(entry.txPackets, 0);
+ entry.operations = Math.max(entry.operations, 0);
}
result.addValues(entry);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 44c88e1..1a2968f 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -65,7 +65,8 @@
private static native void nativeSetSize(long nativeObject, int w, int h);
private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
private static native void nativeSetAlpha(long nativeObject, float alpha);
- private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
+ private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx,
+ float dtdy, float dsdy);
private static native void nativeSetFlags(long nativeObject, int flags, int mask);
private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
private static native void nativeSetFinalCrop(long nativeObject, int l, int t, int r, int b);
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 3505c29..c123a80 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -52,9 +52,64 @@
import java.util.Objects;
/**
- * App entry point to the Autofill Framework.
+ * The {@link AutofillManager} provides ways for apps and custom views to integrate with the
+ * Autofill Framework lifecycle.
*
- * <p>It is safe to call into this from any thread.
+ * <p>The autofill lifecycle starts with the creation of an autofill context associated with an
+ * activity context; the autofill context is created when one of the following methods is called for
+ * the first time in an activity context, and the current user has an enabled autofill service:
+ *
+ * <ul>
+ * <li>{@link #notifyViewEntered(View)}
+ * <li>{@link #notifyViewEntered(View, int, Rect)}
+ * <li>{@link #requestAutofill(View)}
+ * </ul>
+ *
+ * <p>Tipically, the context is automatically created when the first view of the activity is
+ * focused because {@code View.onFocusChanged()} indirectly calls
+ * {@link #notifyViewEntered(View)}. App developers can call {@link #requestAutofill(View)} to
+ * explicitly create it (for example, a custom view developer could offer a contextual menu action
+ * in a text-field view to let users manually request autofill).
+ *
+ * <p>After the context is created, the Android System creates a {@link android.view.ViewStructure}
+ * that represents the view hierarchy by calling
+ * {@link View#dispatchProvideAutofillStructure(android.view.ViewStructure, int)} in the root views
+ * of all application windows. By default, {@code dispatchProvideAutofillStructure()} results in
+ * subsequent calls to {@link View#onProvideAutofillStructure(android.view.ViewStructure, int)} and
+ * {@link View#onProvideAutofillVirtualStructure(android.view.ViewStructure, int)} for each view in
+ * the hierarchy.
+ *
+ * <p>The resulting {@link android.view.ViewStructure} is then passed to the autofill service, which
+ * parses it looking for views that can be autofilled. If the service finds such views, it returns
+ * a data structure to the Android System containing the following optional info:
+ *
+ * <ul>
+ * <li>Datasets used to autofill subsets of views in the activity.
+ * <li>Id of views that the service can save their values for future autofilling.
+ * </ul>
+ *
+ * <p>When the service returns datasets, the Android System displays an autofill dataset picker
+ * UI affordance associated with the view, when the view is focused on and is part of a dataset.
+ * The application can be notified when the affordance is shown by registering an
+ * {@link AutofillCallback} through {@link #registerCallback(AutofillCallback)}. When the user
+ * selects a dataset from the affordance, all views present in the dataset are autofilled, through
+ * calls to {@link View#autofill(AutofillValue)} or {@link View#autofill(SparseArray)}.
+ *
+ * <p>When the service returns ids of savable views, the Android System keeps track of changes
+ * made to these views, so they can be used to determine if the autofill save UI is shown later.
+ *
+ * <p>The context is then finished when one of the following occurs:
+ *
+ * <ul>
+ * <li>{@link #commit()} is called or all savable views are gone.
+ * <li>{@link #cancel()} is called.
+ * </ul>
+ *
+ * <p>Finally, after the autofill context is commited (i.e., not cancelled), the Android System
+ * shows a save UI affordance if the value of savable views have changed. If the user selects the
+ * option to Save, the current value of the views is then sent to the autofill service.
+ *
+ * <p>It is safe to call into its methods from any thread.
*/
@SystemService(Context.AUTOFILL_MANAGER_SERVICE)
public final class AutofillManager {
@@ -1472,10 +1527,10 @@
}
/**
- * Callback for auto-fill related events.
+ * Callback for autofill related events.
*
* <p>Typically used for applications that display their own "auto-complete" views, so they can
- * enable / disable such views when the auto-fill UI affordance is shown / hidden.
+ * enable / disable such views when the autofill UI affordance is shown / hidden.
*/
public abstract static class AutofillCallback {
@@ -1485,7 +1540,7 @@
public @interface AutofillEventType {}
/**
- * The auto-fill input UI affordance associated with the view was shown.
+ * The autofill input UI affordance associated with the view was shown.
*
* <p>If the view provides its own auto-complete UI affordance and its currently shown, it
* should be hidden upon receiving this event.
@@ -1493,7 +1548,7 @@
public static final int EVENT_INPUT_SHOWN = 1;
/**
- * The auto-fill input UI affordance associated with the view was hidden.
+ * The autofill input UI affordance associated with the view was hidden.
*
* <p>If the view provides its own auto-complete UI affordance that was hidden upon a
* {@link #EVENT_INPUT_SHOWN} event, it could be shown again now.
@@ -1501,7 +1556,7 @@
public static final int EVENT_INPUT_HIDDEN = 2;
/**
- * The auto-fill input UI affordance associated with the view won't be shown because
+ * The autofill input UI affordance associated with the view isn't shown because
* autofill is not available.
*
* <p>If the view provides its own auto-complete UI affordance but was not displaying it
diff --git a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
index 1168eec..1811800c 100644
--- a/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
+++ b/core/java/com/android/internal/hardware/AmbientDisplayConfiguration.java
@@ -111,7 +111,7 @@
return mContext.getResources().getString(R.string.config_dozeComponent);
}
- private boolean accessibilityInversionEnabled(int user) {
+ public boolean accessibilityInversionEnabled(int user) {
return boolSettingDefaultOff(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, user);
}
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 40ecc8c..6f54b0c 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -115,4 +115,6 @@
void remQsTile(in ComponentName tile);
void clickQsTile(in ComponentName tile);
void handleSystemKey(in int key);
+
+ void showShutdownUi(boolean isReboot, String reason);
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ae115d3..2a761c6 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -304,7 +304,7 @@
<protected-broadcast android:name="com.android.server.WifiManager.action.DEVICE_IDLE" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
<protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
- <protected-broadcast android:name="com.android.server.action.WIPE_EUICC_DATA" />
+ <protected-broadcast android:name="com.android.internal.action.EUICC_FACTORY_RESET" />
<protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
<protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
<protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
diff --git a/core/res/res/values-television/config.xml b/core/res/res/values-television/config.xml
index d62b93e..cf67abf 100644
--- a/core/res/res/values-television/config.xml
+++ b/core/res/res/values-television/config.xml
@@ -39,4 +39,7 @@
<!-- Whether the device uses the default focus highlight when focus state isn't specified. -->
<bool name="config_useDefaultFocusHighlight">false</bool>
+
+ <!-- Allow SystemUI to show the shutdown dialog -->
+ <bool name="config_showSysuiShutdown">false</bool>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7144127..831a3a8 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3000,4 +3000,7 @@
<!-- Enable the RingtonePickerActivity in 'com.android.providers.media'. -->
<bool name="config_defaultRingtonePickerEnabled">true</bool>
+
+ <!-- Allow SystemUI to show the shutdown dialog -->
+ <bool name="config_showSysuiShutdown">true</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4726dcf..523583a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3067,4 +3067,5 @@
<java-symbol type="bool" name="config_showAreaUpdateInfoSettings" />
<java-symbol type="layout" name="shutdown_dialog" />
<java-symbol type="dimen" name="chooser_service_spacing" />
+ <java-symbol type="bool" name="config_showSysuiShutdown" />
</resources>
diff --git a/data/etc/framework-sysconfig.xml b/data/etc/framework-sysconfig.xml
index 7fafef7..3a81c13 100644
--- a/data/etc/framework-sysconfig.xml
+++ b/data/etc/framework-sysconfig.xml
@@ -28,4 +28,6 @@
<backup-transport-whitelisted-service
service="android/com.android.internal.backup.LocalTransportService" />
+ <!-- Whitelist of bundled applications which all handle URLs to their websites by default -->
+ <app-link package="com.android.carrierdefaultapp" />
</config>
diff --git a/packages/CarrierDefaultApp/AndroidManifest.xml b/packages/CarrierDefaultApp/AndroidManifest.xml
index c309133..1cd7b61 100644
--- a/packages/CarrierDefaultApp/AndroidManifest.xml
+++ b/packages/CarrierDefaultApp/AndroidManifest.xml
@@ -34,6 +34,7 @@
<intent-filter>
<action android:name="com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED" />
<action android:name="com.android.internal.telephony.CARRIER_SIGNAL_RESET" />
+ <action android:name="com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE" />
<action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
@@ -43,10 +44,24 @@
android:name="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
android:label="@string/action_bar_label"
android:theme="@style/AppTheme"
- android:configChanges="keyboardHidden|orientation|screenSize" >
+ android:configChanges="keyboardHidden|orientation|screenSize">
<intent-filter>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
+
+ <activity-alias
+ android:name="com.android.carrierdefaultapp.URLHandlerActivity"
+ android:targetActivity="com.android.carrierdefaultapp.CaptivePortalLoginActivity"
+ android:enabled="false" >
+ <intent-filter>
+ <action android:name="android.intent.action.VIEW" />
+ <category android:name="android.intent.category.DEFAULT"/>
+ <category android:name="android.intent.category.BROWSABLE" />
+ <data android:scheme="http" />
+ <data android:scheme="https" />
+ <data android:host="*" />
+ </intent-filter>
+ </activity-alias>
</application>
</manifest>
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
index 6194b87..b0052cc 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CaptivePortalLoginActivity.java
@@ -20,6 +20,9 @@
import android.app.LoadedApk;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
@@ -34,6 +37,7 @@
import android.telephony.CarrierConfigManager;
import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.TypedValue;
@@ -68,7 +72,7 @@
private static final boolean DBG = true;
private static final int SOCKET_TIMEOUT_MS = 10 * 1000;
- public static final int NETWORK_REQUEST_TIMEOUT_MS = 5 * 1000;
+ private static final int NETWORK_REQUEST_TIMEOUT_MS = 5 * 1000;
private URL mUrl;
private Network mNetwork;
@@ -188,16 +192,19 @@
CarrierActionUtils.applyCarrierAction(
CarrierActionUtils.CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS, getIntent(),
getApplicationContext());
-
+ CarrierActionUtils.applyCarrierAction(
+ CarrierActionUtils.CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER, getIntent(),
+ getApplicationContext());
+ CarrierActionUtils.applyCarrierAction(
+ CarrierActionUtils.CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL, getIntent(),
+ getApplicationContext());
}
finishAndRemoveTask();
}
private URL getUrlForCaptivePortal() {
String url = getIntent().getStringExtra(TelephonyIntents.EXTRA_REDIRECTION_URL_KEY);
- if (url.isEmpty()) {
- url = mCm.getCaptivePortalServerUrl();
- }
+ if (TextUtils.isEmpty(url)) url = mCm.getCaptivePortalServerUrl();
final CarrierConfigManager configManager = getApplicationContext()
.getSystemService(CarrierConfigManager.class);
final int subId = getIntent().getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
@@ -437,6 +444,27 @@
}
}
+ /**
+ * This alias presents the target activity, CaptivePortalLoginActivity, as a independent
+ * entity with its own intent filter to handle URL links. This alias will be enabled/disabled
+ * dynamically to handle url links based on the network conditions.
+ */
+ public static String getAlias(Context context) {
+ try {
+ PackageInfo p = context.getPackageManager().getPackageInfo(context.getPackageName(),
+ PackageManager.GET_ACTIVITIES | PackageManager.MATCH_DISABLED_COMPONENTS);
+ for (ActivityInfo activityInfo : p.activities) {
+ String targetActivity = activityInfo.targetActivity;
+ if (CaptivePortalLoginActivity.class.getName().equals(targetActivity)) {
+ return activityInfo.name;
+ }
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
private static void logd(String s) {
Rlog.d(TAG, s);
}
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
index 0213306..a2bf964 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CarrierActionUtils.java
@@ -19,8 +19,10 @@
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.telephony.SubscriptionManager;
@@ -49,6 +51,10 @@
public static final int CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION = 4;
public static final int CARRIER_ACTION_SHOW_NO_DATA_SERVICE_NOTIFICATION = 5;
public static final int CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS = 6;
+ public static final int CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER = 7;
+ public static final int CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER = 8;
+ public static final int CARRIER_ACTION_REGISTER_DEFAULT_NETWORK_AVAIL = 9;
+ public static final int CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL = 10;
public static void applyCarrierAction(int actionIdx, Intent intent, Context context) {
switch (actionIdx) {
@@ -73,6 +79,18 @@
case CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS:
onCancelAllNotifications(context);
break;
+ case CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER:
+ onEnableDefaultURLHandler(context);
+ break;
+ case CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER:
+ onDisableDefaultURLHandler(context);
+ break;
+ case CARRIER_ACTION_REGISTER_DEFAULT_NETWORK_AVAIL:
+ onRegisterDefaultNetworkAvail(intent, context);
+ break;
+ case CARRIER_ACTION_DEREGISTER_DEFAULT_NETWORK_AVAIL:
+ onDeregisterDefaultNetworkAvail(intent, context);
+ break;
default:
loge("unsupported carrier action index: " + actionIdx);
}
@@ -94,6 +112,38 @@
telephonyMgr.carrierActionSetMeteredApnsEnabled(subId, ENABLE);
}
+ private static void onEnableDefaultURLHandler(Context context) {
+ logd("onEnableDefaultURLHandler");
+ final PackageManager pm = context.getPackageManager();
+ pm.setComponentEnabledSetting(
+ new ComponentName(context, CaptivePortalLoginActivity.getAlias(context)),
+ PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
+ }
+
+ private static void onDisableDefaultURLHandler(Context context) {
+ logd("onDisableDefaultURLHandler");
+ final PackageManager pm = context.getPackageManager();
+ pm.setComponentEnabledSetting(
+ new ComponentName(context, CaptivePortalLoginActivity.getAlias(context)),
+ PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
+ }
+
+ private static void onRegisterDefaultNetworkAvail(Intent intent, Context context) {
+ int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultVoiceSubscriptionId());
+ logd("onRegisterDefaultNetworkAvail subId: " + subId);
+ final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ telephonyMgr.carrierActionReportDefaultNetworkStatus(subId, true);
+ }
+
+ private static void onDeregisterDefaultNetworkAvail(Intent intent, Context context) {
+ int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
+ SubscriptionManager.getDefaultVoiceSubscriptionId());
+ logd("onDeregisterDefaultNetworkAvail subId: " + subId);
+ final TelephonyManager telephonyMgr = context.getSystemService(TelephonyManager.class);
+ telephonyMgr.carrierActionReportDefaultNetworkStatus(subId, false);
+ }
+
private static void onDisableRadio(Intent intent, Context context) {
int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
SubscriptionManager.getDefaultVoiceSubscriptionId());
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
index d5d0b79..02c61d7 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/CustomConfigLoader.java
@@ -22,7 +22,6 @@
import android.telephony.Rlog;
import android.text.TextUtils;
import android.util.Log;
-import android.util.Pair;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.util.ArrayUtils;
@@ -95,6 +94,12 @@
configs = b.getStringArray(CarrierConfigManager
.KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET);
break;
+ case TelephonyIntents.ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE:
+ configs = b.getStringArray(CarrierConfigManager
+ .KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE);
+ arg1 = String.valueOf(intent.getBooleanExtra(TelephonyIntents
+ .EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY, false));
+ break;
default:
Rlog.e(TAG, "load carrier config failure with un-configured key: " +
intent.getAction());
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index 8f62100..306f9ac 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -223,6 +223,8 @@
mProviderFriendlyName = savedState.getString(KEY_PROVIDER_FRIENDLY_NAME);
}
update(mConfig, mInfo, mNetworkInfo);
+
+ // Do not evict old scan results on initial creation
updateRssi();
updateSeen();
mId = sLastId.incrementAndGet();
@@ -442,10 +444,6 @@
}
private void evictOldScanResults() {
- if (WifiTracker.sStaleScanResults) {
- // Do not evict old scan results unless we are scanning and have fresh results.
- return;
- }
long nowMs = SystemClock.elapsedRealtime();
for (Iterator<ScanResult> iter = mScanResultCache.values().iterator(); iter.hasNext(); ) {
ScanResult result = iter.next();
@@ -509,12 +507,8 @@
* results, returning the best RSSI for all matching AccessPoints averaged with the previous
* value. If the access point is not connected and there are no scan results, the rssi will be
* set to {@link #UNREACHABLE_RSSI}.
- *
- * <p>Old scan results will be evicted from the cache when this method is invoked.
*/
private void updateRssi() {
- evictOldScanResults();
-
if (this.isActive()) {
return;
}
@@ -533,14 +527,8 @@
}
}
- /**
- * Updates {@link #mSeen} based on the scan result cache.
- *
- * <p>Old scan results will be evicted from the cache when this method is invoked.
- */
+ /** Updates {@link #mSeen} based on the scan result cache. */
private void updateSeen() {
- evictOldScanResults();
-
// TODO(sghuman): Set to now if connected
long seen = 0;
@@ -1030,12 +1018,22 @@
mAccessPointListener = listener;
}
- boolean update(ScanResult result) {
+ /**
+ * Update the AP with the given scan result.
+ *
+ * @param result the ScanResult to add to the AccessPoint scan cache
+ * @param evictOldScanResults whether stale scan results should be removed
+ * from the cache during this update process
+ * @return true if the scan result update caused a change in state which would impact ranking
+ * or AccessPoint rendering (e.g. wifi level, security)
+ */
+ boolean update(ScanResult result, boolean evictOldScanResults) {
if (matches(result)) {
int oldLevel = getLevel();
/* Add or update the scan result for the BSSID */
mScanResultCache.put(result.BSSID, result);
+ if (evictOldScanResults) evictOldScanResults();
updateSeen();
updateRssi();
int newLevel = getLevel();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index b299961..f8e2f8b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -145,7 +145,7 @@
Scanner mScanner;
@GuardedBy("mLock")
- static boolean sStaleScanResults = true;
+ private boolean mStaleScanResults = true;
public WifiTracker(Context context, WifiListener wifiListener,
boolean includeSaved, boolean includeScans) {
@@ -354,7 +354,7 @@
* <p>This should always be called when done with a WifiTracker (if startTracking was called) to
* ensure proper cleanup and prevent any further callbacks from occurring.
*
- * <p>Calling this method will set the {@link #sStaleScanResults} bit, which prevents
+ * <p>Calling this method will set the {@link #mStaleScanResults} bit, which prevents
* {@link WifiListener#onAccessPointsChanged()} callbacks from being invoked (until the bit
* is unset on the next SCAN_RESULTS_AVAILABLE_ACTION).
*/
@@ -372,7 +372,7 @@
mWorkHandler.removePendingMessages();
mMainHandler.removePendingMessages();
- sStaleScanResults = true;
+ mStaleScanResults = true;
}
}
@@ -478,14 +478,14 @@
/**
* Safely modify {@link #mInternalAccessPoints} by acquiring {@link #mLock} first.
*
- * <p>Will not perform the update if {@link #sStaleScanResults} is true
+ * <p>Will not perform the update if {@link #mStaleScanResults} is true
*/
private void updateAccessPoints() {
List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
final List<ScanResult> newScanResults = mWifiManager.getScanResults();
synchronized (mLock) {
- if(!sStaleScanResults) {
+ if(!mStaleScanResults) {
updateAccessPointsLocked(newScanResults, configs);
}
}
@@ -495,7 +495,7 @@
* Update the internal list of access points.
*
* <p>Do not called directly (except for forceUpdate), use {@link #updateAccessPoints()} which
- * respects {@link #sStaleScanResults}.
+ * respects {@link #mStaleScanResults}.
*/
@GuardedBy("mLock")
private void updateAccessPointsLocked(final List<ScanResult> newScanResults,
@@ -569,7 +569,8 @@
boolean found = false;
for (AccessPoint accessPoint : apMap.getAll(result.SSID)) {
- if (accessPoint.update(result)) {
+ // We want to evict old scan results if are current results are not stale
+ if (accessPoint.update(result, !mStaleScanResults)) {
found = true;
break;
}
@@ -642,7 +643,8 @@
for (int i = 0; i < N; i++) {
if (cache.get(i).matches(result)) {
AccessPoint ret = cache.remove(i);
- ret.update(result);
+ // evict old scan results only if we have fresh results
+ ret.update(result, !mStaleScanResults);
return ret;
}
}
@@ -842,7 +844,7 @@
// Only notify listeners of changes if we have fresh scan results, otherwise the
// UI will be updated with stale results. We want to copy the APs regardless,
// for instances where forceUpdate was invoked by the caller.
- if (sStaleScanResults) {
+ if (mStaleScanResults) {
copyAndNotifyListeners(false /*notifyListeners*/);
} else {
copyAndNotifyListeners(true /*notifyListeners*/);
@@ -897,7 +899,7 @@
switch (msg.what) {
case MSG_UPDATE_ACCESS_POINTS:
if (msg.arg1 == CLEAR_STALE_SCAN_RESULTS) {
- sStaleScanResults = false;
+ mStaleScanResults = false;
}
updateAccessPoints();
break;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 2f02b9b..88d3a32 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -247,7 +247,7 @@
scanResult.BSSID = "bssid";
scanResult.timestamp = SystemClock.elapsedRealtime() * 1000;
scanResult.capabilities = "";
- assertThat(ap.update(scanResult)).isTrue();
+ assertThat(ap.update(scanResult, true /* evict old scan results */)).isTrue();
assertThat(ap.getRssi()).isEqualTo(expectedRssi);
}
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 76d9823..df6587e 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -137,7 +137,6 @@
private Looper mMainLooper;
private int mOriginalScoringUiSettingValue;
- private boolean mOriginalStaleScanResultsValue;
@Before
public void setUp() {
@@ -213,7 +212,6 @@
Settings.Global.NETWORK_SCORING_UI_ENABLED,
1 /* enabled */);
- mOriginalStaleScanResultsValue = WifiTracker.sStaleScanResults;
}
@After
@@ -222,8 +220,6 @@
InstrumentationRegistry.getTargetContext().getContentResolver(),
Settings.Global.NETWORK_SCORING_UI_ENABLED,
mOriginalScoringUiSettingValue);
-
- WifiTracker.sStaleScanResults = mOriginalStaleScanResultsValue;
}
private static ScanResult buildScanResult1() {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
index bb21fb3..1f633da 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/GlobalActions.java
@@ -26,6 +26,8 @@
int VERSION = 1;
void showGlobalActions(GlobalActionsManager manager);
+ default void showShutdownUi(boolean isReboot, String reason) {
+ }
@ProvidesInterface(version = GlobalActionsManager.VERSION)
public interface GlobalActionsManager {
diff --git a/packages/SystemUI/res/drawable/ic_close_white_rounded.xml b/packages/SystemUI/res/drawable/ic_close_white_rounded.xml
new file mode 100644
index 0000000..ca37698
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_close_white_rounded.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18.3,5.71a0.996,0.996 0,0 0,-1.41 0L12,10.59 7.11,5.7A0.996,0.996 0,1 0,5.7 7.11L10.59,12 5.7,16.89a0.996,0.996 0,1 0,1.41 1.41L12,13.41l4.89,4.89a0.996,0.996 0,1 0,1.41 -1.41L13.41,12l4.89,-4.89c0.38,-0.38 0.38,-1.02 0,-1.4z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_minus.xml b/packages/SystemUI/res/drawable/ic_qs_minus.xml
index 6a3410a..ead6b03 100644
--- a/packages/SystemUI/res/drawable/ic_qs_minus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_minus.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2015 The Android Open Source Project
+ 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.
@@ -15,12 +15,10 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24.0dp"
- android:viewportHeight="48.0"
- android:viewportWidth="48.0"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
android:width="24.0dp" >
-
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M38.0,26.0L10.0,26.0l0.0,-4.0l28.0,0.0l0.0,4.0z" />
-
-</vector>
\ No newline at end of file
+ android:pathData="M18,13H6c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h12c0.55,0 1,0.45 1,1v0C19,12.55 18.55,13 18,13z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_plus.xml b/packages/SystemUI/res/drawable/ic_qs_plus.xml
index 393f51c..f1b19e1e 100644
--- a/packages/SystemUI/res/drawable/ic_qs_plus.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_plus.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2015 The Android Open Source Project
+ 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.
@@ -15,12 +15,10 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24.0dp"
- android:viewportHeight="48.0"
- android:viewportWidth="48.0"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
android:width="24.0dp" >
-
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M38.0,26.0L26.0,26.0l0.0,12.0l-4.0,0.0L22.0,26.0L10.0,26.0l0.0,-4.0l12.0,0.0L22.0,10.0l4.0,0.0l0.0,12.0l12.0,0.0l0.0,4.0z" />
-
-</vector>
\ No newline at end of file
+ android:pathData="M18,13h-5v5c0,0.55 -0.45,1 -1,1h0c-0.55,0 -1,-0.45 -1,-1v-5H6c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h5V6c0,-0.55 0.45,-1 1,-1h0c0.55,0 1,0.45 1,1v5h5c0.55,0 1,0.45 1,1v0C19,12.55 18.55,13 18,13z"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
index 370f89c..d73e2a4 100644
--- a/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
+++ b/packages/SystemUI/res/drawable/stat_sys_managed_profile_status.xml
@@ -22,19 +22,19 @@
The asset contains a briefcase symbol of 15.26dp x 13.6dp in the center.
-->
<path
- android:fillColor="@android:color/white"
+ android:fillColor="#ff000000"
android:pathData="M15.0815,4.5903 L15.0815,3.43636 L13.9276,2.2 L9.14696,2.2 L7.99302,3.43636
L7.99302,4.5903 L9.14696,4.5903 L9.14696,3.43636 L13.9276,3.43636
L13.9276,4.5903 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="#ff000000"
android:pathData="M18.0488,4.5903 L5.02575,4.5903 C4.36635,4.5903,3.87181,5.08485,3.87181,5.74424
L3.87181,9.28848 C3.87181,9.94788,4.36635,10.4424,5.02575,10.4424
L9.72393,10.4424 L9.72393,9.28848 L13.2682,9.28848 L13.2682,10.4424
L17.9664,10.4424 C18.6257,10.4424,19.1203,9.94788,19.1203,9.28848
L19.1203,5.74424 C19.2027,5.08485,18.6257,4.5903,18.0488,4.5903 Z" />
<path
- android:fillColor="@android:color/white"
+ android:fillColor="#ff000000"
android:pathData="M9.80635,12.8327 L9.80635,11.6788 L4.44878,11.6788 L4.44878,14.6461
C4.44878,15.3055,4.94332,15.8,5.60272,15.8 L17.3894,15.8
C18.0488,15.8,18.5433,15.3055,18.5433,14.6461 L18.5433,11.6788 L13.2682,11.6788
diff --git a/packages/SystemUI/res/layout/volume_zen_footer.xml b/packages/SystemUI/res/layout/volume_zen_footer.xml
index 38627b6..7ffcb1e 100644
--- a/packages/SystemUI/res/layout/volume_zen_footer.xml
+++ b/packages/SystemUI/res/layout/volume_zen_footer.xml
@@ -51,7 +51,7 @@
android:clickable="true"
android:contentDescription="@string/accessibility_desc_close"
android:scaleType="center"
- android:src="@drawable/ic_close_white" />
+ android:src="@drawable/ic_close_white_rounded" />
<TextView
android:id="@+id/zen_introduction_message"
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 5516983..3826bdd 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -59,7 +59,7 @@
android:clickable="true"
android:contentDescription="@string/accessibility_desc_close"
android:scaleType="center"
- android:src="@drawable/ic_close_white" />
+ android:src="@drawable/ic_close_white_rounded" />
<TextView
android:id="@+id/zen_introduction_message"
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 0b59e1d..11f3fc0 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -726,8 +726,8 @@
<string name="pip_phone_minimize" msgid="1079119422589131792">"Minimitza"</string>
<string name="pip_phone_close" msgid="8416647892889710330">"Tanca"</string>
<string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"Arrossega cap avall per ignorar-ho"</string>
- <string name="pip_menu_title" msgid="3328510504196964712">"Menú per a Imatge en imatge"</string>
- <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> està en imatge en imatge"</string>
+ <string name="pip_menu_title" msgid="3328510504196964712">"Menú per a Pantalla en pantalla"</string>
+ <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> està en pantalla en pantalla"</string>
<string name="pip_notification_message" msgid="4171698133469539591">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string>
<string name="pip_play" msgid="1417176722760265888">"Reprodueix"</string>
<string name="pip_pause" msgid="8881063404466476571">"Posa en pausa"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 1271a27..60510d3 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -67,12 +67,12 @@
<string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"Սարքի վրա այս պահին մուտք գործած օգտատերը չի կարող միացնել USB վրիպազերծումը: Այս գործառույթից օգտվելու համար մուտք գործեք ադմինիստրատորի հաշվով:"</string>
<string name="compat_mode_on" msgid="6623839244840638213">"Խոշորացնել` էկրանը լցնելու համար"</string>
<string name="compat_mode_off" msgid="4434467572461327898">"Ձգել` էկրանը լցնելու համար"</string>
- <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Պահում է էկրանի հանույթը…"</string>
- <string name="screenshot_saving_title" msgid="8242282144535555697">"Պահում է էկրանի հանույթը..."</string>
- <string name="screenshot_saving_text" msgid="2419718443411738818">"Էկրանի հանույթը պահվում է:"</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի հանույթը լուսանկարվել է:"</string>
+ <string name="screenshot_saving_ticker" msgid="7403652894056693515">"Պահում է էկրանի պատկերը…"</string>
+ <string name="screenshot_saving_title" msgid="8242282144535555697">"Պահում է էկրանի պատկերը..."</string>
+ <string name="screenshot_saving_text" msgid="2419718443411738818">"Էկրանի պատկերը պահվում է:"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"Էկրանի պատկերը լուսանկարվել է:"</string>
<string name="screenshot_saved_text" msgid="2685605830386712477">"Հպեք՝ էկրանի պատկերը տեսնելու համար:"</string>
- <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի հանույթը:"</string>
+ <string name="screenshot_failed_title" msgid="705781116746922771">"Չհաջողվեց լուսանկարել էկրանի պատկերը:"</string>
<string name="screenshot_failed_to_save_unknown_text" msgid="7887826345701753830">"Էկրանի պատկերը պահելիս խնդիր առաջացավ:"</string>
<string name="screenshot_failed_to_save_text" msgid="2592658083866306296">"Չհաջողվեց պահել էկրանի պատկերը սահմանափակ հիշողության պատճառով:"</string>
<string name="screenshot_failed_to_capture_text" msgid="173674476457581486">"Հավելվածը կամ ձեր կազմակերպությունը չի թույլատրում էկրանի պատկերի ստացումը"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
index 2bec2c7..58119f5 100644
--- a/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
+++ b/packages/SystemUI/src/com/android/systemui/RoundedCorners.java
@@ -24,6 +24,7 @@
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnLayoutChangeListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
@@ -69,12 +70,14 @@
mOverlay = LayoutInflater.from(mContext)
.inflate(R.layout.rounded_corners, null);
mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
+ mOverlay.setAlpha(0);
mOverlay.findViewById(R.id.right).setRotation(90);
mContext.getSystemService(WindowManager.class)
.addView(mOverlay, getWindowLayoutParams());
mBottomOverlay = LayoutInflater.from(mContext)
.inflate(R.layout.rounded_corners, null);
+ mBottomOverlay.setAlpha(0);
mBottomOverlay.findViewById(R.id.right).setRotation(180);
mBottomOverlay.findViewById(R.id.left).setRotation(270);
WindowManager.LayoutParams layoutParams = getWindowLayoutParams();
@@ -88,6 +91,23 @@
mDensity = metrics.density;
Dependency.get(TunerService.class).addTunable(this, SIZE);
+
+ mOverlay.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+ @Override
+ public void onLayoutChange(View v, int left, int top, int right, int bottom,
+ int oldLeft,
+ int oldTop, int oldRight, int oldBottom) {
+ mOverlay.removeOnLayoutChangeListener(this);
+ mOverlay.animate()
+ .alpha(1)
+ .setDuration(1000)
+ .start();
+ mBottomOverlay.animate()
+ .alpha(1)
+ .setDuration(1000)
+ .start();
+ }
+ });
}
private void setupPadding(int padding) {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
index f07027e..09a08f0 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsComponent.java
@@ -46,6 +46,11 @@
}
@Override
+ public void handleShowShutdownUi(boolean isReboot, String reason) {
+ mExtension.get().showShutdownUi(isReboot, reason);
+ }
+
+ @Override
public void handleShowGlobalActionsMenu() {
mExtension.get().showGlobalActions(this);
}
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 7799c01..33d5617 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -116,8 +116,6 @@
private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
- private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
-
private final Context mContext;
private final GlobalActionsManager mWindowManagerFuncs;
private final AudioManager mAudioManager;
@@ -682,10 +680,7 @@
/** {@inheritDoc} */
public void onClick(DialogInterface dialog, int which) {
Action item = mAdapter.getItem(which);
- if ((item instanceof PowerAction)
- || (item instanceof RestartAction)) {
- if (mDialog != null) mDialog.fadeOut();
- } else if (!(item instanceof SilentModeTriStateAction)) {
+ if (!(item instanceof SilentModeTriStateAction)) {
dialog.dismiss();
}
item.onPress();
@@ -1325,23 +1320,6 @@
.start();
}
- public void fadeOut() {
- mHardwareLayout.setTranslationX(0);
- mHardwareLayout.setAlpha(1);
- mListView.animate()
- .alpha(0)
- .translationX(getAnimTranslation())
- .setDuration(300)
- .setInterpolator(new LogAccelerateInterpolator())
- .setUpdateListener(animation -> {
- float frac = animation.getAnimatedFraction();
- float alpha = NotificationUtils.interpolate(
- ScrimController.GRADIENT_SCRIM_ALPHA, SHUTDOWN_SCRIM_ALPHA, frac);
- mGradientDrawable.setAlpha((int) (alpha * 255));
- })
- .start();
- }
-
private float getAnimTranslation() {
return getContext().getResources().getDimension(
com.android.systemui.R.dimen.global_actions_panel_width) / 2;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
index 08b7b71..2cf230c 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsImpl.java
@@ -14,17 +14,33 @@
package com.android.systemui.globalactions;
+import android.app.Dialog;
+import android.app.KeyguardManager;
+import android.app.WallpaperColors;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.Point;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+import com.android.internal.R;
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
+import com.android.internal.colorextraction.drawable.GradientDrawable;
+import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
-import com.android.systemui.R;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import android.content.Context;
-import android.support.v7.view.ContextThemeWrapper;
-
public class GlobalActionsImpl implements GlobalActions {
+ private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
+
private final Context mContext;
private final KeyguardMonitor mKeyguardMonitor;
private final DeviceProvisionedController mDeviceProvisionedController;
@@ -44,4 +60,51 @@
mGlobalActions.showDialog(mKeyguardMonitor.isShowing(),
mDeviceProvisionedController.isDeviceProvisioned());
}
+
+ @Override
+ public void showShutdownUi(boolean isReboot, String reason) {
+ GradientDrawable background = new GradientDrawable(mContext);
+ background.setAlpha((int) (SHUTDOWN_SCRIM_ALPHA * 255));
+
+ Dialog d = new Dialog(mContext,
+ com.android.systemui.R.style.Theme_SystemUI_Dialog_GlobalActions);
+ // Window initialization
+ Window window = d.getWindow();
+ window.getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
+ window.getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
+ window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
+ window.requestFeature(Window.FEATURE_NO_TITLE);
+ window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
+ | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
+ window.addFlags(
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+ | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+ | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
+ window.setBackgroundDrawable(background);
+ window.setWindowAnimations(R.style.Animation_Toast);
+
+ d.setContentView(R.layout.shutdown_dialog);
+ d.setCancelable(false);
+
+ int color = Utils.getColorAttr(mContext, com.android.systemui.R.attr.wallpaperTextColor);
+ boolean onKeyguard = mContext.getSystemService(
+ KeyguardManager.class).isKeyguardLocked();
+
+ ProgressBar bar = d.findViewById(R.id.progress);
+ bar.getIndeterminateDrawable().setTint(color);
+ TextView message = d.findViewById(R.id.text1);
+ message.setTextColor(color);
+ if (isReboot) message.setText(R.string.reboot_to_reset_message);
+
+ Point displaySize = new Point();
+ mContext.getDisplay().getRealSize(displaySize);
+ GradientColors colors = Dependency.get(SysuiColorExtractor.class).getColors(
+ onKeyguard ? WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM);
+ background.setColors(colors, false);
+ background.setScreenSize(displaySize.x, displaySize.y);
+
+ d.show();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
index 1240e05..cc7798e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
+++ b/packages/SystemUI/src/com/android/systemui/recents/IRecentsSystemUserCallbacks.aidl
@@ -31,4 +31,5 @@
void sendRecentsDrawnEvent();
void sendDockingTopTaskEvent(int dragMode, in Rect initialRect);
void sendLaunchRecentsEvent();
+ void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index de2ace4..86dde54 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -54,9 +54,11 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
+import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
+import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
import com.android.systemui.recents.events.component.ShowUserToastEvent;
import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -612,6 +614,14 @@
}
});
}
+
+ // This will catch the cases when a user launches from recents to another app
+ // (and vice versa) that is not in the recents stack (such as home or bugreport) and it
+ // would not reset the wait for transition flag. This will catch it and make sure that the
+ // flag is reset.
+ if (!event.visible) {
+ mImpl.setWaitingForTransitionStart(false);
+ }
}
/**
@@ -684,6 +694,11 @@
}
}
+ public final void onBusEvent(LaunchTaskFailedEvent event) {
+ // Reset the transition when tasks fail to launch
+ mImpl.setWaitingForTransitionStart(false);
+ }
+
public final void onBusEvent(ConfigurationChangedEvent event) {
// Update the configuration for the Recents component when the activity configuration
// changes as well
@@ -711,6 +726,25 @@
}
}
+ public final void onBusEvent(SetWaitingForTransitionStartEvent event) {
+ int processUser = sSystemServicesProxy.getProcessUser();
+ if (sSystemServicesProxy.isSystemUser(processUser)) {
+ mImpl.setWaitingForTransitionStart(event.waitingForTransitionStart);
+ } else {
+ postToSystemUser(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mUserToSystemCallbacks.setWaitingForTransitionStartEvent(
+ event.waitingForTransitionStart);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Callback failed", e);
+ }
+ }
+ });
+ }
+ }
+
/**
* Attempts to register with the system user.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 7cd93bb..86e93fd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -24,12 +24,11 @@
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
import android.app.ActivityOptions;
+import android.app.ActivityOptions.OnAnimationStartedListener;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -208,6 +207,20 @@
protected static RecentsTaskLoadPlan sInstanceLoadPlan;
// Stores the last pinned task time
protected static long sLastPipTime = -1;
+ // Stores whether we are waiting for a transition to/from recents to start. During this time,
+ // we disallow the user from manually toggling recents until the transition has started.
+ private static boolean mWaitingForTransitionStart = false;
+ // Stores whether or not the user toggled while we were waiting for a transition to/from
+ // recents. In this case, we defer the toggle state until then and apply it immediately after.
+ private static boolean mToggleFollowingTransitionStart = true;
+
+ private ActivityOptions.OnAnimationStartedListener mResetToggleFlagListener =
+ new OnAnimationStartedListener() {
+ @Override
+ public void onAnimationStarted() {
+ setWaitingForTransitionStart(false);
+ }
+ };
protected Context mContext;
protected Handler mHandler;
@@ -365,6 +378,11 @@
return;
}
+ if (mWaitingForTransitionStart) {
+ mToggleFollowingTransitionStart = true;
+ return;
+ }
+
mDraggingInRecents = false;
mLaunchedWhileDocking = false;
mTriggeredFromAltTab = false;
@@ -638,6 +656,18 @@
}
}
+ public void setWaitingForTransitionStart(boolean waitingForTransitionStart) {
+ if (mWaitingForTransitionStart == waitingForTransitionStart) {
+ return;
+ }
+
+ mWaitingForTransitionStart = waitingForTransitionStart;
+ if (!waitingForTransitionStart && mToggleFollowingTransitionStart) {
+ toggleRecents(DividerView.INVALID_RECENTS_GROW_TARGET);
+ }
+ mToggleFollowingTransitionStart = false;
+ }
+
/**
* Returns the preloaded load plan and invalidates it.
*/
@@ -865,8 +895,9 @@
}
AppTransitionAnimationSpec[] specsArray = new AppTransitionAnimationSpec[specs.size()];
specs.toArray(specsArray);
+
return new Pair<>(ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
- specsArray, mHandler, null, this), null);
+ specsArray, mHandler, mResetToggleFlagListener, this), null);
} else {
// Update the destination rect
Task toTask = new Task();
@@ -884,8 +915,10 @@
return Lists.newArrayList(new AppTransitionAnimationSpec(
toTask.key.id, thumbnail, rect));
});
+
return new Pair<>(ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
- mHandler, future.getFuture(), null, false /* scaleUp */), future);
+ mHandler, future.getFuture(), mResetToggleFlagListener, false /* scaleUp */),
+ future);
}
}
@@ -991,6 +1024,10 @@
launchState.launchedToTaskId = runningTaskId;
launchState.launchedWithAltTab = mTriggeredFromAltTab;
+ // Disable toggling of recents between starting the activity and it is visible and the app
+ // has started its transition into recents.
+ setWaitingForTransitionStart(useThumbnailTransition);
+
// Preload the icon (this will be a null-op if we have preloaded the icon already in
// preloadRecents())
preloadIcon(runningTaskId);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
index 3921a20..1285626 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsSystemUser.java
@@ -29,6 +29,7 @@
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.DockedTopTaskEvent;
import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
+import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
import com.android.systemui.recents.misc.ForegroundThread;
@@ -105,4 +106,10 @@
public void sendLaunchRecentsEvent() throws RemoteException {
EventBus.getDefault().post(new RecentsActivityStartingEvent());
}
+
+ @Override
+ public void setWaitingForTransitionStartEvent(boolean waitingForTransitionStart) {
+ EventBus.getDefault().post(new SetWaitingForTransitionStartEvent(
+ waitingForTransitionStart));
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java
new file mode 100644
index 0000000..d9cf5fb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/component/SetWaitingForTransitionStartEvent.java
@@ -0,0 +1,31 @@
+/*
+ * 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.recents.events.component;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when we are setting/resetting the flag to wait for the transition to start.
+ */
+public class SetWaitingForTransitionStartEvent extends EventBus.Event {
+
+ public final boolean waitingForTransitionStart;
+
+ public SetWaitingForTransitionStartEvent(boolean waitingForTransitionStart) {
+ this.waitingForTransitionStart = waitingForTransitionStart;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 968b77f..67685b8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -54,6 +54,7 @@
import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
+import com.android.systemui.recents.events.component.SetWaitingForTransitionStartEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
@@ -117,31 +118,58 @@
final Rect windowRect = Recents.getSystemServices().getWindowRect();
transitionFuture = getAppTransitionFuture(
() -> composeAnimationSpecs(task, stackView, destinationStack, windowRect));
- animStartedListener = () -> {
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
- EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
- stackView.cancelAllTaskViewAnimations();
+ animStartedListener = new OnAnimationStartedListener() {
+ private boolean mHandled;
- if (screenPinningRequested) {
- // Request screen pinning after the animation runs
- mStartScreenPinningRunnable.taskId = task.key.id;
- mHandler.postDelayed(mStartScreenPinningRunnable, 350);
+ @Override
+ public void onAnimationStarted() {
+ if (mHandled) {
+ return;
+ }
+ mHandled = true;
+
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+ EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ stackView.cancelAllTaskViewAnimations();
+
+ if (screenPinningRequested) {
+ // Request screen pinning after the animation runs
+ mStartScreenPinningRunnable.taskId = task.key.id;
+ mHandler.postDelayed(mStartScreenPinningRunnable, 350);
+ }
+
+ // Reset the state where we are waiting for the transition to start
+ EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
}
};
} else {
// This is only the case if the task is not on screen (scrolled offscreen for example)
transitionFuture = null;
- animStartedListener = () -> {
- // If we are launching into another task, cancel the previous task's
- // window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
- EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
- stackView.cancelAllTaskViewAnimations();
+ animStartedListener = new OnAnimationStartedListener() {
+ private boolean mHandled;
+
+ @Override
+ public void onAnimationStarted() {
+ if (mHandled) {
+ return;
+ }
+ mHandled = true;
+
+ // If we are launching into another task, cancel the previous task's
+ // window transition
+ EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(task));
+ EventBus.getDefault().send(new ExitRecentsWindowFirstAnimationFrameEvent());
+ stackView.cancelAllTaskViewAnimations();
+
+ // Reset the state where we are waiting for the transition to start
+ EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(false));
+ }
};
}
+ EventBus.getDefault().send(new SetWaitingForTransitionStartEvent(true));
final ActivityOptions opts = ActivityOptions.makeMultiThumbFutureAspectScaleAnimation(mContext,
mHandler, transitionFuture != null ? transitionFuture.future : null,
animStartedListener, true /* scaleUp */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index f9407dd..2f4cd0d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -79,6 +79,7 @@
private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS = 32 << MSG_SHIFT;
private static final int MSG_HANDLE_SYSTEM_KEY = 33 << MSG_SHIFT;
private static final int MSG_SHOW_GLOBAL_ACTIONS = 34 << MSG_SHIFT;
+ private static final int MSG_SHOW_SHUTDOWN_UI = 35 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -136,6 +137,7 @@
default void handleSystemKey(int arg1) { }
default void handleShowGlobalActionsMenu() { }
+ default void handleShowShutdownUi(boolean isReboot, String reason) { }
}
@VisibleForTesting
@@ -429,6 +431,15 @@
}
}
+ @Override
+ public void showShutdownUi(boolean isReboot, String reason) {
+ synchronized (mLock) {
+ mHandler.removeMessages(MSG_SHOW_SHUTDOWN_UI);
+ mHandler.obtainMessage(MSG_SHOW_SHUTDOWN_UI, isReboot ? 1 : 0, 0, reason)
+ .sendToTarget();
+ }
+ }
+
private final class H extends Handler {
private H(Looper l) {
super(l);
@@ -610,6 +621,11 @@
mCallbacks.get(i).handleShowGlobalActionsMenu();
}
break;
+ case MSG_SHOW_SHUTDOWN_UI:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).handleShowShutdownUi(msg.arg1 != 0, (String) msg.obj);
+ }
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index 881de67..a6691b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -50,6 +50,7 @@
import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.policy.UserSwitcherController;
/**
@@ -346,6 +347,9 @@
applyDarkness(R.id.signal_cluster, tintArea, intensity, iconColor);
applyDarkness(R.id.battery, tintArea, intensity, iconColor);
applyDarkness(R.id.clock, tintArea, intensity, iconColor);
+ // Reload user avatar
+ ((UserInfoControllerImpl) Dependency.get(UserInfoController.class))
+ .onDensityOrFontScaleChanged();
}
private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 479b945..1d64480 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -543,7 +543,7 @@
mKeyguardFadingOutInProgress = false;
mAnimatingDozeUnlock = false;
}
- if (mWakingUpFromAodAnimationRunning) {
+ if (mWakingUpFromAodAnimationRunning && !mDeferFinishedListener) {
mWakingUpFromAodAnimationRunning = false;
mWakingUpFromAodInProgress = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 6f710da..06cdfae 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -103,7 +103,7 @@
private boolean mDeferScrimFadeOut;
// Dismiss action to be launched when we stop dozing or the keyguard is gone.
- private PendingDismissActionRequest mPendingDismissAction;
+ private DismissWithActionRequest mPendingWakeupAction;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@@ -174,7 +174,7 @@
private void hideBouncer(boolean destroyView) {
mBouncer.hide(destroyView);
- cancelPendingDismissAction();
+ cancelPendingWakeupAction();
}
private void showBouncer() {
@@ -187,11 +187,11 @@
public void dismissWithAction(OnDismissAction r, Runnable cancelAction,
boolean afterKeyguardGone) {
if (mShowing) {
- cancelPendingDismissAction();
+ cancelPendingWakeupAction();
// If we're dozing, this needs to be delayed until after we wake up - unless we're
// wake-and-unlocking, because there dozing will last until the end of the transition.
if (mDozing && !isWakeAndUnlocking()) {
- mPendingDismissAction = new PendingDismissActionRequest(
+ mPendingWakeupAction = new DismissWithActionRequest(
r, cancelAction, afterKeyguardGone);
return;
}
@@ -280,7 +280,7 @@
updateStates();
if (!dozing) {
- launchPendingDismissAction();
+ launchPendingWakeupAction();
}
}
}
@@ -357,7 +357,7 @@
*/
public void hide(long startTime, long fadeoutDuration) {
mShowing = false;
- launchPendingDismissAction();
+ launchPendingWakeupAction();
if (KeyguardUpdateMonitor.getInstance(mContext).needsSlowUnlockTransition()) {
fadeoutDuration = KEYGUARD_DISMISS_DURATION_LOCKED;
@@ -685,9 +685,9 @@
return mStatusBar.getStatusBarView().getViewRootImpl();
}
- public void launchPendingDismissAction() {
- PendingDismissActionRequest request = mPendingDismissAction;
- mPendingDismissAction = null;
+ public void launchPendingWakeupAction() {
+ DismissWithActionRequest request = mPendingWakeupAction;
+ mPendingWakeupAction = null;
if (request != null) {
if (mShowing) {
dismissWithAction(request.dismissAction, request.cancelAction,
@@ -698,20 +698,20 @@
}
}
- public void cancelPendingDismissAction() {
- PendingDismissActionRequest request = mPendingDismissAction;
- mPendingDismissAction = null;
+ public void cancelPendingWakeupAction() {
+ DismissWithActionRequest request = mPendingWakeupAction;
+ mPendingWakeupAction = null;
if (request != null && request.cancelAction != null) {
request.cancelAction.run();
}
}
- private static class PendingDismissActionRequest {
+ private static class DismissWithActionRequest {
final OnDismissAction dismissAction;
final Runnable cancelAction;
final boolean afterKeyguardGone;
- PendingDismissActionRequest(OnDismissAction dismissAction, Runnable cancelAction,
+ DismissWithActionRequest(OnDismissAction dismissAction, Runnable cancelAction,
boolean afterKeyguardGone) {
this.dismissAction = dismissAction;
this.cancelAction = cancelAction;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
index b1e4b03..527addf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -131,6 +131,7 @@
final int userId = userInfo.id;
final boolean isGuest = userInfo.isGuest();
final String userName = userInfo.name;
+ final boolean lightIcon = mContext.getThemeResId() != R.style.Theme_SystemUI_Light;
final Resources res = mContext.getResources();
final int avatarSize = Math.max(
@@ -154,7 +155,7 @@
.setIcon(rawAvatar).setBadgeIfManagedUser(mContext, userId).bake();
} else {
avatar = UserIcons.getDefaultUserIcon(isGuest? UserHandle.USER_NULL : userId,
- /* light= */ true);
+ lightIcon);
}
// If it's a single-user device, get the profile name, since the nickname is not
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 4bbe895..291ec1a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -3714,6 +3714,9 @@
* See {@link AmbientState#setDark}.
*/
public void setDark(boolean dark, boolean animate, @Nullable PointF touchWakeUpScreenLocation) {
+ if (mAmbientState.isDark() == dark) {
+ return;
+ }
mAmbientState.setDark(dark);
if (animate && mAnimationsEnabled) {
mDarkNeedsAnimation = true;
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index 28e3427..c4dc506 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -276,6 +276,42 @@
// Count of saved Passpoint providers device has ever connected to.
optional int32 num_passpoint_providers_successfully_connected = 63;
+
+ // Histogram counting instances of scans with N many ScanResults with unique ssids
+ repeated NumConnectableNetworksBucket total_ssids_in_scan_histogram = 64;
+
+ // Histogram counting instances of scans with N many ScanResults/bssids
+ repeated NumConnectableNetworksBucket total_bssids_in_scan_histogram = 65;
+
+ // Histogram counting instances of scans with N many unique open ssids
+ repeated NumConnectableNetworksBucket available_open_ssids_in_scan_histogram = 66;
+
+ // Histogram counting instances of scans with N many bssids for open networks
+ repeated NumConnectableNetworksBucket available_open_bssids_in_scan_histogram = 67;
+
+ // Histogram counting instances of scans with N many unique ssids for saved networks
+ repeated NumConnectableNetworksBucket available_saved_ssids_in_scan_histogram = 68;
+
+ // Histogram counting instances of scans with N many bssids for saved networks
+ repeated NumConnectableNetworksBucket available_saved_bssids_in_scan_histogram = 69;
+
+ // Histogram counting instances of scans with N many unique SSIDs for open or saved networks
+ repeated NumConnectableNetworksBucket available_open_or_saved_ssids_in_scan_histogram = 70;
+
+ // Histogram counting instances of scans with N many BSSIDs for open or saved networks
+ repeated NumConnectableNetworksBucket available_open_or_saved_bssids_in_scan_histogram = 71;
+
+ // Histogram counting instances of scans with N many ScanResults matching unique saved passpoint providers
+ repeated NumConnectableNetworksBucket available_saved_passpoint_provider_profiles_in_scan_histogram = 72;
+
+ // Histogram counting instances of scans with N many ScanResults BSSIDs matching a saved passpoint provider
+ repeated NumConnectableNetworksBucket available_saved_passpoint_provider_bssids_in_scan_histogram = 73;
+
+ // Counts the number of AllSingleScanLister.onResult calls with a full band scan result
+ optional int32 full_band_all_single_scan_listener_results = 74;
+
+ // Counts the number of AllSingleScanLister.onResult calls with a partial (channels) scan result
+ optional int32 partial_all_single_scan_listener_results = 75;
}
// Information that gets logged for every WiFi connection.
@@ -883,3 +919,11 @@
}
}
+// Data point used to build 'Number of Connectable Network' histograms
+message NumConnectableNetworksBucket {
+ // Number of connectable networks seen in a scan result
+ optional int32 num_connectable_networks = 1 [default = 0];
+
+ // Number of scan results with num_connectable_networks
+ optional int32 count = 2 [default = 0];
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 38327bc..84017e7 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13367,7 +13367,6 @@
final ActivityRecord r = ActivityRecord.isInStackLocked(token);
if (r != null) {
final ActivityOptions activityOptions = r.pendingOptions;
- r.pendingOptions = null;
return activityOptions == null ? null : activityOptions.toBundle();
}
return null;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index b0be8f7..015f7f0 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -832,20 +832,23 @@
// functions are ready to use.
//
// For more explanation, see b/62552150 .
- if (usbConnected && !usbConfigured) {
- // Nothing for us to do here.
- // TODO: consider ignoring DISCONNECTED broadcasts as well.
- return;
- }
-
synchronized (Tethering.this.mPublicSync) {
+ // Always record the state of RNDIS.
mRndisEnabled = rndisEnabled;
+
+ if (usbConnected && !usbConfigured) {
+ // Nothing to do here (only CONNECTED, not yet CONFIGURED).
+ return;
+ }
+
// start tethering if we have a request pending
if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
tetherMatchingInterfaces(
IControlsTethering.STATE_TETHERED,
ConnectivityManager.TETHERING_USB);
}
+
+ // TODO: Figure out how to remove the need for this variable.
mUsbTetherRequested = false;
}
}
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index cdf25cf..11a4eb4 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -543,7 +543,9 @@
loadPropertiesFromResource(context, mProperties);
String lpp_profile = mProperties.getProperty("LPP_PROFILE");
// set the persist property LPP_PROFILE for the value
- SystemProperties.set(LPP_PROFILE, lpp_profile);
+ if (lpp_profile != null) {
+ SystemProperties.set(LPP_PROFILE, lpp_profile);
+ }
} else {
// reset the persist property
SystemProperties.set(LPP_PROFILE, "");
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index c1e820c..f8f8ffb 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -1235,6 +1235,7 @@
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setUserAuthenticationRequired(true)
.setUserAuthenticationValidityDurationSeconds(30)
+ .setCriticalToDeviceEncryption(true)
.build());
// Key imported, obtain a reference to it.
SecretKey keyStoreEncryptionKey = (SecretKey) keyStore.getKey(
diff --git a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
index 4981d5c..12b29cf 100644
--- a/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
+++ b/services/core/java/com/android/server/notification/NotificationIntrusivenessExtractor.java
@@ -58,6 +58,10 @@
}
}
+ if (!record.isRecentlyIntrusive()) {
+ return null;
+ }
+
return new RankingReconsideration(record.getKey(), HANG_TIME_MS) {
@Override
public void work() {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 1eabac1..a2fea49 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -8938,9 +8938,12 @@
}
}
- boolean updatedPkgBetter = false;
+ final boolean isUpdatedPkg = updatedPkg != null;
+ final boolean isUpdatedSystemPkg = isUpdatedPkg
+ && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0;
+ boolean isUpdatedPkgBetter = false;
// First check if this is a system package that may involve an update
- if (updatedPkg != null && (policyFlags & PackageParser.PARSE_IS_SYSTEM) != 0) {
+ if (isUpdatedSystemPkg) {
// If new package is not located in "/system/priv-app" (e.g. due to an OTA),
// it needs to drop FLAG_PRIVILEGED.
if (locationIsPrivileged(scanFile)) {
@@ -8984,10 +8987,6 @@
updatedChildPkg.versionCode = pkg.mVersionCode;
}
}
-
- throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at "
- + scanFile + " ignored: updated version " + ps.versionCode
- + " better than this " + pkg.mVersionCode);
} else {
// The current app on the system partition is better than
// what we have updated to on the data partition; switch
@@ -9014,12 +9013,44 @@
synchronized (mPackages) {
mSettings.enableSystemPackageLPw(ps.name);
}
- updatedPkgBetter = true;
+ isUpdatedPkgBetter = true;
}
}
}
- if (updatedPkg != null) {
+ String resourcePath = null;
+ String baseResourcePath = null;
+ if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !isUpdatedPkgBetter) {
+ if (ps != null && ps.resourcePathString != null) {
+ resourcePath = ps.resourcePathString;
+ baseResourcePath = ps.resourcePathString;
+ } else {
+ // Should not happen at all. Just log an error.
+ Slog.e(TAG, "Resource path not set for package " + pkg.packageName);
+ }
+ } else {
+ resourcePath = pkg.codePath;
+ baseResourcePath = pkg.baseCodePath;
+ }
+
+ // Set application objects path explicitly.
+ pkg.setApplicationVolumeUuid(pkg.volumeUuid);
+ pkg.setApplicationInfoCodePath(pkg.codePath);
+ pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
+ pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
+ pkg.setApplicationInfoResourcePath(resourcePath);
+ pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
+ pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
+
+ // throw an exception if we have an update to a system application, but, it's not more
+ // recent than the package we've already scanned
+ if (isUpdatedSystemPkg && !isUpdatedPkgBetter) {
+ throw new PackageManagerException(Log.WARN, "Package " + ps.name + " at "
+ + scanFile + " ignored: updated version " + ps.versionCode
+ + " better than this " + pkg.mVersionCode);
+ }
+
+ if (isUpdatedPkg) {
// An updated system app will not have the PARSE_IS_SYSTEM flag set
// initially
policyFlags |= PackageParser.PARSE_IS_SYSTEM;
@@ -9039,7 +9070,7 @@
* same name installed earlier.
*/
boolean shouldHideSystemApp = false;
- if (updatedPkg == null && ps != null
+ if (!isUpdatedPkg && ps != null
&& (policyFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0 && !isSystemApp(ps)) {
/*
* Check to make sure the signatures match first. If they don't,
@@ -9094,31 +9125,6 @@
}
}
- // TODO: extend to support forward-locked splits
- String resourcePath = null;
- String baseResourcePath = null;
- if ((policyFlags & PackageParser.PARSE_FORWARD_LOCK) != 0 && !updatedPkgBetter) {
- if (ps != null && ps.resourcePathString != null) {
- resourcePath = ps.resourcePathString;
- baseResourcePath = ps.resourcePathString;
- } else {
- // Should not happen at all. Just log an error.
- Slog.e(TAG, "Resource path not set for package " + pkg.packageName);
- }
- } else {
- resourcePath = pkg.codePath;
- baseResourcePath = pkg.baseCodePath;
- }
-
- // Set application objects path explicitly.
- pkg.setApplicationVolumeUuid(pkg.volumeUuid);
- pkg.setApplicationInfoCodePath(pkg.codePath);
- pkg.setApplicationInfoBaseCodePath(pkg.baseCodePath);
- pkg.setApplicationInfoSplitCodePaths(pkg.splitCodePaths);
- pkg.setApplicationInfoResourcePath(resourcePath);
- pkg.setApplicationInfoBaseResourcePath(baseResourcePath);
- pkg.setApplicationInfoSplitResourcePaths(pkg.splitCodePaths);
-
final int userId = ((user == null) ? 0 : user.getIdentifier());
if (ps != null && ps.getInstantApp(userId)) {
scanFlags |= SCAN_AS_INSTANT_APP;
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index e894275..0f61171 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -57,7 +57,9 @@
import android.widget.TextView;
import com.android.internal.telephony.ITelephony;
+import com.android.server.LocalServices;
import com.android.server.pm.PackageManagerService;
+import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.File;
import java.io.IOException;
@@ -288,6 +290,9 @@
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_update_prepare));
} else {
+ if (showSysuiReboot()) {
+ return null;
+ }
pd.setIndeterminate(true);
pd.setMessage(context.getText(
com.android.internal.R.string.reboot_to_update_reboot));
@@ -296,39 +301,12 @@
// Factory reset path. Set the dialog message accordingly.
pd.setTitle(context.getText(com.android.internal.R.string.reboot_to_reset_title));
pd.setMessage(context.getText(
- com.android.internal.R.string.reboot_to_reset_message));
+ com.android.internal.R.string.reboot_to_reset_message));
pd.setIndeterminate(true);
- } else if (mReason != null && mReason.equals(PowerManager.SHUTDOWN_USER_REQUESTED)) {
- Dialog d = new Dialog(context);
- d.setContentView(com.android.internal.R.layout.shutdown_dialog);
- d.setCancelable(false);
-
- int color;
- try {
- boolean onKeyguard = context.getSystemService(
- KeyguardManager.class).isKeyguardLocked();
- WallpaperColors currentColors = context.getSystemService(WallpaperManager.class)
- .getWallpaperColors(onKeyguard ?
- WallpaperManager.FLAG_LOCK : WallpaperManager.FLAG_SYSTEM);
- color = currentColors != null &&
- (currentColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT)
- != 0 ?
- Color.BLACK : Color.WHITE;
- } catch (Exception e) {
- color = Color.WHITE;
- }
-
- ProgressBar bar = d.findViewById(com.android.internal.R.id.progress);
- bar.getIndeterminateDrawable().setTint(color);
- ((TextView) d.findViewById(com.android.internal.R.id.text1)).setTextColor(color);
- d.getWindow().getAttributes().width = ViewGroup.LayoutParams.MATCH_PARENT;
- d.getWindow().getAttributes().height = ViewGroup.LayoutParams.MATCH_PARENT;
- d.getWindow().setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY);
- d.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
- d.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
- d.show();
- return null;
} else {
+ if (showSysuiReboot()) {
+ return null;
+ }
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
pd.setIndeterminate(true);
@@ -340,6 +318,23 @@
return pd;
}
+ private static boolean showSysuiReboot() {
+ Log.d(TAG, "Attempting to use SysUI shutdown UI");
+ try {
+ StatusBarManagerInternal service = LocalServices.getService(
+ StatusBarManagerInternal.class);
+ if (service.showShutdownUi(mReboot, mReason)) {
+ // Sysui will handle shutdown UI.
+ Log.d(TAG, "SysUI handling shutdown UI");
+ return true;
+ }
+ } catch (Exception e) {
+ // If anything went wrong, ignore it and use fallback ui
+ }
+ Log.d(TAG, "SysUI is unavailable");
+ return false;
+ }
+
private static void beginShutdownSequence(Context context) {
synchronized (sIsStartedGuard) {
if (sIsStarted) {
@@ -561,7 +556,7 @@
Thread t = new Thread() {
public void run() {
boolean nfcOff;
- boolean bluetoothOff;
+ boolean bluetoothReadyForShutdown;
boolean radioOff;
final INfcAdapter nfc =
@@ -585,15 +580,15 @@
}
try {
- bluetoothOff = bluetooth == null ||
+ bluetoothReadyForShutdown = bluetooth == null ||
bluetooth.getState() == BluetoothAdapter.STATE_OFF;
- if (!bluetoothOff) {
+ if (!bluetoothReadyForShutdown) {
Log.w(TAG, "Disabling Bluetooth...");
bluetooth.disable(mContext.getPackageName(), false); // disable but don't persist new state
}
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
- bluetoothOff = true;
+ bluetoothReadyForShutdown = true;
}
try {
@@ -618,14 +613,19 @@
sInstance.setRebootProgress(status, null);
}
- if (!bluetoothOff) {
+ if (!bluetoothReadyForShutdown) {
try {
- bluetoothOff = bluetooth.getState() == BluetoothAdapter.STATE_OFF;
+ // BLE only mode can happen when BT is turned off
+ // We will continue shutting down in such case
+ bluetoothReadyForShutdown =
+ bluetooth.getState() == BluetoothAdapter.STATE_OFF ||
+ bluetooth.getState() == BluetoothAdapter.STATE_BLE_TURNING_OFF ||
+ bluetooth.getState() == BluetoothAdapter.STATE_BLE_ON;
} catch (RemoteException ex) {
Log.e(TAG, "RemoteException during bluetooth shutdown", ex);
- bluetoothOff = true;
+ bluetoothReadyForShutdown = true;
}
- if (bluetoothOff) {
+ if (bluetoothReadyForShutdown) {
Log.i(TAG, "Bluetooth turned off.");
}
}
@@ -652,7 +652,7 @@
}
}
- if (radioOff && bluetoothOff && nfcOff) {
+ if (radioOff && bluetoothReadyForShutdown && nfcOff) {
Log.i(TAG, "NFC, Radio and Bluetooth shutdown complete.");
done[0] = true;
break;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index 5e322da..866fdad 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -80,6 +80,8 @@
void setGlobalActionsListener(GlobalActionsListener listener);
void showGlobalActions();
+ boolean showShutdownUi(boolean isReboot, String requestString);
+
public interface GlobalActionsListener {
/**
* Called when sysui starts and connects its status bar, or when the status bar binder
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 2df0f10..5b252e8 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -36,6 +36,7 @@
import android.util.ArrayMap;
import android.util.Slog;
+import com.android.internal.R;
import com.android.internal.statusbar.IStatusBar;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.statusbar.NotificationVisibility;
@@ -329,6 +330,20 @@
} catch (RemoteException ex) {}
}
}
+
+ @Override
+ public boolean showShutdownUi(boolean isReboot, String reason) {
+ if (!mContext.getResources().getBoolean(R.bool.config_showSysuiShutdown)) {
+ return false;
+ }
+ if (mBar != null) {
+ try {
+ mBar.showShutdownUi(isReboot, reason);
+ return true;
+ } catch (RemoteException ex) {}
+ }
+ return false;
+ }
};
// ================================================================================
diff --git a/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java b/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java
index 0508fdf..a12c2c4 100644
--- a/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java
+++ b/services/core/java/com/android/server/wm/RemoteSurfaceTrace.java
@@ -32,7 +32,7 @@
// the surface control.
//
// See cts/hostsidetests/../../SurfaceTraceReceiver.java for parsing side.
-class RemoteSurfaceTrace extends SurfaceControl {
+class RemoteSurfaceTrace extends SurfaceControlWithBackground {
static final String TAG = "RemoteSurfaceTrace";
final FileDescriptor mWriteFd;
@@ -41,7 +41,8 @@
final WindowManagerService mService;
final WindowState mWindow;
- RemoteSurfaceTrace(FileDescriptor fd, SurfaceControl wrapped, WindowState window) {
+ RemoteSurfaceTrace(FileDescriptor fd, SurfaceControlWithBackground wrapped,
+ WindowState window) {
super(wrapped);
mWriteFd = fd;
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 40528d0..7bcad9f 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -52,6 +52,7 @@
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_NONE;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
@@ -760,16 +761,21 @@
if (mUpdateRotation) {
if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
-
- for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
- final DisplayContent displayContent = mChildren.get(displayNdx);
- final int displayId = displayContent.getDisplayId();
- if (displayContent.updateRotationUnchecked(false /* inTransaction */)) {
- mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
- } else if (displayId == DEFAULT_DISPLAY) {
- // TODO(multi-display): Track rotation updates for different displays separately
- mUpdateRotation = false;
- }
+ // TODO(multi-display): Update rotation for different displays separately.
+ final int displayId = defaultDisplay.getDisplayId();
+ if (defaultDisplay.updateRotationUnchecked(false /* inTransaction */)) {
+ mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, displayId).sendToTarget();
+ } else {
+ mUpdateRotation = false;
+ }
+ // Update rotation of VR virtual display separately. Currently this is the only kind of
+ // secondary display that can be rotated because of the single-display limitations in
+ // PhoneWindowManager.
+ final DisplayContent vrDisplay = mService.mVr2dDisplayId != INVALID_DISPLAY
+ ? getDisplayContent(mService.mVr2dDisplayId) : null;
+ if (vrDisplay != null && vrDisplay.updateRotationUnchecked(false /* inTransaction */)) {
+ mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mService.mVr2dDisplayId)
+ .sendToTarget();
}
}
diff --git a/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
new file mode 100644
index 0000000..85ea3c0
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceControlWithBackground.java
@@ -0,0 +1,311 @@
+/*
+ * 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.server.wm;
+
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.view.Surface;
+import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+/**
+ * SurfaceControl extension that has background sized to match its container.
+ */
+class SurfaceControlWithBackground extends SurfaceControl {
+ // SurfaceControl that holds the background behind opaque letterboxed app windows.
+ private SurfaceControl mBackgroundControl;
+
+ // Flags that define whether the background should be shown.
+ private boolean mOpaque;
+ private boolean mVisible;
+
+ // Way to communicate with corresponding window.
+ private WindowSurfaceController mWindowSurfaceController;
+
+ // Rect to hold task bounds when computing metrics for background.
+ private Rect mTmpContainerRect = new Rect();
+
+ // Last metrics applied to the main SurfaceControl.
+ private float mLastWidth, mLastHeight;
+ private float mLastDsDx = 1, mLastDsDy = 1;
+ private float mLastX, mLastY;
+
+ public SurfaceControlWithBackground(SurfaceControlWithBackground other) {
+ super(other);
+ mBackgroundControl = other.mBackgroundControl;
+ mOpaque = other.mOpaque;
+ mVisible = other.mVisible;
+ mWindowSurfaceController = other.mWindowSurfaceController;
+ }
+
+ public SurfaceControlWithBackground(SurfaceSession s, String name, int w, int h, int format,
+ int flags, int windowType, int ownerUid,
+ WindowSurfaceController windowSurfaceController) throws OutOfResourcesException {
+ super(s, name, w, h, format, flags, windowType, ownerUid);
+
+ // We should only show background when the window is letterboxed in a task.
+ if (!windowSurfaceController.mAnimator.mWin.isLetterboxedAppWindow()) {
+ return;
+ }
+ mWindowSurfaceController = windowSurfaceController;
+ mLastWidth = w;
+ mLastHeight = h;
+ mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ mBackgroundControl = new SurfaceControl(s, "Background for - " + name,
+ mTmpContainerRect.width(), mTmpContainerRect.height(), PixelFormat.OPAQUE,
+ flags | SurfaceControl.FX_SURFACE_DIM);
+ }
+
+ @Override
+ public void setAlpha(float alpha) {
+ super.setAlpha(alpha);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.setAlpha(alpha);
+ }
+
+ @Override
+ public void setLayer(int zorder) {
+ super.setLayer(zorder);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ // TODO: Use setRelativeLayer(Integer.MIN_VALUE) when it's fixed.
+ mBackgroundControl.setLayer(zorder - 1);
+ }
+
+ @Override
+ public void setPosition(float x, float y) {
+ super.setPosition(x, y);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mLastX = x;
+ mLastY = y;
+ updateBgPosition();
+ }
+
+ private void updateBgPosition() {
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame;
+ final float offsetX = (mTmpContainerRect.left - winFrame.left) * mLastDsDx;
+ final float offsetY = (mTmpContainerRect.top - winFrame.top) * mLastDsDy;
+ mBackgroundControl.setPosition(mLastX + offsetX, mLastY + offsetY);
+ }
+
+ @Override
+ public void setSize(int w, int h) {
+ super.setSize(w, h);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mLastWidth = w;
+ mLastHeight = h;
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ mBackgroundControl.setSize(mTmpContainerRect.width(), mTmpContainerRect.height());
+ }
+
+ @Override
+ public void setWindowCrop(Rect crop) {
+ super.setWindowCrop(crop);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ if (crop.width() < mLastWidth || crop.height() < mLastHeight) {
+ // We're animating and cropping window, compute the appropriate crop for background.
+ calculateBgCrop(crop);
+ mBackgroundControl.setWindowCrop(mTmpContainerRect);
+ } else {
+ // When not animating just set crop to container rect.
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ mBackgroundControl.setWindowCrop(mTmpContainerRect);
+ }
+ }
+
+ @Override
+ public void setFinalCrop(Rect crop) {
+ super.setFinalCrop(crop);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ if (crop.width() < mLastWidth || crop.height() < mLastHeight) {
+ // We're animating and cropping window, compute the appropriate crop for background.
+ calculateBgCrop(crop);
+ mBackgroundControl.setFinalCrop(mTmpContainerRect);
+ } else {
+ // When not animating just set crop to container rect.
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ mBackgroundControl.setFinalCrop(mTmpContainerRect);
+ }
+ }
+
+ /** Compute background crop based on current animation progress for main surface control. */
+ private void calculateBgCrop(Rect crop) {
+ // Track overall progress of animation by computing cropped portion of status bar.
+ final Rect contentInsets = mWindowSurfaceController.mAnimator.mWin.mContentInsets;
+ float d = contentInsets.top == 0 ? 0 : (float) crop.top / contentInsets.top;
+
+ // Compute additional offset for the background when app window is positioned not at (0,0).
+ // E.g. landscape with navigation bar on the left.
+ final Rect winFrame = mWindowSurfaceController.mAnimator.mWin.mFrame;
+ final int offsetX = (int) (winFrame.left * mLastDsDx * d + 0.5);
+ final int offsetY = (int) (winFrame.top * mLastDsDy * d + 0.5);
+
+ // Compute new scaled width and height for background that will depend on current animation
+ // progress. Those consist of current crop rect for the main surface + scaled areas outside
+ // of letterboxed area.
+ // TODO: Because the progress is computed with low precision we're getting smaller values
+ // for background width/height then screen size at the end of the animation. Will round when
+ // the value is smaller then some empiric epsilon. However, this should be fixed by
+ // computing correct frames for letterboxed windows in WindowState.
+ d = d < 0.02f ? 0 : d;
+ mWindowSurfaceController.getContainerRect(mTmpContainerRect);
+ final int backgroundWidth =
+ (int) (crop.width() + (mTmpContainerRect.width() - mLastWidth) * (1 - d) + 0.5);
+ final int backgroundHeight =
+ (int) (crop.height() + (mTmpContainerRect.height() - mLastHeight) * (1 - d) + 0.5);
+
+ mTmpContainerRect.set(crop);
+ // Make sure that part of background to left/top is visible and scaled.
+ mTmpContainerRect.offset(offsetX, offsetY);
+ // Set correct width/height, so that area to right/bottom is cropped properly.
+ mTmpContainerRect.right = mTmpContainerRect.left + backgroundWidth;
+ mTmpContainerRect.bottom = mTmpContainerRect.top + backgroundHeight;
+ }
+
+ @Override
+ public void setLayerStack(int layerStack) {
+ super.setLayerStack(layerStack);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.setLayerStack(layerStack);
+ }
+
+ @Override
+ public void setOpaque(boolean isOpaque) {
+ super.setOpaque(isOpaque);
+ mOpaque = isOpaque;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void setSecure(boolean isSecure) {
+ super.setSecure(isSecure);
+ }
+
+ @Override
+ public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
+ super.setMatrix(dsdx, dtdx, dtdy, dsdy);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.setMatrix(dsdx, dtdx, dtdy, dsdy);
+ mLastDsDx = dsdx;
+ mLastDsDy = dsdy;
+ updateBgPosition();
+ }
+
+ @Override
+ public void hide() {
+ super.hide();
+ mVisible = false;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void show() {
+ super.show();
+ mVisible = true;
+ updateBackgroundVisibility();
+ }
+
+ @Override
+ public void destroy() {
+ super.destroy();
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.destroy();
+ }
+
+ @Override
+ public void release() {
+ super.release();
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.release();
+ }
+
+ @Override
+ public void setTransparentRegionHint(Region region) {
+ super.setTransparentRegionHint(region);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.setTransparentRegionHint(region);
+ }
+
+ @Override
+ public void deferTransactionUntil(IBinder handle, long frame) {
+ super.deferTransactionUntil(handle, frame);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.deferTransactionUntil(handle, frame);
+ }
+
+ @Override
+ public void deferTransactionUntil(Surface barrier, long frame) {
+ super.deferTransactionUntil(barrier, frame);
+
+ if (mBackgroundControl == null) {
+ return;
+ }
+ mBackgroundControl.deferTransactionUntil(barrier, frame);
+ }
+
+ private void updateBackgroundVisibility() {
+ if (mBackgroundControl == null) {
+ return;
+ }
+ if (mOpaque && mVisible) {
+ mBackgroundControl.show();
+ } else {
+ mBackgroundControl.hide();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index fe5b7f2..079ae40 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -33,7 +33,6 @@
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;
-import com.android.internal.view.SurfaceFlingerVsyncChoreographer;
import com.android.server.AnimationThread;
import java.io.PrintWriter;
@@ -134,26 +133,38 @@
* sure other threads can make progress if this happens.
*/
private void animate(long frameTimeNs) {
- boolean transactionOpen = false;
- try {
- synchronized (mService.mWindowMap) {
- if (!mInitialized) {
- return;
- }
- mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
- mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
- mAnimating = false;
- mAppWindowAnimating = false;
- if (DEBUG_WINDOW_TRACE) {
- Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
- }
+ synchronized (mService.mWindowMap) {
+ if (!mInitialized) {
+ return;
+ }
- if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION animate");
- mService.openSurfaceTransaction();
- transactionOpen = true;
- SurfaceControl.setAnimationTransaction();
+ // Schedule next frame already such that back-pressure happens continuously
+ scheduleAnimation();
+ }
+ // Simulate back-pressure by opening and closing an empty animation transaction. This makes
+ // sure that an animation frame is at least presented once on the screen. We do this outside
+ // of the regular transaction such that we can avoid holding the window manager lock in case
+ // we receive back-pressure from SurfaceFlinger. Since closing an animation transaction
+ // without the window manager locks leads to ordering issues (as the transaction will be
+ // processed only at the beginning of the next frame which may result in another transaction
+ // that was executed later in WM side gets executed first on SF side), we don't update any
+ // Surface properties here such that reordering doesn't cause issues.
+ mService.executeEmptyAnimationTransaction();
+
+ synchronized (mService.mWindowMap) {
+ mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS;
+ mBulkUpdateParams = SET_ORIENTATION_CHANGE_COMPLETE;
+ mAnimating = false;
+ mAppWindowAnimating = false;
+ if (DEBUG_WINDOW_TRACE) {
+ Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime);
+ }
+
+ if (SHOW_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION animate");
+ mService.openSurfaceTransaction();
+ try {
final AccessibilityController accessibilityController =
mService.mAccessibilityController;
final int numDisplays = mDisplayContentsAnimators.size();
@@ -216,27 +227,20 @@
mAnimating |= mService.mDragState.stepAnimationLocked(mCurrentTime);
}
- if (mAnimating) {
- mService.scheduleAnimationLocked();
+ if (!mAnimating) {
+ cancelAnimation();
}
if (mService.mWatermark != null) {
mService.mWatermark.drawIfNeeded();
}
- }
- } catch (RuntimeException e) {
- Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
- } finally {
- if (transactionOpen) {
-
- // Do not hold window manager lock while closing the transaction, as this might be
- // blocking until the next frame, which can lead to total lock starvation.
- mService.closeSurfaceTransaction(false /* withLockHeld */);
+ } catch (RuntimeException e) {
+ Slog.wtf(TAG, "Unhandled exception in Window Manager", e);
+ } finally {
+ mService.closeSurfaceTransaction();
if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION animate");
}
- }
- synchronized (mService.mWindowMap) {
boolean hasPendingLayoutChanges = mService.mRoot.hasPendingLayoutChanges(this);
boolean doRequest = false;
if (mBulkUpdateParams != 0) {
@@ -404,6 +408,13 @@
}
}
+ private void cancelAnimation() {
+ if (mAnimationFrameCallbackScheduled) {
+ mAnimationFrameCallbackScheduled = false;
+ mChoreographer.removeFrameCallback(mAnimationFrameCallback);
+ }
+ }
+
private class DisplayContentsAnimator {
ScreenRotationAnimation mScreenRotationAnimation = null;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b0775dd..8ba36d5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -908,29 +908,16 @@
}
}
- void closeSurfaceTransaction() {
- closeSurfaceTransaction(true /* withLockHeld */);
- }
-
/**
* Closes a surface transaction.
- *
- * @param withLockHeld Whether to acquire the window manager while doing so. In some cases
- * holding the lock my lead to starvation in WM in case closeTransaction
- * blocks and we call it repeatedly, like we do for animations.
*/
- void closeSurfaceTransaction(boolean withLockHeld) {
+ void closeSurfaceTransaction() {
try {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
synchronized (mWindowMap) {
if (mRoot.mSurfaceTraceEnabled) {
mRoot.mRemoteEventTrace.closeSurfaceTransaction();
}
- if (withLockHeld) {
- SurfaceControl.closeTransaction();
- }
- }
- if (!withLockHeld) {
SurfaceControl.closeTransaction();
}
} finally {
@@ -938,6 +925,34 @@
}
}
+ /**
+ * Executes an empty animation transaction without holding the WM lock to simulate
+ * back-pressure. See {@link WindowAnimator#animate} why this is needed.
+ */
+ void executeEmptyAnimationTransaction() {
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "openSurfaceTransaction");
+ synchronized (mWindowMap) {
+ if (mRoot.mSurfaceTraceEnabled) {
+ mRoot.mRemoteEventTrace.openSurfaceTransaction();
+ }
+ SurfaceControl.openTransaction();
+ SurfaceControl.setAnimationTransaction();
+ if (mRoot.mSurfaceTraceEnabled) {
+ mRoot.mRemoteEventTrace.closeSurfaceTransaction();
+ }
+ }
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ }
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "closeSurfaceTransaction");
+ SurfaceControl.closeTransaction();
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
+ }
+ }
+
/** Listener to notify activity manager about app transitions. */
final WindowManagerInternal.AppTransitionListener mActivityManagerAppTransitionNotifier
= new WindowManagerInternal.AppTransitionListener() {
@@ -3471,21 +3486,11 @@
}
if (!mBootAnimationStopped) {
- // Do this one time.
Trace.asyncTraceBegin(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
- try {
- IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
- if (surfaceFlinger != null) {
- Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
- Parcel data = Parcel.obtain();
- data.writeInterfaceToken("android.ui.ISurfaceComposer");
- surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
- data, null, 0);
- data.recycle();
- }
- } catch (RemoteException ex) {
- Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
- }
+ // stop boot animation
+ // formerly we would just kill the process, but we now ask it to exit so it
+ // can choose where to stop the animation.
+ SystemProperties.set("service.bootanim.exit", "1");
mBootAnimationStopped = true;
}
@@ -3494,6 +3499,20 @@
return;
}
+ try {
+ IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
+ if (surfaceFlinger != null) {
+ Slog.i(TAG_WM, "******* TELLING SURFACE FLINGER WE ARE BOOTED!");
+ Parcel data = Parcel.obtain();
+ data.writeInterfaceToken("android.ui.ISurfaceComposer");
+ surfaceFlinger.transact(IBinder.FIRST_CALL_TRANSACTION, // BOOT_FINISHED
+ data, null, 0);
+ data.recycle();
+ }
+ } catch (RemoteException ex) {
+ Slog.e(TAG_WM, "Boot completed: SurfaceFlinger is dead!");
+ }
+
EventLog.writeEvent(EventLogTags.WM_BOOT_ANIMATION_DONE, SystemClock.uptimeMillis());
Trace.asyncTraceEnd(TRACE_TAG_WINDOW_MANAGER, "Stop bootanim", 0);
mDisplayEnabled = true;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index c968653..02242f3 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -3219,6 +3219,15 @@
return !isInMultiWindowMode();
}
+ /** @return true when the window is in fullscreen task, but has non-fullscreen bounds set. */
+ boolean isLetterboxedAppWindow() {
+ final Task task = getTask();
+ final boolean taskIsFullscreen = task != null && task.isFullscreen();
+ final boolean appWindowIsFullscreen = mAppToken != null && !mAppToken.hasBounds();
+
+ return taskIsFullscreen && !appWindowIsFullscreen;
+ }
+
/** Returns the appropriate bounds to use for computing frames. */
private void getContainerBounds(Rect outBounds) {
if (isInMultiWindowMode()) {
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0cc505e..86265c29 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -1200,7 +1200,8 @@
if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
+ w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
- final boolean fullscreen = w.fillsDisplay();
+ final Task task = w.getTask();
+ final boolean fullscreen = w.fillsDisplay() || (task != null && task.isFullscreen());
final boolean isFreeformResizing =
w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
@@ -1526,6 +1527,19 @@
}
}
+ /**
+ * Get rect of the task this window is currently in. If there is no task, rect will be set to
+ * empty.
+ */
+ void getContainerRect(Rect rect) {
+ final Task task = mWin.getTask();
+ if (task != null) {
+ task.getDimBounds(rect);
+ } else {
+ rect.left = rect.top = rect.right = rect.bottom = 0;
+ }
+ }
+
void prepareSurfaceLocked(final boolean recoveringMemory) {
final WindowState w = mWin;
if (!hasSurface()) {
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 27927e6..4819c0f 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -52,7 +52,7 @@
final WindowStateAnimator mAnimator;
- private SurfaceControl mSurfaceControl;
+ private SurfaceControlWithBackground mSurfaceControl;
// Should only be set from within setShown().
private boolean mSurfaceShown = false;
@@ -99,15 +99,10 @@
mWindowType = windowType;
mWindowSession = win.mSession;
- if (DEBUG_SURFACE_TRACE) {
- mSurfaceControl = new SurfaceTrace(
- s, name, w, h, format, flags, windowType, ownerUid);
- } else {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
- mSurfaceControl = new SurfaceControl(
- s, name, w, h, format, flags, windowType, ownerUid);
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
- }
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
+ mSurfaceControl = new SurfaceControlWithBackground(
+ s, name, w, h, format, flags, windowType, ownerUid, this);
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
if (mService.mRoot.mSurfaceTraceEnabled) {
mSurfaceControl = new RemoteSurfaceTrace(
@@ -120,7 +115,7 @@
}
void removeRemoteTrace() {
- mSurfaceControl = new SurfaceControl(mSurfaceControl);
+ mSurfaceControl = new SurfaceControlWithBackground(mSurfaceControl);
}
@@ -293,30 +288,30 @@
mSurfaceControl.setGeometryAppliesWithResize();
}
- void setMatrixInTransaction(float dsdx, float dtdx, float dsdy, float dtdy,
+ void setMatrixInTransaction(float dsdx, float dtdx, float dtdy, float dsdy,
boolean recoveringMemory) {
final boolean matrixChanged = mLastDsdx != dsdx || mLastDtdx != dtdx ||
- mLastDsdy != dsdy || mLastDtdy != dtdy;
+ mLastDtdy != dtdy || mLastDsdy != dsdy;
if (!matrixChanged) {
return;
}
mLastDsdx = dsdx;
mLastDtdx = dtdx;
- mLastDsdy = dsdy;
mLastDtdy = dtdy;
+ mLastDsdy = dsdy;
try {
if (SHOW_TRANSACTIONS) logSurface(
- "MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
+ "MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null);
mSurfaceControl.setMatrix(
- dsdx, dtdx, dsdy, dtdy);
+ dsdx, dtdx, dtdy, dsdy);
} catch (RuntimeException e) {
// If something goes wrong with the surface (such
// as running out of memory), don't take down the
// entire system.
Slog.e(TAG, "Error setting matrix on surface surface" + title
- + " MATRIX [" + dsdx + "," + dtdx + "," + dsdy + "," + dtdy + "]", null);
+ + " MATRIX [" + dsdx + "," + dtdx + "," + dtdy + "," + dsdy + "]", null);
if (!recoveringMemory) {
mAnimator.reclaimSomeSurfaceMemory("matrix", true);
}
@@ -423,6 +418,10 @@
}
}
+ void getContainerRect(Rect rect) {
+ mAnimator.getContainerRect(rect);
+ }
+
boolean showRobustlyInTransaction() {
if (SHOW_TRANSACTIONS) logSurface(
"SHOW (performLayout)", null);
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 3821b9c..bbda1c6 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1022,6 +1022,26 @@
*/
public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET =
"carrier_default_actions_on_reset_string_array";
+
+ /**
+ * Defines carrier-specific actions which act upon
+ * com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE,
+ * used for customization of the default carrier app
+ * Format:
+ * {
+ * "true : CARRIER_ACTION_IDX_1",
+ * "false: CARRIER_ACTION_IDX_2"
+ * }
+ * Where {@code true} is a boolean indicates default network available/unavailable
+ * Where {@code CARRIER_ACTION_IDX} is an integer defined in
+ * {@link com.android.carrierdefaultapp.CarrierActionUtils CarrierActionUtils}
+ * Example:
+ * {@link com.android.carrierdefaultapp.CarrierActionUtils
+ * #CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER enable the app as the default URL handler}
+ * @hide
+ */
+ public static final String KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE =
+ "carrier_default_actions_on_default_network_available_string_array";
/**
* Defines a list of acceptable redirection url for default carrier app
* @hides
@@ -1684,9 +1704,10 @@
sDefaults.putString(KEY_CARRIER_SETUP_APP_STRING, "");
sDefaults.putStringArray(KEY_CARRIER_APP_WAKE_SIGNAL_CONFIG_STRING_ARRAY,
new String[]{
- "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:" +
- "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED," +
- "com.android.internal.telephony.CARRIER_SIGNAL_RESET"
+ "com.android.carrierdefaultapp/.CarrierDefaultBroadcastReceiver:"
+ + "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED,"
+ + "com.android.internal.telephony.CARRIER_SIGNAL_RESET,"
+ + "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE"
});
sDefaults.putStringArray(KEY_CARRIER_APP_NO_WAKE_SIGNAL_CONFIG_STRING_ARRAY, null);
@@ -1694,12 +1715,22 @@
// Default carrier app configurations
sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_REDIRECTION_STRING_ARRAY,
new String[]{
- "4, 1"
+ "9, 4, 1"
+ //9: CARRIER_ACTION_REGISTER_NETWORK_AVAIL
//4: CARRIER_ACTION_DISABLE_METERED_APNS
//1: CARRIER_ACTION_SHOW_PORTAL_NOTIFICATION
});
sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_RESET, new String[]{
- "6" //6: CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS
+ "6, 8"
+ //6: CARRIER_ACTION_CANCEL_ALL_NOTIFICATIONS
+ //8: CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER
+ });
+ sDefaults.putStringArray(KEY_CARRIER_DEFAULT_ACTIONS_ON_DEFAULT_NETWORK_AVAILABLE,
+ new String[] {
+ String.valueOf(false) + ": 7",
+ //7: CARRIER_ACTION_ENABLE_DEFAULT_URL_HANDLER
+ String.valueOf(true) + ": 8"
+ //8: CARRIER_ACTION_DISABLE_DEFAULT_URL_HANDLER
});
sDefaults.putStringArray(KEY_CARRIER_DEFAULT_REDIRECTION_URL_STRING_ARRAY, null);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index b5b32e4..e334c63 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1642,8 +1642,7 @@
* @hide
*/
public String getNetworkCountryIso(int subId) {
- int phoneId = SubscriptionManager.getPhoneId(subId);
- return getNetworkCountryIsoForPhone(phoneId);
+ return getNetworkCountryIsoForPhone(getPhoneId(subId));
}
/**
@@ -1658,7 +1657,14 @@
*/
/** {@hide} */
public String getNetworkCountryIsoForPhone(int phoneId) {
- return getTelephonyProperty(phoneId, TelephonyProperties.PROPERTY_OPERATOR_ISO_COUNTRY, "");
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony == null)
+ return "";
+ return telephony.getNetworkCountryIsoForPhone(phoneId);
+ } catch (RemoteException ex) {
+ return "";
+ }
}
/** Network type is unknown */
@@ -6655,6 +6661,25 @@
}
/**
+ * Action set from carrier signalling broadcast receivers to start/stop reporting default
+ * network available events
+ * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+ * @param subId the subscription ID that this action applies to.
+ * @param report control start/stop reporting network status.
+ * @hide
+ */
+ public void carrierActionReportDefaultNetworkStatus(int subId, boolean report) {
+ try {
+ ITelephony service = getITelephony();
+ if (service != null) {
+ service.carrierActionReportDefaultNetworkStatus(subId, report);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling ITelephony#carrierActionReportDefaultNetworkStatus", e);
+ }
+ }
+
+ /**
* Get aggregated video call data usage since boot.
* Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
*
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index a0e5b7b..9262ec5 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -377,6 +377,13 @@
Bundle getCellLocation(String callingPkg);
/**
+ * Returns the ISO country code equivalent of the current registered
+ * operator's MCC (Mobile Country Code).
+ * @see android.telephony.TelephonyManager#getNetworkCountryIso
+ */
+ String getNetworkCountryIsoForPhone(int phoneId);
+
+ /**
* Returns the neighboring cell information of the device.
*/
List<NeighboringCellInfo> getNeighboringCellInfo(String callingPkg);
@@ -1296,6 +1303,16 @@
void carrierActionSetRadioEnabled(int subId, boolean enabled);
/**
+ * Action set from carrier signalling broadcast receivers to start/stop reporting default
+ * network conditions.
+ * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required
+ * @param subId the subscription ID that this action applies to.
+ * @param report control start/stop reporting default network events.
+ * @hide
+ */
+ void carrierActionReportDefaultNetworkStatus(int subId, boolean report);
+
+ /**
* Get aggregated video call data usage since boot.
* Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
*
diff --git a/telephony/java/com/android/internal/telephony/TelephonyIntents.java b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
index 0343890..f29d993c 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyIntents.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyIntents.java
@@ -447,6 +447,20 @@
"com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE";
/**
+ * <p>Broadcast Action: when system default network available/unavailable with
+ * carrier-disabled mobile data. Intended for carrier apps to set/reset carrier actions when
+ * other network becomes system default network, Wi-Fi for example.
+ * The intent will have the following extra values:</p>
+ * <ul>
+ * <li>defaultNetworkAvailable</li><dd>A boolean indicates default network available.</dd>
+ * <li>subId</li><dd>Sub Id which associated the default data.</dd>
+ * </ul>
+ * <p class="note">This is a protected intent that can only be sent by the system. </p>
+ */
+ public static final String ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE =
+ "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE";
+
+ /**
* <p>Broadcast Action: when framework reset all carrier actions on sim load or absent.
* intended for carrier apps clean up (clear UI e.g.) and only sent to the specified carrier app
* The intent will have the following extra values:</p>
@@ -465,7 +479,7 @@
public static final String EXTRA_APN_PROTO_KEY = "apnProto";
public static final String EXTRA_PCO_ID_KEY = "pcoId";
public static final String EXTRA_PCO_VALUE_KEY = "pcoValue";
-
+ public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE_KEY = "defaultNetworkAvailable";
/**
* Broadcast action to trigger CI OMA-DM Session.
diff --git a/tools/aapt2/ConfigDescription.cpp b/tools/aapt2/ConfigDescription.cpp
index 46098cb..7ff0c72 100644
--- a/tools/aapt2/ConfigDescription.cpp
+++ b/tools/aapt2/ConfigDescription.cpp
@@ -877,7 +877,16 @@
}
bool ConfigDescription::Dominates(const ConfigDescription& o) const {
- if (*this == DefaultConfig() || *this == o) {
+ if (*this == o) {
+ return true;
+ }
+
+ // Locale de-duping is not-trivial, disable for now (b/62409213).
+ if (diff(o) & CONFIG_LOCALE) {
+ return false;
+ }
+
+ if (*this == DefaultConfig()) {
return true;
}
return MatchWithDensity(o) && !o.MatchWithDensity(*this) &&
diff --git a/tools/aapt2/DominatorTree_test.cpp b/tools/aapt2/DominatorTree_test.cpp
index e89c6be..efc523f 100644
--- a/tools/aapt2/DominatorTree_test.cpp
+++ b/tools/aapt2/DominatorTree_test.cpp
@@ -69,14 +69,12 @@
TEST(DominatorTreeTest, DefaultDominatesEverything) {
const ConfigDescription default_config = {};
const ConfigDescription land_config = test::ParseConfigOrDie("land");
- const ConfigDescription sw600dp_land_config =
- test::ParseConfigOrDie("sw600dp-land-v13");
+ const ConfigDescription sw600dp_land_config = test::ParseConfigOrDie("sw600dp-land-v13");
std::vector<std::unique_ptr<ResourceConfigValue>> configs;
configs.push_back(util::make_unique<ResourceConfigValue>(default_config, ""));
configs.push_back(util::make_unique<ResourceConfigValue>(land_config, ""));
- configs.push_back(
- util::make_unique<ResourceConfigValue>(sw600dp_land_config, ""));
+ configs.push_back(util::make_unique<ResourceConfigValue>(sw600dp_land_config, ""));
DominatorTree tree(configs);
PrettyPrinter printer;
@@ -91,16 +89,13 @@
TEST(DominatorTreeTest, ProductsAreDominatedSeparately) {
const ConfigDescription default_config = {};
const ConfigDescription land_config = test::ParseConfigOrDie("land");
- const ConfigDescription sw600dp_land_config =
- test::ParseConfigOrDie("sw600dp-land-v13");
+ const ConfigDescription sw600dp_land_config = test::ParseConfigOrDie("sw600dp-land-v13");
std::vector<std::unique_ptr<ResourceConfigValue>> configs;
configs.push_back(util::make_unique<ResourceConfigValue>(default_config, ""));
configs.push_back(util::make_unique<ResourceConfigValue>(land_config, ""));
- configs.push_back(
- util::make_unique<ResourceConfigValue>(default_config, "phablet"));
- configs.push_back(
- util::make_unique<ResourceConfigValue>(sw600dp_land_config, "phablet"));
+ configs.push_back(util::make_unique<ResourceConfigValue>(default_config, "phablet"));
+ configs.push_back(util::make_unique<ResourceConfigValue>(sw600dp_land_config, "phablet"));
DominatorTree tree(configs);
PrettyPrinter printer;
@@ -118,16 +113,11 @@
const ConfigDescription en_config = test::ParseConfigOrDie("en");
const ConfigDescription en_v21_config = test::ParseConfigOrDie("en-v21");
const ConfigDescription ldrtl_config = test::ParseConfigOrDie("ldrtl-v4");
- const ConfigDescription ldrtl_xhdpi_config =
- test::ParseConfigOrDie("ldrtl-xhdpi-v4");
- const ConfigDescription sw300dp_config =
- test::ParseConfigOrDie("sw300dp-v13");
- const ConfigDescription sw540dp_config =
- test::ParseConfigOrDie("sw540dp-v14");
- const ConfigDescription sw600dp_config =
- test::ParseConfigOrDie("sw600dp-v14");
- const ConfigDescription sw720dp_config =
- test::ParseConfigOrDie("sw720dp-v13");
+ const ConfigDescription ldrtl_xhdpi_config = test::ParseConfigOrDie("ldrtl-xhdpi-v4");
+ const ConfigDescription sw300dp_config = test::ParseConfigOrDie("sw300dp-v13");
+ const ConfigDescription sw540dp_config = test::ParseConfigOrDie("sw540dp-v14");
+ const ConfigDescription sw600dp_config = test::ParseConfigOrDie("sw600dp-v14");
+ const ConfigDescription sw720dp_config = test::ParseConfigOrDie("sw720dp-v13");
const ConfigDescription v20_config = test::ParseConfigOrDie("v20");
std::vector<std::unique_ptr<ResourceConfigValue>> configs;
@@ -135,8 +125,7 @@
configs.push_back(util::make_unique<ResourceConfigValue>(en_config, ""));
configs.push_back(util::make_unique<ResourceConfigValue>(en_v21_config, ""));
configs.push_back(util::make_unique<ResourceConfigValue>(ldrtl_config, ""));
- configs.push_back(
- util::make_unique<ResourceConfigValue>(ldrtl_xhdpi_config, ""));
+ configs.push_back(util::make_unique<ResourceConfigValue>(ldrtl_xhdpi_config, ""));
configs.push_back(util::make_unique<ResourceConfigValue>(sw300dp_config, ""));
configs.push_back(util::make_unique<ResourceConfigValue>(sw540dp_config, ""));
configs.push_back(util::make_unique<ResourceConfigValue>(sw600dp_config, ""));
@@ -148,15 +137,37 @@
std::string expected =
"<default>\n"
- " en\n"
- " en-v21\n"
" ldrtl-v4\n"
" ldrtl-xhdpi-v4\n"
" sw300dp-v13\n"
" sw540dp-v14\n"
" sw600dp-v14\n"
" sw720dp-v13\n"
- " v20\n";
+ " v20\n"
+ "en\n"
+ " en-v21\n";
+ EXPECT_EQ(expected, printer.ToString(&tree));
+}
+
+TEST(DominatorTreeTest, LocalesAreNeverDominated) {
+ const ConfigDescription fr_config = test::ParseConfigOrDie("fr");
+ const ConfigDescription fr_rCA_config = test::ParseConfigOrDie("fr-rCA");
+ const ConfigDescription fr_rFR_config = test::ParseConfigOrDie("fr-rFR");
+
+ std::vector<std::unique_ptr<ResourceConfigValue>> configs;
+ configs.push_back(util::make_unique<ResourceConfigValue>(ConfigDescription::DefaultConfig(), ""));
+ configs.push_back(util::make_unique<ResourceConfigValue>(fr_config, ""));
+ configs.push_back(util::make_unique<ResourceConfigValue>(fr_rCA_config, ""));
+ configs.push_back(util::make_unique<ResourceConfigValue>(fr_rFR_config, ""));
+
+ DominatorTree tree(configs);
+ PrettyPrinter printer;
+
+ std::string expected =
+ "<default>\n"
+ "fr\n"
+ "fr-rCA\n"
+ "fr-rFR\n";
EXPECT_EQ(expected, printer.ToString(&tree));
}
diff --git a/tools/aapt2/optimize/ResourceDeduper_test.cpp b/tools/aapt2/optimize/ResourceDeduper_test.cpp
index 4d00fa6..d9f384c0 100644
--- a/tools/aapt2/optimize/ResourceDeduper_test.cpp
+++ b/tools/aapt2/optimize/ResourceDeduper_test.cpp
@@ -19,69 +19,88 @@
#include "ResourceTable.h"
#include "test/Test.h"
+using ::aapt::test::HasValue;
+using ::testing::Not;
+
namespace aapt {
TEST(ResourceDeduperTest, SameValuesAreDeduped) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
const ConfigDescription default_config = {};
+ const ConfigDescription ldrtl_config = test::ParseConfigOrDie("ldrtl");
+ const ConfigDescription ldrtl_v21_config = test::ParseConfigOrDie("ldrtl-v21");
const ConfigDescription en_config = test::ParseConfigOrDie("en");
const ConfigDescription en_v21_config = test::ParseConfigOrDie("en-v21");
- // Chosen because this configuration is compatible with en.
+ // Chosen because this configuration is compatible with ldrtl/en.
const ConfigDescription land_config = test::ParseConfigOrDie("land");
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .AddString("android:string/dedupe", ResourceId{}, default_config,
- "dedupe")
- .AddString("android:string/dedupe", ResourceId{}, en_config, "dedupe")
- .AddString("android:string/dedupe", ResourceId{}, land_config,
- "dedupe")
- .AddString("android:string/dedupe2", ResourceId{}, default_config,
- "dedupe")
- .AddString("android:string/dedupe2", ResourceId{}, en_config,
- "dedupe")
- .AddString("android:string/dedupe2", ResourceId{}, en_v21_config,
- "keep")
- .AddString("android:string/dedupe2", ResourceId{}, land_config,
- "dedupe")
+ .AddString("android:string/dedupe", ResourceId{}, default_config, "dedupe")
+ .AddString("android:string/dedupe", ResourceId{}, ldrtl_config, "dedupe")
+ .AddString("android:string/dedupe", ResourceId{}, land_config, "dedupe")
+
+ .AddString("android:string/dedupe2", ResourceId{}, default_config, "dedupe")
+ .AddString("android:string/dedupe2", ResourceId{}, ldrtl_config, "dedupe")
+ .AddString("android:string/dedupe2", ResourceId{}, ldrtl_v21_config, "keep")
+ .AddString("android:string/dedupe2", ResourceId{}, land_config, "dedupe")
+
+ .AddString("android:string/dedupe3", ResourceId{}, default_config, "dedupe")
+ .AddString("android:string/dedupe3", ResourceId{}, en_config, "dedupe")
+ .AddString("android:string/dedupe3", ResourceId{}, en_v21_config, "dedupe")
.Build();
ASSERT_TRUE(ResourceDeduper().Consume(context.get(), table.get()));
- EXPECT_EQ(nullptr, test::GetValueForConfig<String>(
- table.get(), "android:string/dedupe", en_config));
- EXPECT_EQ(nullptr, test::GetValueForConfig<String>(
- table.get(), "android:string/dedupe", land_config));
- EXPECT_EQ(nullptr, test::GetValueForConfig<String>(
- table.get(), "android:string/dedupe2", en_config));
- EXPECT_NE(nullptr, test::GetValueForConfig<String>(
- table.get(), "android:string/dedupe2", en_v21_config));
+ EXPECT_THAT(table, Not(HasValue("android:string/dedupe", ldrtl_config)));
+ EXPECT_THAT(table, Not(HasValue("android:string/dedupe", land_config)));
+
+ EXPECT_THAT(table, HasValue("android:string/dedupe2", ldrtl_v21_config));
+ EXPECT_THAT(table, Not(HasValue("android:string/dedupe2", ldrtl_config)));
+
+ EXPECT_THAT(table, HasValue("android:string/dedupe3", default_config));
+ EXPECT_THAT(table, HasValue("android:string/dedupe3", en_config));
+ EXPECT_THAT(table, Not(HasValue("android:string/dedupe3", en_v21_config)));
}
TEST(ResourceDeduperTest, DifferentValuesAreKept) {
std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
const ConfigDescription default_config = {};
- const ConfigDescription en_config = test::ParseConfigOrDie("en");
- const ConfigDescription en_v21_config = test::ParseConfigOrDie("en-v21");
- // Chosen because this configuration is compatible with en.
+ const ConfigDescription ldrtl_config = test::ParseConfigOrDie("ldrtl");
+ const ConfigDescription ldrtl_v21_config = test::ParseConfigOrDie("ldrtl-v21");
+ // Chosen because this configuration is compatible with ldrtl.
const ConfigDescription land_config = test::ParseConfigOrDie("land");
std::unique_ptr<ResourceTable> table =
test::ResourceTableBuilder()
- .AddString("android:string/keep", ResourceId{}, default_config,
- "keep")
- .AddString("android:string/keep", ResourceId{}, en_config, "keep")
- .AddString("android:string/keep", ResourceId{}, en_v21_config,
- "keep2")
+ .AddString("android:string/keep", ResourceId{}, default_config, "keep")
+ .AddString("android:string/keep", ResourceId{}, ldrtl_config, "keep")
+ .AddString("android:string/keep", ResourceId{}, ldrtl_v21_config, "keep2")
.AddString("android:string/keep", ResourceId{}, land_config, "keep2")
.Build();
ASSERT_TRUE(ResourceDeduper().Consume(context.get(), table.get()));
- EXPECT_NE(nullptr, test::GetValueForConfig<String>(
- table.get(), "android:string/keep", en_config));
- EXPECT_NE(nullptr, test::GetValueForConfig<String>(
- table.get(), "android:string/keep", en_v21_config));
- EXPECT_NE(nullptr, test::GetValueForConfig<String>(
- table.get(), "android:string/keep", land_config));
+ EXPECT_THAT(table, HasValue("android:string/keep", ldrtl_config));
+ EXPECT_THAT(table, HasValue("android:string/keep", ldrtl_v21_config));
+ EXPECT_THAT(table, HasValue("android:string/keep", land_config));
+}
+
+TEST(ResourceDeduperTest, LocalesValuesAreKept) {
+ std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
+ const ConfigDescription default_config = {};
+ const ConfigDescription fr_config = test::ParseConfigOrDie("fr");
+ const ConfigDescription fr_rCA_config = test::ParseConfigOrDie("fr-rCA");
+
+ std::unique_ptr<ResourceTable> table =
+ test::ResourceTableBuilder()
+ .AddString("android:string/keep", ResourceId{}, default_config, "keep")
+ .AddString("android:string/keep", ResourceId{}, fr_config, "keep")
+ .AddString("android:string/keep", ResourceId{}, fr_rCA_config, "keep")
+ .Build();
+
+ ASSERT_TRUE(ResourceDeduper().Consume(context.get(), table.get()));
+ EXPECT_THAT(table, HasValue("android:string/keep", default_config));
+ EXPECT_THAT(table, HasValue("android:string/keep", fr_config));
+ EXPECT_THAT(table, HasValue("android:string/keep", fr_rCA_config));
}
} // namespace aapt
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index 01b2d14..8efd56a 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -156,6 +156,23 @@
return arg.Equals(&a);
}
+MATCHER_P(StrValueEq, a,
+ std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
+ return *(arg.value) == a;
+}
+
+MATCHER_P(HasValue, name,
+ std::string(negation ? "does not have" : "has") + " value " +
+ ::testing::PrintToString(name)) {
+ return GetValueForConfig<Value>(&(*arg), name, {}) != nullptr;
+}
+
+MATCHER_P2(HasValue, name, config,
+ std::string(negation ? "does not have" : "has") + " value " +
+ ::testing::PrintToString(name) + " for config " + ::testing::PrintToString(config)) {
+ return GetValueForConfig<Value>(&(*arg), name, config) != nullptr;
+}
+
} // namespace test
} // namespace aapt