1/*
2 * Copyright (C) 2016 Google Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package com.googlecode.android_scripting.facade;
18
19import android.app.AlarmManager;
20import android.app.Service;
21import android.app.admin.DevicePolicyManager;
22import android.content.Context;
23import android.content.Intent;
24import android.media.AudioManager;
25import android.os.PowerManager;
26import android.os.SystemClock;
27import android.os.UserHandle;
28import android.provider.Settings.SettingNotFoundException;
29import android.view.WindowManager;
30
31import com.android.internal.widget.LockPatternUtils;
32import com.googlecode.android_scripting.BaseApplication;
33import com.googlecode.android_scripting.FutureActivityTaskExecutor;
34import com.googlecode.android_scripting.Log;
35import com.googlecode.android_scripting.future.FutureActivityTask;
36import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
37import com.googlecode.android_scripting.rpc.Rpc;
38import com.googlecode.android_scripting.rpc.RpcOptional;
39import com.googlecode.android_scripting.rpc.RpcParameter;
40
41/**
42 * Exposes phone settings functionality.
43 *
44 * @author Frank Spychalski (frank.spychalski@gmail.com)
45 */
46public class SettingsFacade extends RpcReceiver {
47
48    private final Service mService;
49    private final AndroidFacade mAndroidFacade;
50    private final AudioManager mAudio;
51    private final PowerManager mPower;
52    private final AlarmManager mAlarm;
53    private final LockPatternUtils mLockPatternUtils;
54
55    /**
56     * Creates a new SettingsFacade.
57     *
58     * @param service is the {@link Context} the APIs will run under
59     */
60    public SettingsFacade(FacadeManager manager) {
61        super(manager);
62        mService = manager.getService();
63        mAndroidFacade = manager.getReceiver(AndroidFacade.class);
64        mAudio = (AudioManager) mService.getSystemService(Context.AUDIO_SERVICE);
65        mPower = (PowerManager) mService.getSystemService(Context.POWER_SERVICE);
66        mAlarm = (AlarmManager) mService.getSystemService(Context.ALARM_SERVICE);
67        mLockPatternUtils = new LockPatternUtils(mService);
68    }
69
70    @Rpc(description = "Sets the screen timeout to this number of seconds.",
71            returns = "The original screen timeout.")
72    public Integer setScreenTimeout(@RpcParameter(name = "value") Integer value) {
73        Integer oldValue = getScreenTimeout();
74        android.provider.Settings.System.putInt(mService.getContentResolver(),
75                android.provider.Settings.System.SCREEN_OFF_TIMEOUT, value * 1000);
76        return oldValue;
77    }
78
79    @Rpc(description = "Returns the current screen timeout in seconds.",
80            returns = "the current screen timeout in seconds.")
81    public Integer getScreenTimeout() {
82        try {
83            return android.provider.Settings.System.getInt(mService.getContentResolver(),
84                    android.provider.Settings.System.SCREEN_OFF_TIMEOUT) / 1000;
85        } catch (SettingNotFoundException e) {
86            return 0;
87        }
88    }
89
90    @Rpc(description = "Checks the ringer silent mode setting.",
91            returns = "True if ringer silent mode is enabled.")
92    public Boolean checkRingerSilentMode() {
93        return mAudio.getRingerMode() == AudioManager.RINGER_MODE_SILENT;
94    }
95
96    @Rpc(description = "Toggles ringer silent mode on and off.",
97            returns = "True if ringer silent mode is enabled.")
98    public Boolean toggleRingerSilentMode(
99            @RpcParameter(name = "enabled") @RpcOptional Boolean enabled) {
100        if (enabled == null) {
101            enabled = !checkRingerSilentMode();
102        }
103        mAudio.setRingerMode(enabled ? AudioManager.RINGER_MODE_SILENT
104                : AudioManager.RINGER_MODE_NORMAL);
105        return enabled;
106    }
107
108    @Rpc(description = "Set the ringer to a specified mode")
109    public void setRingerMode(@RpcParameter(name = "mode") Integer mode) throws Exception {
110        if (AudioManager.isValidRingerMode(mode)) {
111            mAudio.setRingerMode(mode);
112        } else {
113            throw new Exception("Ringer mode " + mode + " does not exist.");
114        }
115    }
116
117    @Rpc(description = "Returns the current ringtone mode.",
118            returns = "An integer representing the current ringer mode")
119    public Integer getRingerMode() {
120        return mAudio.getRingerMode();
121    }
122
123    @Rpc(description = "Returns the maximum ringer volume.")
124    public int getMaxRingerVolume() {
125        return mAudio.getStreamMaxVolume(AudioManager.STREAM_RING);
126    }
127
128    @Rpc(description = "Returns the current ringer volume.")
129    public int getRingerVolume() {
130        return mAudio.getStreamVolume(AudioManager.STREAM_RING);
131    }
132
133    @Rpc(description = "Sets the ringer volume.")
134    public void setRingerVolume(@RpcParameter(name = "volume") Integer volume) {
135        mAudio.setStreamVolume(AudioManager.STREAM_RING, volume, 0);
136    }
137
138    @Rpc(description = "Returns the maximum media volume.")
139    public int getMaxMediaVolume() {
140        return mAudio.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
141    }
142
143    @Rpc(description = "Returns the current media volume.")
144    public int getMediaVolume() {
145        return mAudio.getStreamVolume(AudioManager.STREAM_MUSIC);
146    }
147
148    @Rpc(description = "Sets the media volume.")
149    public void setMediaVolume(@RpcParameter(name = "volume") Integer volume) {
150        mAudio.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0);
151    }
152
153    @Rpc(description = "Returns the screen backlight brightness.",
154            returns = "the current screen brightness between 0 and 255")
155    public Integer getScreenBrightness() {
156        try {
157            return android.provider.Settings.System.getInt(mService.getContentResolver(),
158                    android.provider.Settings.System.SCREEN_BRIGHTNESS);
159        } catch (SettingNotFoundException e) {
160            return 0;
161        }
162    }
163
164    @Rpc(description = "return the system time since boot in nanoseconds")
165    public long getSystemElapsedRealtimeNanos() {
166        return SystemClock.elapsedRealtimeNanos();
167    }
168
169    @Rpc(description = "Sets the the screen backlight brightness.",
170            returns = "the original screen brightness.")
171    public Integer setScreenBrightness(
172            @RpcParameter(name = "value", description = "brightness value between 0 and 255") Integer value) {
173        if (value < 0) {
174            value = 0;
175        } else if (value > 255) {
176            value = 255;
177        }
178        final int brightness = value;
179        Integer oldValue = getScreenBrightness();
180        android.provider.Settings.System.putInt(mService.getContentResolver(),
181                android.provider.Settings.System.SCREEN_BRIGHTNESS, brightness);
182
183        FutureActivityTask<Object> task = new FutureActivityTask<Object>() {
184            @Override
185            public void onCreate() {
186                super.onCreate();
187                WindowManager.LayoutParams lp = getActivity().getWindow().getAttributes();
188                lp.screenBrightness = brightness * 1.0f / 255;
189                getActivity().getWindow().setAttributes(lp);
190                setResult(null);
191                finish();
192            }
193        };
194
195        FutureActivityTaskExecutor taskExecutor =
196                ((BaseApplication) mService.getApplication()).getTaskExecutor();
197        taskExecutor.execute(task);
198
199        return oldValue;
200    }
201
202    @Rpc(description = "Returns true if the device is in an interactive state.")
203    public Boolean isDeviceInteractive() throws Exception {
204        return mPower.isInteractive();
205    }
206
207    @Rpc(description = "Issues a request to put the device to sleep after a delay.")
208    public void goToSleep(Integer delay) {
209        mPower.goToSleep(SystemClock.uptimeMillis() + delay);
210    }
211
212    @Rpc(description = "Issues a request to put the device to sleep right away.")
213    public void goToSleepNow() {
214        mPower.goToSleep(SystemClock.uptimeMillis());
215    }
216
217    @Rpc(description = "Issues a request to wake the device up right away.")
218    public void wakeUpNow() {
219        mPower.wakeUp(SystemClock.uptimeMillis());
220    }
221
222    @Rpc(description = "Get Up time of device.",
223            returns = "Long value of device up time in milliseconds.")
224    public long getDeviceUpTime() throws Exception {
225        return SystemClock.elapsedRealtime();
226    }
227
228    @Rpc(description = "Set a string password to the device.")
229    public void setDevicePassword(@RpcParameter(name = "password") String password) {
230        // mLockPatternUtils.setLockPatternEnabled(true, UserHandle.myUserId());
231        mLockPatternUtils.setLockScreenDisabled(false, UserHandle.myUserId());
232        mLockPatternUtils.setCredentialRequiredToDecrypt(true);
233        mLockPatternUtils.saveLockPassword(password, null,
234                DevicePolicyManager.PASSWORD_QUALITY_NUMERIC, UserHandle.myUserId());
235    }
236
237    @Rpc(description = "Disable screen lock password on the device.")
238    public void disableDevicePassword() {
239        mLockPatternUtils.clearEncryptionPassword();
240        // mLockPatternUtils.setLockPatternEnabled(false, UserHandle.myUserId());
241        mLockPatternUtils.setLockScreenDisabled(true, UserHandle.myUserId());
242        mLockPatternUtils.setCredentialRequiredToDecrypt(false);
243        mLockPatternUtils.clearEncryptionPassword();
244        mLockPatternUtils.clearLock(UserHandle.myUserId());
245        mLockPatternUtils.setLockScreenDisabled(true, UserHandle.myUserId());
246    }
247
248    @Rpc(description = "Set the system time in epoch.")
249    public void setTime(Long currentTime) {
250        mAlarm.setTime(currentTime);
251    }
252
253    @Rpc(description = "Set the system time zone.")
254    public void setTimeZone(@RpcParameter(name = "timeZone") String timeZone) {
255        mAlarm.setTimeZone(timeZone);
256    }
257
258    @Rpc(description = "Show Home Screen")
259    public void showHomeScreen() {
260        Intent intent = new Intent(Intent.ACTION_MAIN);
261        intent.addCategory(Intent.CATEGORY_HOME);
262        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
263        try {
264            mAndroidFacade.startActivityIntent(intent, false);
265        } catch (RuntimeException e) {
266            Log.d("showHomeScreen RuntimeException" + e);
267        } catch (Exception e){
268            Log.d("showHomeScreen exception" + e);
269        }
270    }
271
272    @Override
273    public void shutdown() {
274        // Nothing to do yet.
275    }
276}
277