Merge "Have UserController use a CarUserSwitchingDialog instead of a UserSwitchingDialog if the FEATURE_AUTOMOTIVE flag is present so Android Auto can customize the look of the dialog." into pi-dev am: f2b624c140
am: 9e3f9281fb
Change-Id: I188d19fbe2428b0146005b99cb8fa965a57c43eb
This commit is contained in:
40
core/res/res/layout/car_user_switching_dialog.xml
Normal file
40
core/res/res/layout/car_user_switching_dialog.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 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.
|
||||
-->
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:fitsSystemWindows="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/user_loading_avatar"
|
||||
android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
|
||||
android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
|
||||
android:layout_centerHorizontal="true"
|
||||
/>
|
||||
|
||||
<TextView android:id="@+id/user_loading"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/car_padding_4"
|
||||
android:textSize="@dimen/car_body1_size"
|
||||
android:textColor="@color/car_body1_light"
|
||||
android:layout_below="@id/user_loading_avatar"
|
||||
android:gravity="center"
|
||||
/>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -24,4 +24,4 @@
|
||||
android:paddingStart="?attr/dialogPreferredPadding"
|
||||
android:paddingEnd="?attr/dialogPreferredPadding"
|
||||
android:paddingTop="24dp"
|
||||
android:paddingBottom="24dp" />
|
||||
android:paddingBottom="24dp" />
|
||||
31
core/res/res/values/colors_car.xml
Normal file
31
core/res/res/values/colors_car.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright 2018, 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.
|
||||
*/
|
||||
-->
|
||||
<resources>
|
||||
<!-- car support colors from
|
||||
https://cs.corp.google.com/android/frameworks/support/car/res/values/colors.xml -->
|
||||
<color name="car_user_switcher_user_image_bgcolor">@color/car_grey_50</color>
|
||||
<color name="car_user_switcher_user_image_fgcolor">@color/car_grey_900</color>
|
||||
<color name="car_card_dark">@color/car_dark_blue_grey_700</color>
|
||||
<color name="car_body1_light">@color/car_grey_100</color>
|
||||
|
||||
<color name="car_grey_50">#fffafafa</color>
|
||||
<color name="car_grey_900">#ff212121</color>
|
||||
<color name="car_dark_blue_grey_700">#ff172026</color>
|
||||
<color name="car_grey_100">#fff5f5f5</color>
|
||||
</resources>
|
||||
27
core/res/res/values/dimens_car.xml
Normal file
27
core/res/res/values/dimens_car.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
-->
|
||||
<resources>
|
||||
<!-- TODO replace with car support lib sizes when available -->
|
||||
<dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
|
||||
<dimen name="car_fullscreen_user_pod_width">243dp</dimen>
|
||||
<dimen name="car_fullscreen_user_pod_height">356dp</dimen>
|
||||
<dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
|
||||
<dimen name="car_fullscreen_user_pod_image_avatar_height">96dp</dimen>
|
||||
<dimen name="car_padding_4">20dp</dimen>
|
||||
<dimen name="car_body1_size">32sp</dimen>
|
||||
</resources>
|
||||
@@ -4957,4 +4957,8 @@
|
||||
<string name="notification_app_name_system">System</string>
|
||||
<!-- Application name displayed in notifications [CHAR LIMIT=60] -->
|
||||
<string name="notification_app_name_settings">Settings</string>
|
||||
|
||||
<!-- Strings for car -->
|
||||
<!-- String displayed when loading a user in the car [CHAR LIMIT=30] -->
|
||||
<string name="car_loading_profile">Loading</string>
|
||||
</resources>
|
||||
|
||||
@@ -3344,4 +3344,19 @@
|
||||
|
||||
<java-symbol type="integer" name="config_lowBatteryAutoTriggerDefaultLevel" />
|
||||
|
||||
<!-- For car devices -->
|
||||
<java-symbol type="string" name="car_loading_profile" />
|
||||
<java-symbol type="color" name="car_body1_light" />
|
||||
<java-symbol type="color" name="car_user_switcher_user_image_bgcolor" />
|
||||
<java-symbol type="color" name="car_user_switcher_user_image_fgcolor" />
|
||||
<java-symbol type="color" name="car_card_dark" />
|
||||
<java-symbol type="dimen" name="car_body1_size" />
|
||||
<java-symbol type="dimen" name="car_padding_4" />
|
||||
<java-symbol type="dimen" name="car_fullscreen_user_pod_icon_text_size" />
|
||||
<java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_height" />
|
||||
<java-symbol type="dimen" name="car_fullscreen_user_pod_image_avatar_width" />
|
||||
<java-symbol type="layout" name="car_user_switching_dialog" />
|
||||
<java-symbol type="id" name="user_loading_avatar" />
|
||||
<java-symbol type="id" name="user_loading" />
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/car_padding_4"
|
||||
android:textSize="@dimen/car_body1_size"
|
||||
android:textColor="@color/qs_user_detail_name"
|
||||
android:textColor="@color/car_body1_light"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:gravity="center"
|
||||
|
||||
@@ -18,20 +18,12 @@
|
||||
android:fitsSystemWindows="true"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@android:color/black"
|
||||
android:background="@color/car_card_dark"
|
||||
android:visibility="gone">
|
||||
|
||||
<!-- This progressbar is activated while we're switching users. -->
|
||||
<ProgressBar
|
||||
android:id="@+id/switching_users"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:indeterminate="true"
|
||||
android:visibility="gone"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/container"
|
||||
android:background="@color/car_card_dark"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<dimen name="car_margin_standard">112dp</dimen>
|
||||
|
||||
<!-- TODO replace with car support lib sizes when available -->
|
||||
<dimen name="car_fullscreen_user_pod_icon_text_size">32sp</dimen>
|
||||
<dimen name="car_fullscreen_user_pod_icon_text_size">64sp</dimen>
|
||||
<dimen name="car_fullscreen_user_pod_width">243dp</dimen>
|
||||
<dimen name="car_fullscreen_user_pod_height">356dp</dimen>
|
||||
<dimen name="car_fullscreen_user_pod_image_avatar_width">96dp</dimen>
|
||||
|
||||
@@ -21,7 +21,6 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.content.Context;
|
||||
import android.view.View;
|
||||
import android.view.ViewStub;
|
||||
import android.widget.ProgressBar;
|
||||
|
||||
import android.support.v7.widget.GridLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
@@ -37,7 +36,6 @@ public class FullscreenUserSwitcher {
|
||||
private final View mContainer;
|
||||
private final View mParent;
|
||||
private final UserGridRecyclerView mUserGridView;
|
||||
private final ProgressBar mSwitchingUsers;
|
||||
private final int mShortAnimDuration;
|
||||
private final StatusBar mStatusBar;
|
||||
private final UserManagerHelper mUserManagerHelper;
|
||||
@@ -60,8 +58,6 @@ public class FullscreenUserSwitcher {
|
||||
|
||||
mShortAnimDuration = mContainer.getResources()
|
||||
.getInteger(android.R.integer.config_shortAnimTime);
|
||||
|
||||
mSwitchingUsers = mParent.findViewById(R.id.switching_users);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
@@ -112,10 +108,11 @@ public class FullscreenUserSwitcher {
|
||||
|
||||
private void toggleSwitchInProgress(boolean inProgress) {
|
||||
if (inProgress) {
|
||||
crossFade(mSwitchingUsers, mContainer);
|
||||
crossFade(mParent, mContainer);
|
||||
} else {
|
||||
crossFade(mContainer, mSwitchingUsers);
|
||||
crossFade(mContainer, mParent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void crossFade(View incoming, View outgoing) {
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* 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.statusbar.car;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.database.DataSetObserver;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.support.v4.view.PagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Gravity;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import com.android.systemui.R;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Displays the dots underneath the ViewPager on the lock screen. This is really just a simplified
|
||||
* version of PagerTitleStrip. We don't inherit from there because it's impossible to bypass some
|
||||
* of the overriden logic in that class.
|
||||
*/
|
||||
public class PageIndicator extends View {
|
||||
private static final String TAG = "PageIndicator";
|
||||
// These can be made a styleable attribute in the future if necessary.
|
||||
private static final int SELECTED_COLOR = 0xFFF5F5F5; // grey 100
|
||||
private static final int UNSELECTED_COLOR = 0xFFBDBDBD; // grey 400
|
||||
private final PageListener mPageListener = new PageListener();
|
||||
|
||||
private ViewPager mPager;
|
||||
private WeakReference<PagerAdapter> mWatchingAdapter;
|
||||
|
||||
private int mPageCount;
|
||||
private int mCurrentPosition;
|
||||
private Paint mPaint;
|
||||
private int mRadius;
|
||||
private int mStep;
|
||||
|
||||
public PageIndicator(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
public PageIndicator(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
mPaint.setStyle(Paint.Style.FILL);
|
||||
mRadius = getResources().getDimensionPixelSize(R.dimen.car_page_indicator_dot_diameter) / 2;
|
||||
mStep = mRadius * 3;
|
||||
}
|
||||
|
||||
public void setupWithViewPager(ViewPager pager) {
|
||||
mPager = pager;
|
||||
|
||||
final PagerAdapter adapter = (PagerAdapter) pager.getAdapter();
|
||||
pager.addOnPageChangeListener(mPageListener);
|
||||
pager.addOnAdapterChangeListener(mPageListener);
|
||||
updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
if (mPager != null) {
|
||||
updateAdapter(mPager.getAdapter(), null);
|
||||
mPager.removeOnPageChangeListener(mPageListener);
|
||||
mPager.removeOnAdapterChangeListener(mPageListener);
|
||||
mPager = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
// Don't draw anything unless there's multiple pages to scroll through. No need to clear
|
||||
// any previous dots, since onDraw provides a canvas that's already cleared.
|
||||
if (mPageCount <= 1)
|
||||
return;
|
||||
|
||||
int x = canvas.getWidth() / 2 - (mPageCount / 2) * mStep;
|
||||
int y = canvas.getHeight() / 2;
|
||||
|
||||
for (int i = 0; i < mPageCount; i++) {
|
||||
if (i == mCurrentPosition) {
|
||||
mPaint.setColor(SELECTED_COLOR);
|
||||
} else {
|
||||
mPaint.setColor(UNSELECTED_COLOR);
|
||||
}
|
||||
|
||||
canvas.drawCircle(x, y, mRadius, mPaint);
|
||||
x += mStep;
|
||||
}
|
||||
}
|
||||
|
||||
void updateAdapter(PagerAdapter oldAdapter, PagerAdapter newAdapter) {
|
||||
if (oldAdapter != null) {
|
||||
oldAdapter.unregisterDataSetObserver(mPageListener);
|
||||
mWatchingAdapter = null;
|
||||
}
|
||||
|
||||
if (newAdapter != null) {
|
||||
newAdapter.registerDataSetObserver(mPageListener);
|
||||
mWatchingAdapter = new WeakReference<>(newAdapter);
|
||||
}
|
||||
|
||||
updateDots();
|
||||
|
||||
if (mPager != null) {
|
||||
requestLayout();
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T getRef(WeakReference<T> weakRef) {
|
||||
if (weakRef == null) {
|
||||
return null;
|
||||
}
|
||||
return weakRef.get();
|
||||
}
|
||||
|
||||
private void updateDots() {
|
||||
PagerAdapter adapter = getRef(mWatchingAdapter);
|
||||
if (adapter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int count = adapter.getCount();
|
||||
if (mPageCount == count) {
|
||||
// Nothing to be done.
|
||||
return;
|
||||
}
|
||||
|
||||
mPageCount = count;
|
||||
mCurrentPosition = 0;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private class PageListener extends DataSetObserver implements ViewPager.OnPageChangeListener,
|
||||
ViewPager.OnAdapterChangeListener {
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int unused1, float unused2, int unused3) { }
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
if (mCurrentPosition == position) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (mPageCount <= position) {
|
||||
Log.e(TAG, "Position out of bounds, position=" + position + " size=" + mPageCount);
|
||||
return;
|
||||
}
|
||||
|
||||
mCurrentPosition = position;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) { }
|
||||
|
||||
@Override
|
||||
public void onAdapterChanged(ViewPager viewPager, PagerAdapter oldAdapter,
|
||||
PagerAdapter newAdapter) {
|
||||
updateAdapter(oldAdapter, newAdapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChanged() {
|
||||
updateDots();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,13 +263,13 @@ public class UserGridRecyclerView extends RecyclerView implements
|
||||
GradientDrawable shape = new GradientDrawable();
|
||||
shape.setShape(GradientDrawable.RADIAL_GRADIENT);
|
||||
shape.setGradientRadius(1.0f);
|
||||
shape.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_bgcolor));
|
||||
shape.setColor(mContext.getColor(R.color.car_grey_50));
|
||||
shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
|
||||
shape.draw(canvas);
|
||||
|
||||
// Draw the letter in the center.
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setColor(mContext.getColor(R.color.car_user_switcher_no_user_image_fgcolor));
|
||||
paint.setColor(mContext.getColor(R.color.car_grey_900));
|
||||
paint.setTextAlign(Align.CENTER);
|
||||
if (isAddUserText) {
|
||||
paint.setTextSize(mRes.getDimensionPixelSize(
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2018 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.am;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Paint.Align;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import com.android.internal.R;
|
||||
|
||||
/**
|
||||
* Dialog to show when a user switch it about to happen for the car. The intent is to snapshot the
|
||||
* screen immediately after the dialog shows so that the user is informed that something is
|
||||
* happening in the background rather than just freeze the screen and not know if the user-switch
|
||||
* affordance was being handled.
|
||||
*
|
||||
*/
|
||||
final class CarUserSwitchingDialog extends UserSwitchingDialog {
|
||||
private static final String TAG = "ActivityManagerCarUserSwitchingDialog";
|
||||
|
||||
public CarUserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
|
||||
UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
|
||||
String switchingToSystemUserMessage) {
|
||||
super(service, context, oldUser, newUser, aboveSystem, switchingFromSystemUserMessage,
|
||||
switchingToSystemUserMessage);
|
||||
|
||||
getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
void inflateContent() {
|
||||
// Set up the dialog contents
|
||||
setCancelable(false);
|
||||
Resources res = getContext().getResources();
|
||||
// Custom view due to alignment and font size requirements
|
||||
View view = LayoutInflater.from(getContext()).inflate(R.layout.car_user_switching_dialog,
|
||||
null);
|
||||
|
||||
((ImageView) view.findViewById(R.id.user_loading_avatar))
|
||||
.setImageBitmap(getDefaultUserIcon(mNewUser));
|
||||
((TextView) view.findViewById(R.id.user_loading))
|
||||
.setText(res.getString(R.string.car_loading_profile));
|
||||
setView(view);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default user icon. This icon is a circle with a letter in it. The letter is
|
||||
* the first character in the username.
|
||||
*
|
||||
* @param userInfo the profile of the user for which the icon should be created
|
||||
*/
|
||||
private Bitmap getDefaultUserIcon(UserInfo userInfo) {
|
||||
Resources res = mContext.getResources();
|
||||
int mPodImageAvatarWidth = res.getDimensionPixelSize(
|
||||
R.dimen.car_fullscreen_user_pod_image_avatar_width);
|
||||
int mPodImageAvatarHeight = res.getDimensionPixelSize(
|
||||
R.dimen.car_fullscreen_user_pod_image_avatar_height);
|
||||
CharSequence displayText = userInfo.name.subSequence(0, 1);
|
||||
Bitmap out = Bitmap.createBitmap(mPodImageAvatarWidth, mPodImageAvatarHeight,
|
||||
Bitmap.Config.ARGB_8888);
|
||||
Canvas canvas = new Canvas(out);
|
||||
|
||||
// Draw the circle background.
|
||||
GradientDrawable shape = new GradientDrawable();
|
||||
shape.setShape(GradientDrawable.RADIAL_GRADIENT);
|
||||
shape.setGradientRadius(1.0f);
|
||||
shape.setColor(mContext.getColor(R.color.car_user_switcher_user_image_bgcolor));
|
||||
shape.setBounds(0, 0, mPodImageAvatarWidth, mPodImageAvatarHeight);
|
||||
shape.draw(canvas);
|
||||
|
||||
// Draw the letter in the center.
|
||||
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setColor(mContext.getColor(R.color.car_user_switcher_user_image_fgcolor));
|
||||
paint.setTextAlign(Align.CENTER);
|
||||
paint.setTextSize(res.getDimensionPixelSize(
|
||||
R.dimen.car_fullscreen_user_pod_icon_text_size));
|
||||
|
||||
Paint.FontMetricsInt metrics = paint.getFontMetricsInt();
|
||||
// The Y coordinate is measured by taking half the height of the pod, but that would
|
||||
// draw the character putting the bottom of the font in the middle of the pod. To
|
||||
// correct this, half the difference between the top and bottom distance metrics of the
|
||||
// font gives the offset of the font. Bottom is a positive value, top is negative, so
|
||||
// the different is actually a sum. The "half" operation is then factored out.
|
||||
canvas.drawText(displayText.toString(), mPodImageAvatarWidth / 2,
|
||||
(mPodImageAvatarHeight - (metrics.bottom + metrics.top)) / 2, paint);
|
||||
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,7 @@ import android.os.storage.StorageManager;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.ArraySet;
|
||||
import android.util.IntArray;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseArray;
|
||||
@@ -86,6 +87,7 @@ import android.util.SparseIntArray;
|
||||
import android.util.TimingsTraceLog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import android.view.Window;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -2177,9 +2179,18 @@ class UserController implements Handler.Callback {
|
||||
|
||||
void showUserSwitchingDialog(UserInfo fromUser, UserInfo toUser,
|
||||
String switchingFromSystemUserMessage, String switchingToSystemUserMessage) {
|
||||
Dialog d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
|
||||
Dialog d;
|
||||
if (!mService.mContext.getPackageManager()
|
||||
.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
|
||||
d = new UserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
|
||||
true /* above system */, switchingFromSystemUserMessage,
|
||||
switchingToSystemUserMessage);
|
||||
} else {
|
||||
d = new CarUserSwitchingDialog(mService, mService.mContext, fromUser, toUser,
|
||||
true /* above system */, switchingFromSystemUserMessage,
|
||||
switchingToSystemUserMessage);
|
||||
}
|
||||
|
||||
d.show();
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ import com.android.internal.annotations.GuardedBy;
|
||||
* in the background rather than just freeze the screen and not know if the user-switch affordance
|
||||
* was being handled.
|
||||
*/
|
||||
final class UserSwitchingDialog extends AlertDialog
|
||||
class UserSwitchingDialog extends AlertDialog
|
||||
implements ViewTreeObserver.OnWindowShownListener {
|
||||
private static final String TAG = "ActivityManagerUserSwitchingDialog";
|
||||
|
||||
@@ -51,53 +51,69 @@ final class UserSwitchingDialog extends AlertDialog
|
||||
private static final int MSG_START_USER = 1;
|
||||
@GuardedBy("this")
|
||||
private boolean mStartedUser;
|
||||
final protected UserInfo mOldUser;
|
||||
final protected UserInfo mNewUser;
|
||||
final private String mSwitchingFromSystemUserMessage;
|
||||
final private String mSwitchingToSystemUserMessage;
|
||||
final protected Context mContext;
|
||||
|
||||
public UserSwitchingDialog(ActivityManagerService service, Context context, UserInfo oldUser,
|
||||
UserInfo newUser, boolean aboveSystem, String switchingFromSystemUserMessage,
|
||||
String switchingToSystemUserMessage) {
|
||||
super(context);
|
||||
|
||||
mContext = context;
|
||||
mService = service;
|
||||
mUserId = newUser.id;
|
||||
mOldUser = oldUser;
|
||||
mNewUser = newUser;
|
||||
mSwitchingFromSystemUserMessage = switchingFromSystemUserMessage;
|
||||
mSwitchingToSystemUserMessage = switchingToSystemUserMessage;
|
||||
|
||||
inflateContent();
|
||||
|
||||
if (aboveSystem) {
|
||||
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
|
||||
}
|
||||
|
||||
WindowManager.LayoutParams attrs = getWindow().getAttributes();
|
||||
attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
|
||||
WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
|
||||
getWindow().setAttributes(attrs);
|
||||
}
|
||||
|
||||
void inflateContent() {
|
||||
// Set up the dialog contents
|
||||
setCancelable(false);
|
||||
Resources res = getContext().getResources();
|
||||
// Custom view due to alignment and font size requirements
|
||||
View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog, null);
|
||||
View view = LayoutInflater.from(getContext()).inflate(R.layout.user_switching_dialog,
|
||||
null);
|
||||
|
||||
String viewMessage = null;
|
||||
if (UserManager.isSplitSystemUser() && newUser.id == UserHandle.USER_SYSTEM) {
|
||||
viewMessage = res.getString(R.string.user_logging_out_message, oldUser.name);
|
||||
} else if (UserManager.isDeviceInDemoMode(context)) {
|
||||
if (oldUser.isDemo()) {
|
||||
if (UserManager.isSplitSystemUser() && mNewUser.id == UserHandle.USER_SYSTEM) {
|
||||
viewMessage = res.getString(R.string.user_logging_out_message, mOldUser.name);
|
||||
} else if (UserManager.isDeviceInDemoMode(mContext)) {
|
||||
if (mOldUser.isDemo()) {
|
||||
viewMessage = res.getString(R.string.demo_restarting_message);
|
||||
} else {
|
||||
viewMessage = res.getString(R.string.demo_starting_message);
|
||||
}
|
||||
} else {
|
||||
if (oldUser.id == UserHandle.USER_SYSTEM) {
|
||||
viewMessage = switchingFromSystemUserMessage;
|
||||
} else if (newUser.id == UserHandle.USER_SYSTEM) {
|
||||
viewMessage = switchingToSystemUserMessage;
|
||||
if (mOldUser.id == UserHandle.USER_SYSTEM) {
|
||||
viewMessage = mSwitchingFromSystemUserMessage;
|
||||
} else if (mNewUser.id == UserHandle.USER_SYSTEM) {
|
||||
viewMessage = mSwitchingToSystemUserMessage;
|
||||
}
|
||||
|
||||
// If switchingFromSystemUserMessage or switchingToSystemUserMessage is null, fallback
|
||||
// to system message.
|
||||
if (viewMessage == null) {
|
||||
viewMessage = res.getString(R.string.user_switching_message, newUser.name);
|
||||
viewMessage = res.getString(R.string.user_switching_message, mNewUser.name);
|
||||
}
|
||||
}
|
||||
((TextView) view.findViewById(R.id.message)).setText(viewMessage);
|
||||
setView(view);
|
||||
|
||||
if (aboveSystem) {
|
||||
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
|
||||
}
|
||||
WindowManager.LayoutParams attrs = getWindow().getAttributes();
|
||||
attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR |
|
||||
WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
|
||||
getWindow().setAttributes(attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user