Snap for 7447836 from ad84b3dd39 to sc-release
Change-Id: Id98b9a7c14ccc08cbbf4899b76cb5bbac30dcfbc
This commit is contained in:
25
res/drawable/ic_upload.xml
Normal file
25
res/drawable/ic_upload.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<!--
|
||||
~ Copyright (C) 2021 The Android Open Source Project
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24.0dp"
|
||||
android:height="24.0dp"
|
||||
android:tint="?android:attr/colorControlNormal"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M18,15v3H6v-3H4v3c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-3H18z M7,9l1.41,1.41L11,7.83V16h2V7.83l2.59,2.58L17,9l-5-5L7,9z" />
|
||||
</vector>
|
||||
@@ -1,38 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2021 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.
|
||||
-->
|
||||
|
||||
<layer-list
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
|
||||
|
||||
<item
|
||||
android:id="@android:id/background">
|
||||
<shape>
|
||||
<corners android:radius="8dp" />
|
||||
<solid android:color="?androidprv:attr/colorSurfaceVariant" />
|
||||
</shape>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@android:id/progress">
|
||||
<clip>
|
||||
<shape>
|
||||
<corners android:radius="8dp" />
|
||||
<solid android:color="?android:attr/textColorPrimary" />
|
||||
</shape>
|
||||
</clip>
|
||||
</item>
|
||||
</layer-list>
|
||||
140
res/layout-land/request_manage_credentials.xml
Normal file
140
res/layout-land/request_manage_credentials.xml
Normal file
@@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright (C) 2021 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"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:weightSum="2">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
style="@style/RequestManageCredentialsHeaderLandscape">
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:scrollbars="none">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/credential_management_app_icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/credential_management_app_title"
|
||||
style="@style/RequestManageCredentialsTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/credential_management_app_description"
|
||||
style="@style/RequestManageCredentialsDescription"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/request_manage_credentials_description" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="true">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/apps_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_panel"
|
||||
style="@style/RequestManageCredentialsButtonPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/dont_allow_button"
|
||||
style="@style/RequestManageCredentialsDontAllowButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/request_manage_credentials_dont_allow" />
|
||||
|
||||
<Space
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:visibility="invisible" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/allow_button"
|
||||
style="@style/RequestManageCredentialsAllowButton"
|
||||
android:theme="@style/RoundedCornerButtonTheme"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/request_manage_credentials_allow" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
android:id="@+id/extended_fab"
|
||||
style="@style/RequestManageCredentialsFab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/request_manage_credentials_more"
|
||||
android:theme="@style/Theme.CollapsingToolbar.Settings"
|
||||
app:backgroundTint="?android:attr/colorAccent"
|
||||
app:elevation="3dp"
|
||||
app:icon="@drawable/ic_arrow_downward"
|
||||
app:iconTint="?android:attr/textColorPrimary"
|
||||
app:layout_anchor="@id/apps_list"
|
||||
app:layout_anchorGravity="bottom|center" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -38,7 +38,7 @@
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginVertical="12dp">
|
||||
android:layout_marginTop="-32dp">
|
||||
|
||||
<com.google.android.setupdesign.view.IllustrationVideoView
|
||||
android:id="@+id/illustration_default"
|
||||
@@ -51,11 +51,13 @@
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/illustration_lottie"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="340dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:visibility="invisible"
|
||||
android:layout_height="400dp"
|
||||
android:layout_marginTop="-48dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone"
|
||||
app:lottie_autoPlay="true"
|
||||
app:lottie_loop="true" />
|
||||
app:lottie_loop="true"
|
||||
app:lottie_speed="1.5" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/illustration_accessibility"
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
<Button
|
||||
android:id="@+id/allow_button"
|
||||
style="@style/RequestManageCredentialsAllowButton"
|
||||
android:theme="@style/RoundedCornerButtonTheme"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/request_manage_credentials_allow"/>
|
||||
@@ -70,8 +71,8 @@
|
||||
app:layout_anchorGravity="bottom|center"
|
||||
app:elevation="3dp"
|
||||
app:icon="@drawable/ic_arrow_downward"
|
||||
app:iconTint="?android:attr/colorAccent"
|
||||
app:backgroundTint="?android:attr/colorPrimary"
|
||||
app:iconTint="?android:attr/textColorPrimary"
|
||||
app:backgroundTint="?android:attr/colorAccent"
|
||||
android:theme="@style/Theme.CollapsingToolbar.Settings"/>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
@@ -6789,9 +6789,9 @@
|
||||
<string name="cert_not_installed">Certificate not installed</string>
|
||||
|
||||
<!-- Title of screen shown to the user when an app requests to manage the user's KeyChain credentials [CHAR LIMIT=NONE] -->
|
||||
<string name="request_manage_credentials_title">Allow <xliff:g id="app_name" example="Ping">%s</xliff:g> to install certificates on this device?</string>
|
||||
<string name="request_manage_credentials_title">Allow <b><xliff:g id="app_name" example="Ping">^1</xliff:g></b> to install certificates on this device?</string>
|
||||
<!-- Description of screen shown to the user when an app requests to manage the user's KeyChain credentials [CHAR LIMIT=NONE] -->
|
||||
<string name="request_manage_credentials_description">These certificates will identify you to the apps and URLs below</string>
|
||||
<string name="request_manage_credentials_description">These certificates will verify you by sharing your device\u2019s unique ID with the apps and URLs below</string>
|
||||
<!-- Label for button to not allow an app to manage the user's KeyChain credentials [CHAR_LIMIT=50] -->
|
||||
<string name="request_manage_credentials_dont_allow">Don\u2019t allow</string>
|
||||
<!-- Label for button to allow an app to manage the user's KeyChain credentials [CHAR_LIMIT=50] -->
|
||||
@@ -6803,7 +6803,9 @@
|
||||
<!-- Summary if there is no certificate management app [CHAR_LIMIT=NONE] -->
|
||||
<string name="no_certificate_management_app">None</string>
|
||||
<!-- Summary of preference if there is a certificate management app [CHAR LIMIT=NONE] -->
|
||||
<string name="certificate_management_app_description">Certificates installed by this app identify you to the apps and URLs below</string>
|
||||
<string name="certificate_management_app_description">Certificates will verify you when you use the apps and URLs below</string>
|
||||
<!-- Label for button to uninstall all certificates installed by the credential management app [CHAR LIMIT=30] -->
|
||||
<string name="uninstall_certs_credential_management_app">Uninstall certificates</string>
|
||||
<!-- Label for button to remove the credential management app [CHAR LIMIT=30] -->
|
||||
<string name="remove_credential_management_app">Remove</string>
|
||||
<!-- List item found in the credential management app's authentication policy [CHAR LIMIT=NONE] -->
|
||||
|
||||
@@ -405,12 +405,6 @@
|
||||
<item name="android:progressDrawable">@drawable/ring_progress</item>
|
||||
</style>
|
||||
|
||||
<style name="HorizontalProgressBarStyle"
|
||||
parent="android:style/Widget.Material.ProgressBar.Horizontal">
|
||||
<item name="android:progressDrawable">@drawable/progress_horizontal</item>
|
||||
<item name="android:scaleY">0.5</item>
|
||||
</style>
|
||||
|
||||
<style name="ActionPrimaryButton" parent="android:Widget.DeviceDefault.Button.Colored">
|
||||
<item name="android:theme">@style/RoundedCornerThemeOverlay</item>
|
||||
</style>
|
||||
@@ -800,10 +794,19 @@
|
||||
<item name="android:background">?android:colorBackground</item>
|
||||
</style>
|
||||
|
||||
<style name="RoundedCornerButtonTheme">
|
||||
<item name="android:buttonCornerRadius">50dp</item>
|
||||
<item name="android:paddingStart">20dp</item>
|
||||
<item name="android:paddingEnd">20dp</item>
|
||||
<item name="android:paddingTop">18dp</item>
|
||||
<item name="android:paddingBottom">18dp</item>
|
||||
</style>
|
||||
|
||||
<style name="RequestManageCredentialsAllowButton" parent="@style/ActionPrimaryButton">
|
||||
<item name="android:fontFamily">google-sans-medium</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="RequestManageCredentialsDontAllowButton"
|
||||
@@ -811,13 +814,13 @@
|
||||
<item name="android:fontFamily">google-sans-medium</item>
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:textColor">?android:attr/colorAccent</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="RequestManageCredentialsFab">
|
||||
<item name="android:textSize">14sp</item>
|
||||
<item name="android:textAllCaps">false</item>
|
||||
<item name="android:textColor">?android:attr/colorAccent</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
<item name="android:layout_marginBottom">12dp</item>
|
||||
</style>
|
||||
|
||||
@@ -829,6 +832,13 @@
|
||||
<item name="android:orientation">vertical</item>
|
||||
</style>
|
||||
|
||||
<style name="RequestManageCredentialsHeaderLandscape">
|
||||
<item name="android:paddingStart">24dp</item>
|
||||
<item name="android:paddingEnd">24dp</item>
|
||||
<item name="android:paddingTop">24dp</item>
|
||||
<item name="android:paddingBottom">24dp</item>
|
||||
</style>
|
||||
|
||||
<style name="RequestManageCredentialsTitle">
|
||||
<item name="android:layout_marginTop">24dp</item>
|
||||
<item name="android:textSize">36sp</item>
|
||||
@@ -839,6 +849,7 @@
|
||||
<item name="android:layout_marginTop">24dp</item>
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:textColor">?android:attr/textColorPrimary</item>
|
||||
<item name="android:alpha">0.7</item>
|
||||
</style>
|
||||
|
||||
<style name="AppAuthenticationPolicyItem">
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
<item name="android:homeAsUpIndicator">@drawable/ic_arrow_back</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:datePickerDialogTheme">@style/PickerDialogTheme.Settings</item>
|
||||
<item name="android:progressBarStyleHorizontal">@style/HorizontalProgressBarStyle</item>
|
||||
|
||||
<item name="fingerprint_layout_theme">@style/FingerprintLayoutTheme</item>
|
||||
<item name="face_layout_theme">@style/FaceLayoutTheme</item>
|
||||
|
||||
@@ -27,19 +27,11 @@
|
||||
android:order="-10000"
|
||||
settings:controller="com.android.settings.security.CredentialManagementAppHeaderController"/>
|
||||
|
||||
<com.android.settingslib.widget.TopIntroPreference
|
||||
android:key="top_intro_request_manage_credentials"
|
||||
android:order="-9999"
|
||||
android:title="@string/request_manage_credentials_description"
|
||||
settings:searchable="false"/>
|
||||
|
||||
<!-- Buttons -->
|
||||
<com.android.settingslib.widget.ActionButtonsPreference
|
||||
android:key="buttons"
|
||||
android:selectable="true"
|
||||
android:order="-9998"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:allowDividerBelow="true"
|
||||
settings:controller="com.android.settings.security.CredentialManagementAppButtonsController"/>
|
||||
|
||||
<!-- Authentication Policy -->
|
||||
@@ -47,7 +39,6 @@
|
||||
android:key="authentication_policy"
|
||||
android:layout="@layout/preference_category_no_label"
|
||||
android:title="@string/summary_placeholder"
|
||||
settings:allowDividerAbove="true"
|
||||
settings:controller="com.android.settings.security.CredentialManagementAppPolicyController"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
@@ -118,7 +118,8 @@ public class AppBatteryPreferenceController extends BasePreferenceController
|
||||
final UserManager userManager =
|
||||
(UserManager) mContext.getSystemService(Context.USER_SERVICE);
|
||||
final BatteryEntry entry = new BatteryEntry(mContext, /* handler */null, userManager,
|
||||
mUidBatteryConsumer, /* isHidden */ false, /* packages */ null, mPackageName);
|
||||
mUidBatteryConsumer, /* isHidden */ false,
|
||||
mUidBatteryConsumer.getUid(), /* packages */ null, mPackageName);
|
||||
AdvancedPowerUsageDetail.startBatteryDetailPage(mParent.getActivity(), mParent,
|
||||
entry, mBatteryPercent);
|
||||
} else {
|
||||
|
||||
@@ -28,6 +28,7 @@ import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.SubSettings;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.transition.SettingsTransitionHelper.TransitionType;
|
||||
|
||||
@@ -181,8 +182,10 @@ public class SubSettingLauncher {
|
||||
|
||||
@VisibleForTesting
|
||||
void launchAsUser(Intent intent, UserHandle userHandle) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
if (!Utils.isPageTransitionEnabled(mContext)) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||
}
|
||||
mContext.startActivityAsUser(intent, userHandle);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,15 +16,25 @@
|
||||
|
||||
package com.android.settings.display;
|
||||
|
||||
import static android.hardware.SensorPrivacyManager.Sensors.CAMERA;
|
||||
import static android.provider.Settings.Secure.CAMERA_AUTOROTATE;
|
||||
|
||||
import static com.android.settings.display.SmartAutoRotateController.hasSufficientPermission;
|
||||
import static com.android.settings.display.SmartAutoRotateController.isRotationResolverServiceAvailable;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.SensorPrivacyManager;
|
||||
import android.os.PowerManager;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.view.RotationPolicy;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
@@ -41,8 +51,21 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle
|
||||
private RotationPolicy.RotationPolicyListener mRotationPolicyListener;
|
||||
private Preference mPreference;
|
||||
|
||||
private final SensorPrivacyManager mPrivacyManager;
|
||||
private final PowerManager mPowerManager;
|
||||
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
refreshSummary(mPreference);
|
||||
}
|
||||
};
|
||||
|
||||
public SmartAutoRotatePreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
mPrivacyManager = SensorPrivacyManager.getInstance(context);
|
||||
mPrivacyManager
|
||||
.addSensorPrivacyListener(CAMERA, (sensor, enabled) -> refreshSummary(mPreference));
|
||||
mPowerManager = context.getSystemService(PowerManager.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,6 +82,8 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
mContext.registerReceiver(mReceiver,
|
||||
new IntentFilter(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED));
|
||||
if (mRotationPolicyListener == null) {
|
||||
mRotationPolicyListener = new RotationPolicy.RotationPolicyListener() {
|
||||
@Override
|
||||
@@ -75,12 +100,27 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
mContext.unregisterReceiver(mReceiver);
|
||||
if (mRotationPolicyListener != null) {
|
||||
RotationPolicy.unregisterRotationPolicyListener(mContext,
|
||||
mRotationPolicyListener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Need this because all controller tests use Roboelectric. No easy way to mock this service,
|
||||
* so we mock the call we need
|
||||
*/
|
||||
@VisibleForTesting
|
||||
boolean isCameraLocked() {
|
||||
return mPrivacyManager.isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isPowerSaveMode() {
|
||||
return mPowerManager.isPowerSaveMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
int activeStringId = R.string.auto_rotate_option_off;
|
||||
@@ -89,7 +129,11 @@ public class SmartAutoRotatePreferenceController extends BasePreferenceControlle
|
||||
mContext.getContentResolver(),
|
||||
CAMERA_AUTOROTATE,
|
||||
0, UserHandle.USER_CURRENT);
|
||||
activeStringId = cameraRotate == 1 ? R.string.auto_rotate_option_face_based
|
||||
activeStringId = cameraRotate == 1 && isRotationResolverServiceAvailable(mContext)
|
||||
&& hasSufficientPermission(mContext)
|
||||
&& !isCameraLocked()
|
||||
&& !isPowerSaveMode()
|
||||
? R.string.auto_rotate_option_face_based
|
||||
: R.string.auto_rotate_option_on;
|
||||
}
|
||||
return mContext.getString(activeStringId);
|
||||
|
||||
@@ -55,6 +55,7 @@ import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -66,6 +67,7 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
|
||||
static final boolean USE_FAKE_DATA = false;
|
||||
private static final int MAX_ITEMS_TO_LIST = USE_FAKE_DATA ? 30 : 20;
|
||||
private static final int MIN_AVERAGE_POWER_THRESHOLD_MILLI_AMP = 10;
|
||||
private static final String MEDIASERVER_PACKAGE_NAME = "mediaserver";
|
||||
|
||||
private final String mPreferenceKey;
|
||||
@VisibleForTesting
|
||||
@@ -303,27 +305,17 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
|
||||
final ArrayList<BatteryEntry> results = new ArrayList<>();
|
||||
final List<UidBatteryConsumer> uidBatteryConsumers =
|
||||
mBatteryUsageStats.getUidBatteryConsumers();
|
||||
|
||||
// Sort to have all apps with "real" UIDs first, followed by apps that are supposed
|
||||
// to be combined with the real ones.
|
||||
uidBatteryConsumers.sort(Comparator.comparingInt(
|
||||
consumer -> consumer.getUid() == getRealUid(consumer) ? 0 : 1));
|
||||
|
||||
for (int i = 0, size = uidBatteryConsumers.size(); i < size; i++) {
|
||||
final UidBatteryConsumer consumer = uidBatteryConsumers.get(i);
|
||||
int realUid = consumer.getUid();
|
||||
final int uid = getRealUid(consumer);
|
||||
|
||||
// Check if this UID is a shared GID. If so, we combine it with the OWNER's
|
||||
// actual app UID.
|
||||
if (isSharedGid(consumer.getUid())) {
|
||||
realUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
|
||||
UserHandle.getAppIdFromSharedAppGid(consumer.getUid()));
|
||||
}
|
||||
|
||||
// Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc).
|
||||
if (isSystemUid(realUid)
|
||||
&& !"mediaserver".equals(consumer.getPackageWithHighestDrain())) {
|
||||
// Use the system UID for all UIDs running in their own sandbox that
|
||||
// are not apps. We exclude mediaserver because we already are expected to
|
||||
// report that as a separate item.
|
||||
realUid = Process.SYSTEM_UID;
|
||||
}
|
||||
|
||||
final String[] packages = mPackageManager.getPackagesForUid(consumer.getUid());
|
||||
final String[] packages = mPackageManager.getPackagesForUid(uid);
|
||||
if (mBatteryUtils.shouldHideUidBatteryConsumerUnconditionally(consumer, packages)) {
|
||||
continue;
|
||||
}
|
||||
@@ -333,11 +325,11 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
|
||||
continue;
|
||||
}
|
||||
|
||||
final int index = batteryEntryList.indexOfKey(realUid);
|
||||
final int index = batteryEntryList.indexOfKey(uid);
|
||||
if (index < 0) {
|
||||
// New entry.
|
||||
batteryEntryList.put(realUid, new BatteryEntry(mContext, mHandler, mUserManager,
|
||||
consumer, isHidden, packages, null, loadDataInBackground));
|
||||
batteryEntryList.put(uid, new BatteryEntry(mContext, mHandler, mUserManager,
|
||||
consumer, isHidden, uid, packages, null, loadDataInBackground));
|
||||
} else {
|
||||
// Combine BatterySippers if we already have one with this UID.
|
||||
final BatteryEntry existingSipper = batteryEntryList.valueAt(index);
|
||||
@@ -385,7 +377,8 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
|
||||
for (int i = 0, size = userBatteryConsumers.size(); i < size; i++) {
|
||||
final UserBatteryConsumer consumer = userBatteryConsumers.get(i);
|
||||
results.add(new BatteryEntry(mContext, mHandler, mUserManager,
|
||||
consumer, /* isHidden */ true, null, null, loadDataInBackground));
|
||||
consumer, /* isHidden */ true, Process.INVALID_UID, null, null,
|
||||
loadDataInBackground));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -400,6 +393,27 @@ public class BatteryAppListPreferenceController extends AbstractPreferenceContro
|
||||
return results;
|
||||
}
|
||||
|
||||
private int getRealUid(UidBatteryConsumer consumer) {
|
||||
int realUid = consumer.getUid();
|
||||
|
||||
// Check if this UID is a shared GID. If so, we combine it with the OWNER's
|
||||
// actual app UID.
|
||||
if (isSharedGid(consumer.getUid())) {
|
||||
realUid = UserHandle.getUid(UserHandle.USER_SYSTEM,
|
||||
UserHandle.getAppIdFromSharedAppGid(consumer.getUid()));
|
||||
}
|
||||
|
||||
// Check if this UID is a system UID (mediaserver, logd, nfc, drm, etc).
|
||||
if (isSystemUid(realUid)
|
||||
&& !MEDIASERVER_PACKAGE_NAME.equals(consumer.getPackageWithHighestDrain())) {
|
||||
// Use the system UID for all UIDs running in their own sandbox that
|
||||
// are not apps. We exclude mediaserver because we already are expected to
|
||||
// report that as a separate item.
|
||||
realUid = Process.SYSTEM_UID;
|
||||
}
|
||||
return realUid;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setUsageSummary(Preference preference, BatteryEntry entry) {
|
||||
// Only show summary when usage time is longer than one minute
|
||||
|
||||
@@ -159,12 +159,15 @@ public class BatteryEntry {
|
||||
|
||||
private final Context mContext;
|
||||
private final BatteryConsumer mBatteryConsumer;
|
||||
private final int mUid;
|
||||
private final boolean mIsHidden;
|
||||
@ConvertUtils.ConsumerType
|
||||
private final int mConsumerType;
|
||||
@BatteryConsumer.PowerComponent
|
||||
private final int mPowerComponentId;
|
||||
private long mUsageDurationMs;
|
||||
private long mTimeInForegroundMs;
|
||||
private long mTimeInBackgroundMs;
|
||||
|
||||
public String name;
|
||||
public Drawable icon;
|
||||
@@ -180,13 +183,13 @@ public class BatteryEntry {
|
||||
}
|
||||
|
||||
public BatteryEntry(Context context, Handler handler, UserManager um,
|
||||
@NonNull BatteryConsumer batteryConsumer, boolean isHidden, String[] packages,
|
||||
@NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
|
||||
String packageName) {
|
||||
this(context, handler, um, batteryConsumer, isHidden, packages, packageName, true);
|
||||
this(context, handler, um, batteryConsumer, isHidden, uid, packages, packageName, true);
|
||||
}
|
||||
|
||||
public BatteryEntry(Context context, Handler handler, UserManager um,
|
||||
@NonNull BatteryConsumer batteryConsumer, boolean isHidden, String[] packages,
|
||||
@NonNull BatteryConsumer batteryConsumer, boolean isHidden, int uid, String[] packages,
|
||||
String packageName, boolean loadDataInBackground) {
|
||||
sHandler = handler;
|
||||
mContext = context;
|
||||
@@ -196,11 +199,11 @@ public class BatteryEntry {
|
||||
mPowerComponentId = -1;
|
||||
|
||||
if (batteryConsumer instanceof UidBatteryConsumer) {
|
||||
mUid = uid;
|
||||
mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY;
|
||||
mConsumedPower = batteryConsumer.getConsumedPower();
|
||||
|
||||
UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
|
||||
int uid = uidBatteryConsumer.getUid();
|
||||
if (mDefaultPackageName == null) {
|
||||
// Apps should only have one package
|
||||
if (packages != null && packages.length == 1) {
|
||||
@@ -222,7 +225,12 @@ public class BatteryEntry {
|
||||
}
|
||||
}
|
||||
getQuickNameIconForUid(uid, packages, loadDataInBackground);
|
||||
mTimeInForegroundMs =
|
||||
uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND);
|
||||
mTimeInBackgroundMs =
|
||||
uidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND);
|
||||
} else if (batteryConsumer instanceof UserBatteryConsumer) {
|
||||
mUid = Process.INVALID_UID;
|
||||
mConsumerType = ConvertUtils.CONSUMER_TYPE_USER_BATTERY;
|
||||
mConsumedPower = batteryConsumer.getConsumedPower();
|
||||
final NameAndIcon nameAndIcon = getNameAndIconFromUserId(
|
||||
@@ -239,6 +247,7 @@ public class BatteryEntry {
|
||||
double appsPowerMah, long usageDurationMs) {
|
||||
mContext = context;
|
||||
mBatteryConsumer = null;
|
||||
mUid = Process.INVALID_UID;
|
||||
mIsHidden = false;
|
||||
mPowerComponentId = powerComponentId;
|
||||
mConsumedPower =
|
||||
@@ -261,6 +270,7 @@ public class BatteryEntry {
|
||||
double devicePowerMah, double appsPowerMah) {
|
||||
mContext = context;
|
||||
mBatteryConsumer = null;
|
||||
mUid = Process.INVALID_UID;
|
||||
mIsHidden = false;
|
||||
mPowerComponentId = powerComponentId;
|
||||
|
||||
@@ -438,7 +448,7 @@ public class BatteryEntry {
|
||||
*/
|
||||
public String getKey() {
|
||||
if (mBatteryConsumer instanceof UidBatteryConsumer) {
|
||||
return Integer.toString(((UidBatteryConsumer) mBatteryConsumer).getUid());
|
||||
return Integer.toString(mUid);
|
||||
} else if (mBatteryConsumer instanceof UserBatteryConsumer) {
|
||||
return "U|" + ((UserBatteryConsumer) mBatteryConsumer).getUserId();
|
||||
} else {
|
||||
@@ -482,11 +492,7 @@ public class BatteryEntry {
|
||||
* Returns the UID of the app described by this entry.
|
||||
*/
|
||||
public int getUid() {
|
||||
if (mBatteryConsumer instanceof UidBatteryConsumer) {
|
||||
return ((UidBatteryConsumer) mBatteryConsumer).getUid();
|
||||
} else {
|
||||
return Process.INVALID_UID;
|
||||
}
|
||||
return mUid;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -494,8 +500,7 @@ public class BatteryEntry {
|
||||
*/
|
||||
public long getTimeInForegroundMs() {
|
||||
if (mBatteryConsumer instanceof UidBatteryConsumer) {
|
||||
return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs(
|
||||
UidBatteryConsumer.STATE_FOREGROUND);
|
||||
return mTimeInForegroundMs;
|
||||
} else {
|
||||
return mUsageDurationMs;
|
||||
}
|
||||
@@ -506,8 +511,7 @@ public class BatteryEntry {
|
||||
*/
|
||||
public long getTimeInBackgroundMs() {
|
||||
if (mBatteryConsumer instanceof UidBatteryConsumer) {
|
||||
return ((UidBatteryConsumer) mBatteryConsumer).getTimeInStateMs(
|
||||
UidBatteryConsumer.STATE_BACKGROUND);
|
||||
return mTimeInBackgroundMs;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
@@ -526,9 +530,15 @@ public class BatteryEntry {
|
||||
*/
|
||||
public void add(BatteryConsumer batteryConsumer) {
|
||||
mConsumedPower += batteryConsumer.getConsumedPower();
|
||||
if (mDefaultPackageName == null && batteryConsumer instanceof UidBatteryConsumer) {
|
||||
mDefaultPackageName =
|
||||
((UidBatteryConsumer) batteryConsumer).getPackageWithHighestDrain();
|
||||
if (batteryConsumer instanceof UidBatteryConsumer) {
|
||||
UidBatteryConsumer uidBatteryConsumer = (UidBatteryConsumer) batteryConsumer;
|
||||
mTimeInForegroundMs += uidBatteryConsumer.getTimeInStateMs(
|
||||
UidBatteryConsumer.STATE_FOREGROUND);
|
||||
mTimeInBackgroundMs += uidBatteryConsumer.getTimeInStateMs(
|
||||
UidBatteryConsumer.STATE_BACKGROUND);
|
||||
if (mDefaultPackageName == null) {
|
||||
mDefaultPackageName = uidBatteryConsumer.getPackageWithHighestDrain();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.location;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.location.SettingInjectorService;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.OnLifecycleEvent;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A abstract class which is responsible for creating the injected location services items.
|
||||
* Developer needs to implement the {@link #injectLocationServices(PreferenceScreen)}.
|
||||
*/
|
||||
public abstract class LocationInjectedServiceBasePreferenceController
|
||||
extends LocationBasePreferenceController implements LifecycleObserver{
|
||||
|
||||
private static final String TAG = "LocationPrefCtrl";
|
||||
@VisibleForTesting
|
||||
static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED =
|
||||
new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
|
||||
|
||||
@VisibleForTesting
|
||||
AppSettingsInjector mInjector;
|
||||
/** Receives UPDATE_INTENT */
|
||||
@VisibleForTesting
|
||||
BroadcastReceiver mInjectedSettingsReceiver;
|
||||
|
||||
public LocationInjectedServiceBasePreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(DashboardFragment fragment) {
|
||||
super.init(fragment);
|
||||
mInjector = new AppSettingsInjector(mContext, getMetricsCategory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
injectLocationServices(screen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method to inject location services in preference screen.
|
||||
* @param screen
|
||||
*/
|
||||
protected abstract void injectLocationServices(PreferenceScreen screen);
|
||||
|
||||
@Override
|
||||
public void onLocationModeChanged(int mode, boolean restricted) {
|
||||
// As a safety measure, also reloads on location mode change to ensure the settings are
|
||||
// up-to-date even if an affected app doesn't send the setting changed broadcast.
|
||||
mInjector.reloadStatusMessages();
|
||||
}
|
||||
|
||||
/** @OnLifecycleEvent(ON_RESUME) */
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
|
||||
public void onResume() {
|
||||
if (mInjectedSettingsReceiver == null) {
|
||||
mInjectedSettingsReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Received settings change intent: " + intent);
|
||||
}
|
||||
mInjector.reloadStatusMessages();
|
||||
}
|
||||
};
|
||||
}
|
||||
mContext.registerReceiver(
|
||||
mInjectedSettingsReceiver, INTENT_FILTER_INJECTED_SETTING_CHANGED);
|
||||
}
|
||||
|
||||
/** @OnLifecycleEvent(ON_PAUSE) */
|
||||
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
|
||||
public void onPause() {
|
||||
mContext.unregisterReceiver(mInjectedSettingsReceiver);
|
||||
}
|
||||
|
||||
protected Map<Integer, List<Preference>> getLocationServices() {
|
||||
// If location access is locked down by device policy then we only show injected settings
|
||||
// for the primary profile.
|
||||
final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
|
||||
|
||||
return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(),
|
||||
(profileUserId != UserHandle.USER_NULL
|
||||
&& mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null)
|
||||
? UserHandle.myUserId() : UserHandle.USER_CURRENT);
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,8 @@ import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.widget.RestrictedAppPreference;
|
||||
|
||||
@@ -30,7 +32,7 @@ import java.util.Map;
|
||||
* Retrieve the Location Services used in work profile user.
|
||||
*/
|
||||
public class LocationInjectedServicesForWorkPreferenceController extends
|
||||
LocationInjectedServicesPreferenceController {
|
||||
LocationInjectedServiceBasePreferenceController {
|
||||
private static final String TAG = "LocationWorkPrefCtrl";
|
||||
|
||||
public LocationInjectedServicesForWorkPreferenceController(Context context, String key) {
|
||||
@@ -38,10 +40,10 @@ public class LocationInjectedServicesForWorkPreferenceController extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
mCategoryLocationServices.removeAll();
|
||||
protected void injectLocationServices(PreferenceScreen screen) {
|
||||
final PreferenceCategory categoryLocationServices =
|
||||
screen.findPreference(getPreferenceKey());
|
||||
final Map<Integer, List<Preference>> prefs = getLocationServices();
|
||||
boolean show = false;
|
||||
for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) {
|
||||
for (Preference pref : entry.getValue()) {
|
||||
if (pref instanceof RestrictedAppPreference) {
|
||||
@@ -49,11 +51,8 @@ public class LocationInjectedServicesForWorkPreferenceController extends
|
||||
}
|
||||
}
|
||||
if (entry.getKey() != UserHandle.myUserId()) {
|
||||
LocationSettings.addPreferencesSorted(entry.getValue(),
|
||||
mCategoryLocationServices);
|
||||
show = true;
|
||||
LocationSettings.addPreferencesSorted(entry.getValue(), categoryLocationServices);
|
||||
}
|
||||
}
|
||||
mCategoryLocationServices.setVisible(show);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,25 +15,14 @@
|
||||
*/
|
||||
package com.android.settings.location;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.location.SettingInjectorService;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.widget.RestrictedAppPreference;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnPause;
|
||||
import com.android.settingslib.core.lifecycle.events.OnResume;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -41,42 +30,20 @@ import java.util.Map;
|
||||
/**
|
||||
* Preference controller for the injected Location Services.
|
||||
*/
|
||||
public class LocationInjectedServicesPreferenceController extends LocationBasePreferenceController
|
||||
implements LifecycleObserver, OnResume, OnPause {
|
||||
public class LocationInjectedServicesPreferenceController
|
||||
extends LocationInjectedServiceBasePreferenceController {
|
||||
|
||||
private static final String TAG = "LocationPrefCtrl";
|
||||
@VisibleForTesting
|
||||
static final IntentFilter INTENT_FILTER_INJECTED_SETTING_CHANGED =
|
||||
new IntentFilter(SettingInjectorService.ACTION_INJECTED_SETTING_CHANGED);
|
||||
|
||||
protected PreferenceCategory mCategoryLocationServices;
|
||||
@VisibleForTesting
|
||||
AppSettingsInjector mInjector;
|
||||
/** Receives UPDATE_INTENT */
|
||||
@VisibleForTesting
|
||||
BroadcastReceiver mInjectedSettingsReceiver;
|
||||
|
||||
public LocationInjectedServicesPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(DashboardFragment fragment) {
|
||||
super.init(fragment);
|
||||
mInjector = new AppSettingsInjector(mContext, getMetricsCategory());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
mCategoryLocationServices = screen.findPreference(getPreferenceKey());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
mCategoryLocationServices.removeAll();
|
||||
protected void injectLocationServices(PreferenceScreen screen) {
|
||||
final PreferenceCategory categoryLocationServices =
|
||||
screen.findPreference(getPreferenceKey());
|
||||
final Map<Integer, List<Preference>> prefs = getLocationServices();
|
||||
boolean show = false;
|
||||
for (Map.Entry<Integer, List<Preference>> entry : prefs.entrySet()) {
|
||||
for (Preference pref : entry.getValue()) {
|
||||
if (pref instanceof RestrictedAppPreference) {
|
||||
@@ -84,53 +51,11 @@ public class LocationInjectedServicesPreferenceController extends LocationBasePr
|
||||
}
|
||||
}
|
||||
if (entry.getKey() == UserHandle.myUserId()) {
|
||||
if (mCategoryLocationServices != null) {
|
||||
if (categoryLocationServices != null) {
|
||||
LocationSettings.addPreferencesSorted(entry.getValue(),
|
||||
mCategoryLocationServices);
|
||||
categoryLocationServices);
|
||||
}
|
||||
show = true;
|
||||
}
|
||||
}
|
||||
mCategoryLocationServices.setVisible(show);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationModeChanged(int mode, boolean restricted) {
|
||||
// As a safety measure, also reloads on location mode change to ensure the settings are
|
||||
// up-to-date even if an affected app doesn't send the setting changed broadcast.
|
||||
mInjector.reloadStatusMessages();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
if (mInjectedSettingsReceiver == null) {
|
||||
mInjectedSettingsReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Received settings change intent: " + intent);
|
||||
}
|
||||
mInjector.reloadStatusMessages();
|
||||
}
|
||||
};
|
||||
}
|
||||
mContext.registerReceiver(
|
||||
mInjectedSettingsReceiver, INTENT_FILTER_INJECTED_SETTING_CHANGED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
mContext.unregisterReceiver(mInjectedSettingsReceiver);
|
||||
}
|
||||
|
||||
protected Map<Integer, List<Preference>> getLocationServices() {
|
||||
// If location access is locked down by device policy then we only show injected settings
|
||||
// for the primary profile.
|
||||
final int profileUserId = Utils.getManagedProfileId(mUserManager, UserHandle.myUserId());
|
||||
|
||||
return mInjector.getInjectedSettings(mFragment.getPreferenceManager().getContext(),
|
||||
(profileUserId != UserHandle.USER_NULL
|
||||
&& mLocationEnabler.getShareLocationEnforcedAdmin(profileUserId) != null)
|
||||
? UserHandle.myUserId() : UserHandle.USER_CURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SignalStrength;
|
||||
@@ -38,6 +39,7 @@ import android.telephony.TelephonyDisplayInfo;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.Html;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.collection.ArrayMap;
|
||||
@@ -55,7 +57,7 @@ import com.android.settings.network.telephony.MobileNetworkActivity;
|
||||
import com.android.settings.network.telephony.MobileNetworkUtils;
|
||||
import com.android.settings.network.telephony.SignalStrengthListener;
|
||||
import com.android.settings.network.telephony.TelephonyDisplayInfoListener;
|
||||
import com.android.settings.widget.GearPreference;
|
||||
import com.android.settings.widget.MutableGearPreference;
|
||||
import com.android.settings.wifi.WifiPickerTrackerHelper;
|
||||
import com.android.settingslib.SignalIcon.MobileIconGroup;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
@@ -115,7 +117,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
// Map of subscription id to Preference
|
||||
private Map<Integer, Preference> mSubscriptionPreferences;
|
||||
private int mStartOrder;
|
||||
private GearPreference mSubsGearPref;
|
||||
private MutableGearPreference mSubsGearPref;
|
||||
private Config mConfig = null;
|
||||
private SubsPrefCtrlInjector mSubsPrefCtrlInjector;
|
||||
private TelephonyDisplayInfo mTelephonyDisplayInfo =
|
||||
@@ -196,6 +198,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
mSignalStrengthListener.pause();
|
||||
mTelephonyDisplayInfoListener.pause();
|
||||
unRegisterReceiver();
|
||||
resetProviderPreferenceSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -238,15 +241,20 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
}
|
||||
if (mSubsGearPref == null) {
|
||||
mPreferenceGroup.removeAll();
|
||||
mSubsGearPref = new GearPreference(mContext, null);
|
||||
mSubsGearPref = new MutableGearPreference(mContext, null);
|
||||
mSubsGearPref.setOnPreferenceClickListener(preference -> {
|
||||
connectCarrierNetwork();
|
||||
return true;
|
||||
});
|
||||
|
||||
mSubsGearPref.setOnGearClickListener(p ->
|
||||
startMobileNetworkActivity(mContext, subInfo.getSubscriptionId()));
|
||||
}
|
||||
|
||||
if (!(mContext.getSystemService(UserManager.class)).isAdminUser()) {
|
||||
mSubsGearPref.setGearEnabled(false);
|
||||
}
|
||||
|
||||
mSubsGearPref.setTitle(SubscriptionUtil.getUniqueSubscriptionDisplayName(
|
||||
subInfo, mContext));
|
||||
mSubsGearPref.setOrder(mStartOrder);
|
||||
@@ -275,6 +283,7 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
String result = mSubsPrefCtrlInjector.getNetworkType(
|
||||
mContext, mConfig, mTelephonyDisplayInfo, subId, isActiveCarrierNetwork);
|
||||
if (mSubsPrefCtrlInjector.isActiveCellularNetwork(mContext) || isActiveCarrierNetwork) {
|
||||
Log.i(TAG, "Active cellular network or active carrier network.");
|
||||
result = mContext.getString(R.string.preference_summary_default_combination,
|
||||
mContext.getString(R.string.mobile_data_connection_active), result);
|
||||
} else if (!isDataInService) {
|
||||
@@ -316,6 +325,13 @@ public class SubscriptionsPreferenceController extends AbstractPreferenceControl
|
||||
return icon;
|
||||
}
|
||||
|
||||
private void resetProviderPreferenceSummary() {
|
||||
if (mSubsGearPref == null) {
|
||||
return;
|
||||
}
|
||||
mSubsGearPref.setSummary("");
|
||||
}
|
||||
|
||||
private void updateForBase() {
|
||||
final Map<Integer, Preference> existingPrefs = mSubscriptionPreferences;
|
||||
mSubscriptionPreferences = new ArrayMap<>();
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.security.AppUriAuthenticationPolicy;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -85,11 +86,13 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter<Recycle
|
||||
ApplicationInfo applicationInfo =
|
||||
mPackageManager.getApplicationInfo(mCredentialManagerPackage, 0);
|
||||
mAppIconView.setImageDrawable(mPackageManager.getApplicationIcon(applicationInfo));
|
||||
mTitleView.setText(mContext.getString(R.string.request_manage_credentials_title,
|
||||
mTitleView.setText(TextUtils.expandTemplate(
|
||||
mContext.getText(R.string.request_manage_credentials_title),
|
||||
applicationInfo.loadLabel(mPackageManager)));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
mAppIconView.setImageDrawable(null);
|
||||
mTitleView.setText(mContext.getString(R.string.request_manage_credentials_title,
|
||||
mTitleView.setText(TextUtils.expandTemplate(
|
||||
mContext.getText(R.string.request_manage_credentials_title),
|
||||
mCredentialManagerPackage));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,12 +80,29 @@ public class CredentialManagementAppButtonsController extends BasePreferenceCont
|
||||
private void displayButtons(PreferenceScreen screen) {
|
||||
if (mHasCredentialManagerPackage) {
|
||||
((ActionButtonsPreference) screen.findPreference(getPreferenceKey()))
|
||||
.setButton1Text(R.string.remove_credential_management_app)
|
||||
.setButton1Icon(R.drawable.ic_undo_24)
|
||||
.setButton1OnClickListener(view -> removeCredentialManagementApp());
|
||||
.setButton1Text(R.string.uninstall_certs_credential_management_app)
|
||||
.setButton1Icon(R.drawable.ic_upload)
|
||||
.setButton1OnClickListener(view -> uninstallCertificates())
|
||||
.setButton2Text(R.string.remove_credential_management_app)
|
||||
.setButton2Icon(R.drawable.ic_delete)
|
||||
.setButton2OnClickListener(view -> removeCredentialManagementApp());
|
||||
}
|
||||
}
|
||||
|
||||
private void uninstallCertificates() {
|
||||
mExecutor.execute(() -> {
|
||||
try {
|
||||
IKeyChainService service = KeyChain.bind(mContext).getService();
|
||||
for (String existingAlias :
|
||||
service.getCredentialManagementAppPolicy().getAliases()) {
|
||||
service.removeKeyPair(existingAlias);
|
||||
}
|
||||
} catch (InterruptedException | RemoteException e) {
|
||||
Log.e(TAG, "Unable to uninstall certificates");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeCredentialManagementApp() {
|
||||
mExecutor.execute(() -> {
|
||||
try {
|
||||
|
||||
@@ -83,7 +83,6 @@ public class CredentialManagementAppHeaderController extends BasePreferenceContr
|
||||
TextView titleView = headerPref.findViewById(R.id.entity_header_title);
|
||||
TextView summary1 = headerPref.findViewById(R.id.entity_header_summary);
|
||||
TextView summary2 = headerPref.findViewById(R.id.entity_header_second_summary);
|
||||
summary1.setVisibility(View.GONE);
|
||||
summary2.setVisibility(View.GONE);
|
||||
|
||||
try {
|
||||
@@ -91,6 +90,7 @@ public class CredentialManagementAppHeaderController extends BasePreferenceContr
|
||||
mPackageManager.getApplicationInfo(mCredentialManagerPackageName, 0);
|
||||
appIconView.setImageDrawable(mPackageManager.getApplicationIcon(applicationInfo));
|
||||
titleView.setText(applicationInfo.loadLabel(mPackageManager));
|
||||
summary1.setText(R.string.certificate_management_app_description);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
appIconView.setImageDrawable(null);
|
||||
titleView.setText(mCredentialManagerPackageName);
|
||||
|
||||
@@ -21,7 +21,10 @@ import android.app.Activity;
|
||||
import android.app.admin.DevicePolicyEventLogger;
|
||||
import android.app.admin.DevicePolicyManager;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
@@ -37,7 +40,9 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -83,6 +88,7 @@ public class RequestManageCredentials extends Activity {
|
||||
private KeyChain.KeyChainConnection mKeyChainConnection;
|
||||
|
||||
private boolean mDisplayingButtonPanel = false;
|
||||
private boolean mIsLandscapeMode = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
@@ -114,6 +120,8 @@ public class RequestManageCredentials extends Activity {
|
||||
.setStrings(mCredentialManagerPackage)
|
||||
.write();
|
||||
setContentView(R.layout.request_manage_credentials);
|
||||
mIsLandscapeMode = getResources().getConfiguration().orientation
|
||||
== Configuration.ORIENTATION_LANDSCAPE;
|
||||
|
||||
mKeyChainTread = new HandlerThread("KeyChainConnection");
|
||||
mKeyChainTread.start();
|
||||
@@ -134,6 +142,9 @@ public class RequestManageCredentials extends Activity {
|
||||
getNumberOfAuthenticationPolicyUris(mAuthenticationPolicy))
|
||||
.write();
|
||||
|
||||
if (mIsLandscapeMode) {
|
||||
loadHeader();
|
||||
}
|
||||
loadRecyclerView();
|
||||
loadButtons();
|
||||
loadExtendedFloatingActionButton();
|
||||
@@ -193,7 +204,7 @@ public class RequestManageCredentials extends Activity {
|
||||
|
||||
CredentialManagementAppAdapter recyclerViewAdapter = new CredentialManagementAppAdapter(
|
||||
this, mCredentialManagerPackage, mAuthenticationPolicy.getAppAndUriMappings(),
|
||||
/* include header= */ true, /* include expander= */ false);
|
||||
/* include header= */ !mIsLandscapeMode, /* include expander= */ false);
|
||||
mRecyclerView.setAdapter(recyclerViewAdapter);
|
||||
}
|
||||
|
||||
@@ -214,12 +225,33 @@ public class RequestManageCredentials extends Activity {
|
||||
private void loadExtendedFloatingActionButton() {
|
||||
mExtendedFab = findViewById(R.id.extended_fab);
|
||||
mExtendedFab.setOnClickListener(v -> {
|
||||
mRecyclerView.scrollToPosition(mAuthenticationPolicy.getAppAndUriMappings().size());
|
||||
final int position = mIsLandscapeMode
|
||||
? mAuthenticationPolicy.getAppAndUriMappings().size() - 1
|
||||
: mAuthenticationPolicy.getAppAndUriMappings().size();
|
||||
mRecyclerView.scrollToPosition(position);
|
||||
mExtendedFab.hide();
|
||||
showButtonPanel();
|
||||
});
|
||||
}
|
||||
|
||||
private void loadHeader() {
|
||||
final ImageView mAppIconView = findViewById(R.id.credential_management_app_icon);
|
||||
final TextView mTitleView = findViewById(R.id.credential_management_app_title);
|
||||
try {
|
||||
ApplicationInfo applicationInfo =
|
||||
getPackageManager().getApplicationInfo(mCredentialManagerPackage, 0);
|
||||
mAppIconView.setImageDrawable(getPackageManager().getApplicationIcon(applicationInfo));
|
||||
mTitleView.setText(TextUtils.expandTemplate(
|
||||
getText(R.string.request_manage_credentials_title),
|
||||
applicationInfo.loadLabel(getPackageManager())));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
mAppIconView.setImageDrawable(null);
|
||||
mTitleView.setText(TextUtils.expandTemplate(
|
||||
getText(R.string.request_manage_credentials_title),
|
||||
mCredentialManagerPackage));
|
||||
}
|
||||
}
|
||||
|
||||
private void setOrUpdateCredentialManagementAppAndFinish() {
|
||||
try {
|
||||
mKeyChainConnection.getService().setCredentialManagementApp(
|
||||
|
||||
@@ -29,7 +29,8 @@ import com.android.settingslib.RestrictedPreference;
|
||||
* A preference with a Gear on the side
|
||||
*/
|
||||
public class GearPreference extends RestrictedPreference implements View.OnClickListener {
|
||||
|
||||
// Default true for gear available even if the preference itself is disabled.
|
||||
protected boolean mGearState = true;
|
||||
private OnGearClickListener mOnGearClickListener;
|
||||
|
||||
public GearPreference(Context context, AttributeSet attrs) {
|
||||
@@ -41,6 +42,16 @@ public class GearPreference extends RestrictedPreference implements View.OnClick
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
/** Sets state of gear button. */
|
||||
public void setGearEnabled(boolean enabled) {
|
||||
mGearState = enabled;
|
||||
}
|
||||
|
||||
/** Gets state of gear button. */
|
||||
public boolean isGearEnabled() {
|
||||
return mGearState;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSecondTargetResId() {
|
||||
return R.layout.preference_widget_gear;
|
||||
@@ -62,7 +73,8 @@ public class GearPreference extends RestrictedPreference implements View.OnClick
|
||||
gear.setVisibility(View.GONE);
|
||||
gear.setOnClickListener(null);
|
||||
}
|
||||
gear.setEnabled(true); // Make gear available even if the preference itself is disabled.
|
||||
// Make gear available even if the preference itself is disabled.
|
||||
gear.setEnabled(mGearState);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
57
src/com/android/settings/widget/MutableGearPreference.java
Normal file
57
src/com/android/settings/widget/MutableGearPreference.java
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.utils.ColorUtil;
|
||||
|
||||
/** A preference with a Gear on the side and mutable Gear color. */
|
||||
public class MutableGearPreference extends GearPreference {
|
||||
private static final int VALUE_ENABLED_ALPHA = 255;
|
||||
|
||||
private ImageView mGear;
|
||||
private Context mContext;
|
||||
private int mDisabledAlphaValue;
|
||||
|
||||
public MutableGearPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mContext = context;
|
||||
mDisabledAlphaValue = (int) (ColorUtil.getDisabledAlpha(context) * VALUE_ENABLED_ALPHA);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGearEnabled(boolean enabled) {
|
||||
if (mGear != null) {
|
||||
mGear.setEnabled(enabled);
|
||||
mGear.setImageAlpha(enabled ? VALUE_ENABLED_ALPHA : mDisabledAlphaValue);
|
||||
}
|
||||
mGearState = enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
mGear = (ImageView) holder.findViewById(R.id.settings_button);
|
||||
setGearEnabled(mGearState);
|
||||
}
|
||||
}
|
||||
136
tests/robotests/res/layout/main_clear.xml
Normal file
136
tests/robotests/res/layout/main_clear.xml
Normal file
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2021 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.
|
||||
-->
|
||||
|
||||
<com.google.android.setupdesign.GlifLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/setup_wizard_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:theme="@style/GlifV3Theme.Footer"
|
||||
android:orientation="vertical"
|
||||
android:icon="@drawable/ic_delete_accent"
|
||||
app:sucHeaderText="@string/main_clear_title">
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/main_clear_scrollview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="@dimen/reset_main_clear_margin_start"
|
||||
android:layout_marginEnd="@dimen/reset_main_clear_margin_end">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/main_clear_container"
|
||||
style="@style/SudContentFrame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
style="@style/TextAppearance.SudGlifItemSummary"
|
||||
android:id="@+id/sud_layout_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_clear_desc"/>
|
||||
<TextView
|
||||
android:id="@+id/also_erases_external"
|
||||
style="@style/TextAppearance.SudGlifItemSummary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:text="@string/main_clear_desc_also_erases_external"/>
|
||||
<TextView
|
||||
android:id="@+id/also_erases_esim"
|
||||
style="@style/TextAppearance.SudGlifItemSummary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:text="@string/main_clear_desc_also_erases_esim"/>
|
||||
<TextView
|
||||
android:id="@+id/accounts_label"
|
||||
style="@style/TextAppearance.SudGlifItemSummary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:text="@string/main_clear_accounts"/>
|
||||
<LinearLayout
|
||||
android:id="@+id/accounts"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
<!-- Do not add any children here as they will be removed in the MainClear.java
|
||||
code. A list of accounts will be inserted programmatically. -->
|
||||
</LinearLayout>
|
||||
<TextView
|
||||
android:id="@+id/other_users_present"
|
||||
style="@style/TextAppearance.SudGlifItemSummary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:text="@string/main_clear_other_users_present"/>
|
||||
<TextView
|
||||
android:id="@+id/no_cancel_mobile_plan"
|
||||
style="@style/TextAppearance.SudGlifItemSummary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
android:text="@string/main_clear_desc_no_cancel_mobile_plan"/>
|
||||
<TextView
|
||||
android:id="@+id/erase_external_option_text"
|
||||
style="@style/TextAppearance.SudGlifItemSummary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_clear_desc_erase_external_storage"/>
|
||||
<LinearLayout
|
||||
android:id="@+id/erase_external_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:focusable="true"
|
||||
android:clickable="true">
|
||||
<CheckBox
|
||||
android:id="@+id/erase_external"
|
||||
style="@style/SudCheckBox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:duplicateParentState="true"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
style="@style/TextAppearance.SudGlifItemTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/erase_external_storage"/>
|
||||
<TextView
|
||||
style="@style/TextAppearance.SudGlifItemSummary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/erase_external_storage_description"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/reset_esim_checkbox"/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</com.google.android.setupdesign.GlifLayout>
|
||||
40
tests/robotests/res/layout/main_clear_confirm.xml
Normal file
40
tests/robotests/res/layout/main_clear_confirm.xml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2021 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.
|
||||
-->
|
||||
<com.google.android.setupdesign.GlifLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:theme="@style/SudThemeGlifV3.DayNight"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/setup_wizard_layout"
|
||||
android:icon="@drawable/ic_delete_accent"
|
||||
app:sucHeaderText="@string/main_clear_confirm_title">
|
||||
|
||||
<LinearLayout
|
||||
style="@style/SudContentFrame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sud_layout_description"
|
||||
style="@style/SudItemTitle.GlifDescription"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_clear_final_desc"/>
|
||||
</LinearLayout>
|
||||
</com.google.android.setupdesign.GlifLayout>
|
||||
@@ -20,11 +20,10 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.PermissionChecker;
|
||||
import android.content.pm.CrossProfileApps;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PermissionInfo;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.os.UserManager;
|
||||
|
||||
@@ -37,19 +36,18 @@ import com.google.common.collect.ImmutableList;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.shadows.ShadowPermissionChecker;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class InteractAcrossProfilesDetailsTest {
|
||||
|
||||
private static final int PERSONAL_PROFILE_ID = 0;
|
||||
private static final int WORK_PROFILE_ID = 10;
|
||||
private static final int PACKAGE_UID = 0;
|
||||
private static final String CROSS_PROFILE_PACKAGE_NAME = "crossProfilePackage";
|
||||
public static final String INTERACT_ACROSS_PROFILES_PERMISSION =
|
||||
"android.permission.INTERACT_ACROSS_PROFILES";
|
||||
|
||||
private final Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private final AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
|
||||
private final PackageManager mPackageManager = mContext.getPackageManager();
|
||||
private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
|
||||
private final CrossProfileApps mCrossProfileApps = mContext.getSystemService(
|
||||
@@ -68,10 +66,10 @@ public class InteractAcrossProfilesDetailsTest {
|
||||
WORK_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME));
|
||||
shadowOf(mCrossProfileApps).addCrossProfilePackage(
|
||||
CROSS_PROFILE_PACKAGE_NAME);
|
||||
String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
|
||||
shadowOf(mAppOpsManager).setMode(
|
||||
appOp, PACKAGE_UID, CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
|
||||
shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo());
|
||||
ShadowPermissionChecker.setResult(
|
||||
CROSS_PROFILE_PACKAGE_NAME,
|
||||
INTERACT_ACROSS_PROFILES_PERMISSION,
|
||||
PermissionChecker.PERMISSION_GRANTED);
|
||||
|
||||
assertThat(InteractAcrossProfilesDetails.getPreferenceSummary(
|
||||
mContext, CROSS_PROFILE_PACKAGE_NAME))
|
||||
@@ -91,11 +89,10 @@ public class InteractAcrossProfilesDetailsTest {
|
||||
WORK_PROFILE_ID, ImmutableList.of(CROSS_PROFILE_PACKAGE_NAME));
|
||||
shadowOf(mCrossProfileApps).addCrossProfilePackage(
|
||||
CROSS_PROFILE_PACKAGE_NAME);
|
||||
String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
|
||||
shadowOf(mAppOpsManager).setMode(
|
||||
appOp, PACKAGE_UID, CROSS_PROFILE_PACKAGE_NAME, AppOpsManager.MODE_IGNORED);
|
||||
shadowOf(mPackageManager).addPermissionInfo(createCrossProfilesPermissionInfo());
|
||||
|
||||
ShadowPermissionChecker.setResult(
|
||||
CROSS_PROFILE_PACKAGE_NAME,
|
||||
INTERACT_ACROSS_PROFILES_PERMISSION,
|
||||
PermissionChecker.PERMISSION_SOFT_DENIED);
|
||||
assertThat(InteractAcrossProfilesDetails.getPreferenceSummary(
|
||||
mContext, CROSS_PROFILE_PACKAGE_NAME))
|
||||
.isEqualTo(mContext.getString(
|
||||
@@ -114,11 +111,4 @@ public class InteractAcrossProfilesDetailsTest {
|
||||
.isEqualTo(mContext.getString(
|
||||
R.string.interact_across_profiles_summary_not_allowed));
|
||||
}
|
||||
|
||||
private PermissionInfo createCrossProfilesPermissionInfo() {
|
||||
PermissionInfo permissionInfo = new PermissionInfo();
|
||||
permissionInfo.name = INTERACT_ACROSS_PROFILES_PERMISSION;
|
||||
permissionInfo.protectionLevel = PermissionInfo.PROTECTION_FLAG_APPOP;
|
||||
return permissionInfo;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import static com.google.common.truth.Truth.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.robolectric.Shadows.shadowOf;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.content.Context;
|
||||
import android.content.PermissionChecker;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
@@ -51,7 +50,6 @@ public class InteractAcrossProfilesSettingsTest {
|
||||
private static final int PERSONAL_PROFILE_ID = 0;
|
||||
private static final int WORK_PROFILE_ID = 10;
|
||||
private static final int WORK_UID = UserHandle.PER_USER_RANGE * WORK_PROFILE_ID;
|
||||
private static final int PACKAGE_UID = 0;
|
||||
|
||||
private static final String PERSONAL_CROSS_PROFILE_PACKAGE = "personalCrossProfilePackage";
|
||||
private static final String PERSONAL_NON_CROSS_PROFILE_PACKAGE =
|
||||
@@ -71,7 +69,6 @@ public class InteractAcrossProfilesSettingsTest {
|
||||
private final UserManager mUserManager = mContext.getSystemService(UserManager.class);
|
||||
private final CrossProfileApps mCrossProfileApps =
|
||||
mContext.getSystemService(CrossProfileApps.class);
|
||||
private final AppOpsManager mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
|
||||
|
||||
@Test
|
||||
public void collectConfigurableApps_fromPersonal_returnsCombinedPackages() {
|
||||
@@ -84,8 +81,8 @@ public class InteractAcrossProfilesSettingsTest {
|
||||
PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
|
||||
shadowOf(mPackageManager).setInstalledPackagesForUserId(
|
||||
WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
|
||||
installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
|
||||
|
||||
List<Pair<ApplicationInfo, UserHandle>> apps =
|
||||
InteractAcrossProfilesSettings.collectConfigurableApps(
|
||||
@@ -110,8 +107,8 @@ public class InteractAcrossProfilesSettingsTest {
|
||||
PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
|
||||
shadowOf(mPackageManager).setInstalledPackagesForUserId(
|
||||
WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
|
||||
installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
|
||||
|
||||
List<Pair<ApplicationInfo, UserHandle>> apps =
|
||||
InteractAcrossProfilesSettings.collectConfigurableApps(
|
||||
@@ -130,7 +127,7 @@ public class InteractAcrossProfilesSettingsTest {
|
||||
PERSONAL_PROFILE_ID, "personal-profile"/* name */, 0/* flags */);
|
||||
shadowOf(mPackageManager).setInstalledPackagesForUserId(
|
||||
PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
|
||||
installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
|
||||
List<Pair<ApplicationInfo, UserHandle>> apps =
|
||||
InteractAcrossProfilesSettings.collectConfigurableApps(
|
||||
@@ -150,10 +147,9 @@ public class InteractAcrossProfilesSettingsTest {
|
||||
PERSONAL_PROFILE_ID, PERSONAL_PROFILE_INSTALLED_PACKAGES);
|
||||
shadowOf(mPackageManager).setInstalledPackagesForUserId(
|
||||
WORK_PROFILE_ID, WORK_PROFILE_INSTALLED_PACKAGES);
|
||||
installCrossProfilePackage(PERSONAL_PROFILE_ID, PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(WORK_PROFILE_ID, WORK_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
installCrossProfilePackage(WORK_CROSS_PROFILE_PACKAGE);
|
||||
shadowOf(mCrossProfileApps).addCrossProfilePackage(PERSONAL_CROSS_PROFILE_PACKAGE);
|
||||
String appOp = AppOpsManager.permissionToOp(INTERACT_ACROSS_PROFILES_PERMISSION);
|
||||
ShadowPermissionChecker.setResult(
|
||||
PERSONAL_CROSS_PROFILE_PACKAGE,
|
||||
INTERACT_ACROSS_PROFILES_PERMISSION,
|
||||
@@ -169,7 +165,7 @@ public class InteractAcrossProfilesSettingsTest {
|
||||
assertThat(numOfApps).isEqualTo(1);
|
||||
}
|
||||
|
||||
private void installCrossProfilePackage(int profileId, String packageName) {
|
||||
private void installCrossProfilePackage(String packageName) {
|
||||
PackageInfo personalPackageInfo = shadowOf(mPackageManager).getInternalMutablePackageInfo(
|
||||
packageName);
|
||||
personalPackageInfo.requestedPermissions = new String[]{
|
||||
|
||||
@@ -20,46 +20,65 @@ import static android.provider.Settings.Secure.CAMERA_AUTOROTATE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.os.UserHandle;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settings.testutils.ResolveInfoBuilder;
|
||||
import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Answers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(shadows = ShadowSensorPrivacyManager.class)
|
||||
public class SmartAutoRotatePreferenceControllerTest {
|
||||
|
||||
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
|
||||
private Context mContext;
|
||||
private static final String PACKAGE_NAME = "package_name";
|
||||
@Mock
|
||||
private PackageManager mPackageManager;
|
||||
@Mock
|
||||
private Resources mResources;
|
||||
private Context mContext;
|
||||
private ContentResolver mContentResolver;
|
||||
private SmartAutoRotatePreferenceController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = Mockito.spy(RuntimeEnvironment.application);
|
||||
FakeFeatureFactory.setupForTest();
|
||||
mContentResolver = RuntimeEnvironment.application.getContentResolver();
|
||||
|
||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||
when(mContext.getResources()).thenReturn(mResources);
|
||||
when(mContext.getContentResolver()).thenReturn(mContentResolver);
|
||||
|
||||
doReturn(PACKAGE_NAME).when(mPackageManager).getRotationResolverPackageName();
|
||||
doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission(
|
||||
Manifest.permission.CAMERA, PACKAGE_NAME);
|
||||
when(mContext.getString(R.string.auto_rotate_option_off))
|
||||
.thenReturn("Off");
|
||||
when(mContext.getString(R.string.auto_rotate_option_on))
|
||||
@@ -68,8 +87,14 @@ public class SmartAutoRotatePreferenceControllerTest {
|
||||
.thenReturn("On - Face-based");
|
||||
|
||||
disableCameraBasedRotation();
|
||||
final ResolveInfo resolveInfo = new ResolveInfoBuilder(PACKAGE_NAME).build();
|
||||
resolveInfo.serviceInfo = new ServiceInfo();
|
||||
when(mPackageManager.resolveService(any(), anyInt())).thenReturn(resolveInfo);
|
||||
|
||||
mController = new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate");
|
||||
mController = Mockito.spy(
|
||||
new SmartAutoRotatePreferenceController(mContext, "smart_auto_rotate"));
|
||||
when(mController.isCameraLocked()).thenReturn(false);
|
||||
when(mController.isPowerSaveMode()).thenReturn(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,33 +107,37 @@ public class SmartAutoRotatePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_settingsIsOff_shouldTurnOffToggle() {
|
||||
public void getSummary_settingsIsOff_returnsOff() {
|
||||
disableAutoRotation();
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("Off");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_settingsIsOn_shouldTurnOnToggle() {
|
||||
public void getSummary_settingsIsOn_returnsOn() {
|
||||
enableAutoRotation();
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("On");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_settingsIsCameraBased_shouldTurnOnToggle() {
|
||||
public void getSummary_autoRotateOffSmartAutoRotateOn_returnsOff() {
|
||||
enableCameraBasedRotation();
|
||||
disableAutoRotation();
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("Off");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_smartAutoRotateOn_returnsFaceBased() {
|
||||
enableCameraBasedRotation();
|
||||
enableAutoRotation();
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("On - Face-based");
|
||||
|
||||
disableAutoRotation();
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("Off");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_settingsIsOff_noSmartAuto_shouldTurnOffToggle() {
|
||||
public void getSummary_noSmartAuto_returnsOff() {
|
||||
disableAutoRotation();
|
||||
Settings.Secure.putStringForUser(mContentResolver,
|
||||
CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT);
|
||||
@@ -118,7 +147,7 @@ public class SmartAutoRotatePreferenceControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updatePreference_settingsIsOn_noSmartAuto_shouldTurnOnToggle() {
|
||||
public void getSummary_noSmartAuto_returnsOn() {
|
||||
enableAutoRotation();
|
||||
Settings.Secure.putStringForUser(mContentResolver,
|
||||
CAMERA_AUTOROTATE, null, UserHandle.USER_CURRENT);
|
||||
@@ -126,6 +155,34 @@ public class SmartAutoRotatePreferenceControllerTest {
|
||||
assertThat(mController.getSummary()).isEqualTo("On");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_noCameraPermission_returnsOn() {
|
||||
enableAutoRotation();
|
||||
enableCameraBasedRotation();
|
||||
doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission(
|
||||
Manifest.permission.CAMERA, PACKAGE_NAME);
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("On");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_cameraDisabled_returnsOn() {
|
||||
enableAutoRotation();
|
||||
enableCameraBasedRotation();
|
||||
when(mController.isCameraLocked()).thenReturn(true);
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("On");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_powerSaveEnabled_returnsOn() {
|
||||
enableAutoRotation();
|
||||
enableCameraBasedRotation();
|
||||
when(mController.isPowerSaveMode()).thenReturn(true);
|
||||
|
||||
assertThat(mController.getSummary()).isEqualTo("On");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAvailabilityStatus() {
|
||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(BasePreferenceController
|
||||
@@ -158,14 +215,14 @@ public class SmartAutoRotatePreferenceControllerTest {
|
||||
|
||||
private void enableAutoRotationPreference() {
|
||||
when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
|
||||
when(mContext.getResources().getBoolean(anyInt())).thenReturn(true);
|
||||
when(mResources.getBoolean(anyInt())).thenReturn(true);
|
||||
Settings.System.putInt(mContentResolver,
|
||||
Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 0);
|
||||
}
|
||||
|
||||
private void disableAutoRotationPreference() {
|
||||
when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true);
|
||||
when(mContext.getResources().getBoolean(anyInt())).thenReturn(true);
|
||||
when(mResources.getBoolean(anyInt())).thenReturn(true);
|
||||
Settings.System.putInt(mContentResolver,
|
||||
Settings.System.HIDE_ROTATION_LOCK_TOGGLE_FOR_ACCESSIBILITY, 1);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ public class BatteryEntryTest {
|
||||
when(consumer.getUid()).thenReturn(APP_UID);
|
||||
when(consumer.getPackageWithHighestDrain()).thenReturn(highDrainPackage);
|
||||
return new BatteryEntry(mMockContext, mockHandler, mockUserManager,
|
||||
consumer, false, packages, packageName);
|
||||
consumer, false, APP_UID, packages, packageName);
|
||||
}
|
||||
|
||||
private BatteryEntry createAggregateBatteryEntry(int powerComponentId) {
|
||||
@@ -108,7 +108,7 @@ public class BatteryEntryTest {
|
||||
UserBatteryConsumer consumer = mock(UserBatteryConsumer.class);
|
||||
when(consumer.getUserId()).thenReturn(userId);
|
||||
return new BatteryEntry(mMockContext, mockHandler, mockUserManager,
|
||||
consumer, false, null, null);
|
||||
consumer, false, 0, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -169,12 +169,12 @@ public class BatteryEntryTest {
|
||||
|
||||
@Test
|
||||
public void getTimeInForegroundMs_app() {
|
||||
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
|
||||
mockUserManager, mUidBatteryConsumer, false, null, null);
|
||||
|
||||
when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_FOREGROUND))
|
||||
.thenReturn(100L);
|
||||
|
||||
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
|
||||
mockUserManager, mUidBatteryConsumer, false, 0, null, null);
|
||||
|
||||
assertThat(entry.getTimeInForegroundMs()).isEqualTo(100L);
|
||||
}
|
||||
|
||||
@@ -188,12 +188,12 @@ public class BatteryEntryTest {
|
||||
|
||||
@Test
|
||||
public void getTimeInBackgroundMs_app() {
|
||||
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
|
||||
mockUserManager, mUidBatteryConsumer, false, null, null);
|
||||
|
||||
when(mUidBatteryConsumer.getTimeInStateMs(UidBatteryConsumer.STATE_BACKGROUND))
|
||||
.thenReturn(100L);
|
||||
|
||||
final BatteryEntry entry = new BatteryEntry(RuntimeEnvironment.application, mockHandler,
|
||||
mockUserManager, mUidBatteryConsumer, false, 0, null, null);
|
||||
|
||||
assertThat(entry.getTimeInBackgroundMs()).isEqualTo(100L);
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.os.UserHandle;
|
||||
import com.android.settings.testutils.FakeFeatureFactory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
@@ -316,6 +317,7 @@ public final class ConvertUtilsTest {
|
||||
.isEqualTo(entry.mConsumePower * ratio);
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testUtcToLocalTime_returnExpectedResult() {
|
||||
ConvertUtils.sZoneId = null;
|
||||
@@ -336,6 +338,7 @@ public final class ConvertUtilsTest {
|
||||
assertThat(ConvertUtils.sLocale).isEqualTo(new Locale("en_US"));
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testUtcToLocalTimeHour_12HourFormat_returnExpectedResult() {
|
||||
ConvertUtils.sZoneIdForHour = null;
|
||||
@@ -357,6 +360,7 @@ public final class ConvertUtilsTest {
|
||||
assertThat(ConvertUtils.sLocaleForHour).isEqualTo(new Locale("en_US"));
|
||||
}
|
||||
|
||||
@Ignore
|
||||
@Test
|
||||
public void testUtcToLocalTimeHour_24HourFormat_returnExpectedResult() {
|
||||
ConvertUtils.sZoneIdForHour = null;
|
||||
|
||||
@@ -67,8 +67,6 @@ public class LocationInjectedServicesPreferenceControllerTest {
|
||||
@Mock
|
||||
private PreferenceCategory mCategoryPrimary;
|
||||
@Mock
|
||||
private PreferenceCategory mCategoryManaged;
|
||||
@Mock
|
||||
private PreferenceScreen mScreen;
|
||||
@Mock
|
||||
private AppSettingsInjector mSettingsInjector;
|
||||
@@ -114,31 +112,6 @@ public class LocationInjectedServicesPreferenceControllerTest {
|
||||
verify(mContext).unregisterReceiver(mController.mInjectedSettingsReceiver);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateState_shouldRemoveAllAndAddInjectedSettings() {
|
||||
final List<Preference> preferences = new ArrayList<>();
|
||||
final Map<Integer, List<Preference>> map = new ArrayMap<>();
|
||||
final Preference pref1 = new Preference(mContext);
|
||||
pref1.setTitle("Title1");
|
||||
final Preference pref2 = new Preference(mContext);
|
||||
pref2.setTitle("Title2");
|
||||
preferences.add(pref1);
|
||||
preferences.add(pref2);
|
||||
map.put(UserHandle.myUserId(), preferences);
|
||||
doReturn(map)
|
||||
.when(mSettingsInjector).getInjectedSettings(any(Context.class), anyInt());
|
||||
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
|
||||
ShadowUserManager.getShadow().setProfileIdsWithDisabled(new int[]{UserHandle.myUserId()});
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
|
||||
mController.updateState(mCategoryPrimary);
|
||||
|
||||
verify(mCategoryPrimary).removeAll();
|
||||
verify(mCategoryPrimary).addPreference(pref1);
|
||||
verify(mCategoryPrimary).addPreference(pref2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void workProfileDisallowShareLocationOn_getParentUserLocationServicesOnly() {
|
||||
final int fakeWorkProfileId = 123;
|
||||
@@ -158,7 +131,6 @@ public class LocationInjectedServicesPreferenceControllerTest {
|
||||
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(mCategoryPrimary);
|
||||
verify(mSettingsInjector).getInjectedSettings(
|
||||
any(Context.class), eq(UserHandle.myUserId()));
|
||||
}
|
||||
@@ -178,7 +150,6 @@ public class LocationInjectedServicesPreferenceControllerTest {
|
||||
enforcingUsers);
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(mCategoryPrimary);
|
||||
verify(mSettingsInjector).getInjectedSettings(
|
||||
any(Context.class), eq(UserHandle.USER_CURRENT));
|
||||
}
|
||||
@@ -216,7 +187,6 @@ public class LocationInjectedServicesPreferenceControllerTest {
|
||||
when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser()).thenReturn(componentName);
|
||||
|
||||
mController.displayPreference(mScreen);
|
||||
mController.updateState(mCategoryPrimary);
|
||||
|
||||
assertThat(pref.isEnabled()).isFalse();
|
||||
assertThat(pref.isDisabledByAdmin()).isTrue();
|
||||
|
||||
@@ -40,6 +40,7 @@ import android.net.ConnectivityManager;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.os.Looper;
|
||||
import android.os.UserManager;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.ServiceState;
|
||||
import android.telephony.SignalStrength;
|
||||
@@ -81,6 +82,8 @@ import java.util.List;
|
||||
public class SubscriptionsPreferenceControllerTest {
|
||||
private static final String KEY = "preference_group";
|
||||
|
||||
@Mock
|
||||
private UserManager mUserManager;
|
||||
@Mock
|
||||
private SubscriptionManager mSubscriptionManager;
|
||||
@Mock
|
||||
@@ -121,10 +124,12 @@ public class SubscriptionsPreferenceControllerTest {
|
||||
when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
|
||||
when(mContext.getSystemService(ConnectivityManager.class)).thenReturn(mConnectivityManager);
|
||||
when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
|
||||
when(mContext.getSystemService(UserManager.class)).thenReturn(mUserManager);
|
||||
when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
|
||||
when(mConnectivityManager.getActiveNetwork()).thenReturn(mActiveNetwork);
|
||||
when(mConnectivityManager.getNetworkCapabilities(mActiveNetwork))
|
||||
.thenReturn(mNetworkCapabilities);
|
||||
when(mUserManager.isAdminUser()).thenReturn(true);
|
||||
when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
|
||||
|
||||
mPreferenceManager = new PreferenceManager(mContext);
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.widget;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/** Unittest for GearPreference */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class GearPreferenceTest {
|
||||
@Mock
|
||||
private GearPreference.OnGearClickListener mOnGearClickListener;
|
||||
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private GearPreference mGearPreference;
|
||||
private PreferenceViewHolder mViewHolder;
|
||||
private View mGearView;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mGearPreference =
|
||||
new GearPreference(mContext, null);
|
||||
int layoutId = ResourcesUtils.getResourcesId(mContext, "layout", "preference_widget_gear");
|
||||
PreferenceViewHolder holder =
|
||||
PreferenceViewHolder.createInstanceForTests(
|
||||
LayoutInflater.from(ApplicationProvider.getApplicationContext())
|
||||
.inflate(layoutId, null));
|
||||
mViewHolder = spy(holder);
|
||||
mGearView = new View(mContext, null);
|
||||
int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button");
|
||||
when(mViewHolder.findViewById(gearId)).thenReturn(mGearView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_gearIsVisible() {
|
||||
mGearPreference.setOnGearClickListener(mOnGearClickListener);
|
||||
|
||||
mGearPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
assertThat(mGearView.getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_gearIsGone() {
|
||||
mGearPreference.setOnGearClickListener(null);
|
||||
|
||||
mGearPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
assertThat(mGearView.getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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.widget;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.TypedValue;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/** Unittest for MutableGearPreference */
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class MutableGearPreferenceTest {
|
||||
@Mock
|
||||
private MutableGearPreference.OnGearClickListener mOnGearClickListener;
|
||||
|
||||
private Context mContext = ApplicationProvider.getApplicationContext();
|
||||
private MutableGearPreference mMutableGearPreference;
|
||||
private PreferenceViewHolder mViewHolder;
|
||||
private ImageView mGearView;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mMutableGearPreference =
|
||||
new MutableGearPreference(mContext, null);
|
||||
int layoutId =
|
||||
ResourcesUtils.getResourcesId(mContext, "layout", "preference_widget_gear");
|
||||
PreferenceViewHolder holder =
|
||||
PreferenceViewHolder.createInstanceForTests(
|
||||
LayoutInflater.from(ApplicationProvider.getApplicationContext())
|
||||
.inflate(layoutId, null));
|
||||
mViewHolder = spy(holder);
|
||||
mGearView = spy(new ImageView(mContext, null));
|
||||
int gearId = ResourcesUtils.getResourcesId(mContext, "id", "settings_button");
|
||||
when(mViewHolder.findViewById(gearId)).thenReturn(mGearView);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onBindViewHolder_gearChangeAlpha() {
|
||||
mMutableGearPreference.setGearEnabled(false);
|
||||
mMutableGearPreference.setOnGearClickListener(mOnGearClickListener);
|
||||
|
||||
mMutableGearPreference.onBindViewHolder(mViewHolder);
|
||||
|
||||
verify(mGearView).setImageAlpha(anyInt());
|
||||
}
|
||||
|
||||
private static int getDisabledAlphaValue(Context context) {
|
||||
TypedValue value = new TypedValue();
|
||||
context.getTheme().resolveAttribute(android.R.attr.disabledAlpha, value, true);
|
||||
return (int) (value.getFloat() * 255);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user