Merge "Mark only browser as default in app detail page"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 0501077..9c8a677 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -83,7 +83,7 @@
<uses-permission android:name="android.permission.DELETE_PACKAGES"/>
<application android:label="@string/settings_label"
- android:icon="@mipmap/ic_launcher_settings"
+ android:icon="@drawable/ic_launcher_settings"
android:taskAffinity=""
android:theme="@style/Theme.Settings"
android:hardwareAccelerated="true"
@@ -2109,7 +2109,7 @@
<activity android:name="Settings$WifiDisplaySettingsActivity"
android:label="@string/wifi_display_settings_title"
- android:icon="@drawable/ic_settings_display"
+ android:icon="@drawable/ic_cast_24dp"
android:taskAffinity="">
<intent-filter android:priority="1">
<action android:name="android.settings.CAST_SETTINGS" />
diff --git a/res/drawable/ic_cast_24dp.xml b/res/drawable/ic_cast_24dp.xml
new file mode 100644
index 0000000..7dc895e
--- /dev/null
+++ b/res/drawable/ic_cast_24dp.xml
@@ -0,0 +1,26 @@
+<!--
+ 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM1,18v3h3c0,-1.66 -1.34,-3 -3,-3zM1,14v2c2.76,0 5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM1,10v2c4.97,0 9,4.03 9,9h2c0,-6.08 -4.93,-11 -11,-11z"/>
+</vector>
diff --git a/res/drawable/ic_launcher_settings.xml b/res/drawable/ic_launcher_settings.xml
new file mode 100644
index 0000000..57d54e5
--- /dev/null
+++ b/res/drawable/ic_launcher_settings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<maskable-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="?android:attr/colorAccent"/>
+ <foreground android:drawable="@mipmap/ic_launcher_settings"/>
+</maskable-icon>
diff --git a/res/drawable/ic_shortcut_battery.xml b/res/drawable/ic_shortcut_battery.xml
index 97fdd11..a61b1a3 100644
--- a/res/drawable/ic_shortcut_battery.xml
+++ b/res/drawable/ic_shortcut_battery.xml
@@ -14,17 +14,20 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="80dp"
- android:height="80dp"
- android:viewportWidth="52.0"
- android:viewportHeight="52.0" >
- <path
- android:fillColor="#FFF5F5F5"
- android:pathData="M2,26a24,24 0 1,0 48,0a24,24 0 1,0 -48,0"/>
- <path
- android:fillColor="@*android:color/accent_device_default_light"
- android:pathData="M29.67,18H28v-2h-4v2h-1.67C21.6,18,21,18.6,21,19.33v15.33C21,35.4,21.6,36,22.33,36h7.33
- C30.4,36,31,35.4,31,34.67V19.33C31,18.6,30.4,18,29.67,18z"/>
-</vector>
\ No newline at end of file
+<maskable-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/shortcut_background"/>
+ <foreground>
+ <vector
+ android:width="120dp"
+ android:height="120dp"
+ android:viewportWidth="78.0"
+ android:viewportHeight="78.0">
+ <group android:translateX="13.0" android:translateY="13.0">
+ <path
+ android:fillColor="@*android:color/accent_device_default_light"
+ android:pathData="M29.67,18H28v-2h-4v2h-1.67C21.6,18,21,18.6,21,19.33v15.33C21,35.4,21.6,36,22.33,36h7.33
+ C30.4,36,31,35.4,31,34.67V19.33C31,18.6,30.4,18,29.67,18z"/>
+ </group>
+ </vector>
+ </foreground>
+</maskable-icon>
\ No newline at end of file
diff --git a/res/drawable/ic_shortcut_data_usage.xml b/res/drawable/ic_shortcut_data_usage.xml
index dddd493..cc0c6bc 100644
--- a/res/drawable/ic_shortcut_data_usage.xml
+++ b/res/drawable/ic_shortcut_data_usage.xml
@@ -14,18 +14,21 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="80dp"
- android:height="80dp"
- android:viewportWidth="52.0"
- android:viewportHeight="52.0" >
- <path
- android:fillColor="#FFF5F5F5"
- android:pathData="M2,26a24,24 0 1,0 48,0a24,24 0 1,0 -48,0"/>
- <path
- android:fillColor="@*android:color/accent_device_default_light"
- android:pathData="M27,16.05v3.03c3.39,0.49,6,3.39,6,6.92c0,0.9-0.18,1.75-0.48,2.54l2.6,1.53C35.68,28.83,36,27.45,36,26
- C36,20.82,32.05,16.55,27,16.05z M26,33c-3.87,0-7-3.13-7-7c0-3.53,2.61-6.43,6-6.92v-3.03c-5.06,0.5-9,4.76-9,9.95
- c0,5.52,4.47,10,9.99,10c3.31,0,6.24-1.61,8.06-4.09l-2.6-1.53C30.17,31.98,28.21,33,26,33z"/>
-</vector>
\ No newline at end of file
+<maskable-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/shortcut_background"/>
+ <foreground>
+ <vector
+ android:width="120dp"
+ android:height="120dp"
+ android:viewportWidth="78.0"
+ android:viewportHeight="78.0">
+ <group android:translateX="13.0" android:translateY="13.0">
+ <path
+ android:fillColor="@*android:color/accent_device_default_light"
+ android:pathData="M27,16.05v3.03c3.39,0.49,6,3.39,6,6.92c0,0.9-0.18,1.75-0.48,2.54l2.6,1.53C35.68,28.83,36,27.45,36,26
+ C36,20.82,32.05,16.55,27,16.05z M26,33c-3.87,0-7-3.13-7-7c0-3.53,2.61-6.43,6-6.92v-3.03c-5.06,0.5-9,4.76-9,9.95
+ c0,5.52,4.47,10,9.99,10c3.31,0,6.24-1.61,8.06-4.09l-2.6-1.53C30.17,31.98,28.21,33,26,33z"/>
+ </group>
+ </vector>
+ </foreground>
+</maskable-icon>
\ No newline at end of file
diff --git a/res/drawable/ic_shortcut_wireless.xml b/res/drawable/ic_shortcut_wireless.xml
index d5607e5..a5fc43a 100644
--- a/res/drawable/ic_shortcut_wireless.xml
+++ b/res/drawable/ic_shortcut_wireless.xml
@@ -14,16 +14,19 @@
~ See the License for the specific language governing permissions and
~ limitations under the License
-->
-<vector
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="80dp"
- android:height="80dp"
- android:viewportWidth="52.0"
- android:viewportHeight="52.0" >
- <path
- android:fillColor="#FFF5F5F5"
- android:pathData="M2,26a24,24 0 1,0 48,0a24,24 0 1,0 -48,0"/>
- <path
- android:fillColor="@*android:color/accent_device_default_light"
- android:pathData="M26.01,35.49L37.64,21c-0.45-0.34-4.93-4-11.64-4c-6.72,0-11.19,3.66-11.64,4l11.63,14.49L26,35.5L26.01,35.49z"/>
-</vector>
\ No newline at end of file
+<maskable-icon xmlns:android="http://schemas.android.com/apk/res/android">
+ <background android:drawable="@color/shortcut_background"/>
+ <foreground>
+ <vector
+ android:width="120dp"
+ android:height="120dp"
+ android:viewportWidth="78.0"
+ android:viewportHeight="78.0">
+ <group android:translateX="13.0" android:translateY="13.0">
+ <path
+ android:fillColor="@*android:color/accent_device_default_light"
+ android:pathData="M26.01,35.49L37.64,21c-0.45-0.34-4.93-4-11.64-4c-6.72,0-11.19,3.66-11.64,4l11.63,14.49L26,35.5L26.01,35.49z"/>
+ </group>
+ </vector>
+ </foreground>
+</maskable-icon>
\ No newline at end of file
diff --git a/res/layout/shortcut_badge_maskable.xml b/res/layout/shortcut_badge_maskable.xml
new file mode 100644
index 0000000..e1d555a
--- /dev/null
+++ b/res/layout/shortcut_badge_maskable.xml
@@ -0,0 +1,36 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="@dimen/shortcut_size_maskable"
+ android:layout_height="@dimen/shortcut_size_maskable"
+ android:background="@color/shortcut_background">
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="22"/>
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:tint="@color/icon_accent"
+ android:scaleType="fitCenter"
+ android:layout_weight="16"/>
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="22"/>
+</LinearLayout>
\ No newline at end of file
diff --git a/res/mipmap-hdpi/ic_launcher_settings.png b/res/mipmap-hdpi/ic_launcher_settings.png
index 252e6b4..ddce98e 100644
--- a/res/mipmap-hdpi/ic_launcher_settings.png
+++ b/res/mipmap-hdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/mipmap-mdpi/ic_launcher_settings.png b/res/mipmap-mdpi/ic_launcher_settings.png
index d2ecee9..86f3be8 100644
--- a/res/mipmap-mdpi/ic_launcher_settings.png
+++ b/res/mipmap-mdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/mipmap-xhdpi/ic_launcher_settings.png b/res/mipmap-xhdpi/ic_launcher_settings.png
index fa8c813..360aa69 100644
--- a/res/mipmap-xhdpi/ic_launcher_settings.png
+++ b/res/mipmap-xhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/mipmap-xxhdpi/ic_launcher_settings.png b/res/mipmap-xxhdpi/ic_launcher_settings.png
index 3fa69e9..7cb67a9 100644
--- a/res/mipmap-xxhdpi/ic_launcher_settings.png
+++ b/res/mipmap-xxhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/mipmap-xxxhdpi/ic_launcher_settings.png b/res/mipmap-xxxhdpi/ic_launcher_settings.png
index 72946b7..3fec9c4 100644
--- a/res/mipmap-xxxhdpi/ic_launcher_settings.png
+++ b/res/mipmap-xxxhdpi/ic_launcher_settings.png
Binary files differ
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 300d73a..fdb1265 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -114,4 +114,7 @@
<!-- Color for the background of the donut graph.-->
<color name="donut_background_grey">#ffd7d7d7</color>
+ <!-- Color for the background of the shortcut icons.-->
+ <color name="shortcut_background">#fff5f5f5</color>
+
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 2bc83c1..0ddc634 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -245,7 +245,9 @@
<dimen name="mdm_app_name_padding_left">16dp</dimen>
<dimen name="mdm_app_icon_width_height">56dp</dimen>
+ <dimen name="shortcut_size_maskable">120dp</dimen>
<dimen name="shortcut_size">40dp</dimen>
+ <dimen name="shortcut_icon_size">16dp</dimen>
<dimen name="badge_size">10dp</dimen>
<!-- Admin support contact details dialog. -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 9610af9..3e3cf14 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5411,6 +5411,8 @@
<string name="vpn_not_supported_by_this_app">Not supported by this app</string>
<!-- Preference title for forcing all network connections to go through VPN. -->
<string name="vpn_require_connection">Only allow connections through VPN</string>
+ <!-- Dialog message title to confirm forcing all network connections to go through VPN. [CHAR LIMIT=40] -->
+ <string name="vpn_require_connection_title">Require VPN connection?</string>
<!-- Preference summary when the preference to force all network connections to go through a VPN is enabled, blocking all other network traffic. In this case apps must use the VPN for all connections. -->
<string name="vpn_lockdown_active">Lockdown active</string>
<!-- Preference summary when the preference to force all network connections to go through a VPN is disabled. In this case use of the VPN is optional for apps. -->
diff --git a/src/com/android/settings/CreateShortcut.java b/src/com/android/settings/CreateShortcut.java
index 56ab34a..bd71377 100644
--- a/src/com/android/settings/CreateShortcut.java
+++ b/src/com/android/settings/CreateShortcut.java
@@ -29,6 +29,7 @@
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.drawable.Icon;
+import android.graphics.drawable.MaskableIconDrawable;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.support.annotation.VisibleForTesting;
@@ -68,19 +69,22 @@
protected Intent createResultIntent(Intent shortcutIntent, ResolveInfo resolveInfo,
CharSequence label) {
shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
-
+ ShortcutManager sm = getSystemService(ShortcutManager.class);
ActivityInfo activityInfo = resolveInfo.activityInfo;
- Bitmap icon = activityInfo.icon != 0 ? createIcon(activityInfo.icon) : null;
+ Icon maskableIcon = activityInfo.icon != 0 ? Icon.createWithMaskableBitmap(
+ createIcon(activityInfo.icon,
+ R.layout.shortcut_badge_maskable,
+ getResources().getDimensionPixelSize(R.dimen.shortcut_size_maskable))) :
+ Icon.createWithResource(this, R.drawable.ic_launcher_settings);
String shortcutId = SHORTCUT_ID_PREFIX +
shortcutIntent.getComponent().flattenToShortString();
ShortcutInfo info = new ShortcutInfo.Builder(this, shortcutId)
.setShortLabel(label)
.setIntent(shortcutIntent)
- .setIcon(icon != null ? Icon.createWithBitmap(icon) :
- Icon.createWithResource(this, R.mipmap.ic_launcher_settings))
+ .setIcon(maskableIcon)
.build();
- Intent intent = getSystemService(ShortcutManager.class).createShortcutResultIntent(info);
+ Intent intent = sm.createShortcutResultIntent(info);
if (intent == null) {
intent = new Intent();
}
@@ -88,7 +92,12 @@
Intent.ShortcutIconResource.fromContext(this, R.mipmap.ic_launcher_settings));
intent.putExtra(Intent.EXTRA_SHORTCUT_INTENT, shortcutIntent);
intent.putExtra(Intent.EXTRA_SHORTCUT_NAME, label);
- intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, icon);
+
+ if (activityInfo.icon != 0) {
+ intent.putExtra(Intent.EXTRA_SHORTCUT_ICON, createIcon(activityInfo.icon,
+ R.layout.shortcut_badge,
+ getResources().getDimensionPixelSize(R.dimen.shortcut_size)));
+ }
return intent;
}
@@ -101,12 +110,12 @@
info.activityInfo.name);
}
- private Bitmap createIcon(int resource) {
+ private Bitmap createIcon(int resource, int layoutRes, int size) {
Context context = new ContextThemeWrapper(this, android.R.style.Theme_Material);
- View view = LayoutInflater.from(context).inflate(R.layout.shortcut_badge, null);
+ View view = LayoutInflater.from(context).inflate(layoutRes, null);
((ImageView) view.findViewById(android.R.id.icon)).setImageResource(resource);
- int spec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+ int spec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY);
view.measure(spec, spec);
Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(),
Config.ARGB_8888);
diff --git a/src/com/android/settings/applications/ManageApplications.java b/src/com/android/settings/applications/ManageApplications.java
index 22f1627..19f1022 100644
--- a/src/com/android/settings/applications/ManageApplications.java
+++ b/src/com/android/settings/applications/ManageApplications.java
@@ -329,7 +329,8 @@
mApplications.setExtraViewController(new MusicViewHolderController(
context,
new StorageStatsSource(context),
- mVolumeUuid));
+ mVolumeUuid,
+ UserHandle.of(UserHandle.getUserId(mCurrentUid))));
}
mListView.setAdapter(mApplications);
mListView.setRecyclerListener(mApplications);
@@ -870,6 +871,12 @@
public void setExtraViewController(FileViewHolderController extraViewController) {
mExtraViewController = extraViewController;
+ mBgHandler.post(() -> {
+ mExtraViewController.queryStats();
+ mFgHandler.post(() -> {
+ onExtraViewCompleted();
+ });
+ });
}
public void resume(int sort) {
@@ -957,10 +964,6 @@
break;
}
- if (mExtraViewController != null) {
- mExtraViewController.queryStats();
- }
-
filterObj = new CompoundFilter(filterObj, ApplicationsState.FILTER_NOT_HIDE);
AppFilter finalFilterObj = filterObj;
mBgHandler.post(() -> {
@@ -1178,6 +1181,23 @@
}
}
+ public void onExtraViewCompleted() {
+ int size = mActive.size();
+ // If we have no elements, don't do anything.
+ if (size < 1) {
+ 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);
+ }
+
public int getCount() {
if (mEntries == null) {
return 0;
diff --git a/src/com/android/settings/applications/MusicViewHolderController.java b/src/com/android/settings/applications/MusicViewHolderController.java
index 18c87db..fd7e320 100644
--- a/src/com/android/settings/applications/MusicViewHolderController.java
+++ b/src/com/android/settings/applications/MusicViewHolderController.java
@@ -38,18 +38,20 @@
private StorageStatsSource mSource;
private String mVolumeUuid;
private long mMusicSize;
+ private UserHandle mUser;
public MusicViewHolderController(
- Context context, StorageStatsSource source, String volumeUuid) {
+ Context context, StorageStatsSource source, String volumeUuid, UserHandle user) {
mContext = context;
mSource = source;
mVolumeUuid = volumeUuid;
+ mUser = user;
}
@Override
@WorkerThread
public void queryStats() {
- mMusicSize = mSource.getExternalStorageStats(mVolumeUuid, UserHandle.CURRENT).audioBytes;
+ mMusicSize = mSource.getExternalStorageStats(mVolumeUuid, mUser).audioBytes;
}
@Override
@@ -69,7 +71,7 @@
Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
intent.setData(DocumentsContract.buildRootUri(AUTHORITY_MEDIA, "audio_root"));
intent.addCategory(Intent.CATEGORY_DEFAULT);
- intent.putExtra(Intent.EXTRA_USER_ID, UserHandle.CURRENT);
+ intent.putExtra(Intent.EXTRA_USER_ID, mUser);
Utils.launchIntent(fragment, intent);
}
}
diff --git a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
index 69105b5..0db8c20 100644
--- a/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
+++ b/src/com/android/settings/dashboard/DashboardFeatureProviderImpl.java
@@ -28,7 +28,9 @@
import android.util.Log;
import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.SettingsActivity;
+import com.android.settings.SubSettings;
import com.android.settings.core.instrumentation.MetricsFeatureProvider;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.drawer.CategoryManager;
@@ -198,6 +200,8 @@
return;
}
final Intent intent = new Intent(tile.intent)
+ .putExtra(SettingsActivity.EXTRA_SOURCE_METRICS_CATEGORY,
+ MetricsEvent.DASHBOARD_SUMMARY)
.putExtra(SettingsDrawerActivity.EXTRA_SHOW_MENU, true)
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
launchIntentOrSelectProfile(activity, tile, intent);
@@ -222,10 +226,15 @@
}
final ComponentName cn = intent.getComponent();
if (cn == null) {
+ // Not loggable
+ return;
+ } else if (TextUtils.equals(cn.getPackageName(), mContext.getPackageName())) {
+ // Going to a Setting internal page, skip click logging in favor of page's own
+ // visibility logging.
return;
}
mMetricsFeatureProvider.action(mContext,
- MetricsProto.MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
+ MetricsEvent.ACTION_SETTINGS_TILE_CLICK,
cn.flattenToString());
}
}
diff --git a/src/com/android/settings/vpn2/ConfirmLockdownFragment.java b/src/com/android/settings/vpn2/ConfirmLockdownFragment.java
index 0d40e4c..2e0914e 100644
--- a/src/com/android/settings/vpn2/ConfirmLockdownFragment.java
+++ b/src/com/android/settings/vpn2/ConfirmLockdownFragment.java
@@ -78,7 +78,8 @@
final boolean wasLockdown = getArguments().getBoolean(ARG_LOCKDOWN_SRC);
final boolean nowLockdown = getArguments().getBoolean(ARG_LOCKDOWN_DST);
- final int titleId = replacing ? R.string.vpn_replace_vpn_title : R.string.vpn_set_vpn_title;
+ final int titleId = (nowLockdown ? R.string.vpn_require_connection_title :
+ (replacing ? R.string.vpn_replace_vpn_title : R.string.vpn_set_vpn_title));
final int actionId =
(replacing ? R.string.vpn_replace :
(nowLockdown ? R.string.vpn_turn_on : R.string.okay));
diff --git a/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java b/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java
index 00b2446..0d3f3b6 100644
--- a/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java
+++ b/src/com/android/settings/wifi/WriteWifiConfigToNfcDialog.java
@@ -145,7 +145,7 @@
passwordHex = String.format(PASSWORD_FORMAT, passwordLength, passwordHex).toUpperCase();
- if (wpsNfcConfigurationToken.contains(passwordHex)) {
+ if (wpsNfcConfigurationToken != null && wpsNfcConfigurationToken.contains(passwordHex)) {
mWpsNfcConfigurationToken = wpsNfcConfigurationToken;
Activity activity = getOwnerActivity();
diff --git a/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java b/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
index 2a2de66..4af0707 100644
--- a/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/MusicViewHolderControllerTest.java
@@ -66,7 +66,8 @@
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mVolume = new VolumeInfo("id", 0, null, "id");
- mController = new MusicViewHolderController(mContext, mSource, mVolume.fsUuid);
+ mController = new MusicViewHolderController(mContext, mSource, mVolume.fsUuid,
+ new UserHandle(0));
LayoutInflater inflater = LayoutInflater.from(mContext);
mHolder = AppViewHolder.createOrRecycle(inflater, null);
diff --git a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
index 834b2ad..33eb29f 100644
--- a/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
+++ b/tests/robotests/src/com/android/settings/dashboard/DashboardFeatureProviderImplTest.java
@@ -44,6 +44,7 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
+import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
import org.robolectric.shadows.ShadowApplication;
@@ -55,6 +56,7 @@
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -175,6 +177,33 @@
}
@Test
+ public void bindPreference_toInternalSettingActivity_shouldBindToDirectLaunchIntentAndNotLog() {
+ final Preference preference = new Preference(RuntimeEnvironment.application);
+ final Tile tile = new Tile();
+ tile.metaData = new Bundle();
+ tile.userHandle = new ArrayList<>();
+ tile.userHandle.add(mock(UserHandle.class));
+ tile.intent = new Intent();
+ tile.intent.setComponent(
+ new ComponentName(RuntimeEnvironment.application.getPackageName(), "class"));
+
+ when(mActivity.getSystemService(Context.USER_SERVICE))
+ .thenReturn(mUserManager);
+ when(mActivity.getApplicationContext().getPackageName())
+ .thenReturn(RuntimeEnvironment.application.getPackageName());
+
+ mImpl.bindPreferenceToTile(mActivity, MetricsProto.MetricsEvent.SETTINGS_GESTURES,
+ preference, tile, "123", Preference.DEFAULT_ORDER);
+ preference.getOnPreferenceClickListener().onPreferenceClick(null);
+ verify(mFeatureFactory.metricsFeatureProvider, never()).action(
+ any(Context.class),
+ eq(MetricsProto.MetricsEvent.ACTION_SETTINGS_TILE_CLICK),
+ eq(tile.intent.getComponent().flattenToString()));
+ verify(mActivity)
+ .startActivityForResultAsUser(any(Intent.class), anyInt(), any(UserHandle.class));
+ }
+
+ @Test
public void bindPreference_withNullKeyNullPriority_shouldGenerateKeyAndPriority() {
final Preference preference = new Preference(
ShadowApplication.getInstance().getApplicationContext());
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.java
new file mode 100644
index 0000000..e4421ee
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowNfcAdapter.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.testutils.shadow;
+
+import android.app.Activity;
+import android.content.Context;
+import android.nfc.NfcAdapter;
+import android.os.Bundle;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
+import org.robolectric.util.ReflectionHelpers;
+import org.robolectric.util.ReflectionHelpers.ClassParameter;
+
+/**
+ * Shadow of {@link NfcAdapter}.
+ */
+@Implements(NfcAdapter.class)
+public class ShadowNfcAdapter {
+ private static boolean sReaderModeEnabled;
+
+ @Implementation
+ public void enableReaderMode(Activity activity, NfcAdapter.ReaderCallback callback, int flags,
+ Bundle extras) {
+ sReaderModeEnabled = true;
+ }
+
+ @Implementation
+ public static NfcAdapter getDefaultAdapter(Context context) {
+ return ReflectionHelpers.callConstructor(
+ NfcAdapter.class, ClassParameter.from(Context.class, context));
+ }
+
+ public static boolean isReaderModeEnabled() {
+ return sReaderModeEnabled;
+ }
+
+ @Resetter
+ public static void reset() {
+ sReaderModeEnabled = false;
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/wifi/WriteWifiConfigToNfcDialogTest.java b/tests/robotests/src/com/android/settings/wifi/WriteWifiConfigToNfcDialogTest.java
new file mode 100644
index 0000000..6e45cde
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/wifi/WriteWifiConfigToNfcDialogTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.wifi;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.when;
+
+import android.app.Activity;
+import android.content.Context;
+import android.net.wifi.WifiManager;
+import android.view.inputmethod.InputMethodManager;
+
+import com.android.settings.SettingsRobolectricTestRunner;
+import com.android.settings.TestConfig;
+import com.android.settings.testutils.shadow.ShadowNfcAdapter;
+
+import org.junit.After;
+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;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+@Config(
+ manifest = TestConfig.MANIFEST_PATH,
+ sdk = TestConfig.SDK_VERSION,
+ shadows = ShadowNfcAdapter.class
+)
+public class WriteWifiConfigToNfcDialogTest {
+ private static final int NETWORK_ID = 17;
+
+ @Mock Activity mActivity;
+ @Mock WifiManager mWifiManager;
+
+ private WriteWifiConfigToNfcDialog mWriteWifiConfigToNfcDialog;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mActivity.getApplicationContext()).thenReturn(mActivity);
+ when(mActivity.getSystemService(Context.INPUT_METHOD_SERVICE))
+ .thenReturn(ReflectionHelpers.newInstance(InputMethodManager.class));
+
+ mWriteWifiConfigToNfcDialog = new WriteWifiConfigToNfcDialog(RuntimeEnvironment.application,
+ NETWORK_ID, 0 /* security */, mWifiManager);
+ mWriteWifiConfigToNfcDialog.setOwnerActivity(mActivity);
+ mWriteWifiConfigToNfcDialog.onCreate(null /* savedInstanceState */);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowNfcAdapter.reset();
+ }
+
+ @Test
+ public void testOnClick_nfcConfigurationTokenDoesNotContainPasswordHex() {
+ when(mWifiManager.getWpsNfcConfigurationToken(NETWORK_ID)).thenReturn("blah");
+
+ mWriteWifiConfigToNfcDialog.onClick(null);
+
+ assertThat(ShadowNfcAdapter.isReaderModeEnabled()).isFalse();
+ }
+
+ @Test
+ public void testOnClick_nfcConfigurationTokenIsNull() {
+ when(mWifiManager.getWpsNfcConfigurationToken(NETWORK_ID)).thenReturn(null);
+
+ mWriteWifiConfigToNfcDialog.onClick(null);
+
+ assertThat(ShadowNfcAdapter.isReaderModeEnabled()).isFalse();
+ }
+
+ @Test
+ public void testOnClick_nfcConfigurationTokenContainsPasswordHex() {
+ // This is the corresponding passwordHex for an empty string password.
+ when(mWifiManager.getWpsNfcConfigurationToken(NETWORK_ID)).thenReturn("10270000");
+
+ mWriteWifiConfigToNfcDialog.onClick(null);
+
+ assertThat(ShadowNfcAdapter.isReaderModeEnabled()).isTrue();
+ }
+}