AppPreferencesImpl.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. /*
  2. * ownCloud Android client application
  3. *
  4. * @author David A. Velasco
  5. * @author Chris Narkiewicz Chris Narkiewicz
  6. * Copyright (C) 2016 ownCloud Inc.
  7. * Copyright (C) 2019 Chris Narkiewicz <hello@ezaquarii.com>
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2,
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. package com.nextcloud.client.preferences;
  22. import android.annotation.SuppressLint;
  23. import android.content.Context;
  24. import android.content.SharedPreferences;
  25. import com.nextcloud.client.account.CurrentAccountProvider;
  26. import com.nextcloud.client.account.User;
  27. import com.nextcloud.client.account.UserAccountManagerImpl;
  28. import com.owncloud.android.datamodel.ArbitraryDataProvider;
  29. import com.owncloud.android.datamodel.FileDataStorageManager;
  30. import com.owncloud.android.datamodel.OCFile;
  31. import com.owncloud.android.ui.activity.PassCodeActivity;
  32. import com.owncloud.android.ui.activity.SettingsActivity;
  33. import com.owncloud.android.utils.FileSortOrder;
  34. import java.util.Set;
  35. import java.util.concurrent.CopyOnWriteArraySet;
  36. import androidx.annotation.Nullable;
  37. import androidx.annotation.VisibleForTesting;
  38. import static com.owncloud.android.ui.fragment.OCFileListFragment.FOLDER_LAYOUT_LIST;
  39. /**
  40. * Implementation of application-wide preferences using {@link SharedPreferences}.
  41. *
  42. * Users should not use this class directly. Please use {@link AppPreferences} interface
  43. * instead.
  44. */
  45. public final class AppPreferencesImpl implements AppPreferences {
  46. /**
  47. * Constant to access value of last path selected by the user to upload a file shared from other app.
  48. * Value handled by the app without direct access in the UI.
  49. */
  50. public static final String AUTO_PREF__LAST_SEEN_VERSION_CODE = "lastSeenVersionCode";
  51. public static final String STORAGE_PATH = "storage_path";
  52. public static final String STORAGE_PATH_VALID = "storage_path_valid";
  53. public static final String PREF__DARK_THEME = "dark_theme_mode";
  54. public static final float DEFAULT_GRID_COLUMN = 3f;
  55. private static final String AUTO_PREF__LAST_UPLOAD_PATH = "last_upload_path";
  56. private static final String AUTO_PREF__UPLOAD_FROM_LOCAL_LAST_PATH = "upload_from_local_last_path";
  57. private static final String AUTO_PREF__UPLOAD_FILE_EXTENSION_MAP_URL = "prefs_upload_file_extension_map_url";
  58. private static final String AUTO_PREF__UPLOAD_FILE_EXTENSION_URL = "prefs_upload_file_extension_url";
  59. private static final String AUTO_PREF__UPLOADER_BEHAVIOR = "prefs_uploader_behaviour";
  60. private static final String AUTO_PREF__GRID_COLUMNS = "grid_columns";
  61. private static final String AUTO_PREF__SHOW_DETAILED_TIMESTAMP = "detailed_timestamp";
  62. private static final String PREF__INSTANT_UPLOADING = "instant_uploading";
  63. private static final String PREF__INSTANT_VIDEO_UPLOADING = "instant_video_uploading";
  64. private static final String PREF__SHOW_HIDDEN_FILES = "show_hidden_files_pref";
  65. private static final String PREF__LEGACY_CLEAN = "legacyClean";
  66. private static final String PREF__KEYS_MIGRATION = "keysMigration";
  67. private static final String PREF__FIX_STORAGE_PATH = "storagePathFix";
  68. private static final String PREF__KEYS_REINIT = "keysReinit";
  69. private static final String PREF__AUTO_UPLOAD_UPDATE_PATH = "autoUploadPathUpdate";
  70. private static final String PREF__PUSH_TOKEN = "pushToken";
  71. private static final String PREF__AUTO_UPLOAD_SPLIT_OUT = "autoUploadEntriesSplitOut";
  72. private static final String PREF__AUTO_UPLOAD_INIT = "autoUploadInit";
  73. private static final String PREF__FOLDER_SORT_ORDER = "folder_sort_order";
  74. private static final String PREF__FOLDER_LAYOUT = "folder_layout";
  75. private static final String PREF__LOCK_TIMESTAMP = "lock_timestamp";
  76. private static final String PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS = "show_media_scan_notifications";
  77. private static final String PREF__LOCK = SettingsActivity.PREFERENCE_LOCK;
  78. private static final String PREF__SELECTED_ACCOUNT_NAME = "select_oc_account";
  79. private static final String PREF__MIGRATED_USER_ID = "migrated_user_id";
  80. private static final String PREF__PHOTO_SEARCH_TIMESTAMP = "photo_search_timestamp";
  81. private static final String PREF__POWER_CHECK_DISABLED = "power_check_disabled";
  82. private static final String PREF__PIN_BRUTE_FORCE_COUNT = "pin_brute_force_count";
  83. private final Context context;
  84. private final SharedPreferences preferences;
  85. private final CurrentAccountProvider currentAccountProvider;
  86. private final ListenerRegistry listeners;
  87. /**
  88. * Adapter delegating raw {@link SharedPreferences.OnSharedPreferenceChangeListener} calls
  89. * with key-value pairs to respective {@link com.nextcloud.client.preferences.AppPreferences.Listener} method.
  90. */
  91. static class ListenerRegistry implements SharedPreferences.OnSharedPreferenceChangeListener {
  92. private final AppPreferences preferences;
  93. private final Set<Listener> listeners;
  94. ListenerRegistry(AppPreferences preferences) {
  95. this.preferences = preferences;
  96. this.listeners = new CopyOnWriteArraySet<>();
  97. }
  98. void add(@Nullable final Listener listener) {
  99. if (listener != null) {
  100. listeners.add(listener);
  101. }
  102. }
  103. void remove(@Nullable final Listener listener) {
  104. if (listener != null) {
  105. listeners.remove(listener);
  106. }
  107. }
  108. @Override
  109. public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
  110. if (PREF__DARK_THEME.equals(key)) {
  111. DarkMode mode = preferences.getDarkThemeMode();
  112. for(Listener l : listeners) {
  113. l.onDarkThemeModeChanged(mode);
  114. }
  115. }
  116. }
  117. }
  118. /**
  119. * This is a temporary workaround to access app preferences in places that cannot use
  120. * dependency injection yet. Use injected component via {@link AppPreferences} interface.
  121. *
  122. * WARNING: this creates new instance! it does not return app-wide singleton
  123. *
  124. * @param context Context used to create shared preferences
  125. * @return New instance of app preferences component
  126. */
  127. @Deprecated
  128. public static AppPreferences fromContext(Context context) {
  129. final CurrentAccountProvider currentAccountProvider = UserAccountManagerImpl.fromContext(context);
  130. final SharedPreferences prefs = android.preference.PreferenceManager.getDefaultSharedPreferences(context);
  131. return new AppPreferencesImpl(context, prefs, currentAccountProvider);
  132. }
  133. AppPreferencesImpl(Context appContext, SharedPreferences preferences, CurrentAccountProvider currentAccountProvider) {
  134. this.context = appContext;
  135. this.preferences = preferences;
  136. this.currentAccountProvider = currentAccountProvider;
  137. this.listeners = new ListenerRegistry(this);
  138. this.preferences.registerOnSharedPreferenceChangeListener(listeners);
  139. }
  140. @Override
  141. public void addListener(@Nullable AppPreferences.Listener listener) {
  142. this.listeners.add(listener);
  143. }
  144. @Override
  145. public void removeListener(@Nullable AppPreferences.Listener listener) {
  146. this.listeners.remove(listener);
  147. }
  148. @Override
  149. public void setKeysReInitEnabled() {
  150. preferences.edit().putBoolean(PREF__KEYS_REINIT, true).apply();
  151. }
  152. @Override
  153. public boolean isKeysReInitEnabled() {
  154. return preferences.getBoolean(PREF__KEYS_REINIT, false);
  155. }
  156. @Override
  157. public void setPushToken(String pushToken) {
  158. preferences.edit().putString(PREF__PUSH_TOKEN, pushToken).apply();
  159. }
  160. @Override
  161. public String getPushToken() {
  162. return preferences.getString(PREF__PUSH_TOKEN, "");
  163. }
  164. @Override
  165. public boolean instantPictureUploadEnabled() {
  166. return preferences.getBoolean(PREF__INSTANT_UPLOADING, false);
  167. }
  168. @Override
  169. public boolean instantVideoUploadEnabled() {
  170. return preferences.getBoolean(PREF__INSTANT_VIDEO_UPLOADING, false);
  171. }
  172. @Override
  173. public boolean isShowHiddenFilesEnabled() {
  174. return preferences.getBoolean(PREF__SHOW_HIDDEN_FILES, false);
  175. }
  176. @Override
  177. public void setShowHiddenFilesEnabled(boolean enabled) {
  178. preferences.edit().putBoolean(PREF__SHOW_HIDDEN_FILES, enabled).apply();
  179. }
  180. @Override
  181. public int getUploadUrlFileExtensionUrlSelectedPos() {
  182. return preferences.getInt(AUTO_PREF__UPLOAD_FILE_EXTENSION_URL, 0);
  183. }
  184. @Override
  185. public void setUploadUrlFileExtensionUrlSelectedPos(int selectedPos) {
  186. preferences.edit().putInt(AUTO_PREF__UPLOAD_FILE_EXTENSION_URL, selectedPos).apply();
  187. }
  188. @Override
  189. public int getUploadMapFileExtensionUrlSelectedPos() {
  190. return preferences.getInt(AUTO_PREF__UPLOAD_FILE_EXTENSION_MAP_URL, 0);
  191. }
  192. @Override
  193. public void setUploadMapFileExtensionUrlSelectedPos(int selectedPos) {
  194. preferences.edit().putInt(AUTO_PREF__UPLOAD_FILE_EXTENSION_MAP_URL, selectedPos).apply();
  195. }
  196. @Override
  197. public String getUploadFromLocalLastPath() {
  198. return preferences.getString(AUTO_PREF__UPLOAD_FROM_LOCAL_LAST_PATH, "");
  199. }
  200. @Override
  201. public void setUploadFromLocalLastPath(String path) {
  202. preferences.edit().putString(AUTO_PREF__UPLOAD_FROM_LOCAL_LAST_PATH, path).apply();
  203. }
  204. @Override
  205. public String getLastUploadPath() {
  206. return preferences.getString(AUTO_PREF__LAST_UPLOAD_PATH, "");
  207. }
  208. @Override
  209. public void setLastUploadPath(String path) {
  210. preferences.edit().putString(AUTO_PREF__LAST_UPLOAD_PATH, path).apply();
  211. }
  212. @Override
  213. public String getLockPreference() {
  214. return preferences.getString(PREF__LOCK, SettingsActivity.LOCK_NONE);
  215. }
  216. @Override
  217. public void setLockPreference(String lockPreference) {
  218. preferences.edit().putString(PREF__LOCK, lockPreference).apply();
  219. }
  220. @Override
  221. public void setPassCode(String d1, String d2, String d3, String d4) {
  222. preferences
  223. .edit()
  224. .putString(PassCodeActivity.PREFERENCE_PASSCODE_D1, d1)
  225. .putString(PassCodeActivity.PREFERENCE_PASSCODE_D2, d2)
  226. .putString(PassCodeActivity.PREFERENCE_PASSCODE_D3, d3)
  227. .putString(PassCodeActivity.PREFERENCE_PASSCODE_D4, d4)
  228. .apply();
  229. }
  230. @Override
  231. public String[] getPassCode() {
  232. return new String[] {
  233. preferences.getString(PassCodeActivity.PREFERENCE_PASSCODE_D1, null),
  234. preferences.getString(PassCodeActivity.PREFERENCE_PASSCODE_D2, null),
  235. preferences.getString(PassCodeActivity.PREFERENCE_PASSCODE_D3, null),
  236. preferences.getString(PassCodeActivity.PREFERENCE_PASSCODE_D4, null),
  237. };
  238. }
  239. @Override
  240. public boolean isFingerprintUnlockEnabled() {
  241. return preferences.getBoolean(SettingsActivity.PREFERENCE_USE_FINGERPRINT, false);
  242. }
  243. @Override
  244. public String getFolderLayout(OCFile folder) {
  245. return getFolderPreference(context,
  246. currentAccountProvider.getUser(),
  247. PREF__FOLDER_LAYOUT,
  248. folder,
  249. FOLDER_LAYOUT_LIST);
  250. }
  251. @Override
  252. public void setFolderLayout(@Nullable OCFile folder, String layoutName) {
  253. setFolderPreference(context,
  254. currentAccountProvider.getUser(),
  255. PREF__FOLDER_LAYOUT,
  256. folder,
  257. layoutName);
  258. }
  259. @Override
  260. public FileSortOrder getSortOrderByFolder(OCFile folder) {
  261. return FileSortOrder.sortOrders.get(getFolderPreference(context,
  262. currentAccountProvider.getUser(),
  263. PREF__FOLDER_SORT_ORDER,
  264. folder,
  265. FileSortOrder.sort_a_to_z.name));
  266. }
  267. @Override
  268. public void setSortOrder(@Nullable OCFile folder, FileSortOrder sortOrder) {
  269. setFolderPreference(context,
  270. currentAccountProvider.getUser(),
  271. PREF__FOLDER_SORT_ORDER,
  272. folder,
  273. sortOrder.name);
  274. }
  275. @Override
  276. public FileSortOrder getSortOrderByType(FileSortOrder.Type type) {
  277. return getSortOrderByType(type, FileSortOrder.sort_a_to_z);
  278. }
  279. @Override
  280. public FileSortOrder getSortOrderByType(FileSortOrder.Type type, FileSortOrder defaultOrder) {
  281. User user = currentAccountProvider.getUser();
  282. if (user.isAnonymous()) {
  283. return defaultOrder;
  284. }
  285. ArbitraryDataProvider dataProvider = new ArbitraryDataProvider(context.getContentResolver());
  286. String value = dataProvider.getValue(user.getAccountName(), PREF__FOLDER_SORT_ORDER + "_" + type);
  287. return value.isEmpty() ? defaultOrder : FileSortOrder.sortOrders.get(value);
  288. }
  289. @Override
  290. public void setSortOrder(FileSortOrder.Type type, FileSortOrder sortOrder) {
  291. User user = currentAccountProvider.getUser();
  292. ArbitraryDataProvider dataProvider = new ArbitraryDataProvider(context.getContentResolver());
  293. dataProvider.storeOrUpdateKeyValue(user.getAccountName(), PREF__FOLDER_SORT_ORDER + "_" + type, sortOrder.name);
  294. }
  295. @Override
  296. public boolean isLegacyClean() {
  297. return preferences.getBoolean(PREF__LEGACY_CLEAN, false);
  298. }
  299. @Override
  300. public void setLegacyClean(boolean isLegacyClean) {
  301. preferences.edit().putBoolean(PREF__LEGACY_CLEAN, isLegacyClean).apply();
  302. }
  303. @Override
  304. public boolean isKeysMigrationEnabled() {
  305. return preferences.getBoolean(PREF__KEYS_MIGRATION, false);
  306. }
  307. @Override
  308. public void setKeysMigrationEnabled(boolean keysMigration) {
  309. preferences.edit().putBoolean(PREF__KEYS_MIGRATION, keysMigration).apply();
  310. }
  311. @Override
  312. public boolean isStoragePathFixEnabled() {
  313. return preferences.getBoolean(PREF__FIX_STORAGE_PATH, false);
  314. }
  315. @Override
  316. public void setStoragePathFixEnabled(boolean storagePathFixEnabled) {
  317. preferences.edit().putBoolean(PREF__FIX_STORAGE_PATH, storagePathFixEnabled).apply();
  318. }
  319. @Override
  320. public boolean isAutoUploadPathsUpdateEnabled() {
  321. return preferences.getBoolean(PREF__AUTO_UPLOAD_UPDATE_PATH, false);
  322. }
  323. @Override
  324. public void setAutoUploadPathsUpdateEnabled(boolean pathUpdate) {
  325. preferences.edit().putBoolean(PREF__AUTO_UPLOAD_UPDATE_PATH, pathUpdate).apply();
  326. }
  327. @Override
  328. public boolean isAutoUploadSplitEntriesEnabled() {
  329. return preferences.getBoolean(PREF__AUTO_UPLOAD_SPLIT_OUT, false);
  330. }
  331. @Override
  332. public void setAutoUploadSplitEntriesEnabled(boolean splitOut) {
  333. preferences.edit().putBoolean(PREF__AUTO_UPLOAD_SPLIT_OUT, splitOut).apply();
  334. }
  335. @Override
  336. public boolean isAutoUploadInitialized() {
  337. return preferences.getBoolean(PREF__AUTO_UPLOAD_INIT, false);
  338. }
  339. @Override
  340. public void setAutoUploadInit(boolean autoUploadInit) {
  341. preferences.edit().putBoolean(PREF__AUTO_UPLOAD_INIT, autoUploadInit).apply();
  342. }
  343. @Override
  344. public int getUploaderBehaviour() {
  345. return preferences.getInt(AUTO_PREF__UPLOADER_BEHAVIOR, 1);
  346. }
  347. @Override
  348. public void setDarkThemeMode(DarkMode mode) {
  349. preferences.edit().putString(PREF__DARK_THEME, mode.name()).apply();
  350. }
  351. @Override
  352. public DarkMode getDarkThemeMode() {
  353. try {
  354. return DarkMode.valueOf(preferences.getString(PREF__DARK_THEME, DarkMode.SYSTEM.name()));
  355. } catch (ClassCastException e) {
  356. preferences.edit().putString(PREF__DARK_THEME, DarkMode.SYSTEM.name()).apply();
  357. return DarkMode.SYSTEM;
  358. }
  359. }
  360. @Override
  361. public void setUploaderBehaviour(int uploaderBehaviour) {
  362. preferences.edit().putInt(AUTO_PREF__UPLOADER_BEHAVIOR, uploaderBehaviour).apply();
  363. }
  364. /**
  365. * Gets the grid columns which the user has set last.
  366. *
  367. * @return grid columns grid columns
  368. */
  369. @Override
  370. public float getGridColumns() {
  371. float columns = preferences.getFloat(AUTO_PREF__GRID_COLUMNS, DEFAULT_GRID_COLUMN);
  372. if (columns < 0) {
  373. return DEFAULT_GRID_COLUMN;
  374. } else {
  375. return columns;
  376. }
  377. }
  378. /**
  379. * Saves the grid columns which the user has set last.
  380. *
  381. * @param gridColumns the uploader behavior
  382. */
  383. @Override
  384. public void setGridColumns(float gridColumns) {
  385. preferences.edit().putFloat(AUTO_PREF__GRID_COLUMNS, gridColumns).apply();
  386. }
  387. @Override
  388. public int getLastSeenVersionCode() {
  389. return preferences.getInt(AUTO_PREF__LAST_SEEN_VERSION_CODE, 0);
  390. }
  391. @Override
  392. public void setLastSeenVersionCode(int versionCode) {
  393. preferences.edit().putInt(AUTO_PREF__LAST_SEEN_VERSION_CODE, versionCode).apply();
  394. }
  395. @Override
  396. public long getLockTimestamp() {
  397. return preferences.getLong(PREF__LOCK_TIMESTAMP, 0);
  398. }
  399. @Override
  400. public void setLockTimestamp(long timestamp) {
  401. preferences.edit().putLong(PREF__LOCK_TIMESTAMP, timestamp).apply();
  402. }
  403. @Override
  404. public boolean isShowDetailedTimestampEnabled() {
  405. return preferences.getBoolean(AUTO_PREF__SHOW_DETAILED_TIMESTAMP, false);
  406. }
  407. @Override
  408. public void setShowDetailedTimestampEnabled(boolean showDetailedTimestamp) {
  409. preferences.edit().putBoolean(AUTO_PREF__SHOW_DETAILED_TIMESTAMP, showDetailedTimestamp).apply();
  410. }
  411. @Override
  412. public boolean isShowMediaScanNotifications() {
  413. return preferences.getBoolean(PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS, true);
  414. }
  415. @Override
  416. public void setShowMediaScanNotifications(boolean value) {
  417. preferences.edit().putBoolean(PREF__SHOW_MEDIA_SCAN_NOTIFICATIONS, value).apply();
  418. }
  419. @Override
  420. public void removeLegacyPreferences() {
  421. preferences.edit()
  422. .remove("instant_uploading")
  423. .remove("instant_video_uploading")
  424. .remove("instant_upload_path")
  425. .remove("instant_upload_path_use_subfolders")
  426. .remove("instant_upload_on_wifi")
  427. .remove("instant_upload_on_charging")
  428. .remove("instant_video_upload_path")
  429. .remove("instant_video_upload_path_use_subfolders")
  430. .remove("instant_video_upload_on_wifi")
  431. .remove("instant_video_uploading")
  432. .remove("instant_video_upload_on_charging")
  433. .remove("prefs_instant_behaviour")
  434. .apply();
  435. }
  436. @Override
  437. public void clear() {
  438. preferences.edit().clear().apply();
  439. }
  440. @Override
  441. public String getStoragePath(String defaultPath) {
  442. return preferences.getString(STORAGE_PATH, defaultPath);
  443. }
  444. @SuppressLint("ApplySharedPref")
  445. @Override
  446. public void setStoragePath(String path) {
  447. preferences.edit().putString(STORAGE_PATH, path).commit(); // commit synchronously
  448. }
  449. @SuppressLint("ApplySharedPref")
  450. @Override
  451. public void setStoragePathValid() {
  452. preferences.edit().putBoolean(STORAGE_PATH_VALID, true).commit();
  453. }
  454. @Override
  455. public boolean isStoragePathValid() {
  456. return preferences.getBoolean(STORAGE_PATH_VALID, false);
  457. }
  458. /**
  459. * Removes keys migration key from shared preferences.
  460. */
  461. @SuppressLint("ApplySharedPref")
  462. @Override
  463. public void removeKeysMigrationPreference() {
  464. preferences.edit().remove(AppPreferencesImpl.PREF__KEYS_MIGRATION).commit(); // commit synchronously
  465. }
  466. @Override
  467. public String getCurrentAccountName() {
  468. return preferences.getString(PREF__SELECTED_ACCOUNT_NAME, null);
  469. }
  470. @Override
  471. public void setCurrentAccountName(String accountName) {
  472. preferences.edit().putString(PREF__SELECTED_ACCOUNT_NAME, accountName).apply();
  473. }
  474. @Override
  475. public boolean isUserIdMigrated() {
  476. return preferences.getBoolean(PREF__MIGRATED_USER_ID, false);
  477. }
  478. @Override
  479. public void setMigratedUserId(boolean value) {
  480. preferences.edit().putBoolean(PREF__MIGRATED_USER_ID, value).apply();
  481. }
  482. @Override
  483. public void setPhotoSearchTimestamp(long timestamp) {
  484. preferences.edit().putLong(PREF__PHOTO_SEARCH_TIMESTAMP, timestamp).apply();
  485. }
  486. @Override
  487. public long getPhotoSearchTimestamp() {
  488. return preferences.getLong(PREF__PHOTO_SEARCH_TIMESTAMP, 0);
  489. }
  490. /**
  491. * Get preference value for a folder.
  492. * If folder is not set itself, it finds an ancestor that is set.
  493. *
  494. * @param context Context object.
  495. * @param preferenceName Name of the preference to lookup.
  496. * @param folder Folder.
  497. * @param defaultValue Fallback value in case no ancestor is set.
  498. * @return Preference value
  499. */
  500. private static String getFolderPreference(final Context context,
  501. final User user,
  502. final String preferenceName,
  503. final OCFile folder,
  504. final String defaultValue) {
  505. if (user.isAnonymous()) {
  506. return defaultValue;
  507. }
  508. ArbitraryDataProvider dataProvider = new ArbitraryDataProvider(context.getContentResolver());
  509. FileDataStorageManager storageManager = new FileDataStorageManager(user.toPlatformAccount(), context.getContentResolver());
  510. String value = dataProvider.getValue(user.getAccountName(), getKeyFromFolder(preferenceName, folder));
  511. OCFile prefFolder = folder;
  512. while (prefFolder != null && value.isEmpty()) {
  513. prefFolder = storageManager.getFileById(prefFolder.getParentId());
  514. value = dataProvider.getValue(user.getAccountName(), getKeyFromFolder(preferenceName, prefFolder));
  515. }
  516. return value.isEmpty() ? defaultValue : value;
  517. }
  518. /**
  519. * Set preference value for a folder.
  520. *
  521. * @param context Context object.
  522. * @param preferenceName Name of the preference to set.
  523. * @param folder Folder.
  524. * @param value Preference value to set.
  525. */
  526. private static void setFolderPreference(final Context context,
  527. final User user,
  528. final String preferenceName,
  529. @Nullable final OCFile folder,
  530. final String value) {
  531. ArbitraryDataProvider dataProvider = new ArbitraryDataProvider(context.getContentResolver());
  532. dataProvider.storeOrUpdateKeyValue(user.getAccountName(), getKeyFromFolder(preferenceName, folder), value);
  533. }
  534. private static String getKeyFromFolder(String preferenceName, @Nullable OCFile folder) {
  535. final String folderIdString = String.valueOf(folder != null ? folder.getFileId() :
  536. FileDataStorageManager.ROOT_PARENT_ID);
  537. return preferenceName + "_" + folderIdString;
  538. }
  539. @Override
  540. public boolean isPowerCheckDisabled() {
  541. return preferences.getBoolean(PREF__POWER_CHECK_DISABLED, false);
  542. }
  543. @Override
  544. public void setPowerCheckDisabled(boolean value) {
  545. preferences.edit().putBoolean(PREF__POWER_CHECK_DISABLED, value).apply();
  546. }
  547. public void increasePinWrongAttempts() {
  548. int count = preferences.getInt(PREF__PIN_BRUTE_FORCE_COUNT, 0);
  549. preferences.edit().putInt(PREF__PIN_BRUTE_FORCE_COUNT, count + 1).apply();
  550. }
  551. @Override
  552. public void resetPinWrongAttempts() {
  553. preferences.edit().putInt(PREF__PIN_BRUTE_FORCE_COUNT, 0).apply();
  554. }
  555. public int pinBruteForceDelay() {
  556. int count = preferences.getInt(PREF__PIN_BRUTE_FORCE_COUNT, 0);
  557. return computeBruteForceDelay(count);
  558. }
  559. @VisibleForTesting
  560. public int computeBruteForceDelay(int count) {
  561. return (int) Math.min(count / 3d, 10);
  562. }
  563. }