summaryrefslogtreecommitdiff
path: root/packages/SystemUI/src/com/android/keyguard/clock/SettingsWrapper.java
blob: 096e94348429ed51587f9cb10aad09a9ddc9d2b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Copyright (C) 2019 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.keyguard.clock;

import android.annotation.Nullable;
import android.content.ContentResolver;
import android.provider.Settings;
import android.util.Log;

import com.android.internal.annotations.VisibleForTesting;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * Wrapper around Settings used for testing.
 */
public class SettingsWrapper {

    private static final String TAG = "ClockFaceSettings";
    private static final String CUSTOM_CLOCK_FACE = Settings.Secure.LOCK_SCREEN_CUSTOM_CLOCK_FACE;
    private static final String DOCKED_CLOCK_FACE = Settings.Secure.DOCKED_CLOCK_FACE;
    private static final String CLOCK_FIELD = "clock";

    private final ContentResolver mContentResolver;
    private final Migration mMigration;

    SettingsWrapper(ContentResolver contentResolver) {
        this(contentResolver, new Migrator(contentResolver));
    }

    @VisibleForTesting
    SettingsWrapper(ContentResolver contentResolver, Migration migration) {
        mContentResolver = contentResolver;
        mMigration = migration;
    }

    /**
     * Gets the value stored in settings for the custom clock face.
     *
     * @param userId ID of the user.
     */
    String getLockScreenCustomClockFace(int userId) {
        return decode(
                Settings.Secure.getStringForUser(mContentResolver, CUSTOM_CLOCK_FACE, userId),
                userId);
    }

    /**
     * Gets the value stored in settings for the clock face to use when docked.
     *
     * @param userId ID of the user.
     */
    String getDockedClockFace(int userId) {
        return Settings.Secure.getStringForUser(mContentResolver, DOCKED_CLOCK_FACE, userId);
    }

    /**
     * Decodes the string stored in settings, which should be formatted as JSON.
     * @param value String stored in settings. If value is not JSON, then the settings is
     *              overwritten with JSON containing the prior value.
     * @return ID of the clock face to show on AOD and lock screen. If value is not JSON, the value
     *         is returned.
     */
    @VisibleForTesting
    String decode(@Nullable String value, int userId) {
        if (value == null) {
            return value;
        }
        JSONObject json;
        try {
            json = new JSONObject(value);
        } catch (JSONException ex) {
            Log.e(TAG, "Settings value is not valid JSON", ex);
            // The settings value isn't JSON since it didn't parse so migrate the value to JSON.
            // TODO(b/135674383): Remove this migration path in the following release.
            mMigration.migrate(value, userId);
            return value;
        }
        try {
            return json.getString(CLOCK_FIELD);
        } catch (JSONException ex) {
            Log.e(TAG, "JSON object does not contain clock field.", ex);
            return null;
        }
    }

    interface Migration {
        void migrate(String value, int userId);
    }

    /**
     * Implementation of {@link Migration} that writes valid JSON back to Settings.
     */
    private static final class Migrator implements Migration {

        private final ContentResolver mContentResolver;

        Migrator(ContentResolver contentResolver) {
            mContentResolver = contentResolver;
        }

        /**
         * Migrate settings values that don't parse by converting to JSON format.
         *
         * Values in settings must be JSON to be backed up and restored. To help users maintain
         * their current settings, convert existing values into the JSON format.
         *
         * TODO(b/135674383): Remove this migration code in the following release.
         */
        @Override
        public void migrate(String value, int userId) {
            try {
                JSONObject json = new JSONObject();
                json.put(CLOCK_FIELD, value);
                Settings.Secure.putStringForUser(mContentResolver, CUSTOM_CLOCK_FACE,
                        json.toString(),
                        userId);
            } catch (JSONException ex) {
                Log.e(TAG, "Failed migrating settings value to JSON format", ex);
            }
        }
    }
}