Merge "Fix rounded corners fangs in RTL" into oc-dr1-dev
diff --git a/core/res/res/layout/shutdown_dialog.xml b/core/res/res/layout/shutdown_dialog.xml
new file mode 100644
index 0000000..398bfb1
--- /dev/null
+++ b/core/res/res/layout/shutdown_dialog.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2014 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.
+-->
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:gravity="center_horizontal" >
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="6" />
+
+ <TextView
+ android:id="@id/text1"
+ android:layout_width="wrap_content"
+ android:layout_height="32dp"
+ android:text="@string/shutdown_progress"
+ android:textDirection="locale"
+ android:textSize="24sp"
+ android:textAppearance="?attr/textAppearanceLarge"
+ android:gravity="center"
+ android:layout_marginBottom="24dp"
+ android:fontFamily="@string/config_headlineFontFamily"/>
+
+ <ProgressBar
+ android:id="@id/progress"
+ android:layout_width="30dp"
+ android:layout_height="30dp"
+ style="?attr/progressBarStyleLarge" />
+
+ <Space
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="10" />
+
+</LinearLayout>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 99807f9..50550a4 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3058,4 +3058,5 @@
<java-symbol type="array" name="config_batteryPackageTypeSystem" />
<java-symbol type="array" name="config_batteryPackageTypeService" />
<java-symbol type="bool" name="config_showAreaUpdateInfoSettings" />
+ <java-symbol type="layout" name="shutdown_dialog" />
</resources>
diff --git a/packages/SystemUI/res/drawable/brightness_mirror_background.xml b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
index 0c69d89..b3a0484 100644
--- a/packages/SystemUI/res/drawable/brightness_mirror_background.xml
+++ b/packages/SystemUI/res/drawable/brightness_mirror_background.xml
@@ -15,5 +15,5 @@
~ limitations under the License
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
- <solid android:color="?android:attr/colorPrimary" />
+ <solid android:color="@color/qs_background_dark" />
</shape>
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 2ff626a..f8b7b8a 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -33,13 +33,13 @@
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="32dp"
+ android:layout_height="40dp"
android:layout_alignParentEnd="true"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
android:orientation="horizontal">
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 53d9cc5..8048c68 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -23,7 +23,8 @@
android:drawableTop="@drawable/recents_empty"
android:drawablePadding="25dp"
android:textSize="16sp"
- android:textColor="#ffffffff"
+ android:drawableTint="?attr/bgProtectTextColor"
+ android:textColor="?attr/bgProtectTextColor"
android:text="@string/recents_empty_message"
android:fontFamily="sans-serif"
android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml
index 34b4e17..10b4316 100644
--- a/packages/SystemUI/res/layout/recents_stack_action_button.xml
+++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml
@@ -24,7 +24,7 @@
android:paddingBottom="12dp"
android:text="@string/recents_stack_action_button_label"
android:textSize="14sp"
- android:textColor="#FFFFFF"
+ android:textColor="?attr/bgProtectTextColor"
android:textAllCaps="true"
android:shadowColor="#99000000"
android:shadowDx="0"
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 5274b64..93a0742 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android">
- <style name="RecentsTheme" parent="@android:style/Theme.Material">
+ <style name="RecentsTheme" parent="RecentsBase">
<!-- NoTitle -->
<item name="android:windowNoTitle">true</item>
<!-- Misc -->
@@ -27,6 +27,12 @@
<item name="android:ambientShadowAlpha">0.35</item>
</style>
+ <!-- OverlayManager might replace this style entirely, use RecentsTheme to set a property
+ that should exist in both light and dark versions of Recents -->
+ <style name="RecentsBase" parent="@android:style/Theme.Material">
+ <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_dark</item>
+ <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_dark</item>
+ </style>
<!-- Recents theme -->
<style name="RecentsTheme.Wallpaper">
@@ -35,6 +41,8 @@
<item name="android:windowShowWallpaper">true</item>
<item name="android:windowDisablePreview">true</item>
<item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
+ <item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
+ <item name="bgProtectSecondaryTextColor">?android:attr/textColorSecondaryInverse</item>
</style>
<style name="ClearAllButtonDefaultMargins">
@@ -47,6 +55,8 @@
<!-- Performance optimized Recents theme (no wallpaper) -->
<style name="RecentsTheme.NoWallpaper">
<item name="android:windowBackground">@android:color/black</item>
+ <item name="bgProtectTextColor">@android:color/white</item>
+ <item name="bgProtectSecondaryTextColor">@android:color/white</item>
</style>
<!-- Theme used for the activity that shows when the system forced an app to be resizable -->
@@ -290,7 +300,10 @@
<style name="Animation.StatusBar">
</style>
- <style name="systemui_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+ <!-- Overlay manager may replace this theme -->
+ <style name="systemui_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
+
+ <style name="systemui_theme" parent="systemui_base">
<item name="lightIconTheme">@style/DualToneLightTheme</item>
<item name="darkIconTheme">@style/DualToneDarkTheme</item>
<item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
@@ -303,7 +316,10 @@
<item name="*android:successColor">?android:attr/textColorPrimaryInverse</item>
</style>
- <style name="qs_theme" parent="systemui_theme">
+ <!-- Overlay manager may replace this theme -->
+ <style name="qs_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings" />
+
+ <style name="qs_theme" parent="qs_base">
<item name="lightIconTheme">@style/QSIconTheme</item>
<item name="darkIconTheme">@style/QSIconTheme</item>
</style>
@@ -459,7 +475,7 @@
<item name="android:paddingEnd">8dp</item>
</style>
- <style name="edit_theme" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+ <style name="edit_theme" parent="qs_base">
<item name="android:colorBackground">?android:attr/colorSecondary</item>
</style>
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index bb0f2f9..22bb2a3 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -19,6 +19,7 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
+import android.content.res.Configuration;
import android.provider.Settings;
import android.util.AttributeSet;
import android.view.Gravity;
@@ -28,9 +29,15 @@
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
-
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.leak.RotationUtils;
+
+import java.util.ArrayList;
+
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
public class HardwareUiLayout extends FrameLayout implements Tunable {
@@ -49,7 +56,7 @@
private int mEndPoint;
private boolean mEdgeBleed;
private boolean mRoundedDivider;
- private boolean mLandscape;
+ private int mRotation = ROTATION_NONE;
private boolean mRotatedBackground;
public HardwareUiLayout(Context context, AttributeSet attrs) {
@@ -93,8 +100,10 @@
private void updateEdgeMargin(int edge) {
if (mChild != null) {
MarginLayoutParams params = (MarginLayoutParams) mChild.getLayoutParams();
- if (mLandscape) {
+ if (mRotation == ROTATION_LANDSCAPE) {
params.topMargin = edge;
+ } else if (mRotation == ROTATION_SEASCAPE) {
+ params.bottomMargin = edge;
} else {
params.rightMargin = edge;
}
@@ -118,6 +127,7 @@
mChild.addOnLayoutChangeListener(
(v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) ->
updatePosition());
+ updateRotation();
} else {
return;
}
@@ -127,30 +137,69 @@
animateChild(mOldHeight, newHeight);
}
post(() -> updatePosition());
- boolean landscape = getMeasuredWidth() > getMeasuredHeight();
- if (landscape != mLandscape) {
- mLandscape = landscape;
- if (mLandscape) {
- toLandscape();
- if (mChild instanceof LinearLayout) {
- mRotatedBackground = true;
- mBackground.setRotatedBackground(true);
- ((LinearLayout) mChild).setOrientation(LinearLayout.HORIZONTAL);
- swapDimens(mChild);
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateRotation();
+ }
+
+ private void updateRotation() {
+ int rotation = RotationUtils.getRotation(getContext());
+ if (rotation != mRotation) {
+ rotate(mRotation, rotation);
+ mRotation = rotation;
+ }
+ }
+
+ private void rotate(int from, int to) {
+ if (from != ROTATION_NONE && to != ROTATION_NONE) {
+ // Rather than handling this confusing case, just do 2 rotations.
+ rotate(from, ROTATION_NONE);
+ rotate(ROTATION_NONE, to);
+ return;
+ }
+ if (from == ROTATION_LANDSCAPE || to == ROTATION_SEASCAPE) {
+ rotateRight();
+ } else {
+ rotateLeft();
+ }
+ if (to != ROTATION_NONE) {
+ if (mChild instanceof LinearLayout) {
+ mRotatedBackground = true;
+ mBackground.setRotatedBackground(true);
+ LinearLayout linearLayout = (LinearLayout) mChild;
+ if (to == ROTATION_SEASCAPE) {
+ swapOrder(linearLayout);
}
- } else {
- fromLandscape();
- if (mChild instanceof LinearLayout) {
- mRotatedBackground = false;
- mBackground.setRotatedBackground(false);
- ((LinearLayout) mChild).setOrientation(LinearLayout.VERTICAL);
- swapDimens(mChild);
+ linearLayout.setOrientation(LinearLayout.HORIZONTAL);
+ swapDimens(this.mChild);
+ }
+ } else {
+ if (mChild instanceof LinearLayout) {
+ mRotatedBackground = false;
+ mBackground.setRotatedBackground(false);
+ LinearLayout linearLayout = (LinearLayout) mChild;
+ if (from == ROTATION_SEASCAPE) {
+ swapOrder(linearLayout);
}
+ linearLayout.setOrientation(LinearLayout.VERTICAL);
+ swapDimens(mChild);
}
}
}
- private void fromLandscape() {
+ private void swapOrder(LinearLayout linearLayout) {
+ ArrayList<View> children = new ArrayList<>();
+ for (int i = 0; i < linearLayout.getChildCount(); i++) {
+ children.add(0, linearLayout.getChildAt(i));
+ linearLayout.removeViewAt(i);
+ }
+ children.forEach(v -> linearLayout.addView(v));
+ }
+
+ private void rotateRight() {
rotateRight(this);
rotateRight(mChild);
swapDimens(this);
@@ -202,7 +251,7 @@
return retGravity;
}
- private void toLandscape() {
+ private void rotateLeft() {
rotateLeft(this);
rotateLeft(mChild);
swapDimens(this);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 1a8a474..31d41ac 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -682,10 +682,14 @@
/** {@inheritDoc} */
public void onClick(DialogInterface dialog, int which) {
- if (!(mAdapter.getItem(which) instanceof SilentModeTriStateAction)) {
+ Action item = mAdapter.getItem(which);
+ if ((item instanceof PowerAction)
+ || (item instanceof RestartAction)) {
+ if (mDialog != null) mDialog.fadeOut();
+ } else if (!(item instanceof SilentModeTriStateAction)) {
dialog.dismiss();
}
- mAdapter.getItem(which).onPress();
+ item.onPress();
}
/**
@@ -1321,6 +1325,17 @@
.start();
}
+ public void fadeOut() {
+ mHardwareLayout.setTranslationX(0);
+ mHardwareLayout.setAlpha(1);
+ mListView.animate()
+ .alpha(0)
+ .translationX(getAnimTranslation())
+ .setDuration(300)
+ .setInterpolator(new LogAccelerateInterpolator())
+ .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/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 17a0d33..77c3bfa 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -16,7 +16,9 @@
import android.content.Context;
import android.util.Log;
+import android.view.ContextThemeWrapper;
+import com.android.systemui.R;
import com.android.systemui.plugins.qs.*;
import com.android.systemui.plugins.qs.QSTileView;
import com.android.systemui.qs.external.CustomTile;
@@ -78,7 +80,7 @@
@Override
public QSTileView createTileView(QSTile tile, boolean collapsedView) {
- Context context = mHost.getContext();
+ Context context = new ContextThemeWrapper(mHost.getContext(), R.style.qs_theme);
QSIconView icon = tile.createTileView(context);
if (collapsedView) {
return new QSTileBaseView(context, icon, collapsedView);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 4de1214..fa16f8e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -24,6 +24,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.Bundle;
@@ -42,9 +43,9 @@
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.keyguard.LatencyTracker;
import com.android.systemui.DejankUtils;
import com.android.systemui.Interpolators;
-import com.android.keyguard.LatencyTracker;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
@@ -110,11 +111,10 @@
private RecentsPackageMonitor mPackageMonitor;
private Handler mHandler = new Handler();
private long mLastTabKeyEventTime;
- private int mLastDeviceOrientation = Configuration.ORIENTATION_UNDEFINED;
- private int mLastDisplayDensity;
private boolean mFinishedOnStartup;
private boolean mIgnoreAltTabRelease;
private boolean mIsVisible;
+ private Configuration mLastConfig;
// Top level views
private RecentsView mRecentsView;
@@ -333,16 +333,11 @@
setContentView(R.layout.recents);
takeKeyEvents(true);
mRecentsView = findViewById(R.id.recents_view);
- mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
- View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
- View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mScrimViews = new SystemBarScrimViews(this);
getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
- Configuration appConfiguration = Utilities.getAppConfiguration(this);
- mLastDeviceOrientation = appConfiguration.orientation;
- mLastDisplayDensity = appConfiguration.densityDpi;
+ mLastConfig = Utilities.getAppConfiguration(this);
mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
@Override
@@ -485,10 +480,15 @@
Configuration newDeviceConfiguration = Utilities.getAppConfiguration(this);
int numStackTasks = mRecentsView.getStack().getStackTaskCount();
EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
- mLastDeviceOrientation != newDeviceConfiguration.orientation,
- mLastDisplayDensity != newDeviceConfiguration.densityDpi, numStackTasks > 0));
- mLastDeviceOrientation = newDeviceConfiguration.orientation;
- mLastDisplayDensity = newDeviceConfiguration.densityDpi;
+ mLastConfig.orientation != newDeviceConfiguration.orientation,
+ mLastConfig.densityDpi != newDeviceConfiguration.densityDpi, numStackTasks > 0));
+
+ int configDiff = mLastConfig.updateFrom(newDeviceConfiguration);
+
+ // Recreate activity if an overlay was enabled/disabled
+ if ((configDiff & ActivityInfo.CONFIG_ASSETS_PATHS) != 0) {
+ recreate();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 521157d..d74970f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -43,14 +43,14 @@
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.util.leak.RotationUtils;
import java.util.ArrayList;
-public class ScreenPinningRequest implements View.OnClickListener {
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
- private static final int ROTATION_NONE = 0;
- private static final int ROTATION_LANDSCAPE = 1;
- private static final int ROTATION_SEASCAPE = 2;
+public class ScreenPinningRequest implements View.OnClickListener {
private final Context mContext;
@@ -160,7 +160,7 @@
DisplayMetrics metrics = new DisplayMetrics();
mWindowManager.getDefaultDisplay().getMetrics(metrics);
float density = metrics.density;
- int rotation = getRotation(mContext);
+ int rotation = RotationUtils.getRotation(mContext);
inflateView(rotation);
int bgColor = mContext.getColor(
@@ -202,19 +202,6 @@
mContext.registerReceiver(mReceiver, filter);
}
- private int getRotation(Context context) {
- Configuration config = mContext.getResources().getConfiguration();
- int rot = context.getDisplay().getRotation();
- if (config.smallestScreenWidthDp < 600) {
- if (rot == Surface.ROTATION_90) {
- return ROTATION_LANDSCAPE;
- } else if (rot == Surface.ROTATION_270) {
- return ROTATION_SEASCAPE;
- }
- }
- return ROTATION_NONE;
- }
-
private void inflateView(int rotation) {
// We only want this landscape orientation on <600dp, so rather than handle
// resource overlay for -land and -sw600dp-land, just inflate this
@@ -287,14 +274,14 @@
protected void onConfigurationChanged() {
removeAllViews();
- inflateView(getRotation(mContext));
+ inflateView(RotationUtils.getRotation(mContext));
}
private final Runnable mUpdateLayoutRunnable = new Runnable() {
@Override
public void run() {
if (mLayout != null && mLayout.getParent() != null) {
- mLayout.setLayoutParams(getRequestLayoutParams(getRotation(mContext)));
+ mLayout.setLayoutParams(getRequestLayoutParams(RotationUtils.getRotation(mContext)));
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 9ca756c..c1c41be0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -151,6 +151,12 @@
mColorExtractor = Dependency.get(SysuiColorExtractor.class);
LayoutInflater inflater = LayoutInflater.from(context);
+
+ mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
+ addView(mEmptyView);
+
+ boolean usingDarkText =
+ Color.luminance(mEmptyView.getTextColors().getDefaultColor()) < 0.5f;
if (RecentsDebugFlags.Static.EnableStackActionButton) {
mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button,
this, false);
@@ -160,10 +166,21 @@
EventBus.getDefault().send(new DismissAllTaskViewsEvent());
}
});
+ // Disable black shadow if text color is already dark.
+ if (usingDarkText) {
+ mStackActionButton.setShadowLayer(0, 0, 0, 0);
+ }
addView(mStackActionButton);
}
- mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
- addView(mEmptyView);
+
+ // Let's also require dark status and nav bars if the text is dark
+ int systemBarsStyle = usingDarkText ? View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR |
+ View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR : 0;
+
+ setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
+ View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
+ View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
+ systemBarsStyle);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index bcba789..f6fab44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1150,7 +1150,6 @@
ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
Dependency.get(ExtensionController.class).newExtension(QS.class)
.withPlugin(QS.class)
- .withUiMode(UI_MODE_TYPE_CAR, () -> new QSFragment())
.withDefault(() -> new QSFragment())
.build());
final QSTileHost qsh = SystemUIFactory.getInstance().createQSTileHost(mContext, this,
@@ -1318,6 +1317,9 @@
.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
mKeyguardIndicationController.setVisible(mState == StatusBarState.KEYGUARD);
mKeyguardIndicationController.setDozing(mDozing);
+ if (mBrightnessMirrorController != null) {
+ mBrightnessMirrorController.onOverlayChanged();
+ }
}
protected void reevaluateStyles() {
@@ -4207,7 +4209,7 @@
}
if (shouldBeKeyguard) {
showKeyguardImpl();
- } else if (!shouldBeKeyguard && mIsKeyguard) {
+ } else {
return hideKeyguardImpl();
}
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index ad406c7..ab55b23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -84,7 +84,6 @@
.setInterpolator(Interpolators.ALPHA_IN);
}
-
public void setLocation(View original) {
original.getLocationInWindow(mInt2Cache);
@@ -115,7 +114,15 @@
mBrightnessMirror.setLayoutParams(lp);
}
+ public void onOverlayChanged() {
+ reinflate();
+ }
+
public void onDensityOrFontScaleChanged() {
+ reinflate();
+ }
+
+ private void reinflate() {
int index = mStatusBarWindow.indexOfChild(mBrightnessMirror);
mStatusBarWindow.removeView(mBrightnessMirror);
mBrightnessMirror = LayoutInflater.from(mBrightnessMirror.getContext()).inflate(
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 2981b39..9d197d7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -2589,9 +2589,6 @@
}
updateAnimationState(false, child);
- // Make sure the clipRect we might have set is removed
- expandableView.setClipTopAmount(0);
-
focusNextViewIfFocused(child);
}
@@ -3038,10 +3035,6 @@
private void generateChildRemovalEvents() {
for (View child : mChildrenToRemoveAnimated) {
boolean childWasSwipedOut = mSwipedOutViews.contains(child);
- int animationType = childWasSwipedOut
- ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
- : AnimationEvent.ANIMATION_TYPE_REMOVE;
- AnimationEvent event = new AnimationEvent(child, animationType);
// we need to know the view after this one
float removedTranslation = child.getTranslationY();
@@ -3052,7 +3045,16 @@
removedTranslation = row.getTranslationWhenRemoved();
ignoreChildren = false;
}
+ childWasSwipedOut |= Math.abs(row.getTranslation()) == row.getWidth();
}
+ if (!childWasSwipedOut) {
+ Rect clipBounds = child.getClipBounds();
+ childWasSwipedOut = clipBounds.height() == 0;
+ }
+ int animationType = childWasSwipedOut
+ ? AnimationEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
+ : AnimationEvent.ANIMATION_TYPE_REMOVE;
+ AnimationEvent event = new AnimationEvent(child, animationType);
event.viewAfterChangingView = getFirstChildBelowTranlsationY(removedTranslation,
ignoreChildren);
mAnimationEvents.add(event);
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
new file mode 100644
index 0000000..ad20900
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/RotationUtils.java
@@ -0,0 +1,39 @@
+/*
+ * 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.util.leak;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.view.Surface;
+
+public class RotationUtils {
+
+ public static final int ROTATION_NONE = 0;
+ public static final int ROTATION_LANDSCAPE = 1;
+ public static final int ROTATION_SEASCAPE = 2;
+
+ public static int getRotation(Context context) {
+ Configuration config = context.getResources().getConfiguration();
+ int rot = context.getDisplay().getRotation();
+ if (config.smallestScreenWidthDp < 600) {
+ if (rot == Surface.ROTATION_90) {
+ return ROTATION_LANDSCAPE;
+ } else if (rot == Surface.ROTATION_270) {
+ return ROTATION_SEASCAPE;
+ }
+ }
+ return ROTATION_NONE;
+ }
+}
diff --git a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
index ba1c91c..8b6ee2b 100644
--- a/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
+++ b/packages/overlays/SysuiDarkThemeOverlay/AndroidManifest.xml
@@ -2,7 +2,7 @@
package="com.android.systemui.theme.dark"
android:versionCode="1"
android:versionName="1.0">
- <overlay android:targetPackage="android" android:priority="1"/>
+ <overlay android:targetPackage="com.android.systemui" android:priority="1"/>
<application android:label="@string/sysui_overlay_dark" android:hasCode="false"/>
</manifest>
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
new file mode 100644
index 0000000..0c1b0ef
--- /dev/null
+++ b/packages/overlays/SysuiDarkThemeOverlay/res/values/styles.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="qs_base" parent="android:Theme.DeviceDefault">
+ <item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
+ <item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
+ <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
+ <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
+ <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
+ <item name="android:colorBackgroundFloating">#000</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml b/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
deleted file mode 100644
index 7e2b955..0000000
--- a/packages/overlays/SysuiDarkThemeOverlay/res/values/themes_device_defaults.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault">
- <item name="android:colorPrimary">@*android:color/primary_device_default_settings</item>
- <item name="android:colorPrimaryDark">@*android:color/primary_dark_device_default_settings</item>
- <!-- textColorPrimaryInverse is used on the lock screen and this means that we can't just
- invert text colors otherwise we won't have contrast on the keyguard -->
- <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_dark</item>
- <!-- same for textColorSecondaryInverse -->
- <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_dark</item>
- <item name="android:colorSecondary">@*android:color/secondary_device_default_settings</item>
- <item name="android:colorAccent">@*android:color/accent_device_default_dark</item>
- <item name="android:colorControlNormal">?android:attr/textColorPrimary</item>
- <item name="android:colorBackgroundFloating">#000</item>
- </style>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
index 1745b4c..0a8749c 100644
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/AndroidManifest.xml
@@ -2,7 +2,7 @@
package="com.android.systemui.theme.lightwallpaper"
android:versionCode="1"
android:versionName="1.0">
- <overlay android:targetPackage="android" android:priority="2"/>
+ <overlay android:targetPackage="com.android.systemui" android:priority="2"/>
<application android:label="@string/sysui_overlay_light" android:hasCode="false"/>
</manifest>
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml
new file mode 100644
index 0000000..53912b5
--- /dev/null
+++ b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/styles.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <style name="systemui_base" parent="@*android:style/Theme.DeviceDefault.QuickSettings">
+ <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
+ <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+ </style>
+
+ <style name="RecentsBase" parent="@android:style/Theme.Material">
+ <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
+ <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml b/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml
deleted file mode 100644
index 877ebf8..0000000
--- a/packages/overlays/SysuiLightWallpaperThemeOverlay/res/values/themes_device_defaults.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="Theme.DeviceDefault.QuickSettings" parent="android:Theme.DeviceDefault.Light">
- <item name="android:textColorPrimaryInverse">@*android:color/primary_text_material_light</item>
- <item name="android:textColorSecondaryInverse">@*android:color/secondary_text_material_light</item>
- </style>
-</resources>
\ No newline at end of file
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index e2956dd..b657335 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -16,6 +16,7 @@
package com.android.server.connectivity;
+import static android.hardware.usb.UsbManager.USB_CONFIGURED;
import static android.hardware.usb.UsbManager.USB_CONNECTED;
import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
import static android.net.ConnectivityManager.getNetworkTypeName;
@@ -703,7 +704,7 @@
private void showTetheredNotification(int id) {
NotificationManager notificationManager =
- (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
return;
}
@@ -764,7 +765,7 @@
private void clearTetheredNotification() {
NotificationManager notificationManager =
- (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+ (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null && mLastNotificationId != 0) {
notificationManager.cancelAsUser(null, mLastNotificationId,
UserHandle.ALL);
@@ -803,11 +804,37 @@
private void handleUsbAction(Intent intent) {
final boolean usbConnected = intent.getBooleanExtra(USB_CONNECTED, false);
+ final boolean usbConfigured = intent.getBooleanExtra(USB_CONFIGURED, false);
final boolean rndisEnabled = intent.getBooleanExtra(USB_FUNCTION_RNDIS, false);
+
+ mLog.log(String.format("USB bcast connected:%s configured:%s rndis:%s",
+ usbConnected, usbConfigured, rndisEnabled));
+
+ // There are three types of ACTION_USB_STATE:
+ //
+ // - DISCONNECTED (USB_CONNECTED and USB_CONFIGURED are 0)
+ // Meaning: USB connection has ended either because of
+ // software reset or hard unplug.
+ //
+ // - CONNECTED (USB_CONNECTED is 1, USB_CONFIGURED is 0)
+ // Meaning: the first stage of USB protocol handshake has
+ // occurred but it is not complete.
+ //
+ // - CONFIGURED (USB_CONNECTED and USB_CONFIGURED are 1)
+ // Meaning: the USB handshake is completely done and all the
+ // 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) {
mRndisEnabled = rndisEnabled;
// start tethering if we have a request pending
- if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
+ if (usbConfigured && mRndisEnabled && mUsbTetherRequested) {
tetherMatchingInterfaces(
IControlsTethering.STATE_TETHERED,
ConnectivityManager.TETHERING_USB);
@@ -983,7 +1010,7 @@
public int setUsbTethering(boolean enable) {
if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
- UsbManager usbManager = mContext.getSystemService(UsbManager.class);
+ UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
synchronized (mPublicSync) {
if (enable) {
diff --git a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
index 1fc1684..09fd96b 100644
--- a/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
+++ b/services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java
@@ -76,6 +76,10 @@
}
}
+ final String logmsg = String.format("initOffloadControl(%s)",
+ (controlCb == null) ? "null"
+ : "0x" + Integer.toHexString(System.identityHashCode(controlCb)));
+
mTetheringOffloadCallback = new TetheringOffloadCallback(mHandler, mControlCallback);
final CbResults results = new CbResults();
try {
@@ -86,11 +90,11 @@
results.errMsg = errMsg;
});
} catch (RemoteException e) {
- mLog.e("failed to initOffload: " + e);
+ record(logmsg, e);
return false;
}
- if (!results.success) mLog.e("initOffload failed: " + results.errMsg);
+ record(logmsg, results);
return results.success;
}
@@ -108,14 +112,18 @@
mOffloadControl = null;
mTetheringOffloadCallback = null;
mControlCallback = null;
+ mLog.log("stopOffloadControl()");
}
public boolean setUpstreamParameters(
String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) {
- iface = iface != null ? iface : NO_INTERFACE_NAME;
- v4addr = v4addr != null ? v4addr : NO_IPV4_ADDRESS;
- v4gateway = v4gateway != null ? v4gateway : NO_IPV4_GATEWAY;
- v6gws = v6gws != null ? v6gws : new ArrayList<>();
+ iface = (iface != null) ? iface : NO_INTERFACE_NAME;
+ v4addr = (v4addr != null) ? v4addr : NO_IPV4_ADDRESS;
+ v4gateway = (v4gateway != null) ? v4gateway : NO_IPV4_GATEWAY;
+ v6gws = (v6gws != null) ? v6gws : new ArrayList<>();
+
+ final String logmsg = String.format("setUpstreamParameters(%s, %s, %s, [%s])",
+ iface, v4addr, v4gateway, String.join(",", v6gws));
final CbResults results = new CbResults();
try {
@@ -126,14 +134,27 @@
results.errMsg = errMsg;
});
} catch (RemoteException e) {
- mLog.e("failed to setUpstreamParameters: " + e);
+ record(logmsg, e);
return false;
}
- if (!results.success) mLog.e("setUpstreamParameters failed: " + results.errMsg);
+ record(logmsg, results);
return results.success;
}
+ private void record(String msg, Throwable t) {
+ mLog.e(msg + " -> exception: " + t);
+ }
+
+ private void record(String msg, CbResults results) {
+ final String logmsg = msg + " -> " + results;
+ if (!results.success) {
+ mLog.e(logmsg);
+ } else {
+ mLog.log(logmsg);
+ }
+ }
+
private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub {
public final Handler handler;
public final ControlCallback controlCb;
@@ -162,5 +183,13 @@
private static class CbResults {
boolean success;
String errMsg;
+
+ public String toString() {
+ if (success) {
+ return "ok";
+ } else {
+ return "fail: " + errMsg;
+ }
+ }
}
}
diff --git a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
index ebb9450..c6ec287 100644
--- a/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
+++ b/services/core/java/com/android/server/policy/ImmersiveModeConfirmation.java
@@ -19,6 +19,7 @@
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
+import android.app.ActivityThread;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -79,7 +80,7 @@
boolean mVrModeEnabled = false;
public ImmersiveModeConfirmation(Context context) {
- mContext = context;
+ mContext = ActivityThread.currentActivityThread().getSystemUiContext();
mHandler = new H();
mShowDelayMs = getNavBarExitDuration() * 3;
mPanicThresholdMs = context.getResources()
diff --git a/services/core/java/com/android/server/power/ShutdownThread.java b/services/core/java/com/android/server/power/ShutdownThread.java
index 02f2afc..56612ad 100644
--- a/services/core/java/com/android/server/power/ShutdownThread.java
+++ b/services/core/java/com/android/server/power/ShutdownThread.java
@@ -23,14 +23,17 @@
import android.app.ProgressDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.IBluetoothManager;
-import android.media.AudioAttributes;
-import android.nfc.NfcAdapter;
-import android.nfc.INfcAdapter;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.om.IOverlayManager;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
+import android.media.AudioAttributes;
+import android.nfc.INfcAdapter;
+import android.nfc.NfcAdapter;
import android.os.FileUtils;
import android.os.Handler;
import android.os.PowerManager;
@@ -39,24 +42,21 @@
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
+import android.os.SystemVibrator;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.Vibrator;
-import android.os.SystemVibrator;
-import android.os.storage.IStorageShutdownObserver;
import android.os.storage.IStorageManager;
-import android.system.ErrnoException;
-import android.system.Os;
-
+import android.os.storage.IStorageShutdownObserver;
+import android.util.Log;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+import android.widget.ProgressBar;
+import android.widget.TextView;
import com.android.internal.telephony.ITelephony;
import com.android.server.pm.PackageManagerService;
-import android.util.Log;
-import android.view.WindowManager;
-
-import java.io.BufferedReader;
import java.io.File;
-import java.io.FileReader;
import java.io.IOException;
public final class ShutdownThread extends Thread {
@@ -243,15 +243,7 @@
shutdownInner(context, confirm);
}
- private static void beginShutdownSequence(Context context) {
- synchronized (sIsStartedGuard) {
- if (sIsStarted) {
- Log.d(TAG, "Shutdown sequence already running, returning.");
- return;
- }
- sIsStarted = true;
- }
-
+ private static ProgressDialog showShutdownDialog(Context context) {
// Throw up a system dialog to indicate the device is rebooting / shutting down.
ProgressDialog pd = new ProgressDialog(context);
@@ -303,6 +295,32 @@
pd.setMessage(context.getText(
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 = Color.WHITE;
+ try {
+ IOverlayManager service = IOverlayManager.Stub.asInterface(
+ ServiceManager.getService(Context.OVERLAY_SERVICE));
+ if (service.getOverlayInfo("com.android.systemui.theme.lightwallpaper", 0).isEnabled()) {
+ color = Color.BLACK;
+ }
+ } catch (Exception e) {
+ // Shutdown UI really shouldn't crash or have strict dependencies on other services.
+ Log.w(TAG, "Problem getting overlay state", e);
+ }
+ 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 {
pd.setTitle(context.getText(com.android.internal.R.string.power_off));
pd.setMessage(context.getText(com.android.internal.R.string.shutdown_progress));
@@ -312,8 +330,19 @@
pd.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
pd.show();
+ return pd;
+ }
- sInstance.mProgressDialog = pd;
+ private static void beginShutdownSequence(Context context) {
+ synchronized (sIsStartedGuard) {
+ if (sIsStarted) {
+ Log.d(TAG, "Shutdown sequence already running, returning.");
+ return;
+ }
+ sIsStarted = true;
+ }
+
+ sInstance.mProgressDialog = showShutdownDialog(context);
sInstance.mContext = context;
sInstance.mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
diff --git a/tests/net/java/com/android/server/connectivity/TetheringTest.java b/tests/net/java/com/android/server/connectivity/TetheringTest.java
index ab874ce..acf9e8f7 100644
--- a/tests/net/java/com/android/server/connectivity/TetheringTest.java
+++ b/tests/net/java/com/android/server/connectivity/TetheringTest.java
@@ -16,6 +16,11 @@
package com.android.server.connectivity;
+import static android.hardware.usb.UsbManager.USB_CONFIGURED;
+import static android.hardware.usb.UsbManager.USB_CONNECTED;
+import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.ConnectivityManager.TETHERING_WIFI;
+import static android.net.ConnectivityManager.TETHERING_USB;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
@@ -133,6 +138,7 @@
public Object getSystemService(String name) {
if (Context.CONNECTIVITY_SERVICE.equals(name)) return mConnectivityManager;
if (Context.WIFI_SERVICE.equals(name)) return mWifiManager;
+ if (Context.USB_SERVICE.equals(name)) return mUsbManager;
return super.getSystemService(name);
}
}
@@ -145,7 +151,7 @@
when(mResources.getStringArray(com.android.internal.R.array.config_tether_usb_regexs))
.thenReturn(new String[0]);
when(mResources.getStringArray(com.android.internal.R.array.config_tether_wifi_regexs))
- .thenReturn(new String[]{ "test_wlan\\d" });
+ .thenReturn(new String[]{ "test_wlan\\d", "test_rndis\\d" });
when(mResources.getStringArray(com.android.internal.R.array.config_tether_bluetooth_regexs))
.thenReturn(new String[0]);
when(mResources.getIntArray(com.android.internal.R.array.config_tether_upstream_types))
@@ -245,6 +251,14 @@
mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
+ private void sendUsbBroadcast(boolean connected, boolean configured, boolean rndisFunction) {
+ final Intent intent = new Intent(UsbManager.ACTION_USB_STATE);
+ intent.putExtra(USB_CONNECTED, connected);
+ intent.putExtra(USB_CONFIGURED, configured);
+ intent.putExtra(USB_FUNCTION_RNDIS, rndisFunction);
+ mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+ }
+
private void verifyInterfaceServingModeStarted() throws Exception {
verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
verify(mNMService, times(1))
@@ -287,6 +301,32 @@
}
@Test
+ public void testUsbConfiguredBroadcastStartsTethering() throws Exception {
+ when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
+
+ // Emulate pressing the USB tethering button in Settings UI.
+ mTethering.startTethering(TETHERING_USB, null, false);
+ mLooper.dispatchAll();
+ verify(mUsbManager, times(1)).setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS, false);
+
+ // Pretend we receive a USB connected broadcast. Here we also pretend
+ // that the RNDIS function is somehow enabled, so that we see if we
+ // might trip ourselves up.
+ sendUsbBroadcast(true, false, true);
+ mLooper.dispatchAll();
+ // This should produce no activity of any kind.
+ verifyNoMoreInteractions(mConnectivityManager);
+ verifyNoMoreInteractions(mNMService);
+
+ // Pretend we then receive USB configured broadcast.
+ sendUsbBroadcast(true, true, true);
+ mLooper.dispatchAll();
+ // Now we should see the start of tethering mechanics (in this case:
+ // tetherMatchingInterfaces() which starts by fetching all interfaces).
+ verify(mNMService, times(1)).listInterfaces();
+ }
+
+ @Test
public void failingLocalOnlyHotspotLegacyApBroadcastWithIfaceStatusChanged() throws Exception {
failingLocalOnlyHotspotLegacyApBroadcast(true);
}
@@ -366,7 +406,7 @@
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+ mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
@@ -394,7 +434,7 @@
when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+ mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);
@@ -440,7 +480,7 @@
/////
// Emulate pressing the WiFi tethering button.
- mTethering.stopTethering(ConnectivityManager.TETHERING_WIFI);
+ mTethering.stopTethering(TETHERING_WIFI);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).stopSoftAp();
verifyNoMoreInteractions(mWifiManager);
@@ -476,7 +516,7 @@
doThrow(new RemoteException()).when(mNMService).setIpForwardingEnabled(true);
// Emulate pressing the WiFi tethering button.
- mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+ mTethering.startTethering(TETHERING_WIFI, null, false);
mLooper.dispatchAll();
verify(mWifiManager, times(1)).startSoftAp(null);
verifyNoMoreInteractions(mWifiManager);