17f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau/* 27f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * Copyright (C) 2015 The Android Open Source Project 37f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * 47f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * Licensed under the Apache License, Version 2.0 (the "License"); 57f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * you may not use this file except in compliance with the License. 67f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * You may obtain a copy of the License at 77f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * 87f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * http://www.apache.org/licenses/LICENSE-2.0 97f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * 107f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * Unless required by applicable law or agreed to in writing, software 117f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * distributed under the License is distributed on an "AS IS" BASIS, 127f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * See the License for the specific language governing permissions and 147f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau * limitations under the License. 157f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau */ 167f70ba18e6760c2539704c16cf3865bf49953d50Billy Laupackage com.android.settings.applications; 177f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 187f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.app.AlertDialog; 197f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.app.AppOpsManager; 207f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.ActivityNotFoundException; 217f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.ComponentName; 227f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.Context; 237f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.Intent; 247f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.pm.ApplicationInfo; 257f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.content.pm.PackageManager; 267f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.os.Bundle; 277f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.os.UserHandle; 287f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.preference.Preference; 297f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.preference.Preference.OnPreferenceChangeListener; 307f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.preference.Preference.OnPreferenceClickListener; 317f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.preference.SwitchPreference; 327f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.provider.Settings; 337f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport android.util.Log; 347f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 357f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport com.android.internal.logging.MetricsLogger; 367f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport com.android.settings.InstrumentedFragment; 377f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport com.android.settings.R; 38bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lauimport com.android.settings.applications.AppStateAppOpsBridge.PermissionState; 397f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport com.android.settings.applications.AppStateWriteSettingsBridge.WriteSettingsState; 407f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport com.android.settingslib.applications.ApplicationsState; 417f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport com.android.settingslib.applications.ApplicationsState.AppEntry; 427f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 437f70ba18e6760c2539704c16cf3865bf49953d50Billy Lauimport java.util.List; 447f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 457f70ba18e6760c2539704c16cf3865bf49953d50Billy Laupublic class WriteSettingsDetails extends AppInfoWithHeader implements OnPreferenceChangeListener, 467f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau OnPreferenceClickListener { 477f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 487f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private static final String KEY_APP_OPS_PREFERENCE_SCREEN = "app_ops_preference_screen"; 497f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private static final String KEY_APP_OPS_SETTINGS_SWITCH = "app_ops_settings_switch"; 507f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private static final String KEY_APP_OPS_SETTINGS_PREFS = "app_ops_settings_preference"; 517f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private static final String KEY_APP_OPS_SETTINGS_DESC = "app_ops_settings_description"; 527f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private static final String LOG_TAG = "WriteSettingsDetails"; 537f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 547f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private static final int [] APP_OPS_OP_CODE = { 557f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau AppOpsManager.OP_WRITE_SETTINGS 567f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau }; 577f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 587f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau // Use a bridge to get the overlay details but don't initialize it to connect with all state. 597f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau // TODO: Break out this functionality into its own class. 607f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private AppStateWriteSettingsBridge mAppBridge; 617f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private AppOpsManager mAppOpsManager; 627f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private SwitchPreference mSwitchPref; 637f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private Preference mWriteSettingsPrefs; 647f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private Preference mWriteSettingsDesc; 657f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private Intent mSettingsIntent; 667f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private WriteSettingsState mWriteSettingsState; 677f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 687f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau @Override 697f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau public void onCreate(Bundle savedInstanceState) { 707f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau super.onCreate(savedInstanceState); 717f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 727f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau Context context = getActivity(); 737f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mAppBridge = new AppStateWriteSettingsBridge(context, mState, null); 747f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 757f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 767f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau addPreferencesFromResource(R.xml.app_ops_permissions_details); 777f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mSwitchPref = (SwitchPreference) findPreference(KEY_APP_OPS_SETTINGS_SWITCH); 787f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mWriteSettingsPrefs = findPreference(KEY_APP_OPS_SETTINGS_PREFS); 797f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mWriteSettingsDesc = findPreference(KEY_APP_OPS_SETTINGS_DESC); 807f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 817f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau getPreferenceScreen().setTitle(R.string.write_settings); 827f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mSwitchPref.setTitle(R.string.permit_write_settings); 837f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mWriteSettingsPrefs.setTitle(R.string.write_settings_preference); 847f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mWriteSettingsDesc.setSummary(R.string.write_settings_description); 857f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 867f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mSwitchPref.setOnPreferenceChangeListener(this); 877f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mWriteSettingsPrefs.setOnPreferenceClickListener(this); 887f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 897f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mSettingsIntent = new Intent(Intent.ACTION_MAIN) 907f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau .addCategory(Settings.INTENT_CATEGORY_USAGE_ACCESS_CONFIG) 917f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau .setPackage(mPackageName); 927f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 937f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 947f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau @Override 957f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau public boolean onPreferenceClick(Preference preference) { 967f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau if (preference == mWriteSettingsPrefs) { 977f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau if (mSettingsIntent != null) { 987f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau try { 997f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau getActivity().startActivityAsUser(mSettingsIntent, new UserHandle(mUserId)); 1007f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } catch (ActivityNotFoundException e) { 101bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau Log.w(LOG_TAG, "Unable to launch write system settings " + mSettingsIntent, e); 1027f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1037f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1047f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return true; 1057f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1067f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return false; 1077f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1087f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1097f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau @Override 1107f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau public boolean onPreferenceChange(Preference preference, Object newValue) { 1117f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau if (preference == mSwitchPref) { 112bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau if (mWriteSettingsState != null && (Boolean) newValue != mWriteSettingsState 113bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau .isPermissible()) { 114bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau setCanWriteSettings(!mWriteSettingsState.isPermissible()); 1157f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau refreshUi(); 1167f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1177f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return true; 1187f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1197f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return false; 1207f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1217f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1227f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private void setCanWriteSettings(boolean newState) { 1237f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mAppOpsManager.setMode(AppOpsManager.OP_WRITE_SETTINGS, 1247f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mPackageInfo.applicationInfo.uid, mPackageName, newState 1257f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau ? AppOpsManager.MODE_ALLOWED : AppOpsManager.MODE_ERRORED); 1267f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1277f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1287f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau private boolean canWriteSettings(String pkgName) { 1297f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau int result = mAppOpsManager.noteOpNoThrow(AppOpsManager.OP_WRITE_SETTINGS, 1307f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mPackageInfo.applicationInfo.uid, pkgName); 1317f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau if (result == AppOpsManager.MODE_ALLOWED) { 1327f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return true; 1337f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1347f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1357f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return false; 1367f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1377f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1387f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau @Override 1397f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau protected boolean refreshUi() { 1407f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mWriteSettingsState = mAppBridge.getWriteSettingsInfo(mPackageName, 1417f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mPackageInfo.applicationInfo.uid); 1427f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 143bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau boolean canWrite = mWriteSettingsState.isPermissible(); 1447f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mSwitchPref.setChecked(canWrite); 145fee785645b57c519a31ed403e60e8f76dcc8abbbBilly Lau // you can't ask a user for a permission you didn't even declare! 146fee785645b57c519a31ed403e60e8f76dcc8abbbBilly Lau mSwitchPref.setEnabled(mWriteSettingsState.permissionDeclared); 1477f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau mWriteSettingsPrefs.setEnabled(canWrite); 148bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau getPreferenceScreen().removePreference(mWriteSettingsPrefs); 1497f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1507f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return true; 1517f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1527f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1537f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau @Override 1547f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau protected AlertDialog createDialog(int id, int errorCode) { 1557f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return null; 1567f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1577f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1587f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau @Override 1597f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau protected int getMetricsCategory() { 1607f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return MetricsLogger.SYSTEM_ALERT_WINDOW_APPS; 1617f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1627f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1637f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau public static CharSequence getSummary(Context context, AppEntry entry) { 164bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau if (entry.extraInfo != null) { 165bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau return getSummary(context, new WriteSettingsState((PermissionState)entry 166bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau .extraInfo)); 167bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau } 168bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau 169bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau // fallback if entry.extrainfo is null - although this should not happen 1707f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return getSummary(context, entry.info.packageName); 1717f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1727f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 173bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau public static CharSequence getSummary(Context context, WriteSettingsState writeSettingsState) { 174bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau return context.getString(writeSettingsState.isPermissible() ? R.string.write_settings_on : 175bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau R.string.write_settings_off); 176bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau } 177bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau 1787f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau public static CharSequence getSummary(Context context, String pkg) { 1797f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau // first check if pkg is a system pkg 1807f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau boolean isSystem = false; 1817f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau PackageManager packageManager = context.getPackageManager(); 1827f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau try { 1837f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau ApplicationInfo appInfo = packageManager.getApplicationInfo(pkg, 0); 1847f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau if ((appInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { 1857f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau isSystem = true; 1867f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1877f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } catch (PackageManager.NameNotFoundException e) { 1887f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau // pkg doesn't even exist? 189bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau Log.w(LOG_TAG, "Package " + pkg + " not found", e); 190bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau return context.getString(R.string.write_settings_off); 1917f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 1927f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 1937f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau AppOpsManager appOpsManager = (AppOpsManager) context.getSystemService(Context 1947f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau .APP_OPS_SERVICE); 1957f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau List<AppOpsManager.PackageOps> packageOps = appOpsManager.getPackagesForOps( 1967f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau APP_OPS_OP_CODE); 1977f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau if (packageOps == null) { 198bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau return context.getString(R.string.write_settings_off); 1997f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 2007f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 2017f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau int uid = isSystem ? 0 : -1; 2027f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau for (AppOpsManager.PackageOps packageOp : packageOps) { 2037f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau if (pkg.equals(packageOp.getPackageName())) { 2047f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau uid = packageOp.getUid(); 2057f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau break; 2067f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 2077f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 2087f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 2097f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau if (uid == -1) { 210bb3aa2632abe5f01edcc5b440bf032ff3d8c3e5fBilly Lau return context.getString(R.string.write_settings_off); 2117f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 2127f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau 2137f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau int mode = appOpsManager.noteOpNoThrow(AppOpsManager.OP_WRITE_SETTINGS, uid, pkg); 2147f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau return context.getString((mode == AppOpsManager.MODE_ALLOWED) ? 2157f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau R.string.write_settings_on : R.string.write_settings_off); 2167f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau } 2177f70ba18e6760c2539704c16cf3865bf49953d50Billy Lau} 218