Snap for 5143127 from 4b19fecd50 to qt-release
Change-Id: Id545a8cbf60928830aab8549139703080e48bd2a
This commit is contained in:
40
res/layout/homepage_condition_footer.xml
Normal file
40
res/layout/homepage_condition_footer.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.
|
||||
-->
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/ContextualCardStyle">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/homepage_condition_footer_height"
|
||||
android:contentDescription="@string/homepage_condition_footer_content_description"
|
||||
android:gravity="end"
|
||||
android:orientation="horizontal"
|
||||
android:paddingTop="@dimen/homepage_condition_footer_padding_top"
|
||||
android:paddingEnd="@dimen/homepage_condition_footer_padding_end">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/collapse_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/ic_expand_less" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
52
res/layout/homepage_condition_header.xml
Normal file
52
res/layout/homepage_condition_header.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/ContextualCardStyle">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/homepage_condition_header_padding_top"
|
||||
android:paddingBottom="@dimen/homepage_condition_header_padding_bottom"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/header_icons_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="@dimen/homepage_condition_header_icons_margin_start"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/expand_indicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="@dimen/homepage_condition_header_indicator_padding_top"
|
||||
android:paddingStart="@dimen/homepage_condition_header_indicator_padding_start"
|
||||
android:paddingEnd="@dimen/homepage_condition_header_indicator_padding_end"
|
||||
android:src="@drawable/ic_expand_more"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
23
res/layout/homepage_condition_header_icon.xml
Normal file
23
res/layout/homepage_condition_header_icon.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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.
|
||||
-->
|
||||
|
||||
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="@dimen/homepage_condition_header_icon_width_height"
|
||||
android:layout_height="@dimen/homepage_condition_header_icon_width_height"
|
||||
android:layout_marginEnd="@dimen/homepage_condition_header_icon_margin_end"
|
||||
android:tint="?android:attr/colorAccent"/>
|
||||
@@ -20,44 +20,48 @@
|
||||
android:id="@+id/instant_app_button_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingTop="24dp"
|
||||
android:paddingStart="68dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:orientation="horizontal">
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/install"
|
||||
style="@style/ActionPrimaryButton"
|
||||
style="@style/SettingsActionButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/install_text"/>
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:text="@string/install_text"
|
||||
android:drawableTop="@drawable/ic_settings_install"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/launch"
|
||||
style="@style/ActionPrimaryButton"
|
||||
style="@style/SettingsActionButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/launch_instant_app"/>
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:text="@string/launch_instant_app"
|
||||
android:drawableTop="@drawable/ic_settings_open"/>
|
||||
</FrameLayout>
|
||||
|
||||
<Space
|
||||
android:layout_width="16dp"
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="wrap_content" />
|
||||
<FrameLayout
|
||||
|
||||
<Button
|
||||
android:id="@+id/clear_data"
|
||||
style="@style/SettingsActionButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="wrap_content">
|
||||
<Button
|
||||
android:id="@+id/clear_data"
|
||||
style="@style/ActionSecondaryButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/clear_instant_app_data"/>
|
||||
</FrameLayout>
|
||||
android:paddingTop="20dp"
|
||||
android:paddingBottom="20dp"
|
||||
android:text="@string/clear_instant_app_data"
|
||||
android:drawableTop="@drawable/ic_settings_delete"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -198,6 +198,12 @@
|
||||
+ (fingerprint_enrolling_content_margin_vertical x 2) -->
|
||||
<dimen name="fingerprint_finish_max_size">288dp</dimen>
|
||||
|
||||
<!-- Face -->
|
||||
<dimen name="face_preview_translate_y">0dp</dimen>
|
||||
<dimen name="face_preview_translate_x">0dp</dimen>
|
||||
<item name="face_preview_scale" format="float" type="dimen">1.0</item>
|
||||
|
||||
<!-- Confirm device credentials -->
|
||||
<dimen name="confirm_credentials_security_method_margin">48dp</dimen>
|
||||
<dimen name="confirm_credentials_layout_width">@dimen/match_parent</dimen>
|
||||
<dimen name="confirm_credentials_top_padding">0dp</dimen>
|
||||
@@ -349,5 +355,16 @@
|
||||
<dimen name="homepage_condition_full_card_padding_end">24dp</dimen>
|
||||
<dimen name="homepage_condition_full_card_padding_top">12dp</dimen>
|
||||
<dimen name="homepage_condition_full_card_padding_bottom">12dp</dimen>
|
||||
<dimen name="homepage_condition_header_padding_top">10dp</dimen>
|
||||
<dimen name="homepage_condition_header_padding_bottom">10dp</dimen>
|
||||
<dimen name="homepage_condition_header_icons_margin_start">24dp</dimen>
|
||||
<dimen name="homepage_condition_header_indicator_padding_top">4dp</dimen>
|
||||
<dimen name="homepage_condition_header_indicator_padding_start">16dp</dimen>
|
||||
<dimen name="homepage_condition_header_indicator_padding_end">16dp</dimen>
|
||||
<dimen name="homepage_condition_footer_height">44dp</dimen>
|
||||
<dimen name="homepage_condition_footer_padding_top">10dp</dimen>
|
||||
<dimen name="homepage_condition_footer_padding_end">10dp</dimen>
|
||||
<dimen name="homepage_condition_header_icon_width_height">24dp</dimen>
|
||||
<dimen name="homepage_condition_header_icon_margin_end">24dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -9105,6 +9105,9 @@
|
||||
<!-- Summary for the condition section on the dashboard, representing number of conditions. [CHAR LIMIT=10] -->
|
||||
<string name="condition_summary" translatable="false"><xliff:g name="count" example="3">%1$d</xliff:g></string>
|
||||
|
||||
<!-- Content description for condition footer button. In talkback mode, double tapping will cause condition list to collapse [CHAR LIMIT=NONE]-->
|
||||
<string name="homepage_condition_footer_content_description">Collapse</string>
|
||||
|
||||
<!-- Title for the suggestions section on the dashboard [CHAR LIMIT=30] -->
|
||||
<string name="suggestions_title_v2">Suggested for You</string>
|
||||
|
||||
@@ -10315,10 +10318,10 @@
|
||||
<!-- UI debug setting: force desktop mode summary [CHAR LIMIT=NONE] -->
|
||||
<string name="force_desktop_mode_summary">Force experimental desktop mode on secondary displays</string>
|
||||
|
||||
<!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=25] -->
|
||||
<string name="hwui_force_dark_title">Force-enable SmartDark</string>
|
||||
<!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=50] -->
|
||||
<string name="hwui_force_dark_summary">Forces the SmartDark feature to be always-on</string>
|
||||
<!-- UI debug setting: Force enable "smart dark" UI rendering feature [CHAR LIMIT=40] -->
|
||||
<string name="hwui_force_dark_title">Override force-dark</string>
|
||||
<!-- UI debug setting: Force enable "smart dark" UI rendering feature summary [CHAR LIMIT=100] -->
|
||||
<string name="hwui_force_dark_summary">Overrides the force-dark feature to be always-on</string>
|
||||
|
||||
<!-- Title for the top level Privacy Settings [CHAR LIMIT=30]-->
|
||||
<string name="privacy_dashboard_title">Privacy</string>
|
||||
|
||||
@@ -264,8 +264,8 @@
|
||||
|
||||
<style name="TextAppearance.Medium" parent="@android:style/TextAppearance.Material.Medium"/>
|
||||
<style name="TextAppearance.Small" parent="@android:style/TextAppearance.Material.Small"/>
|
||||
<style name="TextAppearance.Switch" parent="@android:style/TextAppearance.Material.Title">
|
||||
<item name="android:textSize">18sp</item>
|
||||
<style name="TextAppearance.Switch" parent="@android:style/TextAppearance.DeviceDefault.Widget.ActionBar.Title">
|
||||
<item name="android:textSize">16sp</item>
|
||||
</style>
|
||||
|
||||
<style name="TextAppearance.CategoryTitle"
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
android:key="instant_app_buttons"
|
||||
android:layout="@layout/instant_app_buttons"
|
||||
android:selectable="false"
|
||||
android:order="-9999" />
|
||||
android:order="-9999"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="true"/>
|
||||
|
||||
<com.android.settings.widget.ActionButtonPreference
|
||||
android:key="action_buttons"
|
||||
|
||||
@@ -24,7 +24,8 @@
|
||||
|
||||
<com.android.settings.applications.SpacePreference
|
||||
android:key="storage_space"
|
||||
android:layout_height="8dp" />
|
||||
android:layout_height="8dp"
|
||||
settings:allowDividerAbove="true"/>
|
||||
|
||||
<Preference
|
||||
android:key="storage_used"
|
||||
@@ -41,7 +42,6 @@
|
||||
<PreferenceCategory
|
||||
android:key="storage_category"
|
||||
android:title="@string/app_info_storage_title"
|
||||
settings:allowDividerAbove="false"
|
||||
settings:allowDividerBelow="false">
|
||||
|
||||
<Preference
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
android:key="header_view"
|
||||
android:layout="@layout/settings_entity_header"
|
||||
android:selectable="false"
|
||||
android:order="-10000"/>
|
||||
android:order="-10000"
|
||||
settings:allowDividerBelow="true"/>
|
||||
|
||||
<com.android.settings.widget.ActionButtonPreference
|
||||
android:key="action_buttons"
|
||||
|
||||
@@ -55,27 +55,37 @@ public class AvatarViewMixin implements LifecycleObserver {
|
||||
|
||||
private static final String METHOD_GET_ACCOUNT_AVATAR = "getAccountAvatar";
|
||||
private static final String KEY_AVATAR_BITMAP = "account_avatar";
|
||||
private static final String KEY_ACCOUNT_NAME = "account_name";
|
||||
private static final String EXTRA_ACCOUNT_NAME = "extra.accountName";
|
||||
private static final int REQUEST_CODE = 1013;
|
||||
|
||||
private final Context mContext;
|
||||
private final ImageView mAvatarView;
|
||||
private final MutableLiveData<Bitmap> mAvatarImage;
|
||||
|
||||
private String mAccountName;
|
||||
|
||||
public AvatarViewMixin(SettingsHomepageActivity activity, ImageView avatarView) {
|
||||
mContext = activity.getApplicationContext();
|
||||
mAvatarView = avatarView;
|
||||
mAvatarView.setOnClickListener(v -> {
|
||||
if (hasAccount()) {
|
||||
//TODO(b/117509285) launch the new page of the MeCard
|
||||
} else {
|
||||
final Intent intent = FeatureFactory.getFactory(mContext)
|
||||
.getAccountFeatureProvider()
|
||||
.getAccountSettingsDeeplinkIntent();
|
||||
final Intent intent = FeatureFactory.getFactory(mContext)
|
||||
.getAccountFeatureProvider()
|
||||
.getAccountSettingsDeeplinkIntent();
|
||||
|
||||
if (intent != null) {
|
||||
activity.startActivityForResult(intent, REQUEST_CODE);
|
||||
}
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(mAccountName)) {
|
||||
//TODO(b/117509285) launch the new page of the MeCard
|
||||
intent.putExtra(EXTRA_ACCOUNT_NAME, mAccountName);
|
||||
}
|
||||
|
||||
// Here may have two different UI while start the activity.
|
||||
// It will display adding account UI when device has no any account.
|
||||
// It will display account information page when intent added the specified account.
|
||||
activity.startActivityForResult(intent, REQUEST_CODE);
|
||||
});
|
||||
|
||||
mAvatarImage = new MutableLiveData<>();
|
||||
@@ -91,7 +101,7 @@ public class AvatarViewMixin implements LifecycleObserver {
|
||||
return;
|
||||
}
|
||||
if (hasAccount()) {
|
||||
loadAvatar();
|
||||
loadAccount();
|
||||
} else {
|
||||
mAvatarView.setImageResource(R.drawable.ic_account_circle_24dp);
|
||||
}
|
||||
@@ -104,7 +114,7 @@ public class AvatarViewMixin implements LifecycleObserver {
|
||||
return (accounts != null) && (accounts.length > 0);
|
||||
}
|
||||
|
||||
private void loadAvatar() {
|
||||
private void loadAccount() {
|
||||
final String authority = queryProviderAuthority();
|
||||
if (TextUtils.isEmpty(authority)) {
|
||||
return;
|
||||
@@ -117,6 +127,7 @@ public class AvatarViewMixin implements LifecycleObserver {
|
||||
final Bundle bundle = mContext.getContentResolver().call(uri,
|
||||
METHOD_GET_ACCOUNT_AVATAR, null /* arg */, null /* extras */);
|
||||
final Bitmap bitmap = bundle.getParcelable(KEY_AVATAR_BITMAP);
|
||||
mAccountName = bundle.getString(KEY_ACCOUNT_NAME, "" /* defaultValue */);
|
||||
mAvatarImage.postValue(bitmap);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package com.android.settings.biometrics.face;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.hardware.camera2.CameraAccessException;
|
||||
import android.hardware.camera2.CameraCaptureSession;
|
||||
@@ -31,6 +30,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.util.Size;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Surface;
|
||||
import android.view.TextureView;
|
||||
import android.view.View;
|
||||
@@ -41,11 +41,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.biometrics.BiometricEnrollSidecar;
|
||||
import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Fragment that contains the logic for showing and controlling the camera preview, circular
|
||||
@@ -120,7 +116,6 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
|
||||
@Override
|
||||
public void onOpened(CameraDevice cameraDevice) {
|
||||
mCameraDevice = cameraDevice;
|
||||
|
||||
try {
|
||||
// Configure the size of default buffer
|
||||
SurfaceTexture texture = mTextureView.getSurfaceTexture();
|
||||
@@ -245,11 +240,8 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
|
||||
|
||||
/**
|
||||
* Sets up member variables related to camera.
|
||||
*
|
||||
* @param width The width of available size for camera preview
|
||||
* @param height The height of available size for camera preview
|
||||
*/
|
||||
private void setUpCameraOutputs(int width, int height) {
|
||||
private void setUpCameraOutputs() {
|
||||
try {
|
||||
for (String cameraId : mCameraManager.getCameraIdList()) {
|
||||
CameraCharacteristics characteristics =
|
||||
@@ -265,8 +257,7 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
|
||||
// Get the stream configurations
|
||||
StreamConfigurationMap map = characteristics.get(
|
||||
CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
|
||||
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
|
||||
width, height, MAX_PREVIEW_WIDTH, MAX_PREVIEW_HEIGHT);
|
||||
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class));
|
||||
break;
|
||||
}
|
||||
} catch (CameraAccessException e) {
|
||||
@@ -281,7 +272,7 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
|
||||
*/
|
||||
private void openCamera(int width, int height) {
|
||||
try {
|
||||
setUpCameraOutputs(width, height);
|
||||
setUpCameraOutputs();
|
||||
mCameraManager.openCamera(mCameraId, mCameraStateCallback, mHandler);
|
||||
configureTransform(width, height);
|
||||
} catch (CameraAccessException e) {
|
||||
@@ -292,35 +283,15 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
|
||||
/**
|
||||
* Chooses the optimal resolution for the camera to open.
|
||||
*/
|
||||
private Size chooseOptimalSize(Size[] choices, int textureViewWidth, int textureViewHeight,
|
||||
int maxWidth, int maxHeight) {
|
||||
// Collect the supported resolutions that are at least as big as the preview Surface
|
||||
List<Size> bigEnough = new ArrayList<>();
|
||||
// Collect the supported resolutions that are smaller than the preview Surface
|
||||
List<Size> notBigEnough = new ArrayList<>();
|
||||
|
||||
for (Size option : choices) {
|
||||
if (option.getWidth() <= maxWidth && option.getHeight() <= maxHeight &&
|
||||
option.getHeight() == option.getWidth()) {
|
||||
if (option.getWidth() >= textureViewWidth &&
|
||||
option.getHeight() >= textureViewHeight) {
|
||||
bigEnough.add(option);
|
||||
} else {
|
||||
notBigEnough.add(option);
|
||||
}
|
||||
private Size chooseOptimalSize(Size[] choices) {
|
||||
for (int i = 0; i < choices.length; i++) {
|
||||
if (choices[i].getHeight() == MAX_PREVIEW_HEIGHT
|
||||
&& choices[i].getWidth() == MAX_PREVIEW_WIDTH) {
|
||||
return choices[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Pick the smallest of those big enough. If there is no one big enough, pick the
|
||||
// largest of those not big enough.
|
||||
if (bigEnough.size() > 0) {
|
||||
return Collections.min(bigEnough, new CompareSizesByArea());
|
||||
} else if (notBigEnough.size() > 0) {
|
||||
return Collections.max(notBigEnough, new CompareSizesByArea());
|
||||
} else {
|
||||
Log.e(TAG, "Couldn't find any suitable preview size");
|
||||
return choices[0];
|
||||
}
|
||||
Log.w(TAG, "Unable to find a good resolution");
|
||||
return choices[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -337,19 +308,22 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
|
||||
}
|
||||
|
||||
// Fix the aspect ratio
|
||||
Matrix matrix = new Matrix();
|
||||
float scaleX = (float) viewWidth / mPreviewSize.getWidth();
|
||||
float scaleY = (float) viewHeight / mPreviewSize.getHeight();
|
||||
|
||||
// Now divide by smaller one so it fills up the original space
|
||||
// Now divide by smaller one so it fills up the original space.
|
||||
float smaller = Math.min(scaleX, scaleY);
|
||||
scaleX = scaleX / smaller;
|
||||
scaleY = scaleY / smaller;
|
||||
|
||||
// Apply the scale
|
||||
matrix.setScale(scaleX, scaleY);
|
||||
// Apply the transformation/scale
|
||||
mTextureView.setTranslationX(getResources().getDimension(R.dimen.face_preview_translate_x));
|
||||
mTextureView.setTranslationY(getResources().getDimension(R.dimen.face_preview_translate_y));
|
||||
|
||||
mTextureView.setTransform(matrix);
|
||||
final TypedValue scale = new TypedValue();
|
||||
getResources().getValue(R.dimen.face_preview_scale, scale, true /* resolveRefs */);
|
||||
mTextureView.setScaleX(scaleX * scale.getFloat());
|
||||
mTextureView.setScaleY(scaleY * scale.getFloat());
|
||||
}
|
||||
|
||||
private void closeCamera() {
|
||||
@@ -362,18 +336,4 @@ public class FaceEnrollPreviewFragment extends InstrumentedPreferenceFragment
|
||||
mCameraDevice = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two {@code Size}s based on their areas.
|
||||
*/
|
||||
private static class CompareSizesByArea implements Comparator<Size> {
|
||||
@Override
|
||||
public int compare(Size lhs, Size rhs) {
|
||||
// We cast here to ensure the multiplications won't overflow
|
||||
return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
|
||||
(long) rhs.getWidth() * rhs.getHeight());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.settings.homepage.contextualcards;
|
||||
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
@@ -36,10 +37,15 @@ import com.android.settingslib.utils.ThreadUtils;
|
||||
*/
|
||||
public class CardContentProvider extends ContentProvider {
|
||||
|
||||
private static final String TAG = "CardContentProvider";
|
||||
|
||||
public static final String CARD_AUTHORITY = "com.android.settings.homepage.CardContentProvider";
|
||||
|
||||
public static final Uri URI = new Uri.Builder()
|
||||
.scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(CardContentProvider.CARD_AUTHORITY)
|
||||
.appendPath(CardDatabaseHelper.CARD_TABLE)
|
||||
.build();
|
||||
|
||||
private static final String TAG = "CardContentProvider";
|
||||
/** URI matcher for ContentProvider queries. */
|
||||
private static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
/** URI matcher type for cards table */
|
||||
@@ -98,17 +104,7 @@ public class CardContentProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public int delete(Uri uri, String selection, String[] selectionArgs) {
|
||||
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
try {
|
||||
maybeEnableStrictMode();
|
||||
final SQLiteDatabase database = mDBHelper.getWritableDatabase();
|
||||
final String table = getTableFromMatch(uri);
|
||||
final int rowsDeleted = database.delete(table, selection, selectionArgs);
|
||||
getContext().getContentResolver().notifyChange(uri, null /* observer */);
|
||||
return rowsDeleted;
|
||||
} finally {
|
||||
StrictMode.setThreadPolicy(oldPolicy);
|
||||
}
|
||||
throw new UnsupportedOperationException("delete operation not supported currently.");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,18 +136,7 @@ public class CardContentProvider extends ContentProvider {
|
||||
|
||||
@Override
|
||||
public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
|
||||
final StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
|
||||
try {
|
||||
maybeEnableStrictMode();
|
||||
|
||||
final SQLiteDatabase database = mDBHelper.getWritableDatabase();
|
||||
final String table = getTableFromMatch(uri);
|
||||
final int rowsUpdated = database.update(table, values, selection, selectionArgs);
|
||||
getContext().getContentResolver().notifyChange(uri, null /* observer */);
|
||||
return rowsUpdated;
|
||||
} finally {
|
||||
StrictMode.setThreadPolicy(oldPolicy);
|
||||
}
|
||||
throw new UnsupportedOperationException("update operation not supported currently.");
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -209,16 +209,19 @@ public class CardDatabaseHelper extends SQLiteOpenHelper {
|
||||
* Mark a specific ContextualCard with dismissal flag in the database to indicate that the
|
||||
* card has been dismissed.
|
||||
*
|
||||
* @param cardName the card name of the ContextualCard which is dismissed by user.
|
||||
* @return updated row number
|
||||
* @param context Context
|
||||
* @param cardName The card name of the ContextualCard which is dismissed by user.
|
||||
* @return The number of rows updated
|
||||
*/
|
||||
public int markContextualCardAsDismissed(String cardName) {
|
||||
final SQLiteDatabase database = this.getWritableDatabase();
|
||||
public int markContextualCardAsDismissed(Context context, String cardName) {
|
||||
final SQLiteDatabase database = getWritableDatabase();
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(CardColumns.CARD_DISMISSED, 1);
|
||||
final String selection = CardColumns.NAME + "=?";
|
||||
final String[] selectionArgs = {cardName};
|
||||
final int rowsUpdated = database.update(CARD_TABLE, values, selection, selectionArgs);
|
||||
database.close();
|
||||
context.getContentResolver().notifyChange(CardContentProvider.URI, null);
|
||||
return rowsUpdated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,11 @@ import android.content.ContentProviderClient;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.ContentObserver;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -60,6 +63,19 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
|
||||
mContext = context.getApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
super.onStartLoading();
|
||||
mContext.getContentResolver().registerContentObserver(CardContentProvider.URI,
|
||||
false /*notifyForDescendants*/, mObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
super.onStopLoading();
|
||||
mContext.getContentResolver().unregisterContentObserver(mObserver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDiscardResult(List<ContextualCard> result) {
|
||||
|
||||
@@ -184,4 +200,14 @@ public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>
|
||||
}
|
||||
return -1L;
|
||||
}
|
||||
|
||||
private final ContentObserver mObserver = new ContentObserver(
|
||||
new Handler(Looper.getMainLooper())) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
if (isStarted()) {
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public class ControllerRendererPool {
|
||||
if (ConditionContextualCardController.class == clz) {
|
||||
return new ConditionContextualCardController(context);
|
||||
} else if (SliceContextualCardController.class == clz) {
|
||||
return new SliceContextualCardController();
|
||||
return new SliceContextualCardController(context);
|
||||
} else if (LegacySuggestionContextualCardController.class == clz) {
|
||||
return new LegacySuggestionContextualCardController(context);
|
||||
}
|
||||
|
||||
@@ -77,13 +77,13 @@ public class ConditionContextualCardController implements ContextualCardControll
|
||||
|
||||
@Override
|
||||
public void onActionClick(ContextualCard contextualCard) {
|
||||
|
||||
final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard;
|
||||
mConditionManager.onActionClick(card.getConditionId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismissed(ContextualCard contextualCard) {
|
||||
final ConditionalContextualCard card = (ConditionalContextualCard) contextualCard;
|
||||
mConditionManager.onActionClick(card.getConditionId());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -93,8 +93,8 @@ public class ConditionContextualCardController implements ContextualCardControll
|
||||
final boolean isOddNumber = conditionCards.size() % 2 == 1;
|
||||
if (isOddNumber) {
|
||||
final int lastIndex = conditionCards.size() - 1;
|
||||
final ConditionalContextualCard card = (ConditionalContextualCard) conditionCards.get(
|
||||
lastIndex);
|
||||
final ConditionalContextualCard card = (ConditionalContextualCard) conditionCards
|
||||
.get(lastIndex);
|
||||
conditionCards.set(lastIndex, card.mutate().setIsHalfWidth(false).build());
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ public class ConditionContextualCardRenderer implements ContextualCardRenderer {
|
||||
viewContext, MetricsProto.MetricsEvent.ACTION_SETTINGS_CONDITION_BUTTON,
|
||||
card.getMetricsConstant());
|
||||
mControllerRendererPool.getController(mContext, card.getCardType())
|
||||
.onDismissed(card);
|
||||
.onActionClick(card);
|
||||
});
|
||||
} else {
|
||||
button.setVisibility(View.GONE);
|
||||
|
||||
@@ -16,9 +16,14 @@
|
||||
|
||||
package com.android.settings.homepage.contextualcards.slices;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.homepage.contextualcards.CardContentProvider;
|
||||
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
|
||||
import com.android.settings.homepage.contextualcards.ContextualCard;
|
||||
import com.android.settings.homepage.contextualcards.ContextualCardController;
|
||||
import com.android.settings.homepage.contextualcards.ContextualCardUpdateListener;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
|
||||
/**
|
||||
* Card controller for {@link ContextualCard} built as slices.
|
||||
@@ -27,8 +32,13 @@ public class SliceContextualCardController implements ContextualCardController {
|
||||
|
||||
private static final String TAG = "SliceCardController";
|
||||
|
||||
private Context mContext;
|
||||
private ContextualCardUpdateListener mCardUpdateListener;
|
||||
|
||||
public SliceContextualCardController(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCardType() {
|
||||
return ContextualCard.CardType.SLICE;
|
||||
@@ -46,11 +56,14 @@ public class SliceContextualCardController implements ContextualCardController {
|
||||
|
||||
@Override
|
||||
public void onDismissed(ContextualCard card) {
|
||||
//TODO(b/113783548): Mark this card as dismissed in db and reload loader.
|
||||
ThreadUtils.postOnBackgroundThread(() -> {
|
||||
final CardDatabaseHelper dbHelper = CardDatabaseHelper.getInstance(mContext);
|
||||
dbHelper.markContextualCardAsDismissed(mContext, card.getName());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCardUpdateListener(ContextualCardUpdateListener listener) {
|
||||
mCardUpdateListener = listener;
|
||||
mCardUpdateListener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
47
src/com/android/settings/wifi/qrcode/QrCodeGenerator.java
Normal file
47
src/com/android/settings/wifi/qrcode/QrCodeGenerator.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.settings.wifi.qrcode;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
|
||||
public final class QrCodeGenerator {
|
||||
/**
|
||||
* Generates a barcode image with {@code contents}.
|
||||
*
|
||||
* @param contents The contents to encode in the barcode
|
||||
* @param size The preferred image size in pixels
|
||||
* @return Barcode bitmap
|
||||
*/
|
||||
public static Bitmap encodeQrCode(String contents, int size)
|
||||
throws WriterException, IllegalArgumentException {
|
||||
final BitMatrix qrBits = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE,
|
||||
size, size);
|
||||
final Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565);
|
||||
for (int x = 0; x < size; x++) {
|
||||
for (int y = 0; y < size; y++) {
|
||||
bitmap.setPixel(x, y, qrBits.get(x, y) ? Color.BLACK : Color.WHITE);
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
@@ -71,6 +71,7 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
|
||||
private WifiManager mWifiManager;
|
||||
private boolean mRestartWifiApAfterConfigChange;
|
||||
private boolean mUnavailable;
|
||||
|
||||
@VisibleForTesting
|
||||
TetherChangeReceiver mTetherChangeReceiver;
|
||||
@@ -94,6 +95,15 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
return "WifiTetherSettings";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
super.onCreate(icicle);
|
||||
setIfOnlyAvailableForAdmins(true);
|
||||
if (isUiRestricted()) {
|
||||
mUnavailable = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
@@ -109,6 +119,9 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
if (mUnavailable) {
|
||||
return;
|
||||
}
|
||||
// Assume we are in a SettingsActivity. This is only safe because we currently use
|
||||
// SettingsActivity as base for all preference fragments.
|
||||
final SettingsActivity activity = (SettingsActivity) getActivity();
|
||||
@@ -122,6 +135,13 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
if (mUnavailable) {
|
||||
if (!isUiRestrictedByOnlyAdmin()) {
|
||||
getEmptyTextView().setText(R.string.tethering_settings_not_available);
|
||||
}
|
||||
getPreferenceScreen().removeAll();
|
||||
return;
|
||||
}
|
||||
final Context context = getContext();
|
||||
if (context != null) {
|
||||
context.registerReceiver(mTetherChangeReceiver, TETHER_STATE_CHANGE_FILTER);
|
||||
@@ -131,6 +151,9 @@ public class WifiTetherSettings extends RestrictedDashboardFragment
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
if (mUnavailable) {
|
||||
return;
|
||||
}
|
||||
final Context context = getContext();
|
||||
if (context != null) {
|
||||
context.unregisterReceiver(mTetherChangeReceiver);
|
||||
|
||||
@@ -18,16 +18,25 @@ package com.android.settings.accounts;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.content.ContentProvider;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.settings.homepage.SettingsHomepageActivity;
|
||||
@@ -44,6 +53,7 @@ import org.robolectric.annotation.Config;
|
||||
import org.robolectric.annotation.Implementation;
|
||||
import org.robolectric.annotation.Implements;
|
||||
import org.robolectric.shadow.api.Shadow;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
import org.robolectric.shadows.ShadowPackageManager;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@@ -51,6 +61,7 @@ public class AvatarViewMixinTest {
|
||||
private static final String DUMMY_ACCOUNT = "test@domain.com";
|
||||
private static final String DUMMY_DOMAIN = "domain.com";
|
||||
private static final String DUMMY_AUTHORITY = "authority.domain.com";
|
||||
private static final String METHOD_GET_ACCOUNT_AVATAR = "getAccountAvatar";
|
||||
|
||||
private Context mContext;
|
||||
private ImageView mImageView;
|
||||
@@ -128,6 +139,31 @@ public class AvatarViewMixinTest {
|
||||
assertThat(avatarViewMixin.queryProviderAuthority()).isEqualTo(DUMMY_AUTHORITY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void callWithGetAccountAvatarMethod_useDummyData_shouldReturnAccountNameAndAvatar() {
|
||||
final ShadowContentResolver shadowContentResolver = Shadow.extract(
|
||||
mContext.getContentResolver());
|
||||
final Uri uri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(
|
||||
DUMMY_AUTHORITY).build();
|
||||
final ContentProvider mockContentProvider = mock(ContentProvider.class);
|
||||
|
||||
ShadowContentResolver.registerProviderInternal(DUMMY_AUTHORITY, mockContentProvider);
|
||||
|
||||
final Bundle bundle = new Bundle();
|
||||
final Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
|
||||
bundle.putParcelable("account_avatar", bitmap);
|
||||
bundle.putString("account_name", DUMMY_ACCOUNT);
|
||||
doReturn(bundle).when(mockContentProvider).call(anyString(), anyString(),
|
||||
any(Bundle.class));
|
||||
|
||||
final Bundle expectBundle = shadowContentResolver.call(uri, METHOD_GET_ACCOUNT_AVATAR,
|
||||
null /* arg */, null /* extras */);
|
||||
|
||||
final Object object = bundle.getParcelable("account_avatar");
|
||||
assertThat(object instanceof Bitmap).isTrue();
|
||||
assertThat(bundle.getString("account_name")).isEqualTo(DUMMY_ACCOUNT);
|
||||
}
|
||||
|
||||
@Implements(value = AccountFeatureProviderImpl.class)
|
||||
public static class ShadowAccountFeatureProviderImpl {
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.settings.applications.appinfo;
|
||||
|
||||
import static com.android.settings.core.FeatureFlags.DATA_USAGE_V2;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@@ -33,6 +35,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.INetworkStatsSession;
|
||||
import android.os.Bundle;
|
||||
import android.util.FeatureFlagUtils;
|
||||
|
||||
import androidx.loader.app.LoaderManager;
|
||||
import androidx.preference.Preference;
|
||||
@@ -65,6 +68,7 @@ public class AppDataUsagePreferenceControllerTest {
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = spy(RuntimeEnvironment.application.getApplicationContext());
|
||||
FeatureFlagUtils.setEnabled(mContext, DATA_USAGE_V2, false);
|
||||
mController = spy(new AppDataUsagePreferenceController(mContext, "test_key"));
|
||||
mController.setParentFragment(mFragment);
|
||||
}
|
||||
|
||||
@@ -77,11 +77,6 @@ public class AppMemoryPreferenceControllerTest {
|
||||
when(mFragment.getActivity()).thenReturn(mActivity);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowUserManager.getShadow().reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Config(qualifiers = "mcc999")
|
||||
public void getAvailabilityStatus_developmentSettingsEnabled_shouldReturnAvailable() {
|
||||
|
||||
@@ -28,6 +28,7 @@ import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.usage.NetworkStatsManager;
|
||||
import android.content.Context;
|
||||
import android.net.NetworkPolicyManager;
|
||||
|
||||
@@ -68,6 +69,8 @@ public class DataUsageSummaryTest {
|
||||
private SummaryLoader mSummaryLoader;
|
||||
@Mock
|
||||
private NetworkPolicyManager mNetworkPolicyManager;
|
||||
@Mock
|
||||
private NetworkStatsManager mNetworkStatsManager;
|
||||
private Context mContext;
|
||||
private FragmentActivity mActivity;
|
||||
private SummaryLoader.SummaryProvider mSummaryProvider;
|
||||
@@ -86,16 +89,12 @@ public class DataUsageSummaryTest {
|
||||
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mActivity = spy(Robolectric.buildActivity(FragmentActivity.class).get());
|
||||
doReturn(mNetworkStatsManager).when(mActivity).getSystemService(NetworkStatsManager.class);
|
||||
|
||||
mSummaryProvider = DataUsageSummary.SUMMARY_PROVIDER_FACTORY
|
||||
.createSummaryProvider(mActivity, mSummaryLoader);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowUserManager.getShadow().reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void formatUsage_shouldLookLikeFormatFileSize() {
|
||||
SettingsShadowResources.overrideResource(com.android.internal.R.string.fileSizeSuffix,
|
||||
|
||||
@@ -75,7 +75,6 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowEnableDevelopmentSettingWarningDialog.reset();
|
||||
mShadowUserManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -70,7 +70,6 @@ public class DevelopmentSwitchBarControllerTest {
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowUtils.reset();
|
||||
ShadowUserManager.getShadow().reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -95,15 +95,12 @@ public class CardContentProviderTest {
|
||||
assertThat(count).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void cardData_delete() {
|
||||
mResolver.insert(mUri, generateOneRow());
|
||||
final int delCount = mResolver.delete(mUri, null, null);
|
||||
|
||||
assertThat(delCount).isGreaterThan(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void cardData_update() {
|
||||
mResolver.insert(mUri, generateOneRow());
|
||||
|
||||
@@ -113,16 +110,6 @@ public class CardContentProviderTest {
|
||||
final String strWhere = CardDatabaseHelper.CardColumns.NAME + "=?";
|
||||
final String[] selectionArgs = {"auto_rotate"};
|
||||
final int updateCount = mResolver.update(mUri, values, strWhere, selectionArgs);
|
||||
|
||||
assertThat(updateCount).isGreaterThan(0);
|
||||
|
||||
final String[] columns = {CardDatabaseHelper.CardColumns.SCORE};
|
||||
final Cursor cr = mResolver.query(mUri, columns, strWhere, selectionArgs, null);
|
||||
cr.moveToFirst();
|
||||
final double qryScore = cr.getDouble(0);
|
||||
|
||||
cr.close();
|
||||
assertThat(qryScore).isEqualTo(updatingScore);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,28 +132,6 @@ public class CardContentProviderTest {
|
||||
verify(mProvider).enableStrictMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete_isMainThread_shouldEnableStrictMode() {
|
||||
ShadowThreadUtils.setIsMainThread(true);
|
||||
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
|
||||
|
||||
mProvider.delete(mUri, null, null);
|
||||
|
||||
verify(mProvider).enableStrictMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void update_isMainThread_shouldEnableStrictMode() {
|
||||
ShadowThreadUtils.setIsMainThread(true);
|
||||
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(CardDatabaseHelper.CardColumns.SCORE, "0.01");
|
||||
|
||||
mProvider.update(mUri, values, null, null);
|
||||
|
||||
verify(mProvider).enableStrictMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void insert_notMainThread_shouldNotEnableStrictMode() {
|
||||
ShadowThreadUtils.setIsMainThread(false);
|
||||
@@ -187,28 +152,6 @@ public class CardContentProviderTest {
|
||||
verify(mProvider, never()).enableStrictMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void delete_notMainThread_shouldNotEnableStrictMode() {
|
||||
ShadowThreadUtils.setIsMainThread(false);
|
||||
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
|
||||
|
||||
mProvider.delete(mUri, null, null);
|
||||
|
||||
verify(mProvider, never()).enableStrictMode();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void update_notMainThread_shouldNotEnableStrictMode() {
|
||||
ShadowThreadUtils.setIsMainThread(false);
|
||||
ReflectionHelpers.setStaticField(Build.class, "IS_DEBUGGABLE", true);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(CardDatabaseHelper.CardColumns.SCORE, "0.01");
|
||||
|
||||
mProvider.update(mUri, values, null, null);
|
||||
|
||||
verify(mProvider, never()).enableStrictMode();
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void getType_shouldCrash() {
|
||||
mProvider.getType(null);
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.settings.homepage.contextualcards.slices;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.android.settings.homepage.contextualcards.CardContentProvider;
|
||||
import com.android.settings.homepage.contextualcards.CardDatabaseHelper;
|
||||
import com.android.settings.homepage.contextualcards.ContextualCard;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.Robolectric;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.shadows.ShadowContentResolver;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
public class SliceContextualCardControllerTest {
|
||||
|
||||
private static final String TEST_SLICE_URI = "content://test/test";
|
||||
private static final String TEST_CARD_NAME = "test_card_name";
|
||||
|
||||
private Context mContext;
|
||||
private CardContentProvider mProvider;
|
||||
private ContentResolver mResolver;
|
||||
private SliceContextualCardController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mProvider = Robolectric.setupContentProvider(CardContentProvider.class);
|
||||
ShadowContentResolver.registerProviderInternal(CardContentProvider.CARD_AUTHORITY,
|
||||
mProvider);
|
||||
mResolver = mContext.getContentResolver();
|
||||
mController = new SliceContextualCardController(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onDismissed_cardShouldBeMarkedAsDismissed() {
|
||||
final Uri providerUri = CardContentProvider.URI;
|
||||
final ContextualCard card = new ContextualCard.Builder()
|
||||
.setName(TEST_CARD_NAME)
|
||||
.setCardType(ContextualCard.CardType.SLICE)
|
||||
.setSliceUri(Uri.parse(TEST_SLICE_URI))
|
||||
.build();
|
||||
mResolver.insert(providerUri, generateOneRow());
|
||||
|
||||
mController.onDismissed(card);
|
||||
|
||||
final String[] columns = {CardDatabaseHelper.CardColumns.CARD_DISMISSED};
|
||||
final String selection = CardDatabaseHelper.CardColumns.NAME + "=?";
|
||||
final String[] selectionArgs = {TEST_CARD_NAME};
|
||||
final Cursor cr = mResolver.query(providerUri, columns, selection, selectionArgs, null);
|
||||
cr.moveToFirst();
|
||||
final int qryDismissed = cr.getInt(0);
|
||||
cr.close();
|
||||
|
||||
assertThat(qryDismissed).isEqualTo(1);
|
||||
}
|
||||
|
||||
private ContentValues generateOneRow() {
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(CardDatabaseHelper.CardColumns.NAME, TEST_CARD_NAME);
|
||||
values.put(CardDatabaseHelper.CardColumns.TYPE, 1);
|
||||
values.put(CardDatabaseHelper.CardColumns.SCORE, 0.9);
|
||||
values.put(CardDatabaseHelper.CardColumns.SLICE_URI, TEST_SLICE_URI);
|
||||
values.put(CardDatabaseHelper.CardColumns.CATEGORY, 2);
|
||||
values.put(CardDatabaseHelper.CardColumns.PACKAGE_NAME, "com.android.settings");
|
||||
values.put(CardDatabaseHelper.CardColumns.APP_VERSION, 10001);
|
||||
values.put(CardDatabaseHelper.CardColumns.CARD_DISMISSED, 0);
|
||||
|
||||
return values;
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.usage.NetworkStatsManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.provider.Settings;
|
||||
@@ -48,6 +49,8 @@ public class DataUsagePreferenceControllerTest {
|
||||
|
||||
@Mock
|
||||
private TelephonyManager mTelephonyManager;
|
||||
@Mock
|
||||
private NetworkStatsManager mNetworkStatsManager;
|
||||
private DataUsagePreferenceController mController;
|
||||
private SwitchPreference mPreference;
|
||||
private Context mContext;
|
||||
@@ -59,6 +62,7 @@ public class DataUsagePreferenceControllerTest {
|
||||
mContext = spy(Robolectric.setupActivity(Activity.class));
|
||||
doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
|
||||
doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
|
||||
doReturn(mNetworkStatsManager).when(mContext).getSystemService(NetworkStatsManager.class);
|
||||
|
||||
mPreference = new SwitchPreference(mContext);
|
||||
mController = new DataUsagePreferenceController(mContext, "data_usage");
|
||||
|
||||
@@ -48,7 +48,6 @@ public class RedactionInterstitialTest {
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
ShadowUserManager.getShadow().reset();
|
||||
ShadowRestrictedLockUtilsInternal.reset();
|
||||
}
|
||||
|
||||
|
||||
@@ -57,11 +57,6 @@ public class EncryptionStatusPreferenceControllerTest {
|
||||
mPreference = new Preference(mContext);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mShadowUserManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_admin_true() {
|
||||
mShadowUserManager.setIsAdminUser(true);
|
||||
|
||||
@@ -63,11 +63,6 @@ public class RestrictedEncryptionPreferenceControllerTest {
|
||||
mUserManager = ShadowUserManager.getShadow();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mUserManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isAvailable_noRestriction_shouldReturnTrue() {
|
||||
assertThat(mCredentialStoragePreferenceController.isAvailable()).isTrue();
|
||||
|
||||
@@ -90,7 +90,6 @@ public class SlicesDatabaseAccessorTest {
|
||||
|
||||
@After
|
||||
public void cleanUp() {
|
||||
ShadowUserManager.getShadow().reset();
|
||||
DatabaseTestUtils.clearDb(mContext);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,6 @@ public class SystemDashboardFragmentTest {
|
||||
@After
|
||||
public void tearDown() {
|
||||
SettingsShadowResources.reset();
|
||||
ShadowUserManager.getShadow().reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -49,19 +49,6 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
|
||||
private int[] profileIdsForUser = new int[0];
|
||||
private boolean mUserSwitchEnabled;
|
||||
|
||||
|
||||
@Resetter
|
||||
public void reset() {
|
||||
mUserInfos.clear();
|
||||
mRestrictions.clear();
|
||||
mUserProfileInfos.clear();
|
||||
mRestrictionSources.clear();
|
||||
mManagedProfiles.clear();
|
||||
mIsQuietModeEnabled = false;
|
||||
mUserSwitchEnabled = false;
|
||||
profileIdsForUser = new int[0];
|
||||
}
|
||||
|
||||
public void setUserInfo(int userHandle, UserInfo userInfo) {
|
||||
mUserInfos.put(userHandle, userInfo);
|
||||
}
|
||||
@@ -90,7 +77,7 @@ public class ShadowUserManager extends org.robolectric.shadows.ShadowUserManager
|
||||
}
|
||||
|
||||
@Implementation
|
||||
public List<UserHandle> getUserProfiles(){
|
||||
public List<UserHandle> getUserProfiles() {
|
||||
int[] userIds = getProfileIds(UserHandle.myUserId(), true /* enabledOnly */);
|
||||
List<UserHandle> result = new ArrayList<>(userIds.length);
|
||||
for (int userId : userIds) {
|
||||
|
||||
@@ -63,11 +63,6 @@ public class AddUserWhenLockedPreferenceControllerTest {
|
||||
mController = new AddUserWhenLockedPreferenceController(mContext, "fake_key");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mUserManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void displayPref_NotAdmin_shouldNotDisplay() {
|
||||
mUserManager.setUserInfo(0, mUserInfo);
|
||||
|
||||
@@ -105,11 +105,6 @@ public class EditUserInfoControllerTest {
|
||||
mController = new TestEditUserInfoController();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mUserManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void photoControllerOnActivityResult_whenWaiting_isCalled() {
|
||||
mController.createDialog(mFragment, mCurrentIcon, "test user",
|
||||
|
||||
@@ -45,11 +45,6 @@ public class UserCapabilitiesTest {
|
||||
mUserManager = ShadowUserManager.getShadow();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
mUserManager.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disallowUserSwitch_restrictionIsSet_true() {
|
||||
mUserManager.setUserRestriction(UserHandle.of(UserHandle.myUserId()),
|
||||
|
||||
@@ -30,13 +30,10 @@ import android.view.SurfaceHolder;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.LuminanceSource;
|
||||
import com.google.zxing.RGBLuminanceSource;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.WriterException;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
@@ -111,36 +108,17 @@ public class QrCameraTest {
|
||||
final String googleUrl = "http://www.google.com";
|
||||
|
||||
try {
|
||||
Bitmap bmp = encodeQrCode(googleUrl, 320);
|
||||
int[] intArray = new int[bmp.getWidth() * bmp.getHeight()];
|
||||
final Bitmap bmp = QrCodeGenerator.encodeQrCode(googleUrl, 320);
|
||||
final int[] intArray = new int[bmp.getWidth() * bmp.getHeight()];
|
||||
bmp.getPixels(intArray, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
|
||||
LuminanceSource source = new RGBLuminanceSource(bmp.getWidth(), bmp.getHeight(),
|
||||
intArray);
|
||||
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
final BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
mCamera.decodeImage(bitmap);
|
||||
bmp.recycle();
|
||||
} catch (WriterException e) {
|
||||
}
|
||||
|
||||
assertThat(mQrCode).isEqualTo(googleUrl);
|
||||
}
|
||||
|
||||
private Bitmap encodeQrCode(String qrCode, int size) throws WriterException {
|
||||
BitMatrix qrBits = null;
|
||||
try {
|
||||
qrBits =
|
||||
new MultiFormatWriter().encode(qrCode, BarcodeFormat.QR_CODE, size, size, null);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
// Should never reach here.
|
||||
}
|
||||
assertThat(qrBits).isNotNull();
|
||||
|
||||
Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.RGB_565);
|
||||
for (int x = 0; x < size; ++x) {
|
||||
for (int y = 0; y < size; ++y) {
|
||||
bitmap.setPixel(x, y, qrBits.get(x, y) ? Color.BLACK : Color.WHITE);
|
||||
}
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,15 +18,24 @@ package com.android.settings.wifi.tether;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.nullable;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.testutils.shadow.ShadowWifiManager;
|
||||
|
||||
@@ -37,10 +46,14 @@ import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(shadows = {ShadowWifiManager.class})
|
||||
public class WifiTetherSettingsTest {
|
||||
@@ -98,6 +111,31 @@ public class WifiTetherSettingsTest {
|
||||
.isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startFragment_notAdminUser_shouldRemoveAllPreferences() {
|
||||
final WifiTetherSettings settings = spy(new WifiTetherSettings());
|
||||
final FragmentActivity activity = mock(FragmentActivity.class);
|
||||
when(settings.getActivity()).thenReturn(activity);
|
||||
when(settings.getContext()).thenReturn(mContext);
|
||||
final Resources.Theme theme = mContext.getTheme();
|
||||
when(activity.getTheme()).thenReturn(theme);
|
||||
when(activity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
|
||||
doNothing().when(settings)
|
||||
.onCreatePreferences(any(Bundle.class), nullable(String.class));
|
||||
final FakeFeatureFactory fakeFeatureFactory = FakeFeatureFactory.setupForTest();
|
||||
ReflectionHelpers.setField(settings, "mDashboardFeatureProvider",
|
||||
fakeFeatureFactory.dashboardFeatureProvider);
|
||||
final TextView emptyTextView = mock(TextView.class);
|
||||
ReflectionHelpers.setField(settings, "mEmptyTextView", emptyTextView);
|
||||
final PreferenceScreen screen = mock(PreferenceScreen.class);
|
||||
doReturn(screen).when(settings).getPreferenceScreen();
|
||||
settings.onCreate(Bundle.EMPTY);
|
||||
|
||||
settings.onStart();
|
||||
|
||||
verify(screen).removeAll();
|
||||
}
|
||||
|
||||
private void setupIsTetherAvailable(boolean returnValue) {
|
||||
when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user