• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 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.emulatorprovisionlib;
18 
19 import android.app.Activity;
20 import android.app.ActivityManager;
21 import android.app.StatusBarManager;
22 import android.content.ComponentName;
23 import android.content.Context;
24 import android.content.pm.PackageManager;
25 import android.hardware.input.InputManager;
26 import android.hardware.input.InputManagerGlobal;
27 import android.hardware.input.KeyboardLayout;
28 import android.location.LocationManager;
29 import android.net.wifi.WifiManager;
30 import android.net.wifi.WifiConfiguration;
31 import android.provider.Settings;
32 import android.os.Bundle;
33 import android.os.Process;
34 import android.os.RemoteException;
35 import android.os.ServiceManager;
36 import android.os.SystemProperties;
37 import android.os.UserHandle;
38 import android.os.UserManager;
39 import android.telephony.TelephonyManager;
40 import android.util.Log;
41 import android.view.InputDevice;
42 
43 import com.android.internal.widget.LockPatternUtils;
44 
45 public abstract class ProvisionActivity extends Activity {
TAG()46     protected abstract String TAG();
47     protected StatusBarManager mStatusBarManager;
48 
49     @Override
onCreate(Bundle icicle)50     protected void onCreate(Bundle icicle) {
51         super.onCreate(icicle);
52 
53         if (provisionRequired()) {
54             preProvivion();
55             doProvision();
56             postProvision();
57         } else {
58             Log.w(TAG(), "Already provisioned, remove itself.");
59             removeSelf();
60         }
61 
62         finish();  // terminate the activity.
63     }
64 
preProvivion()65     protected void preProvivion() {
66         final Context appContext = getApplicationContext();
67         if (!isVisibleBackgroundUser(appContext)) {
68             mStatusBarManager = appContext.getSystemService(StatusBarManager.class);
69         }
70 
71         if (mStatusBarManager != null) {
72             mStatusBarManager.setDisabledForSetup(true);
73         }
74     }
75 
postProvision()76     protected void postProvision() {
77         if (mStatusBarManager != null) {
78             mStatusBarManager.setDisabledForSetup(false);
79         }
80 
81 
82         // Add a persistent setting to allow other apps to know the device has been provisioned.
83         Settings.Secure.putInt(getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, 1);
84         Settings.Global.putInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 1);
85         final boolean isDeviceProvisioned = (Settings.Global.getInt(getContentResolver(),
86                 Settings.Global.DEVICE_PROVISIONED, 0) == 1);
87         if (isDeviceProvisioned) {
88             Log.i(TAG(), "Successfully set device_provisioned to 1");
89         } else {
90             Log.e(TAG(), "Unable to set device_provisioned to 1");
91         }
92         removeSelf();
93     }
94 
95     // remove this activity from the package manager.
removeSelf()96     protected void removeSelf() {
97         getPackageManager().setComponentEnabledSetting(
98                 new ComponentName(this, this.getClass()),
99                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
100                 PackageManager.DONT_KILL_APP);
101     }
102 
doProvision()103     protected void doProvision() {
104         provisionWifi("AndroidWifi");
105         provisionKeyboard("qwerty2", SystemProperties.get("vendor.qemu.keyboard_layout"));
106         provisionDisplay();
107         provisionTelephony();
108         provisionLocation();
109         provisionAdb();
110 
111         Settings.Secure.putInt(getContentResolver(), Settings.Secure.INSTALL_NON_MARKET_APPS, 1);
112     }
113 
provisionWifi(final String ssid)114     protected void provisionWifi(final String ssid) {
115         if (isVisibleBackgroundUser(getApplicationContext())) {
116             return;
117         }
118 
119         Settings.Global.putInt(getContentResolver(), Settings.Global.TETHER_OFFLOAD_DISABLED, 1);
120 
121         final WifiManager mWifiManager = getApplicationContext().getSystemService(WifiManager.class);
122         if (!mWifiManager.setWifiEnabled(true)) {
123             Log.e(TAG(), "Unable to turn on Wi-Fi");
124             return;
125         }
126 
127         final int ADD_NETWORK_FAIL = -1;
128         final String quotedSsid = "\"" + ssid + "\"";
129 
130         final WifiConfiguration config = new WifiConfiguration();
131         config.SSID = quotedSsid;
132         config.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OPEN);
133 
134         final int netId = mWifiManager.addNetwork(config);
135         if (netId == ADD_NETWORK_FAIL) {
136             Log.e(TAG(), "Unable to add Wi-Fi network " + quotedSsid + ".");
137         } else if (!mWifiManager.enableNetwork(netId, true)) {
138             Log.e(TAG(), "Unable to enable Wi-Fi network " + quotedSsid + " (netId=" + netId + ")");
139         }
140     }
141 
142     // Set physical keyboard layout based on the system property set by emulator host.
provisionKeyboard(final String deviceName, final String layoutName)143     protected void provisionKeyboard(final String deviceName, final String layoutName) {
144         final InputDevice device = getKeyboardDevice(deviceName);
145         if (device != null && !layoutName.isEmpty()) {
146             setKeyboardLayout(device, layoutName);
147         }
148     }
149 
getKeyboardDevice(final String keyboardDeviceName)150     protected InputDevice getKeyboardDevice(final String keyboardDeviceName) {
151         final int[] deviceIds = InputDevice.getDeviceIds();
152 
153         for (int deviceId : deviceIds) {
154             InputDevice inputDevice = InputDevice.getDevice(deviceId);
155             if (inputDevice != null
156                     && inputDevice.supportsSource(InputDevice.SOURCE_KEYBOARD)
157                     && inputDevice.getName().equals(keyboardDeviceName)) {
158                 return inputDevice;
159             }
160         }
161 
162         return null;
163     }
164 
setKeyboardLayout(final InputDevice keyboardDevice, final String layoutName)165     protected void setKeyboardLayout(final InputDevice keyboardDevice, final String layoutName) {
166         final InputManager im = getApplicationContext().getSystemService(InputManager.class);
167         final KeyboardLayout[] keyboardLayouts = im.getKeyboardLayouts();
168 
169         for (KeyboardLayout keyboardLayout : keyboardLayouts) {
170             if (keyboardLayout.getDescriptor().endsWith(layoutName)) {
171                 InputManagerGlobal.getInstance().setKeyboardLayoutOverrideForInputDevice(
172                         keyboardDevice.getIdentifier(), keyboardLayout.getDescriptor());
173                 return;
174             }
175         }
176     }
177 
provisionDisplay()178     protected void provisionDisplay() {
179         Settings.Global.putInt(getContentResolver(), Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 1);
180 
181         final int screen_off_timeout =
182             SystemProperties.getInt("ro.boot.qemu.settings.system.screen_off_timeout", 0);
183         if (screen_off_timeout > 0) {
184             Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_OFF_TIMEOUT, screen_off_timeout);
185             Log.i(TAG(), "Setting system screen_off_timeout to be " + screen_off_timeout + " ms");
186         }
187 
188         (new LockPatternUtils(this)).setLockScreenDisabled(true,
189             android.os.Process.myUserHandle().getIdentifier());
190 
191         final String displaySettingsProp = "ro.boot.qemu.display.settings.xml";
192         final String displaySettingsName = SystemProperties.get(displaySettingsProp);
193         if ("freeform".equals(displaySettingsName)) {
194             Settings.Global.putInt(getContentResolver(), "sf", 1);
195             Settings.Global.putString(getContentResolver(),
196                                       Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT, "1");
197             Settings.Global.putString(getContentResolver(),
198                                       Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES, "1");
199             Settings.Global.putString(getContentResolver(),
200                                       Settings.Global.DEVELOPMENT_WM_DISPLAY_SETTINGS_PATH,
201                                       "vendor/etc/display_settings_freeform.xml");
202         } else if ("resizable".equals(displaySettingsName)) {
203             // Enable auto rotate for resizable AVD
204             Settings.System.putString(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, "1");
205         } else if (!displaySettingsName.isEmpty()) {
206             Log.e(TAG(), "Unexpected value `" + displaySettingsName + "` in " + displaySettingsProp);
207         }
208         final String autoRotateProp = "ro.boot.qemu.autorotate";
209         final String autoRotateSetting = SystemProperties.get(autoRotateProp);
210         if (!autoRotateSetting.isEmpty()) {
211             Settings.System.putString(getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, autoRotateSetting);
212         }
213     }
214 
215     // required for CTS which uses the mock modem
provisionMockModem()216     private void provisionMockModem() {
217         String value = SystemProperties.get("ro.boot.radio.allow_mock_modem");
218         if (!value.isEmpty()) {
219             if (value.equals("1")) {
220                 value = "true";
221             } else if (value.equals("0")) {
222                 value = "false";
223             }
224 
225             SystemProperties.set("persist.radio.allow_mock_modem", value);
226         }
227     }
228 
provisionTelephony()229     protected void provisionTelephony() {
230         provisionMockModem();
231     }
232 
provisionLocation()233     protected void provisionLocation() {
234         final LocationManager lm = getSystemService(LocationManager.class);
235         lm.setLocationEnabledForUser(true, Process.myUserHandle());
236 
237         // Enable the GPS.
238         // Not needed since this SDK will contain the Settings app.
239         Settings.Secure.putString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
240                 LocationManager.GPS_PROVIDER);
241     }
242 
provisionAdb()243     protected void provisionAdb() {
244         Settings.Global.putInt(getContentResolver(), Settings.Global.ADB_ENABLED, 1);
245         Settings.Global.putInt(getContentResolver(), Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 0);
246     }
247 
provisionRequired()248     protected boolean provisionRequired() {
249         return Settings.Global.getInt(getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 1;
250     }
251 
isVisibleBackgroundUser(Context context)252     protected boolean isVisibleBackgroundUser(Context context) {
253         if (!UserManager.isVisibleBackgroundUsersEnabled()) {
254             return false;
255         }
256         UserHandle user = context.getUser();
257         if (user.isSystem() || user.getIdentifier() == ActivityManager.getCurrentUser()) {
258             return false;
259         }
260         return true;
261     }
262 }
263