Merge "Fix a bug: applied wrong layout for advanecd button flag"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 386f0c2..f07c39f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1896,11 +1896,13 @@
android:icon="@drawable/ic_settings_development"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
+ <!-- Enable if we need to revert to the old development settings
<intent-filter android:priority="1">
<action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
<action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
+ -->
<intent-filter android:priority="50">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
@@ -1919,14 +1921,11 @@
android:icon="@drawable/ic_settings_development"
android:taskAffinity="com.android.settings"
android:parentActivityName="Settings">
-
- <!-- Enable when deleting DevelopmentSettingsActivity
<intent-filter android:priority="1">
<action android:name="android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
<action android:name="com.android.settings.APPLICATION_DEVELOPMENT_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
- -->
<intent-filter android:priority="50">
<action android:name="com.android.settings.action.SETTINGS" />
</intent-filter>
@@ -1994,9 +1993,9 @@
<activity-alias android:name="DevelopmentSettings"
android:exported="true"
android:label="@string/development_settings_title"
- android:targetActivity="Settings$DevelopmentSettingsActivity">
+ android:targetActivity="Settings$DevelopmentSettingsDashboardActivity">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
- android:value="com.android.settings.development.DevelopmentSettings" />
+ android:value="com.android.settings.development.DevelopmentSettingsDashboardFragment" />
</activity-alias>
<activity android:name=".development.AppPicker"
@@ -2011,7 +2010,7 @@
<activity-alias android:name="UsbSettings"
android:exported="true"
android:label="@string/storage_title_usb"
- android:targetActivity="Settings$DevelopmentSettingsActivity">
+ android:targetActivity="Settings$DevelopmentSettingsDashboardActivity">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.deviceinfo.UsbSettings" />
</activity-alias>
diff --git a/res/drawable/line.xml b/res/drawable/line.xml
new file mode 100644
index 0000000..786ed1c
--- /dev/null
+++ b/res/drawable/line.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <solid android:color="@android:color/transparent" />
+
+ <padding
+ android:top="10dp"
+ android:left="10dp"
+ android:right="10dp"
+ android:bottom="10dp"/>
+</shape>
\ No newline at end of file
diff --git a/res/drawable/line_drawable.xml b/res/drawable/line_drawable.xml
new file mode 100644
index 0000000..a524c61
--- /dev/null
+++ b/res/drawable/line_drawable.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/line" />
+
+ <item
+ android:drawable="@drawable/line" />
+</selector>
\ No newline at end of file
diff --git a/res/drawable/thumb.xml b/res/drawable/thumb.xml
new file mode 100644
index 0000000..42fbd8c
--- /dev/null
+++ b/res/drawable/thumb.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <corners
+ android:topLeftRadius="8dp"
+ android:topRightRadius="8dp"
+ android:bottomLeftRadius="8dp"
+ android:bottomRightRadius="8dp"/>
+
+ <padding
+ android:paddingLeft="8dp"
+ android:paddingRight="8dp" />
+
+ <solid android:color="?android:attr/colorControlNormal" />
+
+</shape>
\ No newline at end of file
diff --git a/res/drawable/thumb_drawable.xml b/res/drawable/thumb_drawable.xml
new file mode 100644
index 0000000..b99536d
--- /dev/null
+++ b/res/drawable/thumb_drawable.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2017 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:state_pressed="true"
+ android:drawable="@drawable/thumb"/>
+
+ <item
+ android:drawable="@drawable/thumb"/>
+</selector>
\ No newline at end of file
diff --git a/res/layout/manage_applications_apps.xml b/res/layout/manage_applications_apps.xml
index e4ec871..d362528 100644
--- a/res/layout/manage_applications_apps.xml
+++ b/res/layout/manage_applications_apps.xml
@@ -14,44 +14,53 @@
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
<FrameLayout
- android:layout_width="match_parent"
- android:layout_height="0dp"
- android:layout_weight="1">
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1">
- <LinearLayout android:id="@+id/list_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:visibility="gone">
+ <LinearLayout
+ android:id="@+id/list_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:visibility="gone">
<FrameLayout
android:id="@+id/pinned_header"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
- <FrameLayout android:layout_width="match_parent"
- android:layout_height="0px"
- android:layout_weight="1">
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="0px"
+ android:layout_weight="1">
- <ListView android:id="@android:id/list"
- android:drawSelectorOnTop="false"
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/apps_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:clipToPadding="false"
- android:scrollbarStyle="@integer/preference_scrollbar_style" />
+ settings:fastScrollEnabled="true"
+ settings:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
+ settings:fastScrollHorizontalTrackDrawable="@drawable/line_drawable"
+ settings:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
+ settings:fastScrollVerticalTrackDrawable="@drawable/line_drawable"/>
- <TextView android:id="@android:id/empty"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:text="@string/no_applications"
- android:textAppearance="?android:attr/textAppearanceLarge" />
+ <TextView
+ android:id="@android:id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:text="@string/no_applications"
+ android:textAppearance="?android:attr/textAppearanceLarge"
+ android:visibility="invisible" />
</FrameLayout>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 819c491..9687bf2 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6703,7 +6703,7 @@
<!-- Do not disturb: Subtitle for DND behavior indicating no sound will get past DND due to user and/or API-invoked Total Silence mode. [CHAR LIMIT=40] -->
<string name="zen_mode_behavior_total_silence">No sound (Total Silence)</string>
- <!-- Do not disturb: Used before specifying which sounds can bypass DND (ie: No sound except alarms and reminders). [CHAR LIMIT=30] -->
+ <!-- Do not disturb: Used before specifying which sounds can bypass DND (ie: No sound except alarms and reminders). [CHAR LIMIT=40] -->
<string name="zen_mode_behavior_no_sound_except">No sound except <xliff:g id="categories" example="alarms, media and system feedback">%1$s</xliff:g></string>
<!-- Do not disturb: Specifies sounds that can bypass DND in user and/or API-invoked Alarms Only mode. [CHAR LIMIT=100] -->
diff --git a/res/xml/app_default_settings.xml b/res/xml/app_default_settings.xml
index 196ed9f..d2a1644 100644
--- a/res/xml/app_default_settings.xml
+++ b/res/xml/app_default_settings.xml
@@ -74,8 +74,8 @@
android:title="@string/domain_urls_title"
android:fragment="com.android.settings.applications.ManageDomainUrls" />
- <com.android.settings.WorkOnlyCategory
- android:key="work_defaults"
+ <com.android.settings.widget.WorkOnlyCategory
+ android:key="work_app_defaults"
android:title="@string/default_for_work">
<Preference
@@ -93,6 +93,6 @@
<extra android:name="for_work" android:value="true" />
</Preference>
- </com.android.settings.WorkOnlyCategory>
+ </com.android.settings.widget.WorkOnlyCategory>
</PreferenceScreen>
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index a764d7a..4d19099 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -156,7 +156,7 @@
android:targetClass="com.android.cellbroadcastreceiver.CellBroadcastSettings" />
</com.android.settingslib.RestrictedPreference>
- <com.android.settings.WorkOnlyCategory
+ <com.android.settings.widget.WorkOnlyCategory
android:key="sound_work_settings_section"
android:title="@string/sound_work_settings"
android:order="100">
@@ -193,5 +193,5 @@
android:ringtoneType="alarm"
android:dependency="work_use_personal_sounds" />
- </com.android.settings.WorkOnlyCategory>
+ </com.android.settings.widget.WorkOnlyCategory>
</PreferenceScreen>
diff --git a/res/xml/sound_settings_new_advance_button.xml b/res/xml/sound_settings_new_advance_button.xml
index 6b0ba0e..a1e1a32 100644
--- a/res/xml/sound_settings_new_advance_button.xml
+++ b/res/xml/sound_settings_new_advance_button.xml
@@ -154,7 +154,7 @@
android:targetClass="com.android.cellbroadcastreceiver.CellBroadcastSettings" />
</com.android.settingslib.RestrictedPreference>
- <com.android.settings.WorkOnlyCategory
+ <com.android.settings.widget.WorkOnlyCategory
android:key="sound_work_settings_section"
android:title="@string/sound_work_settings"
android:order="100">
@@ -191,5 +191,5 @@
android:ringtoneType="alarm"
android:dependency="work_use_personal_sounds" />
- </com.android.settings.WorkOnlyCategory>
+ </com.android.settings.widget.WorkOnlyCategory>
</PreferenceScreen>
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 2377ca5..eac3801 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -73,12 +73,12 @@
* @deprecated in favor of {@link DevelopmentSettingsDashboardActivity}.
*/
@Deprecated
- public static class DevelopmentSettingsActivity extends SettingsActivity { /* empty */ }
- public static class DevelopmentSettingsDashboardActivity extends SettingsActivity {
+ public static class DevelopmentSettingsActivity extends SettingsActivity {
public static final boolean isEnabled() {
- return FeatureFlagUtils.isEnabled("dev_option_v2");
+ return FeatureFlagUtils.isEnabled("dev_option_v1");
}
}
+ public static class DevelopmentSettingsDashboardActivity extends SettingsActivity { /* empty */ }
public static class AccessibilitySettingsActivity extends SettingsActivity { /* empty */ }
public static class CaptioningSettingsActivity extends SettingsActivity { /* empty */ }
public static class AccessibilityInversionSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index 973c216..1202d13 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -832,16 +832,16 @@
final boolean showDev = DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(this)
&& !um.hasUserRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES);
- final boolean useDevOptionV2 = Settings.DevelopmentSettingsDashboardActivity.isEnabled();
+ final boolean useDevOptionV1 = Settings.DevelopmentSettingsActivity.isEnabled();
// Enable old Dev option if v2 is disabled
somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.DevelopmentSettingsActivity.class.getName()),
- showDev && !useDevOptionV2, isAdmin)
+ showDev && useDevOptionV1, isAdmin)
|| somethingChanged;
// Enable new Dev option if v2 is enable
somethingChanged = setTileEnabled(new ComponentName(packageName,
Settings.DevelopmentSettingsDashboardActivity.class.getName()),
- showDev && useDevOptionV2, isAdmin)
+ showDev && !useDevOptionV1, isAdmin)
|| somethingChanged;
// Enable/disable backup settings depending on whether the user is admin.
diff --git a/src/com/android/settings/applications/DefaultAppSettings.java b/src/com/android/settings/applications/DefaultAppSettings.java
index bcbc917..1487da3 100644
--- a/src/com/android/settings/applications/DefaultAppSettings.java
+++ b/src/com/android/settings/applications/DefaultAppSettings.java
@@ -26,11 +26,12 @@
import com.android.settings.applications.defaultapps.DefaultBrowserPreferenceController;
import com.android.settings.applications.defaultapps.DefaultEmergencyPreferenceController;
import com.android.settings.applications.defaultapps.DefaultHomePreferenceController;
+import com.android.settings.applications.defaultapps.DefaultPaymentSettingsPreferenceController;
import com.android.settings.applications.defaultapps.DefaultPhonePreferenceController;
import com.android.settings.applications.defaultapps.DefaultSmsPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkBrowserPreferenceController;
+import com.android.settings.widget.WorkOnlyCategoryPreferenceController;
import com.android.settings.applications.defaultapps.DefaultWorkPhonePreferenceController;
-import com.android.settings.applications.defaultapps.DefaultPaymentSettingsPreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.dashboard.SummaryLoader;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -45,6 +46,7 @@
static final String TAG = "DefaultAppSettings";
+ private static final String KEY_DEFAULT_WORK_CATEGORY = "work_app_defaults";
private static final String KEY_ASSIST_VOICE_INPUT = "assist_and_voice_input";
@Override
@@ -69,12 +71,16 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ final List<AbstractPreferenceController> workControllers = new ArrayList<>();
+ workControllers.add(new DefaultWorkPhonePreferenceController(context));
+ workControllers.add(new DefaultWorkBrowserPreferenceController(context));
+ controllers.addAll(workControllers);
+ controllers.add(new WorkOnlyCategoryPreferenceController(
+ context, KEY_DEFAULT_WORK_CATEGORY, workControllers));
controllers.add(new DefaultAssistPreferenceController(context, KEY_ASSIST_VOICE_INPUT,
false /* showSetting */));
controllers.add(new DefaultBrowserPreferenceController(context));
- controllers.add(new DefaultWorkBrowserPreferenceController(context));
controllers.add(new DefaultPhonePreferenceController(context));
- controllers.add(new DefaultWorkPhonePreferenceController(context));
controllers.add(new DefaultSmsPreferenceController(context));
controllers.add(new DefaultEmergencyPreferenceController(context));
controllers.add(new DefaultHomePreferenceController(context));
@@ -97,10 +103,8 @@
List<String> keys = super.getNonIndexableKeys(context);
keys.add(KEY_ASSIST_VOICE_INPUT);
// TODO (b/38230148) Remove these keys when we can differentiate work results
- keys.add((new DefaultWorkPhonePreferenceController(context))
- .getPreferenceKey());
- keys.add((new DefaultWorkBrowserPreferenceController(context))
- .getPreferenceKey());
+ keys.add(DefaultWorkPhonePreferenceController.KEY);
+ keys.add(DefaultWorkBrowserPreferenceController.KEY);
return keys;
}
diff --git a/src/com/android/settings/applications/defaultapps/DefaultWorkBrowserPreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultWorkBrowserPreferenceController.java
index 0792ff9..4dc984b 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultWorkBrowserPreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultWorkBrowserPreferenceController.java
@@ -23,6 +23,7 @@
public class DefaultWorkBrowserPreferenceController extends DefaultBrowserPreferenceController {
+ public static final String KEY = "work_default_browser";
private final UserHandle mUserHandle;
public DefaultWorkBrowserPreferenceController(Context context) {
@@ -35,7 +36,7 @@
@Override
public String getPreferenceKey() {
- return "work_default_browser";
+ return KEY;
}
@Override
diff --git a/src/com/android/settings/applications/defaultapps/DefaultWorkPhonePreferenceController.java b/src/com/android/settings/applications/defaultapps/DefaultWorkPhonePreferenceController.java
index c6d04fa..decff06 100644
--- a/src/com/android/settings/applications/defaultapps/DefaultWorkPhonePreferenceController.java
+++ b/src/com/android/settings/applications/defaultapps/DefaultWorkPhonePreferenceController.java
@@ -23,6 +23,7 @@
public class DefaultWorkPhonePreferenceController extends DefaultPhonePreferenceController {
+ public static final String KEY = "work_default_phone_app";
private final UserHandle mUserHandle;
public DefaultWorkPhonePreferenceController(Context context) {
@@ -43,6 +44,6 @@
@Override
public String getPreferenceKey() {
- return "work_default_phone_app";
+ return KEY;
}
}
diff --git a/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
new file mode 100644
index 0000000..9ac2167
--- /dev/null
+++ b/src/com/android/settings/applications/manageapplications/ApplicationViewHolder.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.manageapplications;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.StringRes;
+import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import com.android.settingslib.applications.ApplicationsState;
+import com.android.settingslib.applications.ApplicationsState.AppEntry;
+
+public class ApplicationViewHolder extends RecyclerView.ViewHolder {
+
+ private final TextView mAppName;
+ private final ImageView mAppIcon;
+
+ @VisibleForTesting
+ final TextView mSummary;
+ @VisibleForTesting
+ final TextView mDisabled;
+
+ ApplicationViewHolder(View itemView) {
+ super(itemView);
+ mAppName = itemView.findViewById(android.R.id.title);
+ mAppIcon = itemView.findViewById(android.R.id.icon);
+ mSummary = itemView.findViewById(R.id.widget_text1);
+ mDisabled = itemView.findViewById(R.id.widget_text2);
+ }
+
+ static View newView(LayoutInflater inflater, ViewGroup parent) {
+ final View root = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.preference_app, parent, false);
+ inflater.inflate(R.layout.widget_text_views,
+ root.findViewById(android.R.id.widget_frame));
+ return root;
+ }
+
+ void setSummary(CharSequence summary) {
+ mSummary.setText(summary);
+ }
+
+ void setSummary(@StringRes int summary) {
+ mSummary.setText(summary);
+ }
+
+ void setEnabled(boolean isEnabled) {
+ itemView.setEnabled(isEnabled);
+ }
+
+ void setTitle(CharSequence title) {
+ if (title == null) {
+ return;
+ }
+ mAppName.setText(title);
+ }
+
+ void setIcon(Drawable icon) {
+ if (icon == null) {
+ return;
+ }
+ mAppIcon.setImageDrawable(icon);
+ }
+
+ void updateDisableView(ApplicationInfo info) {
+ if ((info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
+ mDisabled.setVisibility(View.VISIBLE);
+ mDisabled.setText(R.string.not_installed);
+ } else if (!info.enabled || info.enabledSetting
+ == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+ mDisabled.setVisibility(View.VISIBLE);
+ mDisabled.setText(R.string.disabled);
+ } else {
+ mDisabled.setVisibility(View.GONE);
+ }
+ }
+
+ void updateSizeText(AppEntry entry, CharSequence invalidSizeStr, int whichSize) {
+ if (ManageApplications.DEBUG) {
+ Log.d(ManageApplications.TAG, "updateSizeText of "
+ + entry.label + " " + entry + ": " + entry.sizeStr);
+ }
+ if (entry.sizeStr != null) {
+ switch (whichSize) {
+ case ManageApplications.SIZE_INTERNAL:
+ setSummary(entry.internalSizeStr);
+ break;
+ case ManageApplications.SIZE_EXTERNAL:
+ setSummary(entry.externalSizeStr);
+ break;
+ default:
+ setSummary(entry.sizeStr);
+ break;
+ }
+ } else if (entry.size == ApplicationsState.SIZE_INVALID) {
+ setSummary(invalidSizeStr);
+ }
+ }
+}
diff --git a/src/com/android/settings/applications/manageapplications/FileViewHolderController.java b/src/com/android/settings/applications/manageapplications/FileViewHolderController.java
index 03e2e55..4e6bf26 100644
--- a/src/com/android/settings/applications/manageapplications/FileViewHolderController.java
+++ b/src/com/android/settings/applications/manageapplications/FileViewHolderController.java
@@ -35,12 +35,14 @@
/**
* Initializes the view within an AppViewHolder.
+ *
* @param holder The holder to use to initialize.
*/
- void setupView(AppViewHolder holder);
+ void setupView(ApplicationViewHolder holder);
/**
* Handles the behavior when the view is clicked.
+ *
* @param fragment Fragment where the click originated.
*/
void onClick(Fragment fragment);
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 932b2dd..6b21128 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -40,16 +40,14 @@
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
-import android.content.pm.PackageManager;
-import android.icu.text.AlphabeticIndex;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Handler;
-import android.os.LocaleList;
import android.os.UserHandle;
import android.os.UserManager;
import android.preference.PreferenceFrameLayout;
import android.support.annotation.VisibleForTesting;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
@@ -59,19 +57,11 @@
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.AbsListView;
import android.widget.AdapterView;
-import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
-import android.widget.BaseAdapter;
-import android.widget.Filter;
-import android.widget.Filterable;
import android.widget.FrameLayout;
-import android.widget.ListView;
-import android.widget.SectionIndexer;
import android.widget.Spinner;
-import android.widget.TextView;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
@@ -86,7 +76,6 @@
import com.android.settings.Settings.UsageAccessSettingsActivity;
import com.android.settings.Settings.WriteSettingsActivity;
import com.android.settings.SettingsActivity;
-import com.android.settings.Utils;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
import com.android.settings.applications.AppStateBaseBridge;
@@ -122,13 +111,13 @@
import com.android.settingslib.applications.ApplicationsState.CompoundFilter;
import com.android.settingslib.applications.ApplicationsState.VolumeFilter;
import com.android.settingslib.applications.StorageStatsSource;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.wrapper.PackageManagerWrapper;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
-import java.util.Locale;
import java.util.Set;
/**
@@ -138,7 +127,7 @@
* intent.
*/
public class ManageApplications extends InstrumentedPreferenceFragment
- implements OnItemClickListener, OnItemSelectedListener {
+ implements View.OnClickListener, OnItemSelectedListener {
static final String TAG = "ManageApplications";
static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -185,23 +174,17 @@
private ApplicationsState mApplicationsState;
public int mListType;
- public AppFilterItem mFilter;
-
- public ApplicationsAdapter mApplications;
+ private AppFilterItem mFilter;
+ private ApplicationsAdapter mApplications;
private View mLoadingContainer;
private View mListContainer;
-
- // ListView used to display list
- private ListView mListView;
+ private RecyclerView mRecyclerView;
// Size resource used for packages whose size computation failed for some reason
CharSequence mInvalidSizeStr;
- // layout inflater object used to inflate views
- private LayoutInflater mInflater;
-
private String mCurrentPkgName;
private int mCurrentUid;
@@ -234,6 +217,7 @@
private int mStorageType;
private boolean mIsWorkOnly;
private int mWorkUserId;
+ private View mEmptyView;
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -304,25 +288,14 @@
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
- // initialize the inflater
- mInflater = inflater;
-
mRootView = inflater.inflate(R.layout.manage_applications_apps, null);
mLoadingContainer = mRootView.findViewById(R.id.loading_container);
mListContainer = mRootView.findViewById(R.id.list_container);
if (mListContainer != null) {
// Create adapter and list view here
- View emptyView = mListContainer.findViewById(com.android.internal.R.id.empty);
- ListView lv = mListContainer.findViewById(android.R.id.list);
- if (emptyView != null) {
- lv.setEmptyView(emptyView);
- }
- lv.setOnItemClickListener(this);
- lv.setSaveEnabled(true);
- lv.setItemsCanFocus(true);
- lv.setTextFilterEnabled(true);
- mListView = lv;
- mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter);
+ mEmptyView = mListContainer.findViewById(android.R.id.empty);
+ mApplications = new ApplicationsAdapter(mApplicationsState, this, mFilter,
+ savedInstanceState);
if (savedInstanceState != null) {
mApplications.mHasReceivedLoadEntries =
savedInstanceState.getBoolean(EXTRA_HAS_ENTRIES, false);
@@ -347,11 +320,10 @@
mVolumeUuid,
UserHandle.of(userId)));
}
- mListView.setAdapter(mApplications);
- mListView.setRecyclerListener(mApplications);
- mListView.setFastScrollEnabled(isFastScrollEnabled());
-
- Utils.prepareCustomPreferencesList(container, mRootView, mListView, false);
+ mRecyclerView = mListContainer.findViewById(R.id.apps_list);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(
+ getContext(), RecyclerView.VERTICAL, false /* reverseLayout */));
+ mRecyclerView.setAdapter(mApplications);
}
// We have to do this now because PreferenceFrameLayout looks at it
@@ -492,6 +464,9 @@
outState.putBoolean(EXTRA_SHOW_SYSTEM, mShowSystem);
outState.putBoolean(EXTRA_HAS_ENTRIES, mApplications.mHasReceivedLoadEntries);
outState.putBoolean(EXTRA_HAS_BRIDGE, mApplications.mHasReceivedBridgeCallback);
+ if (mApplications != null) {
+ mApplications.onSaveInstanceState(outState);
+ }
}
@Override
@@ -633,7 +608,6 @@
case R.id.sort_order_alpha:
case R.id.sort_order_size:
mSortOrder = menuId;
- mListView.setFastScrollEnabled(isFastScrollEnabled());
if (mApplications != null) {
mApplications.rebuild(mSortOrder);
}
@@ -667,10 +641,11 @@
}
@Override
- public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ public void onClick(View view) {
if (mApplications == null) {
return;
}
+ final int position = mRecyclerView.getChildAdapterPosition(view);
if (mApplications.getApplicationCount() > position) {
ApplicationsState.AppEntry entry = mApplications.getAppEntry(position);
@@ -757,7 +732,9 @@
mFilterOptions.size() > 1 ? View.VISIBLE : View.GONE);
notifyDataSetChanged();
if (mFilterOptions.size() == 1) {
- if (DEBUG) Log.d(TAG, "Auto selecting filter " + filter);
+ if (DEBUG) {
+ Log.d(TAG, "Auto selecting filter " + filter);
+ }
mManageApplications.mFilterSpinner.setSelection(0);
mManageApplications.onItemSelected(null, null, 0, 0);
}
@@ -777,7 +754,9 @@
notifyDataSetChanged();
if (mManageApplications.mFilter == filter) {
if (mFilterOptions.size() > 0) {
- if (DEBUG) Log.d(TAG, "Auto selecting filter " + mFilterOptions.get(0));
+ if (DEBUG) {
+ Log.d(TAG, "Auto selecting filter " + mFilterOptions.get(0));
+ }
mManageApplications.mFilterSpinner.setSelection(0);
mManageApplications.onItemSelected(null, null, 0, 0);
}
@@ -795,38 +774,25 @@
}
}
- /*
- * Custom adapter implementation for the ListView
- * This adapter maintains a map for each displayed application and its properties
- * An index value on each AppInfo object indicates the correct position or index
- * in the list. If the list gets updated dynamically when the user is viewing the list of
- * applications, we need to return the correct index of position. This is done by mapping
- * the getId methods via the package name into the internal maps and indices.
- * The order of applications in the list is mirrored in mAppLocalList
- */
- static class ApplicationsAdapter extends BaseAdapter implements Filterable,
- ApplicationsState.Callbacks, AppStateBaseBridge.Callback,
- AbsListView.RecyclerListener, SectionIndexer {
+ static class ApplicationsAdapter extends RecyclerView.Adapter<ApplicationViewHolder>
+ implements ApplicationsState.Callbacks, AppStateBaseBridge.Callback {
- private static final SectionInfo[] EMPTY_SECTIONS = new SectionInfo[0];
+ private static final String STATE_LAST_SCROLL_INDEX = "state_last_scroll_index";
+ private static final int VIEW_TYPE_APP = 0;
+ private static final int VIEW_TYPE_EXTRA_VIEW = 1;
private final ApplicationsState mState;
private final ApplicationsState.Session mSession;
private final ManageApplications mManageApplications;
private final Context mContext;
- private final ArrayList<View> mActive = new ArrayList<>();
private final AppStateBaseBridge mExtraInfoBridge;
- private final Handler mBgHandler;
- private final Handler mFgHandler;
private final LoadingViewController mLoadingViewController;
private AppFilterItem mAppFilter;
- private ArrayList<ApplicationsState.AppEntry> mBaseEntries;
private ArrayList<ApplicationsState.AppEntry> mEntries;
private boolean mResumed;
private int mLastSortMode = -1;
private int mWhichSize = SIZE_TOTAL;
- CharSequence mCurFilterPrefix;
private AppFilter mCompositeFilter;
private boolean mHasReceivedLoadEntries;
private boolean mHasReceivedBridgeCallback;
@@ -836,39 +802,11 @@
// fragment is paused. We need this special handling because app entries are added gradually
// when we rebuild the list after the user made some changes, like uninstalling an app.
private int mLastIndex = -1;
- private int mLastTop;
-
- private AlphabeticIndex.ImmutableIndex<Locale> mIndex;
- private SectionInfo[] mSections = EMPTY_SECTIONS;
- private int[] mPositionToSectionIndex;
-
- private Filter mFilter = new Filter() {
- @Override
- protected FilterResults performFiltering(CharSequence constraint) {
- ArrayList<ApplicationsState.AppEntry> entries
- = applyPrefixFilter(constraint, mBaseEntries);
- FilterResults fr = new FilterResults();
- fr.values = entries;
- fr.count = entries.size();
- return fr;
- }
-
- @Override
- @SuppressWarnings("unchecked")
- protected void publishResults(CharSequence constraint, FilterResults results) {
- mCurFilterPrefix = constraint;
- mEntries = (ArrayList<ApplicationsState.AppEntry>) results.values;
- rebuildSections();
- notifyDataSetChanged();
- }
- };
-
public ApplicationsAdapter(ApplicationsState state, ManageApplications manageApplications,
- AppFilterItem appFilter) {
+ AppFilterItem appFilter, Bundle savedInstanceState) {
+ setHasStableIds(true);
mState = state;
- mFgHandler = new Handler();
- mBgHandler = new Handler(mState.getBackgroundLooper());
mSession = state.newSession(this);
mManageApplications = manageApplications;
mLoadingViewController = new LoadingViewController(
@@ -893,6 +831,9 @@
} else {
mExtraInfoBridge = null;
}
+ if (savedInstanceState != null) {
+ mLastIndex = savedInstanceState.getInt(STATE_LAST_SCROLL_INDEX);
+ }
}
public void setCompositeFilter(AppFilter compositeFilter) {
@@ -907,9 +848,11 @@
public void setExtraViewController(FileViewHolderController extraViewController) {
mExtraViewController = extraViewController;
- mBgHandler.post(() -> {
+ // Start to query extra view's stats on background, and once done post result to main
+ // thread.
+ ThreadUtils.postOnBackgroundThread(() -> {
mExtraViewController.queryStats();
- mFgHandler.post(() -> {
+ ThreadUtils.postOnMainThread(() -> {
onExtraViewCompleted();
});
});
@@ -938,11 +881,13 @@
mExtraInfoBridge.pause();
}
}
+ }
+
+ public void onSaveInstanceState(Bundle outState) {
// Record the current scroll position before pausing.
- mLastIndex = mManageApplications.mListView.getFirstVisiblePosition();
- View v = mManageApplications.mListView.getChildAt(0);
- mLastTop =
- (v == null) ? 0 : (v.getTop() - mManageApplications.mListView.getPaddingTop());
+ final LinearLayoutManager layoutManager =
+ (LinearLayoutManager) mManageApplications.mRecyclerView.getLayoutManager();
+ outState.putInt(STATE_LAST_SCROLL_INDEX, layoutManager.findFirstVisibleItemPosition());
}
public void release() {
@@ -960,6 +905,21 @@
rebuild();
}
+ @Override
+ public ApplicationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ final View view = ApplicationViewHolder.newView(
+ LayoutInflater.from(parent.getContext()), parent);
+ return new ApplicationViewHolder(view);
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ boolean isLastItem = (getItemCount() - 1) == position;
+ return hasExtraView() && isLastItem
+ ? VIEW_TYPE_EXTRA_VIEW
+ : VIEW_TYPE_APP;
+ }
+
public void rebuild() {
if (!mHasReceivedLoadEntries
|| (mExtraInfoBridge != null && !mHasReceivedBridgeCallback)) {
@@ -1008,11 +968,11 @@
filterObj = new CompoundFilter(filterObj, ApplicationsState.FILTER_NOT_HIDE);
AppFilter finalFilterObj = filterObj;
- mBgHandler.post(() -> {
+ ThreadUtils.postOnBackgroundThread(() -> {
final ArrayList<AppEntry> entries = mSession.rebuild(finalFilterObj,
comparatorObj, false);
if (entries != null) {
- mFgHandler.post(() -> onRebuildComplete(entries));
+ ThreadUtils.postOnMainThread(() -> onRebuildComplete(entries));
}
});
}
@@ -1031,8 +991,7 @@
ArrayList<ApplicationsState.AppEntry> entries) {
int size = entries.size();
// returnList will not have more entries than entries
- ArrayList<ApplicationsState.AppEntry> returnEntries = new
- ArrayList<ApplicationsState.AppEntry>(size);
+ ArrayList<ApplicationsState.AppEntry> returnEntries = new ArrayList<>(size);
// assume appinfo of same package but different users are grouped together
PackageItemInfo lastInfo = null;
@@ -1055,21 +1014,19 @@
filterType == FILTER_APPS_POWER_WHITELIST_ALL) {
entries = removeDuplicateIgnoringUser(entries);
}
- mBaseEntries = entries;
- if (mBaseEntries != null) {
- mEntries = applyPrefixFilter(mCurFilterPrefix, mBaseEntries);
- rebuildSections();
- } else {
- mEntries = null;
- mSections = EMPTY_SECTIONS;
- mPositionToSectionIndex = null;
- }
-
+ mEntries = entries;
notifyDataSetChanged();
+ if (getItemCount() == 0) {
+ mManageApplications.mRecyclerView.setVisibility(View.GONE);
+ mManageApplications.mEmptyView.setVisibility(View.VISIBLE);
+ } else {
+ mManageApplications.mEmptyView.setVisibility(View.GONE);
+ mManageApplications.mRecyclerView.setVisibility(View.VISIBLE);
+ }
// Restore the last scroll position if the number of entries added so far is bigger than
// it.
- if (mLastIndex != -1 && getCount() > mLastIndex) {
- mManageApplications.mListView.setSelectionFromTop(mLastIndex, mLastTop);
+ if (mLastIndex != -1 && getItemCount() > mLastIndex) {
+ mManageApplications.mRecyclerView.getLayoutManager().scrollToPosition(mLastIndex);
mLastIndex = -1;
}
@@ -1086,45 +1043,6 @@
mManageApplications.setHasInstant(mState.haveInstantApps());
}
- private void rebuildSections() {
- if (mEntries != null && mManageApplications.mListView.isFastScrollEnabled()) {
- // Rebuild sections
- if (mIndex == null) {
- LocaleList locales = mContext.getResources().getConfiguration().getLocales();
- if (locales.size() == 0) {
- locales = new LocaleList(Locale.ENGLISH);
- }
- AlphabeticIndex<Locale> index = new AlphabeticIndex(locales.get(0));
- int localeCount = locales.size();
- for (int i = 1; i < localeCount; i++) {
- index.addLabels(locales.get(i));
- }
- // Ensure we always have some base English locale buckets
- index.addLabels(Locale.ENGLISH);
- mIndex = index.buildImmutableIndex();
- }
-
- ArrayList<SectionInfo> sections = new ArrayList<>();
- int lastSecId = -1;
- int totalEntries = mEntries.size();
- mPositionToSectionIndex = new int[totalEntries];
-
- for (int pos = 0; pos < totalEntries; pos++) {
- String label = mEntries.get(pos).label;
- int secId = mIndex.getBucketIndex(TextUtils.isEmpty(label) ? "" : label);
- if (secId != lastSecId) {
- lastSecId = secId;
- sections.add(new SectionInfo(mIndex.getBucket(secId).getLabel(), pos));
- }
- mPositionToSectionIndex[pos] = sections.size() - 1;
- }
- mSections = sections.toArray(EMPTY_SECTIONS);
- } else {
- mSections = EMPTY_SECTIONS;
- mPositionToSectionIndex = null;
- }
- }
-
@VisibleForTesting
void updateLoading() {
final boolean appLoaded = mHasReceivedLoadEntries && mSession.getAllApps().size() != 0;
@@ -1135,26 +1053,6 @@
}
}
- ArrayList<ApplicationsState.AppEntry> applyPrefixFilter(CharSequence prefix,
- ArrayList<ApplicationsState.AppEntry> origEntries) {
- if (prefix == null || prefix.length() == 0) {
- return origEntries;
- } else {
- String prefixStr = ApplicationsState.normalize(prefix.toString());
- final String spacePrefixStr = " " + prefixStr;
- ArrayList<ApplicationsState.AppEntry> newEntries
- = new ArrayList<ApplicationsState.AppEntry>();
- for (int i = 0; i < origEntries.size(); i++) {
- ApplicationsState.AppEntry entry = origEntries.get(i);
- String nlabel = entry.getNormalizedLabel();
- if (nlabel.startsWith(prefixStr) || nlabel.indexOf(spacePrefixStr) != -1) {
- newEntries.add(entry);
- }
- }
- return newEntries;
- }
- }
-
@Override
public void onExtraInfoUpdated() {
mHasReceivedBridgeCallback = true;
@@ -1186,29 +1084,27 @@
@Override
public void onPackageSizeChanged(String packageName) {
- for (int i = 0; i < mActive.size(); i++) {
- AppViewHolder holder = (AppViewHolder) mActive.get(i).getTag();
- if (holder == null || holder.entry == null) {
+ if (mEntries == null) {
+ return;
+ }
+ final int size = mEntries.size();
+ for (int i = 0; i < size; i++) {
+ final AppEntry entry = mEntries.get(i);
+ final ApplicationInfo info = entry.info;
+ if (info == null && !TextUtils.equals(packageName, info.packageName)) {
continue;
}
- ApplicationInfo info = holder.entry.info;
- if (info == null) {
- continue;
- }
- if (holder.entry.info.packageName.equals(packageName)) {
- synchronized (holder.entry) {
- updateSummary(holder);
- }
- if (holder.entry.info.packageName.equals(mManageApplications.mCurrentPkgName)
- && mLastSortMode == R.id.sort_order_size) {
- // We got the size information for the last app the
- // user viewed, and are sorting by size... they may
- // have cleared data, so we immediately want to resort
- // the list with the new size to reflect it to the user.
- rebuild();
- }
+ if (TextUtils.equals(mManageApplications.mCurrentPkgName, info.packageName)) {
+ // We got the size information for the last app the
+ // user viewed, and are sorting by size... they may
+ // have cleared data, so we immediately want to resort
+ // the list with the new size to reflect it to the user.
+ rebuild();
return;
+ } else {
+ notifyItemChanged(i);
}
+
}
}
@@ -1227,46 +1123,30 @@
}
public void onExtraViewCompleted() {
- int size = mActive.size();
- // If we have no elements, don't do anything.
- if (size < 1) {
+ if (!hasExtraView()) {
return;
}
- AppViewHolder holder = (AppViewHolder) mActive.get(size - 1).getTag();
-
- // HACK: The extra view has no AppEntry -- and should be the only element without one.
- // Thus, if the last active element has no AppEntry, it is the extra view.
- if (holder == null || holder.entry != null) {
- return;
- }
-
- mExtraViewController.setupView(holder);
+ // Update last item - this is assumed to be the extra view.
+ notifyItemChanged(getItemCount() - 1);
}
- public int getCount() {
+ @Override
+ public int getItemCount() {
if (mEntries == null) {
return 0;
}
- int extraViewAddition =
- (mExtraViewController != null && mExtraViewController.shouldShow()) ? 1 : 0;
- return mEntries.size() + extraViewAddition;
+ return mEntries.size() + (hasExtraView() ? 1 : 0);
}
public int getApplicationCount() {
return mEntries != null ? mEntries.size() : 0;
}
- public Object getItem(int position) {
- if (position == mEntries.size()) {
- return mExtraViewController;
- }
+ public AppEntry getAppEntry(int position) {
return mEntries.get(position);
}
- public ApplicationsState.AppEntry getAppEntry(int position) {
- return mEntries.get(position);
- }
-
+ @Override
public long getItemId(int position) {
if (position == mEntries.size()) {
return -1;
@@ -1274,142 +1154,76 @@
return mEntries.get(position).id;
}
- @Override
- public boolean areAllItemsEnabled() {
- return false;
- }
-
- @Override
public boolean isEnabled(int position) {
- if (position == mEntries.size() && mExtraViewController != null &&
- mExtraViewController.shouldShow()) {
- return true;
- }
-
- if (mManageApplications.mListType != LIST_TYPE_HIGH_POWER) {
+ if (getItemViewType(position) == VIEW_TYPE_EXTRA_VIEW
+ || mManageApplications.mListType != LIST_TYPE_HIGH_POWER) {
return true;
}
ApplicationsState.AppEntry entry = mEntries.get(position);
return !PowerWhitelistBackend.getInstance().isSysWhitelisted(entry.info.packageName);
}
- public View getView(int position, View convertView, ViewGroup parent) {
- // A ViewHolder keeps references to children views to avoid unnecessary calls
- // to findViewById() on each row.
- AppViewHolder holder = AppViewHolder.createOrRecycle(mManageApplications.mInflater,
- convertView);
- convertView = holder.rootView;
-
- // Handle the extra view if it is the last entry.
+ @Override
+ public void onBindViewHolder(ApplicationViewHolder holder, int position) {
if (mEntries != null && mExtraViewController != null && position == mEntries.size()) {
+ // set up view for extra view controller
mExtraViewController.setupView(holder);
- convertView.setEnabled(true);
} else {
// Bind the data efficiently with the holder
ApplicationsState.AppEntry entry = mEntries.get(position);
synchronized (entry) {
- holder.entry = entry;
- if (entry.label != null) {
- holder.appName.setText(entry.label);
- }
+ holder.setTitle(entry.label);
mState.ensureIcon(entry);
- if (entry.icon != null) {
- holder.appIcon.setImageDrawable(entry.icon);
- }
- updateSummary(holder);
- updateDisableView(holder.disabled, entry.info);
+ holder.setIcon(entry.icon);
+ updateSummary(holder, entry);
+ holder.updateDisableView(entry.info);
}
- convertView.setEnabled(isEnabled(position));
+ holder.setEnabled(isEnabled(position));
}
-
- mActive.remove(convertView);
- mActive.add(convertView);
- return convertView;
+ holder.itemView.setOnClickListener(mManageApplications);
}
- @VisibleForTesting
- void updateDisableView(TextView view, ApplicationInfo info) {
- if ((info.flags & ApplicationInfo.FLAG_INSTALLED) == 0) {
- view.setVisibility(View.VISIBLE);
- view.setText(R.string.not_installed);
- } else if (!info.enabled || info.enabledSetting
- == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
- view.setVisibility(View.VISIBLE);
- view.setText(R.string.disabled);
- } else {
- view.setVisibility(View.GONE);
- }
- }
-
- private void updateSummary(AppViewHolder holder) {
+ private void updateSummary(ApplicationViewHolder holder, AppEntry entry) {
switch (mManageApplications.mListType) {
case LIST_TYPE_NOTIFICATION:
- if (holder.entry.extraInfo != null) {
- holder.summary.setText(InstalledAppDetails.getNotificationSummary(
- (AppRow) holder.entry.extraInfo, mContext));
+ if (entry.extraInfo != null) {
+ holder.setSummary(InstalledAppDetails.getNotificationSummary(
+ (AppRow) entry.extraInfo, mContext));
} else {
- holder.summary.setText(null);
+ holder.setSummary(null);
}
break;
-
case LIST_TYPE_USAGE_ACCESS:
- if (holder.entry.extraInfo != null) {
- holder.summary.setText((new UsageState((PermissionState) holder.entry
- .extraInfo)).isPermissible()
- ? R.string.app_permission_summary_allowed
- : R.string.app_permission_summary_not_allowed);
+ if (entry.extraInfo != null) {
+ holder.setSummary(
+ (new UsageState((PermissionState) entry.extraInfo)).isPermissible()
+ ? R.string.app_permission_summary_allowed
+ : R.string.app_permission_summary_not_allowed);
} else {
- holder.summary.setText(null);
+ holder.setSummary(null);
}
break;
-
case LIST_TYPE_HIGH_POWER:
- holder.summary.setText(HighPowerDetail.getSummary(mContext, holder.entry));
+ holder.setSummary(HighPowerDetail.getSummary(mContext, entry));
break;
-
case LIST_TYPE_OVERLAY:
- holder.summary.setText(DrawOverlayDetails.getSummary(mContext, holder.entry));
+ holder.setSummary(DrawOverlayDetails.getSummary(mContext, entry));
break;
-
case LIST_TYPE_WRITE_SETTINGS:
- holder.summary.setText(WriteSettingsDetails.getSummary(mContext,
- holder.entry));
+ holder.setSummary(WriteSettingsDetails.getSummary(mContext, entry));
break;
-
case LIST_TYPE_MANAGE_SOURCES:
- holder.summary.setText(ExternalSourcesDetails.getPreferenceSummary(mContext,
- holder.entry));
+ holder.setSummary(ExternalSourcesDetails.getPreferenceSummary(mContext, entry));
break;
-
default:
- holder.updateSizeText(mManageApplications.mInvalidSizeStr, mWhichSize);
+ holder.updateSizeText(entry, mManageApplications.mInvalidSizeStr, mWhichSize);
break;
}
}
- @Override
- public Filter getFilter() {
- return mFilter;
- }
-
- @Override
- public void onMovedToScrapHeap(View view) {
- mActive.remove(view);
- }
-
- @Override
- public Object[] getSections() {
- return mSections;
- }
-
- @Override
- public int getPositionForSection(int sectionIndex) {
- return mSections[sectionIndex].position;
- }
-
- @Override
- public int getSectionForPosition(int position) {
- return mPositionToSectionIndex[position];
+ private boolean hasExtraView() {
+ return mExtraViewController != null
+ && mExtraViewController.shouldShow();
}
}
@@ -1439,21 +1253,6 @@
}
}
- private static class SectionInfo {
- final String label;
- final int position;
-
- public SectionInfo(String label, int position) {
- this.label = label;
- this.position = position;
- }
-
- @Override
- public String toString() {
- return label;
- }
- }
-
public static final SummaryLoader.SummaryProviderFactory SUMMARY_PROVIDER_FACTORY
= new SummaryLoader.SummaryProviderFactory() {
@Override
diff --git a/src/com/android/settings/applications/manageapplications/MusicViewHolderController.java b/src/com/android/settings/applications/manageapplications/MusicViewHolderController.java
index 1e44047..2a2ac3b 100644
--- a/src/com/android/settings/applications/manageapplications/MusicViewHolderController.java
+++ b/src/com/android/settings/applications/manageapplications/MusicViewHolderController.java
@@ -72,11 +72,11 @@
}
@Override
- public void setupView(AppViewHolder holder) {
- holder.appIcon.setImageDrawable(
+ public void setupView(ApplicationViewHolder holder) {
+ holder.setIcon(
new InsetDrawable(mContext.getDrawable(R.drawable.ic_headset_24dp), INSET_SIZE));
- holder.appName.setText(mContext.getText(R.string.audio_files_title));
- holder.summary.setText(Formatter.formatFileSize(mContext, mMusicSize));
+ holder.setTitle(mContext.getText(R.string.audio_files_title));
+ holder.setSummary(Formatter.formatFileSize(mContext, mMusicSize));
}
@Override
diff --git a/src/com/android/settings/applications/manageapplications/PhotosViewHolderController.java b/src/com/android/settings/applications/manageapplications/PhotosViewHolderController.java
index 2d77f26..fafa875 100644
--- a/src/com/android/settings/applications/manageapplications/PhotosViewHolderController.java
+++ b/src/com/android/settings/applications/manageapplications/PhotosViewHolderController.java
@@ -71,11 +71,11 @@
}
@Override
- public void setupView(AppViewHolder holder) {
- holder.appIcon.setImageDrawable(
+ public void setupView(ApplicationViewHolder holder) {
+ holder.setIcon(
new InsetDrawable(mContext.getDrawable(R.drawable.ic_photo_library), INSET_SIZE));
- holder.appName.setText(mContext.getText(R.string.storage_detail_images));
- holder.summary.setText(Formatter.formatFileSize(mContext, mFilesSize));
+ holder.setTitle(mContext.getText(R.string.storage_detail_images));
+ holder.setSummary(Formatter.formatFileSize(mContext, mFilesSize));
}
@Override
diff --git a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
index 0485e69..9d47c65 100644
--- a/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
+++ b/src/com/android/settings/bluetooth/DeviceListPreferenceFragment.java
@@ -53,7 +53,7 @@
private static final String KEY_BT_SCAN = "bt_scan";
- // Copied from DevelopmentSettings.java
+ // Copied from BluetoothDeviceNoNamePreferenceController.java
private static final String BLUETOOTH_SHOW_DEVICES_WITHOUT_NAMES_PROPERTY =
"persist.bluetooth.showdeviceswithoutnames";
diff --git a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
index 17e556e..0744862 100644
--- a/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
+++ b/src/com/android/settings/dashboard/DashboardFragmentRegistry.java
@@ -85,11 +85,11 @@
SystemDashboardFragment.class.getName(), CategoryKey.CATEGORY_SYSTEM);
PARENT_TO_CATEGORY_KEY_MAP.put(LanguageAndInputSettings.class.getName(),
CategoryKey.CATEGORY_SYSTEM_LANGUAGE);
- if (Settings.DevelopmentSettingsDashboardActivity.isEnabled()) {
- PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettingsDashboardFragment.class.getName(),
+ if (Settings.DevelopmentSettingsActivity.isEnabled()) {
+ PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
} else {
- PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettings.class.getName(),
+ PARENT_TO_CATEGORY_KEY_MAP.put(DevelopmentSettingsDashboardFragment.class.getName(),
CategoryKey.CATEGORY_SYSTEM_DEVELOPMENT);
}
PARENT_TO_CATEGORY_KEY_MAP.put(ConfigureNotificationSettings.class.getName(),
diff --git a/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceController.java b/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceController.java
index bb03df1..e4e6493 100644
--- a/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceController.java
+++ b/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceController.java
@@ -40,17 +40,15 @@
static final int STREAMING_LABEL_ID = R.string.bluetooth_select_a2dp_codec_streaming_label;
protected final BluetoothA2dpConfigStore mBluetoothA2dpConfigStore;
- protected final Object mBluetoothA2dpLock;
protected BluetoothA2dp mBluetoothA2dp;
+ protected ListPreference mPreference;
private final String[] mListValues;
private final String[] mListSummaries;
- private ListPreference mPreference;
public AbstractBluetoothA2dpPreferenceController(Context context, Lifecycle lifecycle,
- Object bluetoothA2dpLock, BluetoothA2dpConfigStore store) {
+ BluetoothA2dpConfigStore store) {
super(context);
- mBluetoothA2dpLock = bluetoothA2dpLock;
mBluetoothA2dpConfigStore = store;
mListValues = getListValues();
mListSummaries = getListSummaries();
@@ -80,7 +78,7 @@
writeConfigurationValues(newValue);
final BluetoothCodecConfig codecConfig = mBluetoothA2dpConfigStore.createCodecConfig();
- synchronized (mBluetoothA2dpLock) {
+ synchronized (mBluetoothA2dpConfigStore) {
if (mBluetoothA2dp != null) {
setCodecConfigPreference(codecConfig);
}
@@ -106,7 +104,7 @@
}
BluetoothCodecConfig codecConfig;
- synchronized (mBluetoothA2dpLock) {
+ synchronized (mBluetoothA2dpConfigStore) {
codecConfig = getCodecConfig();
}
@@ -168,7 +166,7 @@
protected abstract String[] getListSummaries();
/**
- * Updates the new value to the {@link BluetoothA2dpConfigStore}.
+ * Updates the new value to the {@link BluetoothA2dpConfigStore} and the {@link BluetoothA2dp}.
*
* @param newValue the new setting value
*/
@@ -197,18 +195,4 @@
return mBluetoothA2dp.getCodecStatus().getCodecConfig();
}
-
- @VisibleForTesting
- BluetoothCodecConfig createCodecConfig(int codecTypeValue, int codecPriorityValue,
- int sampleRateValue, int bitsPerSampleValue,
- int channelModeValue, long codecSpecific1Value,
- long codecSpecific2Value, long codecSpecific3Value,
- long codecSpecific4Value) {
- return new BluetoothCodecConfig(codecTypeValue, codecPriorityValue,
- sampleRateValue, bitsPerSampleValue,
- channelModeValue, codecSpecific1Value,
- codecSpecific2Value, codecSpecific3Value,
- codecSpecific4Value);
- }
-
}
diff --git a/src/com/android/settings/development/AppPicker.java b/src/com/android/settings/development/AppPicker.java
index d038b8f..433f31a 100644
--- a/src/com/android/settings/development/AppPicker.java
+++ b/src/com/android/settings/development/AppPicker.java
@@ -32,7 +32,6 @@
import android.widget.ListView;
import com.android.settings.R;
-import com.android.settings.applications.manageapplications.AppViewHolder;
import java.text.Collator;
import java.util.ArrayList;
diff --git a/src/com/android/settings/applications/manageapplications/AppViewHolder.java b/src/com/android/settings/development/AppViewHolder.java
similarity index 71%
rename from src/com/android/settings/applications/manageapplications/AppViewHolder.java
rename to src/com/android/settings/development/AppViewHolder.java
index 7b9d766..7a90bcf 100644
--- a/src/com/android/settings/applications/manageapplications/AppViewHolder.java
+++ b/src/com/android/settings/development/AppViewHolder.java
@@ -14,9 +14,8 @@
* limitations under the License.
*/
-package com.android.settings.applications.manageapplications;
+package com.android.settings.development;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -57,24 +56,4 @@
return (AppViewHolder)convertView.getTag();
}
}
-
- void updateSizeText(CharSequence invalidSizeStr, int whichSize) {
- if (ManageApplications.DEBUG) Log.i(ManageApplications.TAG, "updateSizeText of "
- + entry.label + " " + entry + ": " + entry.sizeStr);
- if (entry.sizeStr != null) {
- switch (whichSize) {
- case ManageApplications.SIZE_INTERNAL:
- summary.setText(entry.internalSizeStr);
- break;
- case ManageApplications.SIZE_EXTERNAL:
- summary.setText(entry.externalSizeStr);
- break;
- default:
- summary.setText(entry.sizeStr);
- break;
- }
- } else if (entry.size == ApplicationsState.SIZE_INVALID) {
- summary.setText(invalidSizeStr);
- }
- }
}
\ No newline at end of file
diff --git a/src/com/android/settings/development/BluetoothA2dpLock.java b/src/com/android/settings/development/BluetoothA2dpLock.java
new file mode 100644
index 0000000..7058665
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothA2dpLock.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.bluetooth.BluetoothA2dp;
+
+/**
+ * Utility class to provide synchronization locks for {@link BluetoothA2dp}
+ */
+public class BluetoothA2dpLock {
+}
diff --git a/src/com/android/settings/development/BluetoothAudioBitsPerSamplePreferenceController.java b/src/com/android/settings/development/BluetoothAudioBitsPerSamplePreferenceController.java
new file mode 100644
index 0000000..f237ac1
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothAudioBitsPerSamplePreferenceController.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class BluetoothAudioBitsPerSamplePreferenceController extends
+ AbstractBluetoothA2dpPreferenceController {
+
+ private static final int DEFAULT_INDEX = 0;
+ private static final String BLUETOOTH_SELECT_A2DP_BITS_PER_SAMPLE_KEY =
+ "bluetooth_select_a2dp_bits_per_sample";
+
+ public BluetoothAudioBitsPerSamplePreferenceController(Context context, Lifecycle lifecycle,
+ BluetoothA2dpConfigStore store) {
+ super(context, lifecycle, store);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return BLUETOOTH_SELECT_A2DP_BITS_PER_SAMPLE_KEY;
+ }
+
+ @Override
+ protected String[] getListValues() {
+ return mContext.getResources().getStringArray(
+ R.array.bluetooth_a2dp_codec_bits_per_sample_values);
+ }
+
+ @Override
+ protected String[] getListSummaries() {
+ return mContext.getResources().getStringArray(
+ R.array.bluetooth_a2dp_codec_bits_per_sample_summaries);
+ }
+
+ @Override
+ protected int getDefaultIndex() {
+ return DEFAULT_INDEX;
+ }
+
+ @Override
+ protected void writeConfigurationValues(Object newValue) {
+ final int index = mPreference.findIndexOfValue(newValue.toString());
+ int bitsPerSampleValue = BluetoothCodecConfig.BITS_PER_SAMPLE_NONE; // default
+ switch (index) {
+ case 0:
+ // Reset to default
+ break;
+ case 1:
+ bitsPerSampleValue = BluetoothCodecConfig.BITS_PER_SAMPLE_16;
+ break;
+ case 2:
+ bitsPerSampleValue = BluetoothCodecConfig.BITS_PER_SAMPLE_24;
+ break;
+ case 3:
+ bitsPerSampleValue = BluetoothCodecConfig.BITS_PER_SAMPLE_32;
+ break;
+ default:
+ break;
+ }
+ mBluetoothA2dpConfigStore.setBitsPerSample(bitsPerSampleValue);
+ }
+
+ @Override
+ protected int getCurrentA2dpSettingIndex(BluetoothCodecConfig config) {
+ final int bitsPerSample = config.getBitsPerSample();
+ int index = DEFAULT_INDEX;
+ switch (bitsPerSample) {
+ case BluetoothCodecConfig.BITS_PER_SAMPLE_16:
+ index = 1;
+ break;
+ case BluetoothCodecConfig.BITS_PER_SAMPLE_24:
+ index = 2;
+ break;
+ case BluetoothCodecConfig.BITS_PER_SAMPLE_32:
+ index = 3;
+ break;
+ case BluetoothCodecConfig.BITS_PER_SAMPLE_NONE:
+ default:
+ break;
+ }
+ return index;
+ }
+}
diff --git a/src/com/android/settings/development/BluetoothAudioChannelModePreferenceController.java b/src/com/android/settings/development/BluetoothAudioChannelModePreferenceController.java
new file mode 100644
index 0000000..a58c675
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothAudioChannelModePreferenceController.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class BluetoothAudioChannelModePreferenceController extends
+ AbstractBluetoothA2dpPreferenceController {
+
+ private static final int DEFAULT_INDEX = 0;
+ private static final String BLUETOOTH_SELECT_A2DP_CHANNEL_MODE_KEY =
+ "bluetooth_select_a2dp_channel_mode";
+
+ public BluetoothAudioChannelModePreferenceController(Context context, Lifecycle lifecycle,
+ BluetoothA2dpConfigStore store) {
+ super(context, lifecycle, store);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return BLUETOOTH_SELECT_A2DP_CHANNEL_MODE_KEY;
+ }
+
+ @Override
+ protected String[] getListValues() {
+ return mContext.getResources().getStringArray(
+ R.array.bluetooth_a2dp_codec_channel_mode_values);
+ }
+
+ @Override
+ protected String[] getListSummaries() {
+ return mContext.getResources().getStringArray(
+ R.array.bluetooth_a2dp_codec_channel_mode_summaries);
+ }
+
+ @Override
+ protected int getDefaultIndex() {
+ return DEFAULT_INDEX;
+ }
+
+ @Override
+ protected void writeConfigurationValues(Object newValue) {
+ final int index = mPreference.findIndexOfValue(newValue.toString());
+ int channelModeValue = BluetoothCodecConfig.CHANNEL_MODE_NONE; // default
+ switch (index) {
+ case 0:
+ // Reset to default
+ break;
+ case 1:
+ channelModeValue = BluetoothCodecConfig.CHANNEL_MODE_MONO;
+ break;
+ case 2:
+ channelModeValue = BluetoothCodecConfig.CHANNEL_MODE_STEREO;
+ break;
+ default:
+ break;
+ }
+ mBluetoothA2dpConfigStore.setChannelMode(channelModeValue);
+ }
+
+ @Override
+ protected int getCurrentA2dpSettingIndex(BluetoothCodecConfig config) {
+ final int channelMode = config.getChannelMode();
+ int index = DEFAULT_INDEX;
+ switch (channelMode) {
+ case BluetoothCodecConfig.CHANNEL_MODE_MONO:
+ index = 1;
+ break;
+ case BluetoothCodecConfig.CHANNEL_MODE_STEREO:
+ index = 2;
+ break;
+ case BluetoothCodecConfig.CHANNEL_MODE_NONE:
+ default:
+ break;
+ }
+ return index;
+ }
+}
diff --git a/src/com/android/settings/development/BluetoothAudioCodecPreferenceController.java b/src/com/android/settings/development/BluetoothAudioCodecPreferenceController.java
new file mode 100644
index 0000000..2163a70
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothAudioCodecPreferenceController.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class BluetoothAudioCodecPreferenceController extends
+ AbstractBluetoothA2dpPreferenceController {
+
+ private static final int DEFAULT_INDEX = 0;
+ private static final String BLUETOOTH_SELECT_A2DP_CODEC_KEY = "bluetooth_select_a2dp_codec";
+
+ public BluetoothAudioCodecPreferenceController(Context context, Lifecycle lifecycle,
+ BluetoothA2dpConfigStore store) {
+ super(context, lifecycle, store);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return BLUETOOTH_SELECT_A2DP_CODEC_KEY;
+ }
+
+ @Override
+ protected String[] getListValues() {
+ return mContext.getResources().getStringArray(
+ R.array.bluetooth_a2dp_codec_values);
+ }
+
+ @Override
+ protected String[] getListSummaries() {
+ return mContext.getResources().getStringArray(
+ R.array.bluetooth_a2dp_codec_summaries);
+ }
+
+ @Override
+ protected int getDefaultIndex() {
+ return DEFAULT_INDEX;
+ }
+
+ @Override
+ protected void writeConfigurationValues(Object newValue) {
+ final int index = mPreference.findIndexOfValue(newValue.toString());
+ int codecTypeValue = BluetoothCodecConfig.SAMPLE_RATE_NONE; // default
+ int codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT;
+ switch (index) {
+ case 0:
+ // Reset the priority of the current codec to default
+ final String oldValue = mPreference.getValue();
+ switch (mPreference.findIndexOfValue(oldValue)) {
+ case 0:
+ break; // No current codec
+ case 1:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC;
+ break;
+ case 2:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC;
+ break;
+ case 3:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX;
+ break;
+ case 4:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD;
+ break;
+ case 5:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 1:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC;
+ codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
+ break;
+ case 2:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC;
+ codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
+ break;
+ case 3:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX;
+ codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
+ break;
+ case 4:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD;
+ codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
+ break;
+ case 5:
+ codecTypeValue = BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC;
+ codecPriorityValue = BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST;
+ break;
+ case 6:
+ synchronized (mBluetoothA2dpConfigStore) {
+ if (mBluetoothA2dp != null) {
+ mBluetoothA2dp.enableOptionalCodecs();
+ }
+ }
+ return;
+ case 7:
+ synchronized (mBluetoothA2dpConfigStore) {
+ if (mBluetoothA2dp != null) {
+ mBluetoothA2dp.disableOptionalCodecs();
+ }
+ }
+ return;
+ default:
+ break;
+ }
+ mBluetoothA2dpConfigStore.setCodecType(codecTypeValue);
+ mBluetoothA2dpConfigStore.setCodecPriority(codecPriorityValue);
+ }
+
+ @Override
+ protected int getCurrentA2dpSettingIndex(BluetoothCodecConfig config) {
+ final int codecType = config.getCodecType();
+ int index = DEFAULT_INDEX;
+ switch (codecType) {
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_SBC:
+ index = 1;
+ break;
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC:
+ index = 2;
+ break;
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX:
+ index = 3;
+ break;
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_APTX_HD:
+ index = 4;
+ break;
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_LDAC:
+ index = 5;
+ break;
+ case BluetoothCodecConfig.SOURCE_CODEC_TYPE_INVALID:
+ default:
+ break;
+ }
+ return index;
+ }
+}
diff --git a/src/com/android/settings/development/BluetoothAudioQualityPreferenceController.java b/src/com/android/settings/development/BluetoothAudioQualityPreferenceController.java
new file mode 100644
index 0000000..7adf8e6
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothAudioQualityPreferenceController.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+public class BluetoothAudioQualityPreferenceController extends
+ AbstractBluetoothA2dpPreferenceController {
+
+ private static final int DEFAULT_INDEX = 3;
+ private static final String BLUETOOTH_SELECT_A2DP_LDAC_PLAYBACK_QUALITY_KEY =
+ "bluetooth_select_a2dp_ldac_playback_quality";
+
+ public BluetoothAudioQualityPreferenceController(Context context, Lifecycle lifecycle,
+ BluetoothA2dpConfigStore store) {
+ super(context, lifecycle, store);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return BLUETOOTH_SELECT_A2DP_LDAC_PLAYBACK_QUALITY_KEY;
+ }
+
+ @Override
+ protected String[] getListValues() {
+ return mContext.getResources().getStringArray(
+ R.array.bluetooth_a2dp_codec_ldac_playback_quality_values);
+ }
+
+ @Override
+ protected String[] getListSummaries() {
+ return mContext.getResources().getStringArray(
+ R.array.bluetooth_a2dp_codec_ldac_playback_quality_summaries);
+ }
+
+ @Override
+ protected int getDefaultIndex() {
+ return DEFAULT_INDEX;
+ }
+
+ @Override
+ protected void writeConfigurationValues(Object newValue) {
+ final int index = mPreference.findIndexOfValue(newValue.toString());
+ int codecSpecific1Value = 0; // default
+ switch (index) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ codecSpecific1Value = 1000 + index;
+ break;
+ default:
+ break;
+ }
+ mBluetoothA2dpConfigStore.setCodecSpecific1Value(codecSpecific1Value);
+ }
+
+ @Override
+ protected int getCurrentA2dpSettingIndex(BluetoothCodecConfig config) {
+ // The actual values are 0, 1, 2 - those are extracted
+ // as mod-10 remainders of a larger value.
+ // The reason is because within BluetoothCodecConfig we cannot use
+ // a codec-specific value of zero.
+ int index = (int) config.getCodecSpecific1();
+ if (index > 0) {
+ index %= 10;
+ } else {
+ index = DEFAULT_INDEX;
+ }
+ switch (index) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ break;
+ default:
+ index = DEFAULT_INDEX;
+ break;
+ }
+ return index;
+ }
+}
diff --git a/src/com/android/settings/development/BluetoothAudioSampleRatePreferenceController.java b/src/com/android/settings/development/BluetoothAudioSampleRatePreferenceController.java
index 5d84de8..35b449e 100644
--- a/src/com/android/settings/development/BluetoothAudioSampleRatePreferenceController.java
+++ b/src/com/android/settings/development/BluetoothAudioSampleRatePreferenceController.java
@@ -18,8 +18,6 @@
import android.bluetooth.BluetoothCodecConfig;
import android.content.Context;
-import android.support.v7.preference.ListPreference;
-import android.support.v7.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -31,11 +29,9 @@
private static final String BLUETOOTH_SELECT_A2DP_SAMPLE_RATE_KEY =
"bluetooth_select_a2dp_sample_rate";
- private ListPreference mPreference;
-
public BluetoothAudioSampleRatePreferenceController(Context context, Lifecycle lifecycle,
- Object bluetoothA2dpLock, BluetoothA2dpConfigStore store) {
- super(context, lifecycle, bluetoothA2dpLock, store);
+ BluetoothA2dpConfigStore store) {
+ super(context, lifecycle, store);
}
@Override
@@ -44,13 +40,6 @@
}
@Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
-
- mPreference = (ListPreference) screen.findPreference(getPreferenceKey());
- }
-
- @Override
protected String[] getListValues() {
return mContext.getResources().getStringArray(
R.array.bluetooth_a2dp_codec_sample_rate_values);
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index e425fd2..c80416b 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -60,7 +60,8 @@
private static final String TAG = "DevSettingsDashboard";
- private final Object mBluetoothA2dpLock = new Object();
+ private final BluetoothA2dpConfigStore mBluetoothA2dpConfigStore =
+ new BluetoothA2dpConfigStore();
private boolean mIsAvailable = true;
private SwitchBar mSwitchBar;
@@ -104,7 +105,7 @@
@Override
public void onServiceConnected(int profile,
BluetoothProfile proxy) {
- synchronized (mBluetoothA2dpLock) {
+ synchronized (mBluetoothA2dpConfigStore) {
mBluetoothA2dp = (BluetoothA2dp) proxy;
}
for (AbstractPreferenceController controller : mPreferenceControllers) {
@@ -117,7 +118,7 @@
@Override
public void onServiceDisconnected(int profile) {
- synchronized (mBluetoothA2dpLock) {
+ synchronized (mBluetoothA2dpConfigStore) {
mBluetoothA2dp = null;
}
for (AbstractPreferenceController controller : mPreferenceControllers) {
@@ -295,7 +296,7 @@
@Override
protected List<AbstractPreferenceController> getPreferenceControllers(Context context) {
mPreferenceControllers = buildPreferenceControllers(context, getActivity(), getLifecycle(),
- this /* devOptionsDashboardFragment */, mBluetoothA2dpLock,
+ this /* devOptionsDashboardFragment */,
new BluetoothA2dpConfigStore());
return mPreferenceControllers;
}
@@ -349,7 +350,7 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Activity activity, Lifecycle lifecycle, DevelopmentSettingsDashboardFragment fragment,
- Object bluetoothA2dpLock, BluetoothA2dpConfigStore bluetoothA2dpConfigStore) {
+ BluetoothA2dpConfigStore bluetoothA2dpConfigStore) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
controllers.add(new BugReportPreferenceControllerV2(context));
controllers.add(new LocalBackupPasswordPreferenceController(context));
@@ -391,13 +392,16 @@
controllers.add(new BluetoothAbsoluteVolumePreferenceController(context));
controllers.add(new BluetoothInbandRingingPreferenceController(context));
controllers.add(new BluetoothAvrcpVersionPreferenceController(context));
- //controllers.add(new BluetoothAudioCodecPreferenceController(context, lifecycle,
- // bluetoothA2dpLock, bluetoothA2dpConfigStore));
+ controllers.add(new BluetoothAudioCodecPreferenceController(context, lifecycle,
+ bluetoothA2dpConfigStore));
controllers.add(new BluetoothAudioSampleRatePreferenceController(context, lifecycle,
- bluetoothA2dpLock, bluetoothA2dpConfigStore));
- // bluetooth audio bits per sample
- // bluetooth audio channel mode
- // bluetooth audio ldac codec: playback quality
+ bluetoothA2dpConfigStore));
+ controllers.add(new BluetoothAudioBitsPerSamplePreferenceController(context, lifecycle,
+ bluetoothA2dpConfigStore));
+ controllers.add(new BluetoothAudioChannelModePreferenceController(context, lifecycle,
+ bluetoothA2dpConfigStore));
+ controllers.add(new BluetoothAudioQualityPreferenceController(context, lifecycle,
+ bluetoothA2dpConfigStore));
controllers.add(new ShowTapsPreferenceController(context));
controllers.add(new PointerLocationPreferenceController(context));
controllers.add(new ShowSurfaceUpdatesPreferenceController(context));
@@ -463,7 +467,7 @@
context) {
return buildPreferenceControllers(context, null /* activity */,
null /* lifecycle */, null /* devOptionsDashboardFragment */,
- null /* bluetoothA2dpLock */, null /* bluetoothA2dpConfigStore */);
+ null /* bluetoothA2dpConfigStore */);
}
};
}
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index ac318ff..2641f5d 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -35,7 +35,6 @@
import com.android.settings.Utils;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
-import com.android.settings.development.DevelopmentSettings;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settingslib.RestrictedLockUtils;
@@ -221,9 +220,5 @@
mDevHitToast = Toast.makeText(mContext, R.string.show_dev_on,
Toast.LENGTH_LONG);
mDevHitToast.show();
- // This is good time to index the Developer Options
- FeatureFactory.getFactory(mContext).getSearchFeatureProvider().getIndexingManager(mContext)
- .updateFromClassNameResource(DevelopmentSettings.class.getName(),
- true /* includeInSearchResults */);
}
}
diff --git a/src/com/android/settings/display/AppGridView.java b/src/com/android/settings/display/AppGridView.java
index 2d52ef2..148ba83 100644
--- a/src/com/android/settings/display/AppGridView.java
+++ b/src/com/android/settings/display/AppGridView.java
@@ -16,8 +16,6 @@
package com.android.settings.display;
-import com.android.settings.R;
-
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -30,6 +28,8 @@
import android.widget.GridView;
import android.widget.ImageView;
+import com.android.settings.R;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java
index 9608aea..1774615 100644
--- a/src/com/android/settings/search/SearchIndexableResources.java
+++ b/src/com/android/settings/search/SearchIndexableResources.java
@@ -21,6 +21,7 @@
import android.support.annotation.VisibleForTesting;
import android.support.annotation.XmlRes;
import android.text.TextUtils;
+
import com.android.settings.DateTimeSettings;
import com.android.settings.DeviceInfoSettings;
import com.android.settings.DisplaySettings;
@@ -45,7 +46,7 @@
import com.android.settings.datausage.DataUsageMeteredSettings;
import com.android.settings.datausage.DataUsageSummary;
import com.android.settings.deletionhelper.AutomaticStorageManagerSettings;
-import com.android.settings.development.DevelopmentSettings;
+import com.android.settings.development.DevelopmentSettingsDashboardFragment;
import com.android.settings.deviceinfo.Status;
import com.android.settings.deviceinfo.StorageDashboardFragment;
import com.android.settings.deviceinfo.StorageSettings;
@@ -90,6 +91,7 @@
import com.android.settings.wifi.ConfigureWifiSettings;
import com.android.settings.wifi.SavedAccessPointsWifiSettings;
import com.android.settings.wifi.WifiSettings;
+
import java.util.Collection;
import java.util.HashMap;
@@ -189,7 +191,8 @@
addIndex(DateTimeSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_date_time);
addIndex(AccessibilitySettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_accessibility);
addIndex(PrintSettingsFragment.class, NO_DATA_RES_ID, R.drawable.ic_settings_print);
- addIndex(DevelopmentSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_development);
+ addIndex(DevelopmentSettingsDashboardFragment.class, NO_DATA_RES_ID,
+ R.drawable.ic_settings_development);
addIndex(DeviceInfoSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_about);
addIndex(Status.class, NO_DATA_RES_ID, 0 /* icon */);
addIndex(LegalSettings.class, NO_DATA_RES_ID, R.drawable.ic_settings_about);
diff --git a/src/com/android/settings/WorkOnlyCategory.java b/src/com/android/settings/widget/WorkOnlyCategory.java
similarity index 90%
rename from src/com/android/settings/WorkOnlyCategory.java
rename to src/com/android/settings/widget/WorkOnlyCategory.java
index ca4c82d..53badb2 100644
--- a/src/com/android/settings/WorkOnlyCategory.java
+++ b/src/com/android/settings/widget/WorkOnlyCategory.java
@@ -12,13 +12,16 @@
* permissions and limitations under the License.
*/
-package com.android.settings;
+package com.android.settings.widget;
import android.content.Context;
import android.os.UserManager;
import android.support.v7.preference.PreferenceCategory;
import android.util.AttributeSet;
+import com.android.settings.SelfAvailablePreference;
+import com.android.settings.Utils;
+
/**
* A PreferenceCategory that is only visible when the device has a work profile.
*/
diff --git a/src/com/android/settings/widget/WorkOnlyCategoryPreferenceController.java b/src/com/android/settings/widget/WorkOnlyCategoryPreferenceController.java
new file mode 100644
index 0000000..a308b2f
--- /dev/null
+++ b/src/com/android/settings/widget/WorkOnlyCategoryPreferenceController.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import android.content.Context;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import java.util.List;
+
+public class WorkOnlyCategoryPreferenceController extends AbstractPreferenceController
+ implements PreferenceControllerMixin {
+
+ private final String mKey;
+ private final List<AbstractPreferenceController> mChildren;
+
+ public WorkOnlyCategoryPreferenceController(Context context,
+ String key, List<AbstractPreferenceController> childrenControllers) {
+ super(context);
+ mKey = key;
+ mChildren = childrenControllers;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (mChildren == null || mChildren.isEmpty()) {
+ return true;
+ }
+ // Category is available if any child is available
+ for (AbstractPreferenceController controller : mChildren) {
+ if (controller.isAvailable()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return mKey;
+ }
+}
diff --git a/tests/robotests/assets/grandfather_not_in_search_index_provider_registry b/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
index 4ee97fa..85e99c3 100644
--- a/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
+++ b/tests/robotests/assets/grandfather_not_in_search_index_provider_registry
@@ -1,3 +1,3 @@
-com.android.settings.development.DevelopmentSettingsDashboardFragment
+com.android.settings.development.DevelopmentSettings
com.android.settings.display.ScreenZoomPreferenceFragmentForSetupWizard
com.android.settings.search.indexing.FakeSettingsFragment
diff --git a/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java b/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
index c6350ef..ee7bdb0 100644
--- a/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
+++ b/tests/robotests/src/android/bluetooth/BluetoothCodecConfig.java
@@ -24,11 +24,31 @@
public static final int SAMPLE_RATE_NONE = 0;
public static final int SAMPLE_RATE_48000 = 0x1 << 1;
public static final int SOURCE_CODEC_TYPE_INVALID = 1000 * 1000;
+ public static final int SOURCE_CODEC_TYPE_AAC = 1;
public static final int CODEC_PRIORITY_DEFAULT = 0;
+ public static final int CODEC_PRIORITY_HIGHEST = 1000 * 1000;
public static final int BITS_PER_SAMPLE_NONE = 0;
public static final int CHANNEL_MODE_NONE = 0;
+ public static final int BITS_PER_SAMPLE_24 = 0x1 << 1;
+ public static final int CHANNEL_MODE_STEREO = 0x1 << 1;
public int getSampleRate() {
return 0;
}
+
+ public int getCodecType() {
+ return 0;
+ }
+
+ public int getBitsPerSample() {
+ return 0;
+ }
+
+ public int getChannelMode() {
+ return 0;
+ }
+
+ public long getCodecSpecific1() {
+ return 0;
+ }
}
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java
new file mode 100644
index 0000000..cf2403b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ApplicationViewHolderTest.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.applications.manageapplications;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.settings.R;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.applications.ApplicationsState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class ApplicationViewHolderTest {
+
+ private Context mContext;
+ private View mView;
+ private ApplicationViewHolder mHolder;
+
+ @Before
+ public void seUp() {
+ mContext = RuntimeEnvironment.application;
+ mView = ApplicationViewHolder.newView(LayoutInflater.from(mContext),
+ new FrameLayout(mContext));
+ mHolder = new ApplicationViewHolder(mView);
+ }
+
+ @Test
+ public void updateDisableView_appDisabledUntilUsed_shouldSetDisabled() {
+ final ApplicationInfo info = new ApplicationInfo();
+ info.flags = ApplicationInfo.FLAG_INSTALLED;
+ info.enabled = true;
+ info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
+ mHolder.updateDisableView(info);
+
+ assertThat(mHolder.mDisabled.getText()).isEqualTo(mContext.getText(R.string.disabled));
+ }
+
+ @Test
+ public void setSummaries() {
+ mHolder.setSummary("hello");
+ assertThat(mHolder.mSummary.getText()).isEqualTo("hello");
+
+ mHolder.setSummary(R.string.disabled);
+ assertThat(mHolder.mSummary.getText()).isEqualTo(mContext.getText(R.string.disabled));
+ }
+
+ @Test
+ public void updateSize() {
+ final String invalidStr = "invalid";
+ final ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
+ entry.internalSizeStr = "internal";
+ entry.externalSizeStr = "external";
+ entry.sizeStr = entry.internalSizeStr;
+
+ mHolder.updateSizeText(entry, invalidStr, ManageApplications.SIZE_INTERNAL);
+ assertThat(mHolder.mSummary.getText()).isEqualTo(entry.internalSizeStr);
+
+ mHolder.updateSizeText(entry, invalidStr, ManageApplications.SIZE_EXTERNAL);
+ assertThat(mHolder.mSummary.getText()).isEqualTo(entry.externalSizeStr);
+
+ entry.sizeStr = null;
+ entry.size = ApplicationsState.SIZE_INVALID;
+ mHolder.updateSizeText(entry, invalidStr, ManageApplications.SIZE_EXTERNAL);
+ assertThat(mHolder.mSummary.getText()).isEqualTo(invalidStr);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
index 9afaf1f..9eb36ef 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/ManageApplicationsTest.java
@@ -31,19 +31,16 @@
import android.app.Activity;
import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Handler;
+import android.os.Bundle;
import android.os.Looper;
+import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
import com.android.settings.R;
-import com.android.settings.Settings;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settings.testutils.shadow.SettingsShadowResources;
@@ -103,30 +100,6 @@
}
@Test
- public void launchFragment() {
- SettingsRobolectricTestRunner.startSettingsFragment(
- mFragment, Settings.ManageApplicationsActivity.class);
- }
-
- @Test
- public void updateDisableView_appDisabledUntilUsed_shouldSetDisabled() {
- final TextView view = mock(TextView.class);
- final ApplicationInfo info = new ApplicationInfo();
- info.flags = ApplicationInfo.FLAG_INSTALLED;
- info.enabled = true;
- info.enabledSetting = PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
- ManageApplications fragment = mock(ManageApplications.class);
- when(fragment.getActivity()).thenReturn(mock(Activity.class));
- final ManageApplications.ApplicationsAdapter adapter =
- new ManageApplications.ApplicationsAdapter(mState, fragment,
- AppFilterRegistry.getInstance().get(FILTER_APPS_ALL));
-
- adapter.updateDisableView(view, info);
-
- verify(view).setText(R.string.disabled);
- }
-
- @Test
public void updateMenu_mainListType_showAppReset() {
setUpOptionMenus();
ReflectionHelpers.setField(mFragment, "mListType", ManageApplications.LIST_TYPE_MAIN);
@@ -170,14 +143,12 @@
ReflectionHelpers.setField(fragment, "mLoadingContainer", mock(View.class));
ReflectionHelpers.setField(fragment, "mListContainer", mock(View.class));
when(fragment.getActivity()).thenReturn(mock(Activity.class));
- final Handler handler = mock(Handler.class);
final ManageApplications.ApplicationsAdapter adapter =
- spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
- AppFilterRegistry.getInstance().get(FILTER_APPS_ALL)));
+ spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
+ AppFilterRegistry.getInstance().get(FILTER_APPS_ALL), new Bundle()));
final LoadingViewController loadingViewController =
mock(LoadingViewController.class);
ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
- ReflectionHelpers.setField(adapter, "mFgHandler", handler);
// app loading completed
ReflectionHelpers.setField(adapter, "mHasReceivedLoadEntries", true);
@@ -196,15 +167,12 @@
ReflectionHelpers.setField(fragment, "mLoadingContainer", mock(View.class));
ReflectionHelpers.setField(fragment, "mListContainer", mock(View.class));
when(fragment.getActivity()).thenReturn(mock(Activity.class));
-
- final Handler handler = mock(Handler.class);
final ManageApplications.ApplicationsAdapter adapter =
- spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
- AppFilterRegistry.getInstance().get(FILTER_APPS_ALL)));
+ spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
+ AppFilterRegistry.getInstance().get(FILTER_APPS_ALL), new Bundle()));
final LoadingViewController loadingViewController =
mock(LoadingViewController.class);
ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
- ReflectionHelpers.setField(adapter, "mFgHandler", handler);
// app loading not yet completed
ReflectionHelpers.setField(adapter, "mHasReceivedLoadEntries", false);
@@ -218,6 +186,10 @@
public void onRebuildComplete_shouldHideLoadingView() {
final Context context = RuntimeEnvironment.application;
final ManageApplications fragment = mock(ManageApplications.class);
+ final RecyclerView recyclerView = mock(RecyclerView.class);
+ final View emptyView = mock(View.class);
+ ReflectionHelpers.setField(fragment, "mRecyclerView", recyclerView);
+ ReflectionHelpers.setField(fragment, "mEmptyView", emptyView);
final View loadingContainer = mock(View.class);
when(loadingContainer.getContext()).thenReturn(context);
final View listContainer = mock(View.class);
@@ -226,14 +198,12 @@
ReflectionHelpers.setField(fragment, "mLoadingContainer", loadingContainer);
ReflectionHelpers.setField(fragment, "mListContainer", listContainer);
when(fragment.getActivity()).thenReturn(mock(Activity.class));
- final Handler handler = mock(Handler.class);
final ManageApplications.ApplicationsAdapter adapter =
- spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
- AppFilterRegistry.getInstance().get(FILTER_APPS_ALL)));
+ spy(new ManageApplications.ApplicationsAdapter(mState, fragment,
+ AppFilterRegistry.getInstance().get(FILTER_APPS_ALL), new Bundle()));
final LoadingViewController loadingViewController =
mock(LoadingViewController.class);
ReflectionHelpers.setField(adapter, "mLoadingViewController", loadingViewController);
- ReflectionHelpers.setField(adapter, "mFgHandler", handler);
ReflectionHelpers.setField(adapter, "mAppFilter",
AppFilterRegistry.getInstance().get(FILTER_APPS_ALL));
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/MusicViewHolderControllerTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/MusicViewHolderControllerTest.java
index 46a059a..28ac9d9 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/MusicViewHolderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/MusicViewHolderControllerTest.java
@@ -28,11 +28,12 @@
import android.os.storage.VolumeInfo;
import android.provider.DocumentsContract;
import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.applications.StorageStatsSource;
-import com.android.settingslib.deviceinfo.StorageVolumeProvider;
import org.junit.Before;
import org.junit.Test;
@@ -51,14 +52,13 @@
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Fragment mFragment;
@Mock
- private StorageVolumeProvider mSvp;
- @Mock
private StorageStatsSource mSource;
private Context mContext;
private MusicViewHolderController mController;
private VolumeInfo mVolume;
- private AppViewHolder mHolder;
+ private View mView;
+ private ApplicationViewHolder mHolder;
@Before
public void setUp() throws Exception {
@@ -69,25 +69,26 @@
new UserHandle(0));
LayoutInflater inflater = LayoutInflater.from(mContext);
- mHolder = AppViewHolder.createOrRecycle(inflater, null);
+ mView = ApplicationViewHolder.newView(inflater, new FrameLayout(mContext));
+ mHolder = new ApplicationViewHolder(mView);
}
@Test
public void storageShouldBeZeroBytesIfQueriedBeforeStorageQueryFinishes() {
mController.setupView(mHolder);
- assertThat(mHolder.summary.getText().toString()).isEqualTo("0.00 B");
+ assertThat(mHolder.mSummary.getText().toString()).isEqualTo("0.00 B");
}
@Test
public void storageShouldRepresentStorageStatsQuery() throws Exception {
- when(mSource.getExternalStorageStats(nullable(String.class), nullable(UserHandle.class))).thenReturn(
- new StorageStatsSource.ExternalStorageStats(1, 1, 0, 0, 0));
+ when(mSource.getExternalStorageStats(nullable(String.class), nullable(UserHandle.class)))
+ .thenReturn(new StorageStatsSource.ExternalStorageStats(1, 1, 0, 0, 0));
mController.queryStats();
mController.setupView(mHolder);
- assertThat(mHolder.summary.getText().toString()).isEqualTo("1.00 B");
+ assertThat(mHolder.mSummary.getText().toString()).isEqualTo("1.00 B");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/applications/manageapplications/PhotosViewHolderControllerTest.java b/tests/robotests/src/com/android/settings/applications/manageapplications/PhotosViewHolderControllerTest.java
index a051ac3..2a26e31 100644
--- a/tests/robotests/src/com/android/settings/applications/manageapplications/PhotosViewHolderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/manageapplications/PhotosViewHolderControllerTest.java
@@ -27,11 +27,12 @@
import android.os.UserHandle;
import android.os.storage.VolumeInfo;
import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.FrameLayout;
import com.android.settings.TestConfig;
import com.android.settings.testutils.SettingsRobolectricTestRunner;
import com.android.settingslib.applications.StorageStatsSource;
-import com.android.settingslib.deviceinfo.StorageVolumeProvider;
import org.junit.Before;
import org.junit.Test;
@@ -48,14 +49,14 @@
public class PhotosViewHolderControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Fragment mFragment;
-
- @Mock private StorageVolumeProvider mSvp;
@Mock private StorageStatsSource mSource;
private Context mContext;
private PhotosViewHolderController mController;
private VolumeInfo mVolume;
- private AppViewHolder mHolder;
+ private View mView;
+ private ApplicationViewHolder mHolder;
+
@Before
public void setUp() throws Exception {
@@ -66,15 +67,16 @@
new PhotosViewHolderController(
mContext, mSource, mVolume.fsUuid, new UserHandle(0));
- LayoutInflater inflater = LayoutInflater.from(mContext);
- mHolder = AppViewHolder.createOrRecycle(inflater, null);
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ mView = ApplicationViewHolder.newView(inflater, new FrameLayout(mContext));
+ mHolder = new ApplicationViewHolder(mView);
}
@Test
public void storageShouldBeZeroBytesIfQueriedBeforeStorageQueryFinishes() {
mController.setupView(mHolder);
- assertThat(mHolder.summary.getText().toString()).isEqualTo("0.00 B");
+ assertThat(mHolder.mSummary.getText().toString()).isEqualTo("0.00 B");
}
@Test
@@ -85,7 +87,7 @@
mController.queryStats();
mController.setupView(mHolder);
- assertThat(mHolder.summary.getText().toString()).isEqualTo("11.00 B");
+ assertThat(mHolder.mSummary.getText().toString()).isEqualTo("11.00 B");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceControllerTest.java
index e78dd7f..dd29627 100644
--- a/tests/robotests/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/AbstractBluetoothA2dpPreferenceControllerTest.java
@@ -74,7 +74,7 @@
mContext = RuntimeEnvironment.application;
mLifecycle = new Lifecycle();
mController = spy(new AbstractBluetoothA2dpPreferenceControllerImpl(mContext, mLifecycle,
- new Object(), mBluetoothA2dpConfigStore));
+ mBluetoothA2dpConfigStore));
doReturn(mBluetoothCodecConfig).when(mController).getCodecConfig();
doNothing().when(mController).setCodecConfigPreference(any());
when(mBluetoothA2dpConfigStore.createCodecConfig()).thenReturn(mBluetoothCodecConfig);
@@ -138,8 +138,8 @@
AbstractBluetoothA2dpPreferenceController {
public AbstractBluetoothA2dpPreferenceControllerImpl(Context context,
- Lifecycle lifecycle, Object bluetoothA2dpLock, BluetoothA2dpConfigStore store) {
- super(context, lifecycle, bluetoothA2dpLock, store);
+ Lifecycle lifecycle, BluetoothA2dpConfigStore store) {
+ super(context, lifecycle, store);
}
@Override
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothAudioBitsPerSamplePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothAudioBitsPerSamplePreferenceControllerTest.java
new file mode 100644
index 0000000..2438b21
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothAudioBitsPerSamplePreferenceControllerTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.content.Context;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BluetoothAudioBitsPerSamplePreferenceControllerTest {
+
+ @Mock
+ private BluetoothCodecConfig mBluetoothCodecConfig;
+ @Mock
+ private ListPreference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private BluetoothA2dpConfigStore mBluetoothA2dpConfigStore;
+
+ /**
+ * 0: Use System Selection (Default)
+ * 1: 16 bits/sample
+ * 2: 24 bits/sample
+ * 3: 32 bits/sample
+ */
+ private String[] mListValues;
+ private Context mContext;
+ private BluetoothAudioBitsPerSamplePreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new BluetoothAudioBitsPerSamplePreferenceController(mContext,
+ new Lifecycle(), mBluetoothA2dpConfigStore));
+ mListValues = mController.getListValues();
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void writeConfigurationValues_option2_shouldWriteOption2ToSharedStore() {
+ when(mPreference.findIndexOfValue(mListValues[2])).thenReturn(2);
+ mController.writeConfigurationValues(mListValues[2]);
+
+ verify(mBluetoothA2dpConfigStore).setBitsPerSample(BluetoothCodecConfig.BITS_PER_SAMPLE_24);
+ }
+
+ @Test
+ public void writeConfigurationValues_default_shouldSetDefault() {
+ when(mPreference.findIndexOfValue(mListValues[0])).thenReturn(0);
+ mController.writeConfigurationValues(mListValues[0]);
+
+ verify(mBluetoothA2dpConfigStore).setBitsPerSample(
+ BluetoothCodecConfig.BITS_PER_SAMPLE_NONE);
+ }
+
+ @Test
+ public void getCurrentA2dpSettingIndex_option2_shouldReturnSecondIndex() {
+ when(mBluetoothCodecConfig.getBitsPerSample()).thenReturn(
+ BluetoothCodecConfig.BITS_PER_SAMPLE_24);
+
+ final int index = mController.getCurrentA2dpSettingIndex(mBluetoothCodecConfig);
+
+ assertThat(index).isEqualTo(2);
+ }
+
+ @Test
+ public void getCurrentA2dpSettingIndex_unknownOption_shouldReturnDefault() {
+ when(mBluetoothCodecConfig.getCodecType()).thenReturn(1381391835);
+
+ final int index = mController.getCurrentA2dpSettingIndex(mBluetoothCodecConfig);
+
+ assertThat(index).isEqualTo(0);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothAudioChannelModePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothAudioChannelModePreferenceControllerTest.java
new file mode 100644
index 0000000..efcd240
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothAudioChannelModePreferenceControllerTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.content.Context;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BluetoothAudioChannelModePreferenceControllerTest {
+
+ @Mock
+ private BluetoothCodecConfig mBluetoothCodecConfig;
+ @Mock
+ private ListPreference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private BluetoothA2dpConfigStore mBluetoothA2dpConfigStore;
+
+ /**
+ * 0: Use System Selection (Default)
+ * 1: Mono
+ * 2: Stereo
+ */
+ private String[] mListValues;
+ private Context mContext;
+ private BluetoothAudioChannelModePreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new BluetoothAudioChannelModePreferenceController(mContext,
+ new Lifecycle(), mBluetoothA2dpConfigStore));
+ mListValues = mController.getListValues();
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void writeConfigurationValues_option2_shouldWriteOption2ToSharedStore() {
+ when(mPreference.findIndexOfValue(mListValues[2])).thenReturn(2);
+ mController.writeConfigurationValues(mListValues[2]);
+
+ verify(mBluetoothA2dpConfigStore).setChannelMode(BluetoothCodecConfig.CHANNEL_MODE_STEREO);
+ }
+
+ @Test
+ public void writeConfigurationValues_default_shouldSetDefault() {
+ when(mPreference.findIndexOfValue(mListValues[0])).thenReturn(0);
+ mController.writeConfigurationValues(mListValues[0]);
+
+ verify(mBluetoothA2dpConfigStore).setChannelMode(
+ BluetoothCodecConfig.CHANNEL_MODE_NONE);
+ }
+
+ @Test
+ public void getCurrentA2dpSettingIndex_option2_shouldReturnSecondIndex() {
+ when(mBluetoothCodecConfig.getChannelMode()).thenReturn(
+ BluetoothCodecConfig.CHANNEL_MODE_STEREO);
+
+ final int index = mController.getCurrentA2dpSettingIndex(mBluetoothCodecConfig);
+
+ assertThat(index).isEqualTo(2);
+ }
+
+ @Test
+ public void getCurrentA2dpSettingIndex_unknownOption_shouldReturnDefault() {
+ when(mBluetoothCodecConfig.getCodecType()).thenReturn(1381391835);
+
+ final int index = mController.getCurrentA2dpSettingIndex(mBluetoothCodecConfig);
+
+ assertThat(index).isEqualTo(0);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothAudioCodecPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothAudioCodecPreferenceControllerTest.java
new file mode 100644
index 0000000..560a9c3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothAudioCodecPreferenceControllerTest.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.content.Context;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BluetoothAudioCodecPreferenceControllerTest {
+
+ @Mock
+ private BluetoothCodecConfig mBluetoothCodecConfig;
+ @Mock
+ private ListPreference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private BluetoothA2dpConfigStore mBluetoothA2dpConfigStore;
+
+ /**
+ * 0: Use System Selection (Default)
+ * 1: SBC
+ * 2: AAC
+ * 3: Qualcomm aptX audio
+ * 4: Qualcomm aptX HD audio
+ * 5: LDAC
+ * 6: Enable Optional Codecs
+ * 7: Disable Optional Codecs
+ */
+ private String[] mListValues;
+ private Context mContext;
+ private BluetoothAudioCodecPreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new BluetoothAudioCodecPreferenceController(mContext, new Lifecycle(),
+ mBluetoothA2dpConfigStore));
+ mListValues = mController.getListValues();
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void writeConfigurationValues_option2_shouldWriteOption2ToSharedStore() {
+ when(mPreference.findIndexOfValue(mListValues[2])).thenReturn(2);
+ mController.writeConfigurationValues(mListValues[2]);
+
+ verify(mBluetoothA2dpConfigStore).setCodecType(BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC);
+ verify(mBluetoothA2dpConfigStore).setCodecPriority(
+ BluetoothCodecConfig.CODEC_PRIORITY_HIGHEST);
+ }
+
+ @Test
+ public void writeConfigurationValues_default_shouldSetDefaultPriority() {
+ when(mPreference.findIndexOfValue(mListValues[0])).thenReturn(0);
+ mController.writeConfigurationValues(mListValues[0]);
+
+ verify(mBluetoothA2dpConfigStore).setCodecPriority(
+ BluetoothCodecConfig.CODEC_PRIORITY_DEFAULT);
+ }
+
+ @Test
+ public void getCurrentA2dpSettingIndex_option2_shouldReturnSecondIndex() {
+ when(mBluetoothCodecConfig.getCodecType()).thenReturn(
+ BluetoothCodecConfig.SOURCE_CODEC_TYPE_AAC);
+
+ final int index = mController.getCurrentA2dpSettingIndex(mBluetoothCodecConfig);
+
+ assertThat(index).isEqualTo(2);
+ }
+
+ @Test
+ public void getCurrentA2dpSettingIndex_unknownOption_shouldReturnDefault() {
+ when(mBluetoothCodecConfig.getCodecType()).thenReturn(1381391835);
+
+ final int index = mController.getCurrentA2dpSettingIndex(mBluetoothCodecConfig);
+
+ assertThat(index).isEqualTo(0);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothAudioQualityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothAudioQualityPreferenceControllerTest.java
new file mode 100644
index 0000000..e00ac00
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothAudioQualityPreferenceControllerTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.bluetooth.BluetoothCodecConfig;
+import android.content.Context;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.PreferenceScreen;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BluetoothAudioQualityPreferenceControllerTest {
+
+ @Mock
+ private BluetoothCodecConfig mBluetoothCodecConfig;
+ @Mock
+ private ListPreference mPreference;
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private BluetoothA2dpConfigStore mBluetoothA2dpConfigStore;
+
+ /**
+ * 0: Optimized for Audio Quality (990kbps/909kbps)
+ * 1: Balanced Audio And Connection Quality (660kbps/606kbps)
+ * 2: Stereo
+ */
+ private String[] mListValues;
+ private Context mContext;
+ private BluetoothAudioQualityPreferenceController mController;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new BluetoothAudioQualityPreferenceController(mContext,
+ new Lifecycle(), mBluetoothA2dpConfigStore));
+ mListValues = mController.getListValues();
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void writeConfigurationValues_option3_shouldWrite1003ToSharedStore() {
+ when(mPreference.findIndexOfValue(mListValues[3])).thenReturn(3);
+ mController.writeConfigurationValues(mListValues[3]);
+
+ verify(mBluetoothA2dpConfigStore).setCodecSpecific1Value(1003);
+ }
+
+ @Test
+ public void writeConfigurationValues_default_shouldSetDefault() {
+ when(mPreference.findIndexOfValue(mListValues[0])).thenReturn(0);
+ mController.writeConfigurationValues(mListValues[0]);
+
+ verify(mBluetoothA2dpConfigStore).setCodecSpecific1Value(1000);
+ }
+
+ @Test
+ public void getCurrentA2dpSettingIndex_option2_shouldReturnSecondIndex() {
+ when(mBluetoothCodecConfig.getCodecSpecific1()).thenReturn(Long.valueOf(2));
+
+ final int index = mController.getCurrentA2dpSettingIndex(mBluetoothCodecConfig);
+
+ assertThat(index).isEqualTo(2);
+ }
+
+ @Test
+ public void getCurrentA2dpSettingIndex_unknownOption_shouldReturnDefault() {
+ when(mBluetoothCodecConfig.getCodecType()).thenReturn(1381391835);
+
+ final int index = mController.getCurrentA2dpSettingIndex(mBluetoothCodecConfig);
+
+ assertThat(index).isEqualTo(3);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothAudioSampleRatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothAudioSampleRatePreferenceControllerTest.java
index 8919576..f683d21 100644
--- a/tests/robotests/src/com/android/settings/development/BluetoothAudioSampleRatePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BluetoothAudioSampleRatePreferenceControllerTest.java
@@ -70,7 +70,7 @@
mContext = RuntimeEnvironment.application;
mLifecycle = new Lifecycle();
mController = spy(new BluetoothAudioSampleRatePreferenceController(mContext, mLifecycle,
- new Object(), mBluetoothA2dpConfigStore));
+ mBluetoothA2dpConfigStore));
mListValues = mController.getListValues();
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
diff --git a/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java b/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
index e061787..59be160 100644
--- a/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
+++ b/tests/robotests/src/com/android/settings/widget/ValidatedEditTextPreferenceTest.java
@@ -17,6 +17,14 @@
package com.android.settings.widget;
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
import android.text.InputType;
import android.text.TextWatcher;
import android.view.View;
@@ -33,14 +41,6 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
-import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
@RunWith(SettingsRobolectricTestRunner.class)
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
public class ValidatedEditTextPreferenceTest {
diff --git a/tests/robotests/src/com/android/settings/widget/WorkOnlyCategoryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/widget/WorkOnlyCategoryPreferenceControllerTest.java
new file mode 100644
index 0000000..9c7e8fc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/widget/WorkOnlyCategoryPreferenceControllerTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.widget;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class WorkOnlyCategoryPreferenceControllerTest {
+
+ private Context mContext;
+ private WorkOnlyCategoryPreferenceController mController;
+ private List<AbstractPreferenceController> mChildren;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mChildren = new ArrayList<>();
+ mController = new WorkOnlyCategoryPreferenceController(mContext, "pref_key", mChildren);
+ }
+
+ @Test
+ public void isAvailable_noChildren_true() {
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_childrenAvailable_true() {
+ final AbstractPreferenceController child = mock(AbstractPreferenceController.class);
+ when(child.isAvailable()).thenReturn(true);
+ mChildren.add(child);
+
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_childrenUnavailable_false() {
+ final AbstractPreferenceController child = mock(AbstractPreferenceController.class);
+ when(child.isAvailable()).thenReturn(false);
+ mChildren.add(child);
+
+ assertThat(mController.isAvailable()).isFalse();
+ }
+}