Snap for 9121979 from 95d0ec1b00 to udc-release
Change-Id: I93b0fd4dbd9ba8b8a703c17bef5f4a548d62d430
This commit is contained in:
@@ -481,7 +481,7 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.wifi.savedaccesspoints.SavedAccessPointsWifiSettings" />
|
||||
android:value="com.android.settings.wifi.savedaccesspoints2.SavedAccessPointsWifiSettings2" />
|
||||
<meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
|
||||
android:value="@string/menu_key_network"/>
|
||||
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
|
||||
|
||||
@@ -42,8 +42,7 @@
|
||||
android:layout_marginTop="2dp"
|
||||
android:singleLine="false"
|
||||
android:ellipsize="marquee"
|
||||
android:textDirection="locale"
|
||||
android:text="test_summary"/>
|
||||
android:textDirection="locale"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
|
||||
@@ -56,17 +56,6 @@
|
||||
android:layout_toStartOf="@+id/dragHandle"
|
||||
android:layout_below="@id/label"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/default_locale"
|
||||
style="@style/LanguageCheckboxAndLabel"
|
||||
android:layout_marginTop="-28dp"
|
||||
android:paddingStart="56dp"
|
||||
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:text="@string/desc_current_default_language"
|
||||
android:layout_toStartOf="@+id/dragHandle"
|
||||
android:layout_below="@id/label"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/dragHandle"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
@@ -333,12 +333,6 @@
|
||||
<!-- Title for the locale picker activity. [CHAR LIMIT=30]-->
|
||||
<string name="language_picker_title">Languages</string>
|
||||
|
||||
<!-- Title for category of the locale picker . [CHAR LIMIT=50]-->
|
||||
<string name="language_picker_category_title">Preferred language order</string>
|
||||
|
||||
<!-- Description for indication of current system default language. [CHAR LIMIT=50]-->
|
||||
<string name="desc_current_default_language">System language</string>
|
||||
|
||||
<!-- Menu item in the locale menu. Will remove the selected locales. [CHAR LIMIT=30] -->
|
||||
<string name="locale_remove_menu">Remove</string>
|
||||
|
||||
@@ -352,13 +346,13 @@
|
||||
<string name="locale_picker_category_title">Preferred Language</string>
|
||||
|
||||
<!-- Title for the Apps' locale menu entry [CHAR LIMIT=50]-->
|
||||
<string name="app_locales_picker_menu_title">App languages</string>
|
||||
<string name="app_locales_picker_menu_title">App Languages</string>
|
||||
|
||||
<!-- Summary for the app's locale picker activity. [CHAR LIMIT=50]-->
|
||||
<string name="app_locale_picker_summary">Set the language for each app</string>
|
||||
|
||||
<!-- Title for the App's locale picker activity. [CHAR LIMIT=50]-->
|
||||
<string name="app_locale_picker_title">App language</string>
|
||||
<string name="app_locale_picker_title">App Language</string>
|
||||
|
||||
<!-- Category for the suggested app's locales. [CHAR LIMIT=50]-->
|
||||
<string name="suggested_app_locales_title">Suggested languages</string>
|
||||
@@ -381,18 +375,6 @@
|
||||
<!-- Description for introduction of the locale selection supported of app list [CHAR LIMIT=NONE]-->
|
||||
<string name="desc_app_locale_selection_supported">Only apps that support language selection are shown here.</string>
|
||||
|
||||
<!-- Description for the introduction to language picker activity. [CHAR LIMIT=NONE]-->
|
||||
<string name="desc_introduction_of_language_picker">Your system, apps, and websites use the first supported language from your preferred languages.</string>
|
||||
|
||||
<!-- Description for the notice of language picker. [CHAR LIMIT=NONE]-->
|
||||
<string name="desc_notice_of_language_picker">To select a language for each app, go to app language settings.</string>
|
||||
|
||||
<!-- Title for locale helper page [CHAR LIMIT=NONE] -->
|
||||
<string name="desc_locale_helper_footer_general">Learn more about languages</string>
|
||||
|
||||
<!-- Link for Locale helper page. [CHAR LIMIT=NONE]-->
|
||||
<string name="link_locale_picker_footer_learn_more" translatable="false">https://support.google.com/android?p=per_language_app_settings</string>
|
||||
|
||||
<!-- The title of the confirmation dialog shown when the user selects one / several languages and tries to remove them [CHAR LIMIT=60] -->
|
||||
<plurals name="dlg_remove_locales_title">
|
||||
<item quantity="one">Remove selected language?</item>
|
||||
@@ -408,7 +390,7 @@
|
||||
<string name="dlg_remove_locales_error_message">Keep at least one preferred language</string>
|
||||
|
||||
<!-- This text shows in the language picker when the system is not translated into that languages [CHAR LIMIT=80] -->
|
||||
<string name="locale_not_translated">Not available as system language</string>
|
||||
<string name="locale_not_translated">May not be available in some apps</string>
|
||||
|
||||
<!-- Label for an accessibility action that moves a language up in the ordered language list [CHAR LIMIT=20] -->
|
||||
<string name="action_drag_label_move_up">Move up</string>
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 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.
|
||||
-->
|
||||
|
||||
<PreferenceScreen
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:title="@string/language_settings">
|
||||
|
||||
<com.android.settingslib.widget.TopIntroPreference
|
||||
android:title="@string/desc_introduction_of_language_picker"
|
||||
android:persistent="false"
|
||||
android:selectable="false"/>
|
||||
|
||||
<PreferenceCategory
|
||||
android:title="@string/language_picker_category_title">
|
||||
<com.android.settingslib.widget.LayoutPreference
|
||||
android:key="languages_picker"
|
||||
android:layout="@layout/locale_order_list" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<com.android.settingslib.widget.FooterPreference
|
||||
android:key="footer_languages_picker"
|
||||
android:title="@string/desc_notice_of_language_picker"
|
||||
android:persistent="false"
|
||||
android:selectable="false"
|
||||
settings:controller="com.android.settings.localepicker.LocaleHelperPreferenceController"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -182,9 +182,9 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
||||
final TextView title = mLayoutPreference.findViewById(R.id.entity_header_title);
|
||||
title.setText(mCachedDevice.getName());
|
||||
final TextView summary = mLayoutPreference.findViewById(R.id.entity_header_summary);
|
||||
summary.setText(mCachedDevice.getConnectionSummary(true /* shortSummary */));
|
||||
|
||||
if (!mCachedDevice.isConnected() || mCachedDevice.isBusy()) {
|
||||
summary.setText(mCachedDevice.getConnectionSummary(true /* shortSummary */));
|
||||
updateDisconnectLayout();
|
||||
return;
|
||||
}
|
||||
@@ -196,6 +196,9 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
||||
mLayoutPreference.findViewById(R.id.layout_left).setVisibility(View.GONE);
|
||||
mLayoutPreference.findViewById(R.id.layout_right).setVisibility(View.GONE);
|
||||
|
||||
summary.setText(mCachedDevice.getConnectionSummary(
|
||||
BluetoothUtils.getIntMetaData(device, BluetoothDevice.METADATA_MAIN_BATTERY)
|
||||
!= BluetoothUtils.META_INT_ERROR));
|
||||
updateSubLayout(mLayoutPreference.findViewById(R.id.layout_middle),
|
||||
BluetoothDevice.METADATA_MAIN_ICON,
|
||||
BluetoothDevice.METADATA_MAIN_BATTERY,
|
||||
@@ -207,6 +210,7 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont
|
||||
BluetoothDevice.DEVICE_TYPE_UNTETHERED_HEADSET)
|
||||
|| BluetoothUtils.getBooleanMetaData(device,
|
||||
BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)) {
|
||||
summary.setText(mCachedDevice.getConnectionSummary(true /* shortSummary */));
|
||||
updateSubLayout(mLayoutPreference.findViewById(R.id.layout_left),
|
||||
BluetoothDevice.METADATA_UNTETHERED_LEFT_ICON,
|
||||
BluetoothDevice.METADATA_UNTETHERED_LEFT_BATTERY,
|
||||
|
||||
@@ -43,6 +43,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
|
||||
class LocaleDragAndDropAdapter
|
||||
extends RecyclerView.Adapter<LocaleDragAndDropAdapter.CustomViewHolder> {
|
||||
|
||||
@@ -153,10 +154,8 @@ class LocaleDragAndDropAdapter
|
||||
final LocaleDragCell dragCell = holder.getLocaleDragCell();
|
||||
final String label = feedItem.getFullNameNative();
|
||||
final String description = feedItem.getFullNameInUiLanguage();
|
||||
|
||||
dragCell.setLabelAndDescription(label, description);
|
||||
dragCell.setLocalized(feedItem.isTranslated());
|
||||
dragCell.setCurrentDefault(feedItem.getLocale().equals(Locale.getDefault()));
|
||||
dragCell.setMiniLabel(mNumberFormatter.format(i + 1));
|
||||
dragCell.setShowCheckbox(mRemoveMode);
|
||||
dragCell.setShowMiniLabel(!mRemoveMode);
|
||||
|
||||
@@ -33,7 +33,6 @@ class LocaleDragCell extends RelativeLayout {
|
||||
private CheckBox mCheckbox;
|
||||
private TextView mMiniLabel;
|
||||
private TextView mLocalized;
|
||||
private TextView mCurrentDefault;
|
||||
private ImageView mDragHandle;
|
||||
|
||||
public LocaleDragCell(Context context, AttributeSet attrs) {
|
||||
@@ -45,7 +44,6 @@ class LocaleDragCell extends RelativeLayout {
|
||||
super.onFinishInflate();
|
||||
mLabel = (TextView) findViewById(R.id.label);
|
||||
mLocalized = (TextView) findViewById(R.id.l10nWarn);
|
||||
mCurrentDefault = (TextView) findViewById(R.id.default_locale);
|
||||
mMiniLabel = (TextView) findViewById(R.id.miniLabel);
|
||||
mCheckbox = (CheckBox) findViewById(R.id.checkbox);
|
||||
mDragHandle = (ImageView) findViewById(R.id.dragHandle);
|
||||
@@ -102,14 +100,6 @@ class LocaleDragCell extends RelativeLayout {
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate current locale is system default.
|
||||
*/
|
||||
public void setCurrentDefault(boolean isCurrentDefault) {
|
||||
mCurrentDefault.setVisibility(isCurrentDefault ? VISIBLE : GONE);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public ImageView getDragHandle() {
|
||||
return mDragHandle;
|
||||
}
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.localepicker;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.HelpUtils;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
/**
|
||||
* A controller to update current locale information of application.
|
||||
*/
|
||||
public class LocaleHelperPreferenceController extends AbstractPreferenceController {
|
||||
private static final String TAG = LocaleHelperPreferenceController.class.getSimpleName();
|
||||
|
||||
private static final String KEY_FOOTER_LANGUAGE_PICKER = "footer_languages_picker";
|
||||
|
||||
public LocaleHelperPreferenceController(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferenceKey() {
|
||||
return KEY_FOOTER_LANGUAGE_PICKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
FooterPreference footerPreference = screen.findPreference(getPreferenceKey());
|
||||
updateFooterPreference(footerPreference);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void updateFooterPreference(FooterPreference footerPreference) {
|
||||
if (footerPreference != null) {
|
||||
footerPreference.setLearnMoreAction(v -> openLocaleLearnMoreLink());
|
||||
footerPreference.setLearnMoreText(mContext.getString(
|
||||
R.string.desc_locale_helper_footer_general));
|
||||
}
|
||||
}
|
||||
|
||||
private void openLocaleLearnMoreLink() {
|
||||
mContext.startActivity(
|
||||
HelpUtils.getHelpIntent(
|
||||
mContext,
|
||||
mContext.getString(R.string.link_locale_picker_footer_learn_more),
|
||||
/*backupContext=*/""));
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,6 @@ import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.internal.app.LocalePicker;
|
||||
@@ -47,7 +46,6 @@ import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
import com.android.settingslib.search.SearchIndexableRaw;
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -66,7 +64,6 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
|
||||
private static final int REQUEST_LOCALE_PICKER = 0;
|
||||
|
||||
private static final String INDEX_KEY_ADD_LANGUAGE = "add_language";
|
||||
private static final String KEY_LANGUAGES_PICKER = "languages_picker";
|
||||
|
||||
private LocaleDragAndDropAdapter mAdapter;
|
||||
private Menu mMenu;
|
||||
@@ -75,9 +72,6 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
|
||||
private boolean mShowingRemoveDialog;
|
||||
private boolean mIsUiRestricted;
|
||||
|
||||
private LayoutPreference mLocalePickerPreference;
|
||||
private LocaleHelperPreferenceController mLocaleHelperPreferenceController;
|
||||
|
||||
public LocaleListEditor() {
|
||||
super(DISALLOW_CONFIG_LOCALE);
|
||||
}
|
||||
@@ -92,14 +86,6 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
|
||||
super.onCreate(savedInstanceState);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
addPreferencesFromResource(R.xml.languages);
|
||||
final Activity activity = getActivity();
|
||||
activity.setTitle(R.string.language_picker_title);
|
||||
mLocaleHelperPreferenceController = new LocaleHelperPreferenceController(activity);
|
||||
final PreferenceScreen screen = getPreferenceScreen();
|
||||
mLocalePickerPreference = screen.findPreference(KEY_LANGUAGES_PICKER);
|
||||
mLocaleHelperPreferenceController.displayPreference(screen);
|
||||
|
||||
LocaleStore.fillCache(this.getContext());
|
||||
final List<LocaleStore.LocaleInfo> feedsList = getUserLocaleList();
|
||||
mAdapter = new LocaleDragAndDropAdapter(this.getContext(), feedsList);
|
||||
@@ -107,8 +93,11 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstState) {
|
||||
configureDragAndDrop(mLocalePickerPreference);
|
||||
return super.onCreateView(inflater, container, savedInstState);
|
||||
final View result = super.onCreateView(inflater, container, savedInstState);
|
||||
final View myLayout = inflater.inflate(R.layout.locale_order_list, (ViewGroup) result);
|
||||
|
||||
configureDragAndDrop(myLayout);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -298,8 +287,8 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void configureDragAndDrop(LayoutPreference layout) {
|
||||
final RecyclerView list = layout.findViewById(R.id.dragList);
|
||||
private void configureDragAndDrop(View view) {
|
||||
final RecyclerView list = view.findViewById(R.id.dragList);
|
||||
final LocaleLinearLayoutManager llm = new LocaleLinearLayoutManager(getContext(), mAdapter);
|
||||
llm.setAutoMeasureEnabled(true);
|
||||
list.setLayoutManager(llm);
|
||||
@@ -308,7 +297,7 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
|
||||
mAdapter.setRecyclerView(list);
|
||||
list.setAdapter(mAdapter);
|
||||
|
||||
mAddLanguage = layout.findViewById(R.id.add_language);
|
||||
mAddLanguage = view.findViewById(R.id.add_language);
|
||||
mAddLanguage.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
||||
@@ -17,19 +17,18 @@
|
||||
package com.android.settings.spa.app.appsettings
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.pm.ResolveInfo
|
||||
import android.os.UserManager
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal
|
||||
import com.android.settingslib.Utils
|
||||
import com.android.settingslib.spaprivileged.model.app.userId
|
||||
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
|
||||
import com.android.settingslib.spaprivileged.model.app.isDisallowControl
|
||||
|
||||
class AppButtonRepository(private val context: Context) {
|
||||
private val packageManager = context.packageManager
|
||||
private val devicePolicyManager = context.getSystemService(DevicePolicyManager::class.java)!!
|
||||
private val devicePolicyManager = context.devicePolicyManager
|
||||
|
||||
/**
|
||||
* Checks whether the given application is disallowed from modifying.
|
||||
@@ -41,20 +40,10 @@ class AppButtonRepository(private val context: Context) {
|
||||
// If the uninstallation intent is already queued, disable the button.
|
||||
devicePolicyManager.isUninstallInQueue(app.packageName) -> true
|
||||
|
||||
RestrictedLockUtilsInternal.hasBaseUserRestriction(
|
||||
context, UserManager.DISALLOW_APPS_CONTROL, app.userId
|
||||
) -> true
|
||||
|
||||
else -> false
|
||||
else -> app.isDisallowControl(context)
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given application is an active admin.
|
||||
*/
|
||||
fun isActiveAdmin(app: ApplicationInfo): Boolean =
|
||||
devicePolicyManager.packageHasActiveAdmins(app.packageName, app.userId)
|
||||
|
||||
fun getHomePackageInfo(): AppUninstallButton.HomePackages {
|
||||
fun getHomePackageInfo(): HomePackages {
|
||||
val homePackages = mutableSetOf<String>()
|
||||
val homeActivities = ArrayList<ResolveInfo>()
|
||||
val currentDefaultHome = packageManager.getHomeActivities(homeActivities)
|
||||
@@ -66,7 +55,7 @@ class AppButtonRepository(private val context: Context) {
|
||||
homePackages.add(metaPackageName)
|
||||
}
|
||||
}
|
||||
return AppUninstallButton.HomePackages(homePackages, currentDefaultHome)
|
||||
return HomePackages(homePackages, currentDefaultHome)
|
||||
}
|
||||
|
||||
private fun signaturesMatch(packageName1: String, packageName2: String): Boolean = try {
|
||||
@@ -75,4 +64,9 @@ class AppButtonRepository(private val context: Context) {
|
||||
// e.g. named alternate package not found during lookup; this is an expected case sometimes
|
||||
false
|
||||
}
|
||||
|
||||
data class HomePackages(
|
||||
val homePackages: Set<String>,
|
||||
val currentDefaultHome: ComponentName?,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -32,9 +32,11 @@ fun AppButtons(packageInfoPresenter: PackageInfoPresenter) {
|
||||
}
|
||||
|
||||
private class AppButtonsHolder(private val packageInfoPresenter: PackageInfoPresenter) {
|
||||
private val appLaunchButton = AppLaunchButton(context = packageInfoPresenter.context)
|
||||
private val appLaunchButton = AppLaunchButton(packageInfoPresenter)
|
||||
private val appInstallButton = AppInstallButton(packageInfoPresenter)
|
||||
private val appDisableButton = AppDisableButton(packageInfoPresenter)
|
||||
private val appUninstallButton = AppUninstallButton(packageInfoPresenter)
|
||||
private val appClearButton = AppClearButton(packageInfoPresenter)
|
||||
private val appForceStopButton = AppForceStopButton(packageInfoPresenter)
|
||||
|
||||
@Composable
|
||||
@@ -46,14 +48,17 @@ private class AppButtonsHolder(private val packageInfoPresenter: PackageInfoPres
|
||||
|
||||
private fun getActionButtons(packageInfo: PackageInfo): List<ActionButton> = listOfNotNull(
|
||||
appLaunchButton.getActionButton(packageInfo),
|
||||
appInstallButton.getActionButton(packageInfo),
|
||||
appDisableButton.getActionButton(packageInfo),
|
||||
appUninstallButton.getActionButton(packageInfo),
|
||||
appClearButton.getActionButton(packageInfo),
|
||||
appForceStopButton.getActionButton(packageInfo),
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun Dialogs() {
|
||||
appDisableButton.DisableConfirmDialog()
|
||||
appClearButton.ClearConfirmDialog()
|
||||
appForceStopButton.ForceStopConfirmDialog()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.spa.app.appsettings
|
||||
|
||||
import android.content.pm.PackageInfo
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import androidx.compose.material3.AlertDialog
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
import com.android.settingslib.spa.widget.button.ActionButton
|
||||
|
||||
class AppClearButton(
|
||||
private val packageInfoPresenter: PackageInfoPresenter,
|
||||
) {
|
||||
private val context = packageInfoPresenter.context
|
||||
|
||||
private var openConfirmDialog by mutableStateOf(false)
|
||||
|
||||
fun getActionButton(packageInfo: PackageInfo): ActionButton? {
|
||||
val app = packageInfo.applicationInfo
|
||||
if (!app.isInstantApp) return null
|
||||
|
||||
return clearButton()
|
||||
}
|
||||
|
||||
private fun clearButton() = ActionButton(
|
||||
text = context.getString(R.string.clear_instant_app_data),
|
||||
imageVector = Icons.Outlined.Delete,
|
||||
) { openConfirmDialog = true }
|
||||
|
||||
@Composable
|
||||
fun ClearConfirmDialog() {
|
||||
if (!openConfirmDialog) return
|
||||
AlertDialog(
|
||||
onDismissRequest = { openConfirmDialog = false },
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
openConfirmDialog = false
|
||||
packageInfoPresenter.clearInstantApp()
|
||||
},
|
||||
) {
|
||||
Text(stringResource(R.string.clear_instant_app_data))
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { openConfirmDialog = false }) {
|
||||
Text(stringResource(R.string.cancel))
|
||||
}
|
||||
},
|
||||
title = {
|
||||
Text(stringResource(R.string.clear_instant_app_data))
|
||||
},
|
||||
text = {
|
||||
Text(stringResource(R.string.clear_instant_app_confirmation))
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package com.android.settings.spa.app.appsettings
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.os.UserManager
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.ArrowCircleDown
|
||||
import androidx.compose.material.icons.outlined.HideSource
|
||||
@@ -34,10 +31,12 @@ import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Utils
|
||||
import com.android.settings.overlay.FeatureFactory
|
||||
import com.android.settingslib.Utils as SettingsLibUtils
|
||||
import com.android.settingslib.spa.widget.button.ActionButton
|
||||
import com.android.settingslib.spaprivileged.model.app.hasFlag
|
||||
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
|
||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||
import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
|
||||
import com.android.settingslib.spaprivileged.model.app.isDisabledUntilUsed
|
||||
import com.android.settingslib.Utils as SettingsLibUtils
|
||||
|
||||
class AppDisableButton(
|
||||
private val packageInfoPresenter: PackageInfoPresenter,
|
||||
@@ -46,8 +45,8 @@ class AppDisableButton(
|
||||
private val appButtonRepository = AppButtonRepository(context)
|
||||
private val resources = context.resources
|
||||
private val packageManager = context.packageManager
|
||||
private val userManager = context.getSystemService(UserManager::class.java)!!
|
||||
private val devicePolicyManager = context.getSystemService(DevicePolicyManager::class.java)!!
|
||||
private val userManager = context.userManager
|
||||
private val devicePolicyManager = context.devicePolicyManager
|
||||
private val applicationFeatureProvider =
|
||||
FeatureFactory.getFactory(context).getApplicationFeatureProvider(context)
|
||||
|
||||
@@ -55,7 +54,7 @@ class AppDisableButton(
|
||||
|
||||
fun getActionButton(packageInfo: PackageInfo): ActionButton? {
|
||||
val app = packageInfo.applicationInfo
|
||||
if (!app.hasFlag(ApplicationInfo.FLAG_SYSTEM)) return null
|
||||
if (!app.isSystemApp) return null
|
||||
|
||||
return when {
|
||||
app.enabled && !app.isDisabledUntilUsed -> {
|
||||
@@ -84,7 +83,7 @@ class AppDisableButton(
|
||||
SettingsLibUtils.isSystemPackage(resources, packageManager, packageInfo) -> false
|
||||
|
||||
// If this is a device admin, it can't be disabled.
|
||||
appButtonRepository.isActiveAdmin(app) -> false
|
||||
app.isActiveAdmin(context) -> false
|
||||
|
||||
// We don't allow disabling DO/PO on *any* users if it's a system app, because
|
||||
// "disabling" is actually "downgrade to the system version + disable", and "downgrade"
|
||||
|
||||
@@ -36,6 +36,7 @@ import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal
|
||||
import com.android.settingslib.spa.widget.button.ActionButton
|
||||
import com.android.settingslib.spaprivileged.model.app.hasFlag
|
||||
import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
|
||||
import com.android.settingslib.spaprivileged.model.app.userId
|
||||
|
||||
class AppForceStopButton(
|
||||
@@ -61,7 +62,7 @@ class AppForceStopButton(
|
||||
*/
|
||||
private fun isForceStopButtonEnable(app: ApplicationInfo): Boolean = when {
|
||||
// User can't force stop device admin.
|
||||
appButtonRepository.isActiveAdmin(app) -> false
|
||||
app.isActiveAdmin(context) -> false
|
||||
|
||||
appButtonRepository.isDisallowControl(app) -> false
|
||||
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.spa.app.appsettings
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.FileDownload
|
||||
import com.android.settings.R
|
||||
import com.android.settings.applications.AppStoreUtil
|
||||
import com.android.settingslib.spa.widget.button.ActionButton
|
||||
import com.android.settingslib.spaprivileged.model.app.userHandle
|
||||
|
||||
class AppInstallButton(private val packageInfoPresenter: PackageInfoPresenter) {
|
||||
private val context = packageInfoPresenter.context
|
||||
|
||||
fun getActionButton(packageInfo: PackageInfo): ActionButton? {
|
||||
val app = packageInfo.applicationInfo
|
||||
if (!app.isInstantApp) return null
|
||||
|
||||
return AppStoreUtil.getAppStoreLink(packageInfoPresenter.contextAsUser, app.packageName)
|
||||
?.let { intent -> installButton(intent, app) }
|
||||
}
|
||||
|
||||
private fun installButton(intent: Intent, app: ApplicationInfo) = ActionButton(
|
||||
text = context.getString(R.string.install_text),
|
||||
imageVector = Icons.Outlined.FileDownload,
|
||||
) {
|
||||
context.startActivityAsUser(intent, app.userHandle)
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings.spa.app.appsettings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
@@ -26,11 +25,12 @@ import com.android.settings.R
|
||||
import com.android.settingslib.spa.widget.button.ActionButton
|
||||
import com.android.settingslib.spaprivileged.model.app.userHandle
|
||||
|
||||
class AppLaunchButton(private val context: Context) {
|
||||
private val packageManager = context.packageManager
|
||||
class AppLaunchButton(packageInfoPresenter: PackageInfoPresenter) {
|
||||
private val context = packageInfoPresenter.context
|
||||
private val packageManagerAsUser = packageInfoPresenter.packageManagerAsUser
|
||||
|
||||
fun getActionButton(packageInfo: PackageInfo): ActionButton? =
|
||||
packageManager.getLaunchIntentForPackage(packageInfo.packageName)?.let { intent ->
|
||||
packageManagerAsUser.getLaunchIntentForPackage(packageInfo.packageName)?.let { intent ->
|
||||
launchButton(intent, packageInfo.applicationInfo)
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ object AppSettingsProvider : SettingsPageProvider {
|
||||
PackageInfoPresenter(context, packageName, userId, coroutineScope)
|
||||
}
|
||||
AppSettings(packageInfoPresenter)
|
||||
packageInfoPresenter.PageCloser()
|
||||
packageInfoPresenter.PackageRemoveDetector()
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -77,7 +77,13 @@ object AppSettingsProvider : SettingsPageProvider {
|
||||
@Composable
|
||||
private fun AppSettings(packageInfoPresenter: PackageInfoPresenter) {
|
||||
val packageInfo = packageInfoPresenter.flow.collectAsState().value ?: return
|
||||
RegularScaffold(title = stringResource(R.string.application_info_label)) {
|
||||
val app = packageInfo.applicationInfo
|
||||
RegularScaffold(
|
||||
title = stringResource(R.string.application_info_label),
|
||||
actions = {
|
||||
AppSettingsMoreOptions(packageInfoPresenter, app)
|
||||
}
|
||||
) {
|
||||
val appInfoProvider = remember { AppInfoProvider(packageInfo) }
|
||||
|
||||
appInfoProvider.AppInfo()
|
||||
@@ -85,7 +91,6 @@ private fun AppSettings(packageInfoPresenter: PackageInfoPresenter) {
|
||||
AppButtons(packageInfoPresenter)
|
||||
|
||||
Category(title = stringResource(R.string.advanced_apps)) {
|
||||
val app = packageInfo.applicationInfo
|
||||
DisplayOverOtherAppsAppListProvider.InfoPageEntryItem(app)
|
||||
ModifySystemSettingsAppListProvider.InfoPageEntryItem(app)
|
||||
PictureInPictureListProvider.InfoPageEntryItem(app)
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.spa.app.appsettings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
import com.android.settings.Utils
|
||||
import com.android.settingslib.spa.widget.scaffold.MoreOptionsAction
|
||||
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
|
||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||
import com.android.settingslib.spaprivileged.model.app.PackageManagers
|
||||
import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
|
||||
import com.android.settingslib.spaprivileged.model.app.isDisallowControl
|
||||
import com.android.settingslib.spaprivileged.model.app.userId
|
||||
|
||||
@Composable
|
||||
fun AppSettingsMoreOptions(packageInfoPresenter: PackageInfoPresenter, app: ApplicationInfo) {
|
||||
val context = LocalContext.current
|
||||
// We don't allow uninstalling update for DO/PO if it's a system app, because it will clear data
|
||||
// on all users. We also don't allow uninstalling for all users if it's DO/PO for any user.
|
||||
val isProfileOrDeviceOwner = remember(app) {
|
||||
Utils.isProfileOrDeviceOwner(
|
||||
context.userManager, context.devicePolicyManager, app.packageName
|
||||
)
|
||||
}
|
||||
if (isProfileOrDeviceOwner) return
|
||||
val shownUninstallUpdates = remember(app) { isShowUninstallUpdates(context, app) }
|
||||
val shownUninstallForAllUsers = remember(app) { isShowUninstallForAllUsers(context, app) }
|
||||
if (!shownUninstallUpdates && !shownUninstallForAllUsers) return
|
||||
MoreOptionsAction { onDismissRequest ->
|
||||
if (shownUninstallUpdates) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.app_factory_reset)) },
|
||||
onClick = {
|
||||
onDismissRequest()
|
||||
packageInfoPresenter.startUninstallActivity(forAllUsers = false)
|
||||
},
|
||||
)
|
||||
}
|
||||
if (shownUninstallForAllUsers) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.uninstall_all_users_text)) },
|
||||
onClick = {
|
||||
onDismissRequest()
|
||||
packageInfoPresenter.startUninstallActivity(forAllUsers = true)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isShowUninstallUpdates(context: Context, app: ApplicationInfo): Boolean =
|
||||
app.isUpdatedSystemApp && context.userManager.isUserAdmin(app.userId) &&
|
||||
!app.isDisallowControl(context) &&
|
||||
!context.resources.getBoolean(R.bool.config_disable_uninstall_update)
|
||||
|
||||
private fun isShowUninstallForAllUsers(context: Context, app: ApplicationInfo): Boolean =
|
||||
app.userId == 0 && !app.isSystemApp && !app.isInstantApp && !app.isActiveAdmin(context) &&
|
||||
isOtherUserHasInstallPackage(context, app)
|
||||
|
||||
private fun isOtherUserHasInstallPackage(context: Context, app: ApplicationInfo): Boolean =
|
||||
context.userManager.aliveUsers
|
||||
.filter { it.id != app.userId }
|
||||
.any { PackageManagers.isPackageInstalledAsUser(app.packageName, it.id) }
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings.spa.app.appsettings
|
||||
|
||||
import android.app.admin.DevicePolicyManager
|
||||
import android.app.settings.SettingsEnums
|
||||
import android.content.ComponentName
|
||||
import android.content.Intent
|
||||
@@ -24,7 +23,6 @@ import android.content.om.OverlayManager
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageInfo
|
||||
import android.net.Uri
|
||||
import android.os.UserManager
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.outlined.Delete
|
||||
import com.android.settings.R
|
||||
@@ -33,27 +31,27 @@ import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminAd
|
||||
import com.android.settingslib.RestrictedLockUtils
|
||||
import com.android.settingslib.RestrictedLockUtilsInternal
|
||||
import com.android.settingslib.spa.widget.button.ActionButton
|
||||
import com.android.settingslib.spaprivileged.framework.common.devicePolicyManager
|
||||
import com.android.settingslib.spaprivileged.model.app.hasFlag
|
||||
import com.android.settingslib.spaprivileged.model.app.isActiveAdmin
|
||||
import com.android.settingslib.spaprivileged.model.app.userHandle
|
||||
import com.android.settingslib.spaprivileged.model.app.userId
|
||||
|
||||
class AppUninstallButton(private val packageInfoPresenter: PackageInfoPresenter) {
|
||||
private val context = packageInfoPresenter.context
|
||||
private val appButtonRepository = AppButtonRepository(context)
|
||||
private val userManager = context.getSystemService(UserManager::class.java)!!
|
||||
private val overlayManager = context.getSystemService(OverlayManager::class.java)!!
|
||||
private val devicePolicyManager = context.getSystemService(DevicePolicyManager::class.java)!!
|
||||
private val devicePolicyManager = context.devicePolicyManager
|
||||
|
||||
fun getActionButton(packageInfo: PackageInfo): ActionButton? {
|
||||
val app = packageInfo.applicationInfo
|
||||
if (app.hasFlag(ApplicationInfo.FLAG_SYSTEM)) return null
|
||||
if (app.isSystemApp || app.isInstantApp) return null
|
||||
return uninstallButton(app = app, enabled = isUninstallButtonEnabled(app))
|
||||
}
|
||||
|
||||
/** Gets whether a package can be uninstalled. */
|
||||
private fun isUninstallButtonEnabled(app: ApplicationInfo): Boolean = when {
|
||||
// When we have multiple users, there is a separate menu to uninstall for all users.
|
||||
!app.hasFlag(ApplicationInfo.FLAG_INSTALLED) && userManager.users.size >= 2 -> false
|
||||
!app.hasFlag(ApplicationInfo.FLAG_INSTALLED) -> false
|
||||
|
||||
// Not allow to uninstall DO/PO.
|
||||
Utils.isProfileOrDeviceOwner(devicePolicyManager, app.packageName, app.userId) -> false
|
||||
@@ -101,7 +99,7 @@ class AppUninstallButton(private val packageInfoPresenter: PackageInfoPresenter)
|
||||
) { onUninstallClicked(app) }
|
||||
|
||||
private fun onUninstallClicked(app: ApplicationInfo) {
|
||||
if (appButtonRepository.isActiveAdmin(app)) {
|
||||
if (app.isActiveAdmin(context)) {
|
||||
packageInfoPresenter.logAction(SettingsEnums.ACTION_SETTINGS_UNINSTALL_DEVICE_ADMIN)
|
||||
val intent = Intent(context, DeviceAdminAdd::class.java).apply {
|
||||
putExtra(DeviceAdminAdd.EXTRA_DEVICE_ADMIN_PACKAGE_NAME, app.packageName)
|
||||
@@ -115,20 +113,6 @@ class AppUninstallButton(private val packageInfoPresenter: PackageInfoPresenter)
|
||||
RestrictedLockUtils.sendShowAdminSupportDetailsIntent(context, admin)
|
||||
return
|
||||
}
|
||||
startUninstallActivity(app)
|
||||
}
|
||||
|
||||
data class HomePackages(
|
||||
val homePackages: Set<String>,
|
||||
val currentDefaultHome: ComponentName?,
|
||||
)
|
||||
|
||||
private fun startUninstallActivity(app: ApplicationInfo) {
|
||||
val packageUri = Uri.parse("package:${app.packageName}")
|
||||
packageInfoPresenter.logAction(SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP)
|
||||
val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply {
|
||||
putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, !app.hasFlag(ApplicationInfo.FLAG_INSTALLED))
|
||||
}
|
||||
context.startActivityAsUser(intent, app.userHandle)
|
||||
packageInfoPresenter.startUninstallActivity()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.UserHandle
|
||||
import android.util.Log
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -48,9 +49,8 @@ class PackageInfoPresenter(
|
||||
private val coroutineScope: CoroutineScope,
|
||||
) {
|
||||
private val metricsFeatureProvider = FeatureFactory.getFactory(context).metricsFeatureProvider
|
||||
private val packageManager by lazy {
|
||||
context.createContextAsUser(UserHandle.of(userId), 0).packageManager
|
||||
}
|
||||
val contextAsUser by lazy { context.createContextAsUser(UserHandle.of(userId), 0) }
|
||||
val packageManagerAsUser: PackageManager by lazy { contextAsUser.packageManager }
|
||||
private val _flow: MutableStateFlow<PackageInfo?> = MutableStateFlow(null)
|
||||
|
||||
val flow: StateFlow<PackageInfo?> = _flow
|
||||
@@ -66,17 +66,23 @@ class PackageInfoPresenter(
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the page when the package is uninstalled.
|
||||
* Detects the package removed event.
|
||||
*/
|
||||
@Composable
|
||||
fun PageCloser() {
|
||||
fun PackageRemoveDetector() {
|
||||
val intentFilter = IntentFilter(Intent.ACTION_PACKAGE_REMOVED).apply {
|
||||
addDataScheme("package")
|
||||
}
|
||||
val navController = LocalNavController.current
|
||||
DisposableBroadcastReceiverAsUser(userId, intentFilter) { intent ->
|
||||
if (packageName == intent.data?.schemeSpecificPart) {
|
||||
navController.navigateBack()
|
||||
val packageInfo = flow.value
|
||||
if (packageInfo != null && packageInfo.applicationInfo.isSystemApp) {
|
||||
// System app still exists after uninstalling the updates, refresh the page.
|
||||
notifyChange()
|
||||
} else {
|
||||
navController.navigateBack()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,7 +91,7 @@ class PackageInfoPresenter(
|
||||
fun enable() {
|
||||
logAction(SettingsEnums.ACTION_SETTINGS_ENABLE_APP)
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
packageManager.setApplicationEnabledSetting(
|
||||
packageManagerAsUser.setApplicationEnabledSetting(
|
||||
packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, 0
|
||||
)
|
||||
notifyChange()
|
||||
@@ -96,13 +102,32 @@ class PackageInfoPresenter(
|
||||
fun disable() {
|
||||
logAction(SettingsEnums.ACTION_SETTINGS_DISABLE_APP)
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
packageManager.setApplicationEnabledSetting(
|
||||
packageManagerAsUser.setApplicationEnabledSetting(
|
||||
packageName, PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER, 0
|
||||
)
|
||||
notifyChange()
|
||||
}
|
||||
}
|
||||
|
||||
/** Starts the uninstallation activity. */
|
||||
fun startUninstallActivity(forAllUsers: Boolean = false) {
|
||||
logAction(SettingsEnums.ACTION_SETTINGS_UNINSTALL_APP)
|
||||
val packageUri = Uri.parse("package:${packageName}")
|
||||
val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri).apply {
|
||||
putExtra(Intent.EXTRA_UNINSTALL_ALL_USERS, forAllUsers)
|
||||
}
|
||||
context.startActivityAsUser(intent, UserHandle.of(userId))
|
||||
}
|
||||
|
||||
/** Clears this instant app. */
|
||||
fun clearInstantApp() {
|
||||
logAction(SettingsEnums.ACTION_SETTINGS_CLEAR_INSTANT_APP)
|
||||
coroutineScope.launch(Dispatchers.IO) {
|
||||
packageManagerAsUser.deletePackageAsUser(packageName, null, 0, userId)
|
||||
notifyChange()
|
||||
}
|
||||
}
|
||||
|
||||
/** Force stops this package. */
|
||||
fun forceStop() {
|
||||
logAction(SettingsEnums.ACTION_APP_FORCE_STOP)
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.localepicker;
|
||||
|
||||
import static org.mockito.Mockito.anyString;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settingslib.widget.FooterPreference;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class LocaleHelperPreferenceControllerTest {
|
||||
private Context mContext;
|
||||
private LocaleHelperPreferenceController mLocaleHelperPreferenceController;
|
||||
|
||||
@Mock
|
||||
private FooterPreference mMockFooterPreference;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
mContext = ApplicationProvider.getApplicationContext();
|
||||
mLocaleHelperPreferenceController = new LocaleHelperPreferenceController(mContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateFooterPreference_setFooterPreference_hasClickAction() {
|
||||
mLocaleHelperPreferenceController.updateFooterPreference(mMockFooterPreference);
|
||||
verify(mMockFooterPreference).setLearnMoreText(anyString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user