1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of 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,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.tradefed.targetprep;
18 
19 import com.android.ddmlib.IDevice;
20 import com.android.tradefed.build.IBuildInfo;
21 import com.android.tradefed.config.Option;
22 import com.android.tradefed.config.OptionClass;
23 import com.android.tradefed.device.DeviceNotAvailableException;
24 import com.android.tradefed.device.ITestDevice;
25 import com.android.tradefed.device.StubDevice;
26 import com.android.tradefed.log.LogUtil.CLog;
27 import com.android.tradefed.util.BinaryState;
28 import com.android.tradefed.util.MultiMap;
29 
30 import com.google.common.annotations.VisibleForTesting;
31 
32 import java.io.File;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 
39 /**
40  * A {@link ITargetPreparer} that configures a device for testing based on provided {@link Option}s.
41  *
42  * <p>Requires a device where 'adb root' is possible, typically a userdebug build type.
43  *
44  * <p>Should be performed <strong>after</strong> a new build is flashed.
45  */
46 @OptionClass(alias = "device-setup")
47 public class DeviceSetup extends BaseTargetPreparer implements ITargetCleaner {
48 
49     // Networking
50     @Option(name = "airplane-mode",
51             description = "Turn airplane mode on or off")
52     protected BinaryState mAirplaneMode = BinaryState.IGNORE;
53     // ON:  settings put global airplane_mode_on 1
54     //      am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true
55     // OFF: settings put global airplane_mode_on 0
56     //      am broadcast -a android.intent.action.AIRPLANE_MODE --ez state false
57 
58     @Option(name = "data", description = "Turn mobile data on or off")
59     protected BinaryState mData = BinaryState.IGNORE;
60     // ON:  settings put global mobile_data 1
61     //      svc data enable
62     // OFF: settings put global mobile_data 0
63     //      svc data disable
64 
65     @Option(name = "cell", description = "Turn cellular radio on or off")
66     protected BinaryState mCell = BinaryState.IGNORE;
67     // ON:  settings put global cell_on 1
68     // OFF: settings put global cell_on 0
69 
70     @Option(name = "cell-auto-setting", description = "Turn wear cellular mediator on or off")
71     protected BinaryState mCellAutoSetting = BinaryState.IGNORE;
72     // ON:  settings put global clockwork_cell_auto_setting 1
73     // OFF: settings put global clockwork_cell_auto_setting 0
74 
75     @Option(name = "wifi", description = "Turn wifi on or off")
76     protected BinaryState mWifi = BinaryState.IGNORE;
77     // ON:  settings put global wifi_on 1
78     //      svc wifi enable
79     // OFF: settings put global wifi_off 0
80     //      svc wifi disable
81 
82     @Option(name = "wifi-network",
83             description = "The SSID of the network to connect to. Will only attempt to " +
84             "connect to a network if set")
85     protected String mWifiSsid = null;
86 
87     @Option(name = "wifi-psk",
88             description = "The passphrase used to connect to a secured network")
89     protected String mWifiPsk = null;
90 
91     @Option(name = "wifi-watchdog",
92             description = "Turn wifi watchdog on or off")
93     protected BinaryState mWifiWatchdog = BinaryState.IGNORE;
94     // ON:  settings put global wifi_watchdog 1
95     // OFF: settings put global wifi_watchdog 0
96 
97     @Option(name = "disable-cw-wifi-mediator", description = "Turn wifi mediator on or off")
98     protected BinaryState mDisableCwWifiMediator = BinaryState.IGNORE;
99     // ON:  settings put global cw_disable_wifimediator 1
100     // OFF: settings put global cw_disable_wifimediator 0
101 
102     @Option(
103         name = "wifi-scan-always-enabled",
104         description = "Turn wifi scan always enabled on or off"
105     )
106     protected BinaryState mWifiScanAlwaysEnabled = BinaryState.IGNORE;
107     // ON:  settings put global wifi_scan_always_enabled 1
108     // OFF: settings put global wifi_scan_always_enabled 0
109 
110     @Option(name = "ethernet",
111             description = "Turn ethernet on or off")
112     protected BinaryState mEthernet = BinaryState.IGNORE;
113     // ON:  ifconfig eth0 up
114     // OFF: ifconfig eth0 down
115 
116     @Option(name = "bluetooth",
117             description = "Turn bluetooth on or off")
118     protected BinaryState mBluetooth = BinaryState.IGNORE;
119     // ON:  service call bluetooth_manager 6
120     // OFF: service call bluetooth_manager 8
121 
122     @Option(name = "nfc",
123             description = "Turn nfc on or off")
124     protected BinaryState mNfc = BinaryState.IGNORE;
125     // ON:  svc nfc enable
126     // OFF: svc nfc disable
127 
128     // Screen
129     @Option(name = "screen-adaptive-brightness",
130             description = "Turn screen adaptive brightness on or off")
131     protected BinaryState mScreenAdaptiveBrightness = BinaryState.IGNORE;
132     // ON:  settings put system screen_brightness_mode 1
133     // OFF: settings put system screen_brightness_mode 0
134 
135     @Option(name = "screen-brightness",
136             description = "Set the screen brightness. This is uncalibrated from product to product")
137     protected Integer mScreenBrightness = null;
138     // settings put system screen_brightness $N
139 
140     @Option(name = "screen-always-on",
141             description = "Turn 'screen always on' on or off. If ON, then screen-timeout-secs " +
142             "must be unset. Will only work when the device is plugged in")
143     protected BinaryState mScreenAlwaysOn = BinaryState.ON;
144     // ON:  svc power stayon true
145     // OFF: svc power stayon false
146 
147     @Option(name = "screen-timeout-secs",
148             description = "Set the screen timeout in seconds. If set, then screen-always-on must " +
149             "be OFF or DEFAULT")
150     protected Long mScreenTimeoutSecs = null;
151     // settings put system screen_off_timeout $(N * 1000)
152 
153     @Option(name = "screen-ambient-mode",
154             description = "Turn screen ambient mode on or off")
155     protected BinaryState mScreenAmbientMode = BinaryState.IGNORE;
156     // ON:  settings put secure doze_enabled 1
157     // OFF: settings put secure doze_enabled 0
158 
159     @Option(name = "wake-gesture",
160             description = "Turn wake gesture on or off")
161     protected BinaryState mWakeGesture = BinaryState.IGNORE;
162     // ON:  settings put secure wake_gesture_enabled 1
163     // OFF: settings put secure wake_gesture_enabled 0
164 
165     @Option(name = "screen-saver",
166             description = "Turn screen saver on or off")
167     protected BinaryState mScreenSaver = BinaryState.IGNORE;
168     // ON:  settings put secure screensaver_enabled 1
169     // OFF: settings put secure screensaver_enabled 0
170 
171     @Option(name = "notification-led",
172             description = "Turn the notification led on or off")
173     protected BinaryState mNotificationLed = BinaryState.IGNORE;
174     // ON:  settings put system notification_light_pulse 1
175     // OFF: settings put system notification_light_pulse 0
176 
177     @Option(name = "install-non-market-apps",
178             description = "Allow or prevent non-market app to initiate an apk install request")
179     protected BinaryState mInstallNonMarketApps = BinaryState.IGNORE;
180     // ON:  settings put secure install_non_market_apps 1
181     // OFF: settings put secure install_non_market_apps 0
182 
183     // Media
184     @Option(name = "trigger-media-mounted",
185             description = "Trigger a MEDIA_MOUNTED broadcast")
186     protected boolean mTriggerMediaMounted = false;
187     // am broadcast -a android.intent.action.MEDIA_MOUNTED -d file://${EXTERNAL_STORAGE}
188     // --receiver-include-background
189 
190     // Location
191     @Option(name = "location-gps", description = "Turn the GPS location on or off")
192     protected BinaryState mLocationGps = BinaryState.IGNORE;
193     // ON:  settings put secure location_providers_allowed +gps
194     // OFF: settings put secure location_providers_allowed -gps
195 
196     @Option(name = "location-network",
197             description = "Turn the network location on or off")
198     protected BinaryState mLocationNetwork = BinaryState.IGNORE;
199     // ON:  settings put secure location_providers_allowed +network
200     // OFF: settings put secure location_providers_allowed -network
201 
202     // Sensor
203     @Option(name = "auto-rotate",
204             description = "Turn auto rotate on or off")
205     protected BinaryState mAutoRotate = BinaryState.IGNORE;
206     // ON:  settings put system accelerometer_rotation 1
207     // OFF: settings put system accelerometer_rotation 0
208 
209     // Power
210     @Option(name = "battery-saver-mode",
211             description = "Turn battery saver mode manually on or off. If OFF but battery is " +
212             "less battery-saver-trigger, the device will still go into battery saver mode")
213     protected BinaryState mBatterySaver = BinaryState.IGNORE;
214     // ON:  dumpsys battery set usb 0
215     //      settings put global low_power 1
216     // OFF: settings put global low_power 0
217 
218     @Option(name = "battery-saver-trigger",
219             description = "Set the battery saver trigger level. Should be [1-99] to enable, or " +
220             "0 to disable automatic battery saver mode")
221     protected Integer mBatterySaverTrigger = null;
222     // settings put global low_power_trigger_level $N
223 
224     @Option(name = "enable-full-battery-stats-history",
225             description = "Enable full history for batterystats. This option is only " +
226             "applicable for L+")
227     protected boolean mEnableFullBatteryStatsHistory = false;
228     // dumpsys batterystats --enable full-history
229 
230     @Option(name = "disable-doze",
231             description = "Disable device from going into doze mode. This option is only " +
232             "applicable for M+")
233     protected boolean mDisableDoze = false;
234     // dumpsys deviceidle disable
235 
236     // Time
237     @Option(name = "auto-update-time",
238             description = "Turn auto update time on or off")
239     protected BinaryState mAutoUpdateTime = BinaryState.IGNORE;
240     // ON:  settings put global auto_time 1
241     // OFF: settings put global auto_time 0
242 
243     @Option(name = "auto-update-timezone", description = "Turn auto update timezone on or off")
244     protected BinaryState mAutoUpdateTimezone = BinaryState.IGNORE;
245     // ON:  settings put global auto_timezone 1
246     // OFF: settings put global auto_timezone 0
247 
248     @Option(
249         name = "set-timezone",
250         description =
251                 "Set timezone property by TZ name "
252                         + "(http://en.wikipedia.org/wiki/List_of_tz_database_time_zones)"
253     )
254     protected String mTimezone = null;
255 
256     // Calling
257     @Option(name = "disable-dialing",
258             description = "Disable dialing")
259     protected boolean mDisableDialing = true;
260     // setprop ro.telephony.disable-call true"
261 
262     @Option(name = "default-sim-data",
263             description = "Set the default sim card slot for data. Leave unset for single SIM " +
264             "devices")
265     protected Integer mDefaultSimData = null;
266     // settings put global multi_sim_data_call $N
267 
268     @Option(name = "default-sim-voice",
269             description = "Set the default sim card slot for voice calls. Leave unset for single " +
270             "SIM devices")
271     protected Integer mDefaultSimVoice = null;
272     // settings put global multi_sim_voice_call $N
273 
274     @Option(name = "default-sim-sms",
275             description = "Set the default sim card slot for SMS. Leave unset for single SIM " +
276             "devices")
277     protected Integer mDefaultSimSms = null;
278     // settings put global multi_sim_sms $N
279 
280     // Audio
281     private static final boolean DEFAULT_DISABLE_AUDIO = true;
282     @Option(name = "disable-audio",
283             description = "Disable the audio")
284     protected boolean mDisableAudio = DEFAULT_DISABLE_AUDIO;
285     // setprop ro.audio.silent 1"
286 
287     @Option(name = "force-skip-system-props",
288             description = "Force setup to not modify any device system properties. All other " +
289             "system property options will be ignored")
290     protected boolean mForceSkipSystemProps = false;
291 
292     @Option(name = "force-skip-settings",
293             description = "Force setup to not modify any device settings. All other setting " +
294             "options will be ignored.")
295     protected boolean mForceSkipSettings = false;
296 
297     @Option(name = "force-skip-run-commands",
298             description = "Force setup to not run any additional commands. All other commands " +
299             "will be ignored.")
300     protected boolean mForceSkipRunCommands = false;
301 
302     @Option(name = "set-test-harness",
303             description = "Set the read-only test harness flag on boot")
304     protected boolean mSetTestHarness = true;
305     // setprop ro.monkey 1
306     // setprop ro.test_harness 1
307 
308     @Option(name = "disable-dalvik-verifier",
309             description = "Disable the dalvik verifier on device. Allows package-private " +
310             "framework tests to run.")
311     protected boolean mDisableDalvikVerifier = false;
312     // setprop dalvik.vm.dexopt-flags v=n
313 
314     @Option(name = "set-property",
315             description = "Set the specified property on boot. Option may be repeated but only " +
316             "the last value for a given key will be set.")
317     protected Map<String, String> mSetProps = new HashMap<>();
318 
319     @Option(
320         name = "restore-properties",
321         description =
322                 "Restore previous /data/local.prop on tear down, restoring any properties DeviceSetup changed by modifying /data/local.prop."
323     )
324     protected boolean mRestoreProperties = false;
325 
326     protected File mPreviousProperties;
327 
328     @Option(name = "set-system-setting",
329             description = "Change a system (non-secure) setting. Option may be repeated and all " +
330             "key/value pairs will be set in order.")
331     // Use a Multimap since it is possible for a setting to have multiple values for the same key
332     protected MultiMap<String, String> mSystemSettings = new MultiMap<>();
333 
334     @Option(name = "set-secure-setting",
335             description = "Change a secure setting. Option may be repeated and all key/value " +
336             "pairs will be set in order.")
337     // Use a Multimap since it is possible for a setting to have multiple values for the same key
338     protected MultiMap<String, String> mSecureSettings = new MultiMap<>();
339 
340     @Option(name = "set-global-setting",
341             description = "Change a global setting. Option may be repeated and all key/value " +
342             "pairs will be set in order.")
343     // Use a Multimap since it is possible for a setting to have multiple values for the same key
344     protected MultiMap<String, String> mGlobalSettings = new MultiMap<>();
345 
346     @Option(
347         name = "restore-settings",
348         description = "Restore settings modified by this preparer on tear down."
349     )
350     protected boolean mRestoreSettings = false;
351 
352     private Map<String, String> mPreviousSystemSettings = new HashMap<>();
353     private Map<String, String> mPreviousSecureSettings = new HashMap<>();
354     private Map<String, String> mPreviousGlobalSettings = new HashMap<>();
355 
356     protected List<String> mRunCommandBeforeSettings = new ArrayList<>();
357 
358     @Option(name = "run-command",
359             description = "Run an adb shell command. Option may be repeated")
360     protected List<String> mRunCommandAfterSettings = new ArrayList<>();
361 
362     @Option(name = "disconnect-wifi-after-test",
363             description = "Disconnect from wifi network after test completes.")
364     private boolean mDisconnectWifiAfterTest = true;
365 
366     private static final long DEFAULT_MIN_EXTERNAL_STORAGE_KB = 500;
367     @Option(name = "min-external-storage-kb",
368             description="The minimum amount of free space in KB that must be present on device's " +
369             "external storage.")
370     protected long mMinExternalStorageKb = DEFAULT_MIN_EXTERNAL_STORAGE_KB;
371 
372     @Option(name = "local-data-path",
373             description = "Optional local file path of test data to sync to device's external " +
374             "storage. Use --remote-data-path to set remote location.")
375     protected File mLocalDataFile = null;
376 
377     @Option(name = "remote-data-path",
378             description = "Optional file path on device's external storage to sync test data. " +
379             "Must be used with --local-data-path.")
380     protected String mRemoteDataPath = null;
381 
382     // Deprecated options follow
383     /**
384      * @deprecated use min-external-storage-kb instead.
385      */
386     @Option(name = "min-external-store-space",
387             description = "deprecated, use option min-external-storage-kb. The minimum amount of " +
388             "free space in KB that must be present on device's external storage.")
389     @Deprecated
390     private long mDeprecatedMinExternalStoreSpace = DEFAULT_MIN_EXTERNAL_STORAGE_KB;
391 
392     /**
393      * @deprecated use option disable-audio instead.
394      */
395     @Option(name = "audio-silent",
396             description = "deprecated, use option disable-audio. set ro.audio.silent on boot.")
397     @Deprecated
398     private boolean mDeprecatedSetAudioSilent = DEFAULT_DISABLE_AUDIO;
399 
400     /**
401      * @deprecated use option set-property instead.
402      */
403     @Option(name = "setprop",
404             description = "deprecated, use option set-property. set the specified property on " +
405             "boot. Format: --setprop key=value. May be repeated.")
406     @Deprecated
407     private Collection<String> mDeprecatedSetProps = new ArrayList<String>();
408 
409     private static final String PERSIST_PREFIX = "persist.";
410 
411     /**
412      * {@inheritDoc}
413      */
414     @Override
setUp(ITestDevice device, IBuildInfo buildInfo)415     public void setUp(ITestDevice device, IBuildInfo buildInfo) throws DeviceNotAvailableException,
416             TargetSetupError {
417         if (isDisabled()) {
418             return;
419         }
420 
421         CLog.i("Performing setup on %s", device.getSerialNumber());
422 
423         if (device.getOptions().isEnableAdbRoot() && !device.enableAdbRoot()) {
424             throw new TargetSetupError(String.format("Failed to enable adb root on %s",
425                     device.getSerialNumber()), device.getDeviceDescriptor());
426         }
427 
428         // Convert deprecated options into current options
429         processDeprecatedOptions(device);
430         // Convert options into settings and run commands
431         processOptions(device);
432         // Change system props (will reboot device)
433         changeSystemProps(device);
434         // Handle screen always on setting
435         handleScreenAlwaysOnSetting(device);
436         // Run commands designated to be run before changing settings
437         runCommands(device, mRunCommandBeforeSettings);
438         // Change settings
439         changeSettings(device);
440         // Connect wifi after settings since this may take a while
441         connectWifi(device);
442         // Sync data after settings since this may take a while
443         syncTestData(device);
444         // Run commands designated to be run after changing settings
445         runCommands(device, mRunCommandAfterSettings);
446         // Throw an error if there is not enough storage space
447         checkExternalStoreSpace(device);
448 
449         device.clearErrorDialogs();
450     }
451 
452     /**
453      * {@inheritDoc}
454      */
455     @Override
tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)456     public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
457             throws DeviceNotAvailableException {
458         // ignore tearDown if it's a stub device, since there is no real device to clean.
459         if (isDisabled() || device.getIDevice() instanceof StubDevice) {
460             return;
461         }
462 
463         CLog.i("Performing teardown on %s", device.getSerialNumber());
464 
465         if (e instanceof DeviceFailedToBootError) {
466             CLog.d("boot failure: skipping teardown");
467             return;
468         }
469 
470         // Only try to disconnect if wifi ssid is set since isWifiEnabled() is a heavy operation
471         // which should be avoided when possible
472         if (mDisconnectWifiAfterTest && mWifiSsid != null && device.isWifiEnabled()) {
473             boolean result = device.disconnectFromWifi();
474             if (result) {
475                 CLog.i("Successfully disconnected from wifi network on %s",
476                         device.getSerialNumber());
477             } else {
478                 CLog.w("Failed to disconnect from wifi network on %s", device.getSerialNumber());
479             }
480         }
481 
482         if (mRestoreProperties) {
483             if (mPreviousProperties != null) {
484                 device.pushFile(mPreviousProperties, "/data/local.prop");
485             } else {
486                 device.executeShellCommand("rm -f /data/local.prop");
487             }
488             device.reboot();
489         }
490 
491         if (mRestoreSettings) {
492             for (Map.Entry<String, String> entry : mPreviousSystemSettings.entrySet()) {
493                 device.setSetting("system", entry.getKey(), entry.getValue());
494             }
495             for (Map.Entry<String, String> entry : mPreviousGlobalSettings.entrySet()) {
496                 device.setSetting("global", entry.getKey(), entry.getValue());
497             }
498             for (Map.Entry<String, String> entry : mPreviousSecureSettings.entrySet()) {
499                 device.setSetting("secure", entry.getKey(), entry.getValue());
500             }
501         }
502     }
503 
504     /**
505      * Processes the deprecated options converting them into the currently used options.
506      * <p>
507      * This method should be run before any other processing methods. Will throw a
508      * {@link TargetSetupError} if the deprecated option overrides a specified non-deprecated
509      * option.
510      * </p>
511      * @throws TargetSetupError if there is a conflict
512      */
processDeprecatedOptions(ITestDevice device)513     public void processDeprecatedOptions(ITestDevice device) throws TargetSetupError {
514         if (mDeprecatedMinExternalStoreSpace != DEFAULT_MIN_EXTERNAL_STORAGE_KB) {
515             if (mMinExternalStorageKb != DEFAULT_MIN_EXTERNAL_STORAGE_KB) {
516                 throw new TargetSetupError("Deprecated option min-external-store-space conflicts " +
517                         "with option min-external-storage-kb", device.getDeviceDescriptor());
518             }
519             mMinExternalStorageKb = mDeprecatedMinExternalStoreSpace;
520         }
521 
522         if (mDeprecatedSetAudioSilent != DEFAULT_DISABLE_AUDIO) {
523             if (mDisableAudio != DEFAULT_DISABLE_AUDIO) {
524                 throw new TargetSetupError("Deprecated option audio-silent conflicts with " +
525                         "option disable-audio", device.getDeviceDescriptor());
526             }
527             mDisableAudio = mDeprecatedSetAudioSilent;
528         }
529 
530         if (!mDeprecatedSetProps.isEmpty()) {
531             if (!mSetProps.isEmpty()) {
532                 throw new TargetSetupError("Deprecated option setprop conflicts with option " +
533                         "set-property ", device.getDeviceDescriptor());
534             }
535             for (String prop : mDeprecatedSetProps) {
536                 String[] parts = prop.split("=", 2);
537                 String key = parts[0].trim();
538                 String value = parts.length == 2 ? parts[1].trim() : "";
539                 mSetProps.put(key, value);
540             }
541         }
542     }
543 
544     /**
545      * Process all the {@link Option}s and turn them into system props, settings, or run commands.
546      * Does not run any commands on the device at this time.
547      * <p>
548      * Exposed so that children classes may override this.
549      * </p>
550      *
551      * @param device The {@link ITestDevice}
552      * @throws DeviceNotAvailableException if the device is not available
553      * @throws TargetSetupError if the {@link Option}s conflict
554      */
processOptions(ITestDevice device)555     public void processOptions(ITestDevice device) throws DeviceNotAvailableException,
556             TargetSetupError {
557         setSettingForBinaryState(mData, mGlobalSettings, "mobile_data", "1", "0");
558         setCommandForBinaryState(
559                 mData, mRunCommandAfterSettings, "svc data enable", "svc data disable");
560 
561         setSettingForBinaryState(mCell, mGlobalSettings, "cell_on", "1", "0");
562         setSettingForBinaryState(
563                 mCellAutoSetting, mGlobalSettings, "clockwork_cell_auto_setting", "1", "0");
564 
565         setSettingForBinaryState(mWifi, mGlobalSettings, "wifi_on", "1", "0");
566         setCommandForBinaryState(
567                 mWifi, mRunCommandAfterSettings, "svc wifi enable", "svc wifi disable");
568 
569         setSettingForBinaryState(mWifiWatchdog, mGlobalSettings, "wifi_watchdog", "1", "0");
570         setSettingForBinaryState(
571                 mDisableCwWifiMediator, mGlobalSettings, "cw_disable_wifimediator", "1", "0");
572 
573         setSettingForBinaryState(mWifiScanAlwaysEnabled, mGlobalSettings,
574                 "wifi_scan_always_enabled", "1", "0");
575 
576         setCommandForBinaryState(mEthernet, mRunCommandAfterSettings,
577                 "ifconfig eth0 up", "ifconfig eth0 down");
578 
579         setCommandForBinaryState(mBluetooth, mRunCommandAfterSettings,
580                 "service call bluetooth_manager 6", "service call bluetooth_manager 8");
581 
582         setCommandForBinaryState(mNfc, mRunCommandAfterSettings,
583                 "svc nfc enable", "svc nfc disable");
584 
585         if (mScreenBrightness != null && BinaryState.ON.equals(mScreenAdaptiveBrightness)) {
586             throw new TargetSetupError("Option screen-brightness cannot be set when " +
587                     "screen-adaptive-brightness is set to ON", device.getDeviceDescriptor());
588         }
589 
590         setSettingForBinaryState(mScreenAdaptiveBrightness, mSystemSettings,
591                 "screen_brightness_mode", "1", "0");
592 
593         if (mScreenBrightness != null) {
594             mSystemSettings.put("screen_brightness", Integer.toString(mScreenBrightness));
595         }
596 
597         if (mScreenTimeoutSecs != null) {
598             mSystemSettings.put("screen_off_timeout", Long.toString(mScreenTimeoutSecs * 1000));
599         }
600 
601         setSettingForBinaryState(mScreenAmbientMode, mSecureSettings, "doze_enabled", "1", "0");
602 
603         setSettingForBinaryState(mWakeGesture, mSecureSettings, "wake_gesture_enabled", "1", "0");
604 
605         setSettingForBinaryState(mScreenSaver, mSecureSettings, "screensaver_enabled", "1", "0");
606 
607         setSettingForBinaryState(mNotificationLed, mSystemSettings,
608                 "notification_light_pulse", "1", "0");
609 
610         setSettingForBinaryState(mInstallNonMarketApps, mSecureSettings,
611                 "install_non_market_apps", "1", "0");
612 
613         if (mTriggerMediaMounted) {
614             mRunCommandAfterSettings.add(
615                     "am broadcast -a android.intent.action.MEDIA_MOUNTED -d "
616                             + "file://${EXTERNAL_STORAGE} --receiver-include-background");
617         }
618 
619         setSettingForBinaryState(mLocationGps, mSecureSettings,
620                 "location_providers_allowed", "+gps", "-gps");
621 
622         setSettingForBinaryState(mLocationNetwork, mSecureSettings,
623                 "location_providers_allowed", "+network", "-network");
624 
625         setSettingForBinaryState(mAutoRotate, mSystemSettings, "accelerometer_rotation", "1", "0");
626 
627         if (device.getApiLevel() < 22) {
628             setCommandForBinaryState(mBatterySaver, mRunCommandBeforeSettings,
629                 "dumpsys battery set usb 0", null);
630         } else {
631             setCommandForBinaryState(mBatterySaver, mRunCommandBeforeSettings,
632                 "dumpsys battery unplug", null);
633         }
634         setSettingForBinaryState(mBatterySaver, mGlobalSettings, "low_power", "1", "0");
635 
636         if (mBatterySaverTrigger != null) {
637             mGlobalSettings.put("low_power_trigger_level", Integer.toString(mBatterySaverTrigger));
638         }
639 
640         if (mEnableFullBatteryStatsHistory) {
641             mRunCommandAfterSettings.add("dumpsys batterystats --enable full-history");
642         }
643 
644         if (mDisableDoze) {
645             mRunCommandAfterSettings.add("dumpsys deviceidle disable");
646         }
647 
648         setSettingForBinaryState(mAutoUpdateTime, mGlobalSettings, "auto_time", "1", "0");
649 
650         setSettingForBinaryState(mAutoUpdateTimezone, mGlobalSettings, "auto_timezone", "1", "0");
651 
652         if (mTimezone != null) {
653             mSetProps.put("persist.sys.timezone", mTimezone);
654         }
655 
656         if (mDisableDialing) {
657             mSetProps.put("ro.telephony.disable-call", "true");
658         }
659 
660         if (mDefaultSimData != null) {
661             mGlobalSettings.put("multi_sim_data_call", Integer.toString(mDefaultSimData));
662         }
663 
664         if (mDefaultSimVoice != null) {
665             mGlobalSettings.put("multi_sim_voice_call", Integer.toString(mDefaultSimVoice));
666         }
667 
668         if (mDefaultSimSms != null) {
669             mGlobalSettings.put("multi_sim_sms", Integer.toString(mDefaultSimSms));
670         }
671 
672         if (mDisableAudio) {
673             mSetProps.put("ro.audio.silent", "1");
674         }
675 
676         if (mSetTestHarness) {
677             // set both ro.monkey and ro.test_harness, for compatibility with older platforms
678             mSetProps.put("ro.monkey", "1");
679             mSetProps.put("ro.test_harness", "1");
680         }
681 
682         if (mDisableDalvikVerifier) {
683             mSetProps.put("dalvik.vm.dexopt-flags", "v=n");
684         }
685     }
686 
687     /**
688      * Change the system properties on the device.
689      *
690      * @param device The {@link ITestDevice}
691      * @throws DeviceNotAvailableException if the device is not available
692      * @throws TargetSetupError if there was a failure setting the system properties
693      */
changeSystemProps(ITestDevice device)694     private void changeSystemProps(ITestDevice device) throws DeviceNotAvailableException,
695             TargetSetupError {
696         if (mForceSkipSystemProps) {
697             CLog.d("Skipping system props due to force-skip-system-props");
698             return;
699         }
700 
701         StringBuilder sb = new StringBuilder();
702         for (Map.Entry<String, String> prop : mSetProps.entrySet()) {
703             if (prop.getKey().startsWith(PERSIST_PREFIX)) {
704                 String command = String.format("setprop \"%s\" \"%s\"",
705                         prop.getKey(), prop.getValue());
706                 device.executeShellCommand(command);
707             } else {
708                 sb.append(String.format("%s=%s\n", prop.getKey(), prop.getValue()));
709             }
710         }
711 
712         if (sb.length() == 0) {
713             return;
714         }
715 
716         if (mRestoreProperties) {
717             mPreviousProperties = device.pullFile("/data/local.prop");
718         }
719         CLog.d("Pushing the following properties to /data/local.prop:\n%s", sb.toString());
720         boolean result = device.pushString(sb.toString(), "/data/local.prop");
721         if (!result) {
722             throw new TargetSetupError(String.format("Failed to push /data/local.prop to %s",
723                     device.getSerialNumber()), device.getDeviceDescriptor());
724         }
725         // Set reasonable permissions for /data/local.prop
726         device.executeShellCommand("chmod 644 /data/local.prop");
727         CLog.i("Rebooting %s due to system property change", device.getSerialNumber());
728         device.reboot();
729     }
730 
731     /**
732      * Handles screen always on settings.
733      * <p>
734      * This is done in a dedicated function because special handling is required in case of setting
735      * screen to always on.
736      * @throws DeviceNotAvailableException
737      */
handleScreenAlwaysOnSetting(ITestDevice device)738     private void handleScreenAlwaysOnSetting(ITestDevice device)
739             throws DeviceNotAvailableException {
740         String cmd = "svc power stayon %s";
741         switch (mScreenAlwaysOn) {
742             case ON:
743                 CLog.d("Setting screen always on to true");
744                 device.executeShellCommand(String.format(cmd, "true"));
745                 // send MENU press in case keygaurd needs to be dismissed again
746                 device.executeShellCommand("input keyevent 82");
747                 // send HOME press in case keyguard was already dismissed, so we bring device back
748                 // to home screen
749                 device.executeShellCommand("input keyevent 3");
750                 break;
751             case OFF:
752                 CLog.d("Setting screen always on to false");
753                 device.executeShellCommand(String.format(cmd, "false"));
754                 break;
755             case IGNORE:
756                 break;
757         }
758     }
759 
760     /**
761      * Change the settings on the device.
762      * <p>
763      * Exposed so children classes may override.
764      * </p>
765      *
766      * @param device The {@link ITestDevice}
767      * @throws DeviceNotAvailableException if the device is not available
768      * @throws TargetSetupError if there was a failure setting the settings
769      */
changeSettings(ITestDevice device)770     public void changeSettings(ITestDevice device) throws DeviceNotAvailableException,
771             TargetSetupError {
772         if (mForceSkipSettings) {
773             CLog.d("Skipping settings due to force-skip-setttings");
774             return;
775         }
776 
777         if (mSystemSettings.isEmpty() && mSecureSettings.isEmpty() && mGlobalSettings.isEmpty() &&
778                 BinaryState.IGNORE.equals(mAirplaneMode)) {
779             CLog.d("No settings to change");
780             return;
781         }
782 
783         if (device.getApiLevel() < 22) {
784             throw new TargetSetupError(String.format("Changing setting not supported on %s, " +
785                     "must be API 22+", device.getSerialNumber()), device.getDeviceDescriptor());
786         }
787 
788         // Special case airplane mode since it needs to be set before other connectivity settings
789         // For example, it is possible to enable airplane mode and then turn wifi on
790         String command = "am broadcast -a android.intent.action.AIRPLANE_MODE --ez state %s";
791         switch (mAirplaneMode) {
792             case ON:
793                 CLog.d("Changing global setting airplane_mode_on to 1");
794                 device.setSetting("global", "airplane_mode_on", "1");
795                 if (!mForceSkipRunCommands) {
796                     device.executeShellCommand(String.format(command, "true"));
797                 }
798                 break;
799             case OFF:
800                 CLog.d("Changing global setting airplane_mode_on to 0");
801                 device.setSetting("global", "airplane_mode_on", "0");
802                 if (!mForceSkipRunCommands) {
803                     device.executeShellCommand(String.format(command, "false"));
804                 }
805                 break;
806             case IGNORE:
807                 // No-op
808                 break;
809         }
810 
811         for (String key : mSystemSettings.keySet()) {
812             for (String value : mSystemSettings.get(key)) {
813                 if (mRestoreSettings) {
814                     String previousSetting = device.getSetting("system", key);
815                     mPreviousSystemSettings.put(key, previousSetting);
816                 }
817                 CLog.d("Changing system setting %s to %s", key, value);
818                 device.setSetting("system", key, value);
819             }
820         }
821         for (String key : mSecureSettings.keySet()) {
822             for (String value : mSecureSettings.get(key)) {
823                 if (mRestoreSettings) {
824                     String previousSetting = device.getSetting("secure", key);
825                     mPreviousSecureSettings.put(key, previousSetting);
826                 }
827                 CLog.d("Changing secure setting %s to %s", key, value);
828                 device.setSetting("secure", key, value);
829             }
830         }
831 
832         for (String key : mGlobalSettings.keySet()) {
833             for (String value : mGlobalSettings.get(key)) {
834                 if (mRestoreSettings) {
835                     String previousSetting = device.getSetting("global", key);
836                     mPreviousGlobalSettings.put(key, previousSetting);
837                 }
838                 CLog.d("Changing global setting %s to %s", key, value);
839                 device.setSetting("global", key, value);
840             }
841         }
842     }
843 
844     /**
845      * Execute additional commands on the device.
846      *
847      * @param device The {@link ITestDevice}
848      * @param commands The list of commands to run
849      * @throws DeviceNotAvailableException if the device is not available
850      * @throws TargetSetupError if there was a failure setting the settings
851      */
runCommands(ITestDevice device, List<String> commands)852     private void runCommands(ITestDevice device, List<String> commands)
853             throws DeviceNotAvailableException, TargetSetupError {
854         if (mForceSkipRunCommands) {
855             CLog.d("Skipping run commands due to force-skip-run-commands");
856             return;
857         }
858 
859         for (String command : commands) {
860             device.executeShellCommand(command);
861         }
862     }
863 
864     /**
865      * Connects device to Wifi if SSID is specified.
866      *
867      * @param device The {@link ITestDevice}
868      * @throws DeviceNotAvailableException if the device is not available
869      * @throws TargetSetupError if there was a failure setting the settings
870      */
connectWifi(ITestDevice device)871     private void connectWifi(ITestDevice device) throws DeviceNotAvailableException,
872             TargetSetupError {
873         if (mForceSkipRunCommands) {
874             CLog.d("Skipping connect wifi due to force-skip-run-commands");
875             return;
876         }
877 
878         if (mWifiSsid != null) {
879             if (!device.connectToWifiNetwork(mWifiSsid, mWifiPsk)) {
880                 throw new TargetSetupError(String.format(
881                         "Failed to connect to wifi network %s on %s", mWifiSsid,
882                         device.getSerialNumber()), device.getDeviceDescriptor());
883             }
884         }
885     }
886 
887     /**
888      * Syncs a set of test data files, specified via local-data-path, to devices external storage.
889      *
890      * @param device The {@link ITestDevice}
891      * @throws DeviceNotAvailableException if the device is not available
892      * @throws TargetSetupError if data fails to sync
893      */
syncTestData(ITestDevice device)894     private void syncTestData(ITestDevice device) throws DeviceNotAvailableException,
895             TargetSetupError {
896         if (mLocalDataFile == null) {
897             return;
898         }
899 
900         if (!mLocalDataFile.exists() || !mLocalDataFile.isDirectory()) {
901             throw new TargetSetupError(String.format(
902                     "local-data-path %s is not a directory", mLocalDataFile.getAbsolutePath()),
903                     device.getDeviceDescriptor());
904         }
905         String fullRemotePath = device.getIDevice().getMountPoint(IDevice.MNT_EXTERNAL_STORAGE);
906         if (fullRemotePath == null) {
907             throw new TargetSetupError(String.format(
908                     "failed to get external storage path on device %s", device.getSerialNumber()),
909                     device.getDeviceDescriptor());
910         }
911         if (mRemoteDataPath != null) {
912             fullRemotePath = String.format("%s/%s", fullRemotePath, mRemoteDataPath);
913         }
914         boolean result = device.syncFiles(mLocalDataFile, fullRemotePath);
915         if (!result) {
916             // TODO: get exact error code and respond accordingly
917             throw new TargetSetupError(String.format(
918                     "failed to sync test data from local-data-path %s to %s on device %s",
919                     mLocalDataFile.getAbsolutePath(), fullRemotePath, device.getSerialNumber()),
920                     device.getDeviceDescriptor());
921         }
922     }
923 
924     /**
925      * Check that device external store has the required space
926      *
927      * @param device The {@link ITestDevice}
928      * @throws DeviceNotAvailableException if the device is not available or if the device does not
929      * have the required space
930      */
checkExternalStoreSpace(ITestDevice device)931     private void checkExternalStoreSpace(ITestDevice device) throws DeviceNotAvailableException {
932         if (mMinExternalStorageKb <= 0) {
933             return;
934         }
935 
936         long freeSpace = device.getExternalStoreFreeSpace();
937         if (freeSpace < mMinExternalStorageKb) {
938             throw new DeviceNotAvailableException(String.format(
939                     "External store free space %dK is less than required %dK for device %s",
940                     freeSpace , mMinExternalStorageKb, device.getSerialNumber()),
941                     device.getSerialNumber());
942         }
943     }
944 
945     /**
946      * Helper method to add an ON/OFF setting to a setting map.
947      *
948      * @param state The {@link BinaryState}
949      * @param settingsMap The {@link MultiMap} used to store the settings.
950      * @param setting The setting key
951      * @param onValue The value if ON
952      * @param offValue The value if OFF
953      */
setSettingForBinaryState(BinaryState state, MultiMap<String, String> settingsMap, String setting, String onValue, String offValue)954     public static void setSettingForBinaryState(BinaryState state,
955             MultiMap<String, String> settingsMap, String setting, String onValue, String offValue) {
956         switch (state) {
957             case ON:
958                 settingsMap.put(setting, onValue);
959                 break;
960             case OFF:
961                 settingsMap.put(setting, offValue);
962                 break;
963             case IGNORE:
964                 // Do nothing
965                 break;
966         }
967     }
968 
969     /**
970      * Helper method to add an ON/OFF run command to be executed on the device.
971      *
972      * @param state The {@link BinaryState}
973      * @param commands The list of commands to add the on or off command to.
974      * @param onCommand The command to run if ON. Ignored if the command is {@code null}
975      * @param offCommand The command to run if OFF. Ignored if the command is {@code null}
976      */
setCommandForBinaryState(BinaryState state, List<String> commands, String onCommand, String offCommand)977     public static void setCommandForBinaryState(BinaryState state, List<String> commands,
978             String onCommand, String offCommand) {
979         switch (state) {
980             case ON:
981                 if (onCommand != null) {
982                     commands.add(onCommand);
983                 }
984                 break;
985             case OFF:
986                 if (offCommand != null) {
987                     commands.add(offCommand);
988                 }
989                 break;
990             case IGNORE:
991                 // Do nothing
992                 break;
993         }
994     }
995 
996     /**
997      * Exposed for unit testing
998      */
setAirplaneMode(BinaryState airplaneMode)999     protected void setAirplaneMode(BinaryState airplaneMode) {
1000         mAirplaneMode = airplaneMode;
1001     }
1002 
1003     /* Exposed for unit testing */
1004     @VisibleForTesting
setData(BinaryState data)1005     protected void setData(BinaryState data) {
1006         mData = data;
1007     }
1008 
1009     /* Exposed for unit testing */
1010     @VisibleForTesting
setCell(BinaryState cell)1011     protected void setCell(BinaryState cell) {
1012         mCell = cell;
1013     }
1014 
1015     /* Exposed for unit testing */
1016     @VisibleForTesting
setCellAutoSetting(BinaryState cellAutoSetting)1017     protected void setCellAutoSetting(BinaryState cellAutoSetting) {
1018         mCellAutoSetting = cellAutoSetting;
1019     }
1020 
1021     /**
1022      * Exposed for unit testing
1023      */
setWifi(BinaryState wifi)1024     protected void setWifi(BinaryState wifi) {
1025         mWifi = wifi;
1026     }
1027 
1028     /**
1029      * Exposed for unit testing
1030      */
setWifiNetwork(String wifiNetwork)1031     protected void setWifiNetwork(String wifiNetwork) {
1032         mWifiSsid = wifiNetwork;
1033     }
1034 
1035     /**
1036      * Exposed for unit testing
1037      */
setWifiWatchdog(BinaryState wifiWatchdog)1038     protected void setWifiWatchdog(BinaryState wifiWatchdog) {
1039         mWifiWatchdog = wifiWatchdog;
1040     }
1041 
1042     /* Exposed for unit testing */
1043     @VisibleForTesting
setDisableCwWifiMediator(BinaryState disableCwWifiMediator)1044     protected void setDisableCwWifiMediator(BinaryState disableCwWifiMediator) {
1045         mDisableCwWifiMediator = disableCwWifiMediator;
1046     }
1047 
1048     /**
1049      * Exposed for unit testing
1050      */
setWifiScanAlwaysEnabled(BinaryState wifiScanAlwaysEnabled)1051     protected void setWifiScanAlwaysEnabled(BinaryState wifiScanAlwaysEnabled) {
1052         mWifiScanAlwaysEnabled = wifiScanAlwaysEnabled;
1053     }
1054 
1055     /**
1056      * Exposed for unit testing
1057      */
setEthernet(BinaryState ethernet)1058     protected void setEthernet(BinaryState ethernet) {
1059         mEthernet = ethernet;
1060     }
1061 
1062     /**
1063      * Exposed for unit testing
1064      */
setBluetooth(BinaryState bluetooth)1065     protected void setBluetooth(BinaryState bluetooth) {
1066         mBluetooth = bluetooth;
1067     }
1068 
1069     /**
1070      * Exposed for unit testing
1071      */
setNfc(BinaryState nfc)1072     protected void setNfc(BinaryState nfc) {
1073         mNfc = nfc;
1074     }
1075 
1076     /**
1077      * Exposed for unit testing
1078      */
setScreenAdaptiveBrightness(BinaryState screenAdaptiveBrightness)1079     protected void setScreenAdaptiveBrightness(BinaryState screenAdaptiveBrightness) {
1080         mScreenAdaptiveBrightness = screenAdaptiveBrightness;
1081     }
1082 
1083     /**
1084      * Exposed for unit testing
1085      */
setScreenBrightness(Integer screenBrightness)1086     protected void setScreenBrightness(Integer screenBrightness) {
1087         mScreenBrightness = screenBrightness;
1088     }
1089 
1090     /**
1091      * Exposed for unit testing
1092      */
setScreenAlwaysOn(BinaryState screenAlwaysOn)1093     protected void setScreenAlwaysOn(BinaryState screenAlwaysOn) {
1094         mScreenAlwaysOn = screenAlwaysOn;
1095     }
1096 
1097     /**
1098      * Exposed for unit testing
1099      */
setScreenTimeoutSecs(Long screenTimeoutSecs)1100     protected void setScreenTimeoutSecs(Long screenTimeoutSecs) {
1101         mScreenTimeoutSecs = screenTimeoutSecs;
1102     }
1103 
1104     /**
1105      * Exposed for unit testing
1106      */
setScreenAmbientMode(BinaryState screenAmbientMode)1107     protected void setScreenAmbientMode(BinaryState screenAmbientMode) {
1108         mScreenAmbientMode = screenAmbientMode;
1109     }
1110 
1111     /**
1112      * Exposed for unit testing
1113      */
setWakeGesture(BinaryState wakeGesture)1114     protected void setWakeGesture(BinaryState wakeGesture) {
1115         mWakeGesture = wakeGesture;
1116     }
1117 
1118     /**
1119      * Exposed for unit testing
1120      */
setScreenSaver(BinaryState screenSaver)1121     protected void setScreenSaver(BinaryState screenSaver) {
1122         mScreenSaver = screenSaver;
1123     }
1124 
1125     /**
1126      * Exposed for unit testing
1127      */
setNotificationLed(BinaryState notificationLed)1128     protected void setNotificationLed(BinaryState notificationLed) {
1129         mNotificationLed = notificationLed;
1130     }
1131 
1132     /**
1133      * Exposed for unit testing
1134      */
setInstallNonMarketApps(BinaryState installNonMarketApps)1135     protected void setInstallNonMarketApps(BinaryState installNonMarketApps) {
1136         mInstallNonMarketApps = installNonMarketApps;
1137     }
1138 
1139     /**
1140      * Exposed for unit testing
1141      */
setTriggerMediaMounted(boolean triggerMediaMounted)1142     protected void setTriggerMediaMounted(boolean triggerMediaMounted) {
1143         mTriggerMediaMounted = triggerMediaMounted;
1144     }
1145 
1146     /**
1147      * Exposed for unit testing
1148      */
setLocationGps(BinaryState locationGps)1149     protected void setLocationGps(BinaryState locationGps) {
1150         mLocationGps = locationGps;
1151     }
1152 
1153     /**
1154      * Exposed for unit testing
1155      */
setLocationNetwork(BinaryState locationNetwork)1156     protected void setLocationNetwork(BinaryState locationNetwork) {
1157         mLocationNetwork = locationNetwork;
1158     }
1159 
1160     /**
1161      * Exposed for unit testing
1162      */
setAutoRotate(BinaryState autoRotate)1163     protected void setAutoRotate(BinaryState autoRotate) {
1164         mAutoRotate = autoRotate;
1165     }
1166 
1167     /**
1168      * Exposed for unit testing
1169      */
setBatterySaver(BinaryState batterySaver)1170     protected void setBatterySaver(BinaryState batterySaver) {
1171         mBatterySaver = batterySaver;
1172     }
1173 
1174     /**
1175      * Exposed for unit testing
1176      */
setBatterySaverTrigger(Integer batterySaverTrigger)1177     protected void setBatterySaverTrigger(Integer batterySaverTrigger) {
1178         mBatterySaverTrigger = batterySaverTrigger;
1179     }
1180 
1181     /**
1182      * Exposed for unit testing
1183      */
setEnableFullBatteryStatsHistory(boolean enableFullBatteryStatsHistory)1184     protected void setEnableFullBatteryStatsHistory(boolean enableFullBatteryStatsHistory) {
1185         mEnableFullBatteryStatsHistory = enableFullBatteryStatsHistory;
1186     }
1187 
1188     /**
1189      * Exposed for unit testing
1190      */
setDisableDoze(boolean disableDoze)1191     protected void setDisableDoze(boolean disableDoze) {
1192         mDisableDoze = disableDoze;
1193     }
1194 
1195     /**
1196      * Exposed for unit testing
1197      */
setAutoUpdateTime(BinaryState autoUpdateTime)1198     protected void setAutoUpdateTime(BinaryState autoUpdateTime) {
1199         mAutoUpdateTime = autoUpdateTime;
1200     }
1201 
1202     /**
1203      * Exposed for unit testing
1204      */
setAutoUpdateTimezone(BinaryState autoUpdateTimezone)1205     protected void setAutoUpdateTimezone(BinaryState autoUpdateTimezone) {
1206         mAutoUpdateTimezone = autoUpdateTimezone;
1207     }
1208 
1209     /**
1210      * Exposed for unit testing
1211      */
setTimezone(String timezone)1212     protected void setTimezone(String timezone) {
1213         mTimezone = timezone;
1214     }
1215 
1216     /**
1217      * Exposed for unit testing
1218      */
setDisableDialing(boolean disableDialing)1219     protected void setDisableDialing(boolean disableDialing) {
1220         mDisableDialing = disableDialing;
1221     }
1222 
1223     /**
1224      * Exposed for unit testing
1225      */
setDefaultSimData(Integer defaultSimData)1226     protected void setDefaultSimData(Integer defaultSimData) {
1227         mDefaultSimData = defaultSimData;
1228     }
1229 
1230     /**
1231      * Exposed for unit testing
1232      */
setDefaultSimVoice(Integer defaultSimVoice)1233     protected void setDefaultSimVoice(Integer defaultSimVoice) {
1234         mDefaultSimVoice = defaultSimVoice;
1235     }
1236 
1237     /**
1238      * Exposed for unit testing
1239      */
setDefaultSimSms(Integer defaultSimSms)1240     protected void setDefaultSimSms(Integer defaultSimSms) {
1241         mDefaultSimSms = defaultSimSms;
1242     }
1243 
1244     /**
1245      * Exposed for unit testing
1246      */
setDisableAudio(boolean disable)1247     protected void setDisableAudio(boolean disable) {
1248         mDisableAudio = disable;
1249     }
1250 
1251     /**
1252      * Exposed for unit testing
1253      */
setTestHarness(boolean setTestHarness)1254     protected void setTestHarness(boolean setTestHarness) {
1255         mSetTestHarness = setTestHarness;
1256     }
1257 
1258     /**
1259      * Exposed for unit testing
1260      */
setDisableDalvikVerifier(boolean disableDalvikVerifier)1261     protected void setDisableDalvikVerifier(boolean disableDalvikVerifier) {
1262         mDisableDalvikVerifier = disableDalvikVerifier;
1263     }
1264 
1265     /**
1266      * Exposed for unit testing
1267      */
setLocalDataPath(File path)1268     protected void setLocalDataPath(File path) {
1269         mLocalDataFile = path;
1270     }
1271 
1272     /**
1273      * Exposed for unit testing
1274      */
setMinExternalStorageKb(long storageKb)1275     protected void setMinExternalStorageKb(long storageKb) {
1276         mMinExternalStorageKb = storageKb;
1277     }
1278 
1279     /**
1280      * Exposed for unit testing
1281      */
setProperty(String key, String value)1282     protected void setProperty(String key, String value) {
1283         mSetProps.put(key, value);
1284     }
1285 
1286     /** Exposed for unit testing */
setGlobalSetting(String key, String value)1287     public void setGlobalSetting(String key, String value) {
1288         mGlobalSettings.put(key, value);
1289     }
1290 
1291     /** Exposed for unit testing */
setSecureSetting(String key, String value)1292     public void setSecureSetting(String key, String value) {
1293         mSecureSettings.put(key, value);
1294     }
1295 
1296     /** Exposed for unit testing */
setSystemSetting(String key, String value)1297     public void setSystemSetting(String key, String value) {
1298         mSystemSettings.put(key, value);
1299     }
1300 
1301     /** Exposed for unit testing */
setRestoreProperties(boolean restoreProperties)1302     protected void setRestoreProperties(boolean restoreProperties) {
1303         mRestoreProperties = restoreProperties;
1304     }
1305 
1306     /** Exposed for unit testing */
setRestoreSettings(boolean restoreSettings)1307     protected void setRestoreSettings(boolean restoreSettings) {
1308         mRestoreSettings = restoreSettings;
1309     }
1310 
1311     /**
1312      * Exposed for unit testing
1313      * @deprecated use {@link #setMinExternalStorageKb(long)} instead.
1314      */
1315     @Deprecated
setDeprecatedMinExternalStoreSpace(long storeSpace)1316     protected void setDeprecatedMinExternalStoreSpace(long storeSpace) {
1317         mDeprecatedMinExternalStoreSpace = storeSpace;
1318     }
1319 
1320     /**
1321      * Exposed for unit testing
1322      * @deprecated use {@link #setDisableAudio(boolean)} instead.
1323      */
1324     @Deprecated
setDeprecatedAudioSilent(boolean silent)1325     protected void setDeprecatedAudioSilent(boolean silent) {
1326         mDeprecatedSetAudioSilent = silent;
1327     }
1328 
1329     /**
1330      * Exposed for unit testing
1331      * @deprecated use {@link #setProperty(String, String)} instead.
1332      */
1333     @Deprecated
setDeprecatedSetProp(String prop)1334     protected void setDeprecatedSetProp(String prop) {
1335         mDeprecatedSetProps.add(prop);
1336     }
1337 }
1338