165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/*
265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project
365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License");
565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License.
665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at
765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *      http://www.apache.org/licenses/LICENSE-2.0
965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane *
1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software
1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS,
1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and
1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License.
1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */
1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.util;
1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.R;
2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.ContentResolver;
2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context;
2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.res.Resources;
2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.AsyncTask;
2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.IBinder;
2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Parcel;
2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.RemoteException;
2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.ServiceManager;
2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.SystemProperties;
2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.provider.Settings;
3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.provider.Settings.SettingNotFoundException;
3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Log;
3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.IWindowManager;
3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.view.View;
3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList;
3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class SettingsHelper {
3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final String TAG = "SettingsHelper";
4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private static final boolean DEBUG = false;
4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Context mContext;
4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private ContentResolver mContentResolver;
4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private Resources mResources;
4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public SettingsHelper(Context context) {
4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mContext = context;
4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mContentResolver = context.getContentResolver();
4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        mResources = context.getResources();
5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Returns a human readable Status description of the setting's value.
5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getSecureStatusIntSetting(String setting) {
5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        try {
5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return getStatusStringFromInt(Settings.Secure.getInt(mContentResolver, setting));
5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } catch (SettingNotFoundException e) {
5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Log.d(TAG, "setting: " + setting + " not found");
6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // TODO: show error message
6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return null;
6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Returns a string representation of the Integer setting's value.
6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getSecureIntSetting(String setting, String def) {
6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return Integer.toString(
7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                Settings.Secure.getInt(mContentResolver, setting, Integer.parseInt(def)));
7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Returns the int as a boolean, for use in determining "on|off".
7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean getSecureIntValueSettingToBoolean(String setting) {
7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        try {
7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return Settings.Secure.getInt(mContentResolver, setting) == 1;
7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } catch (SettingNotFoundException e) {
8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return false;
8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setSecureIntSetting(String setting, boolean value) {
8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int settingValue = value ? 1 : 0;
8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Settings.Secure.putInt(mContentResolver, setting, settingValue);
8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setSecureIntValueSetting(String setting, Object value) {
9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int settingValue = Integer.parseInt((String) value);
9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Settings.Secure.putInt(mContentResolver, setting, settingValue);
9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Returns a human readable description of the setting's value.
9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getSystemIntSetting(String setting) {
9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        try {
9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return getStatusStringFromInt(Settings.System.getInt(mContentResolver, setting));
10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } catch (SettingNotFoundException e) {
10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Log.d(TAG, "setting: " + setting + " not found");
10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // TODO: show error message
10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return null;
10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean getSystemIntSettingToBoolean(String setting) {
10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        try {
10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return Settings.System.getInt(mContentResolver, setting) == 1;
11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } catch (SettingNotFoundException e) {
11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return false;
11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setSystemIntSetting(String setting, boolean value) {
11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int settingValue = value ? 1 : 0;
11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Settings.System.putInt(mContentResolver, setting, settingValue);
11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setSystemProperties(String setting, String value) {
12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        SystemProperties.set(setting, value);
12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        pokeSystemProperties();
12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getSystemProperties(String setting) {
12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return SystemProperties.get(setting);
12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Returns a human readable description of the setting's value.
13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getSystemBooleanProperties(String setting) {
13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return getStatusStringFromBoolean(SystemProperties.getBoolean(setting, false));
13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    private void pokeSystemProperties() {
13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        (new SystemPropPoker()).execute();
13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    static class SystemPropPoker extends AsyncTask<Void, Void, Void> {
14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        @Override
14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        protected Void doInBackground(Void... params) {
14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            String[] services;
14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            try {
14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                services = ServiceManager.listServices();
14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            } catch (RemoteException e) {
14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                return null;
14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            for (String service : services) {
14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                IBinder obj = ServiceManager.checkService(service);
15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                if (obj != null) {
15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    Parcel data = Parcel.obtain();
15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    try {
15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        obj.transact(IBinder.SYSPROPS_TRANSACTION, data, null, 0);
15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    } catch (RemoteException e) {
15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    } catch (Exception e) {
15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                        Log.i(TAG, "Somone wrote a bad service '" + service
15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                                + "' that doesn't like to be poked: " + e);
15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    }
15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                    data.recycle();
16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                }
16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            }
16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return null;
16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
16665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getGlobalIntSetting(String setting) {
16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        try {
16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return getStatusStringFromInt(Settings.Global.getInt(mContentResolver, setting));
16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } catch (SettingNotFoundException e) {
17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Log.d(TAG, "setting: " + setting + " not found");
17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // TODO: show error message
17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        // Default to OFF if not found.
17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mResources.getString(R.string.action_off_description);
17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public int getGlobalIntSettingToInt(String setting) {
17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        try {
17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return Settings.Global.getInt(mContentResolver, setting);
18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        } catch (SettingNotFoundException e) {
18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            Log.d(TAG, "setting: " + setting + " not found");
18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            // TODO: show error message
18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return 0;
18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean getGlobalIntSettingAsBoolean(String setting) {
18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return Settings.Global.getInt(mContentResolver, setting, 0) != 0;
18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public void setGlobalIntSetting(String setting, boolean value) {
19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int settingValue = value ? 1 : 0;
19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        Settings.Global.putInt(mContentResolver, setting, settingValue);
19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getStatusStringFromBoolean(boolean status) {
19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int descResId = status ? R.string.action_on_description : R.string.action_off_description;
19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mResources.getString(descResId);
19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public String getStatusStringFromInt(int status) {
20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        int descResId = status > 0 ? R.string.action_on_description :
20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane                R.string.action_off_description;
20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return mResources.getString(descResId);
20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    /**
20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * Translates a status string into a boolean value.
20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *
21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @param status Status string ("ON"/"OFF")
21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     * @return true if the provided status string equals the localized
21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     *         R.string.action_on_description; false otherwise.
21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane     */
21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    public boolean getStatusFromString(String status) {
21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        if (status == null) {
21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane            return false;
21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        }
21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane        return status.equalsIgnoreCase(mResources.getString(R.string.action_on_description));
21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane    }
22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane
22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane}
222