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 
17 package com.googlecode.android_scripting.facade;
18 
19 import android.app.AlarmManager;
20 import android.app.Service;
21 import android.app.admin.DevicePolicyManager;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.media.AudioManager;
25 import android.os.PowerManager;
26 import android.os.SystemClock;
27 import android.os.UserHandle;
28 import android.provider.Settings.SettingNotFoundException;
29 import android.view.WindowManager;
30 
31 import com.android.internal.widget.LockPatternUtils;
32 import com.googlecode.android_scripting.BaseApplication;
33 import com.googlecode.android_scripting.FutureActivityTaskExecutor;
34 import com.googlecode.android_scripting.Log;
35 import com.googlecode.android_scripting.future.FutureActivityTask;
36 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
37 import com.googlecode.android_scripting.rpc.Rpc;
38 import com.googlecode.android_scripting.rpc.RpcOptional;
39 import com.googlecode.android_scripting.rpc.RpcParameter;
40 
41 /**
42  * Exposes phone settings functionality.
43  *
44  * @author Frank Spychalski (frank.spychalski@gmail.com)
45  */
46 public 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      */
SettingsFacade(FacadeManager manager)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.")
setScreenTimeout(@pcParametername = "value") Integer value)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.")
getScreenTimeout()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.")
checkRingerSilentMode()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.")
toggleRingerSilentMode( @pcParametername = "enabled") @pcOptional Boolean 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")
setRingerMode(@pcParametername = "mode") Integer 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")
getRingerMode()119     public Integer getRingerMode() {
120         return mAudio.getRingerMode();
121     }
122 
123     @Rpc(description = "Returns the maximum ringer volume.")
getMaxRingerVolume()124     public int getMaxRingerVolume() {
125         return mAudio.getStreamMaxVolume(AudioManager.STREAM_RING);
126     }
127 
128     @Rpc(description = "Returns the current ringer volume.")
getRingerVolume()129     public int getRingerVolume() {
130         return mAudio.getStreamVolume(AudioManager.STREAM_RING);
131     }
132 
133     @Rpc(description = "Sets the ringer volume.")
setRingerVolume(@pcParametername = "volume") Integer 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.")
getMaxMediaVolume()139     public int getMaxMediaVolume() {
140         return mAudio.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
141     }
142 
143     @Rpc(description = "Returns the current media volume.")
getMediaVolume()144     public int getMediaVolume() {
145         return mAudio.getStreamVolume(AudioManager.STREAM_MUSIC);
146     }
147 
148     @Rpc(description = "Sets the media volume.")
setMediaVolume(@pcParametername = "volume") Integer 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")
getScreenBrightness()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")
getSystemElapsedRealtimeNanos()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.")
setScreenBrightness( @pcParametername = "value", description = "brightness value between 0 and 255") Integer value)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.")
isDeviceInteractive()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.")
goToSleep(Integer 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.")
goToSleepNow()213     public void goToSleepNow() {
214         mPower.goToSleep(SystemClock.uptimeMillis());
215     }
216 
217     @Rpc(description = "Issues a request to wake the device up right away.")
wakeUpNow()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.")
getDeviceUpTime()224     public long getDeviceUpTime() throws Exception {
225         return SystemClock.elapsedRealtime();
226     }
227 
228     @Rpc(description = "Set a string password to the device.")
setDevicePassword(@pcParametername = "password") String password)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.")
disableDevicePassword()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.")
setTime(Long currentTime)249     public void setTime(Long currentTime) {
250         mAlarm.setTime(currentTime);
251     }
252 
253     @Rpc(description = "Set the system time zone.")
setTimeZone(@pcParametername = "timeZone") String timeZone)254     public void setTimeZone(@RpcParameter(name = "timeZone") String timeZone) {
255         mAlarm.setTimeZone(timeZone);
256     }
257 
258     @Rpc(description = "Show Home Screen")
showHomeScreen()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
shutdown()273     public void shutdown() {
274         // Nothing to do yet.
275     }
276 }
277