1 /* 2 * Copyright (C) 2014 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.server.devicepolicy; 18 19 import android.app.AppGlobals; 20 import android.app.admin.SystemUpdatePolicy; 21 import android.content.ComponentName; 22 import android.content.pm.PackageInfo; 23 import android.content.pm.PackageManager; 24 import android.content.pm.PackageManager.NameNotFoundException; 25 import android.os.Environment; 26 import android.os.PersistableBundle; 27 import android.os.RemoteException; 28 import android.util.AtomicFile; 29 import android.util.Slog; 30 import android.util.Xml; 31 32 import com.android.internal.annotations.VisibleForTesting; 33 import com.android.internal.util.FastXmlSerializer; 34 35 import org.xmlpull.v1.XmlPullParser; 36 import org.xmlpull.v1.XmlPullParserException; 37 import org.xmlpull.v1.XmlSerializer; 38 39 import java.io.File; 40 import java.io.FileOutputStream; 41 import java.io.IOException; 42 import java.io.InputStream; 43 import java.io.OutputStream; 44 import java.io.PrintWriter; 45 import java.nio.charset.StandardCharsets; 46 import java.util.HashMap; 47 import java.util.Map; 48 import java.util.Set; 49 50 /** 51 * Stores and restores state for the Device and Profile owners. By definition there can be 52 * only one device owner, but there may be a profile owner for each user. 53 */ 54 class DeviceOwner { 55 private static final String TAG = "DevicePolicyManagerService"; 56 57 private static final String DEVICE_OWNER_XML = "device_owner.xml"; 58 private static final String TAG_DEVICE_OWNER = "device-owner"; 59 private static final String TAG_DEVICE_INITIALIZER = "device-initializer"; 60 private static final String TAG_PROFILE_OWNER = "profile-owner"; 61 private static final String ATTR_NAME = "name"; 62 private static final String ATTR_PACKAGE = "package"; 63 private static final String ATTR_COMPONENT_NAME = "component"; 64 private static final String ATTR_USERID = "userId"; 65 private static final String TAG_SYSTEM_UPDATE_POLICY = "system-update-policy"; 66 67 private AtomicFile fileForWriting; 68 69 // Input/Output streams for testing. 70 private InputStream mInputStreamForTest; 71 private OutputStream mOutputStreamForTest; 72 73 // Internal state for the device owner package. 74 private OwnerInfo mDeviceOwner; 75 76 // Internal state for the device initializer package. 77 private OwnerInfo mDeviceInitializer; 78 79 // Internal state for the profile owner packages. 80 private final HashMap<Integer, OwnerInfo> mProfileOwners = new HashMap<Integer, OwnerInfo>(); 81 82 // Local system update policy controllable by device owner. 83 private SystemUpdatePolicy mSystemUpdatePolicy; 84 85 // Private default constructor. 86 private DeviceOwner() { 87 } 88 89 @VisibleForTesting 90 DeviceOwner(InputStream in, OutputStream out) { 91 mInputStreamForTest = in; 92 mOutputStreamForTest = out; 93 } 94 95 /** 96 * Loads the device owner state from disk. 97 */ 98 static DeviceOwner load() { 99 DeviceOwner owner = new DeviceOwner(); 100 if (new File(Environment.getSystemSecureDirectory(), DEVICE_OWNER_XML).exists()) { 101 owner.readOwnerFile(); 102 return owner; 103 } else { 104 return null; 105 } 106 } 107 108 /** 109 * Creates an instance of the device owner object with the device owner set. 110 */ 111 static DeviceOwner createWithDeviceOwner(String packageName, String ownerName) { 112 DeviceOwner owner = new DeviceOwner(); 113 owner.mDeviceOwner = new OwnerInfo(ownerName, packageName); 114 return owner; 115 } 116 117 /** 118 * Creates an instance of the device owner object with the device initializer set. 119 */ 120 static DeviceOwner createWithDeviceInitializer(ComponentName admin) { 121 DeviceOwner owner = new DeviceOwner(); 122 owner.mDeviceInitializer = new OwnerInfo(null, admin); 123 return owner; 124 } 125 126 /** 127 * Creates an instance of the device owner object with the profile owner set. 128 */ 129 static DeviceOwner createWithProfileOwner(ComponentName admin, String ownerName, int userId) { 130 DeviceOwner owner = new DeviceOwner(); 131 owner.mProfileOwners.put(userId, new OwnerInfo(ownerName, admin)); 132 return owner; 133 } 134 135 String getDeviceOwnerPackageName() { 136 return mDeviceOwner != null ? mDeviceOwner.packageName : null; 137 } 138 139 String getDeviceOwnerName() { 140 return mDeviceOwner != null ? mDeviceOwner.name : null; 141 } 142 143 void setDeviceOwner(String packageName, String ownerName) { 144 mDeviceOwner = new OwnerInfo(ownerName, packageName); 145 } 146 147 void clearDeviceOwner() { 148 mDeviceOwner = null; 149 } 150 151 ComponentName getDeviceInitializerComponent() { 152 return mDeviceInitializer.admin; 153 } 154 155 String getDeviceInitializerPackageName() { 156 return mDeviceInitializer != null ? mDeviceInitializer.packageName : null; 157 } 158 159 void setDeviceInitializer(ComponentName admin) { 160 mDeviceInitializer = new OwnerInfo(null, admin); 161 } 162 163 void clearDeviceInitializer() { 164 mDeviceInitializer = null; 165 } 166 167 boolean hasDeviceInitializer() { 168 return mDeviceInitializer != null; 169 } 170 171 void setProfileOwner(ComponentName admin, String ownerName, int userId) { 172 mProfileOwners.put(userId, new OwnerInfo(ownerName, admin)); 173 } 174 175 void removeProfileOwner(int userId) { 176 mProfileOwners.remove(userId); 177 } 178 179 ComponentName getProfileOwnerComponent(int userId) { 180 OwnerInfo profileOwner = mProfileOwners.get(userId); 181 return profileOwner != null ? profileOwner.admin : null; 182 } 183 184 String getProfileOwnerName(int userId) { 185 OwnerInfo profileOwner = mProfileOwners.get(userId); 186 return profileOwner != null ? profileOwner.name : null; 187 } 188 189 Set<Integer> getProfileOwnerKeys() { 190 return mProfileOwners.keySet(); 191 } 192 193 SystemUpdatePolicy getSystemUpdatePolicy() { 194 return mSystemUpdatePolicy; 195 } 196 197 void setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy) { 198 mSystemUpdatePolicy = systemUpdatePolicy; 199 } 200 201 void clearSystemUpdatePolicy() { 202 mSystemUpdatePolicy = null; 203 } 204 205 boolean hasDeviceOwner() { 206 return mDeviceOwner != null; 207 } 208 209 static boolean isInstalled(String packageName, PackageManager pm) { 210 try { 211 PackageInfo pi; 212 if ((pi = pm.getPackageInfo(packageName, 0)) != null) { 213 if ((pi.applicationInfo.flags) != 0) { 214 return true; 215 } 216 } 217 } catch (NameNotFoundException nnfe) { 218 Slog.w(TAG, "Device Owner package " + packageName + " not installed."); 219 } 220 return false; 221 } 222 223 static boolean isInstalledForUser(String packageName, int userHandle) { 224 try { 225 PackageInfo pi = (AppGlobals.getPackageManager()) 226 .getPackageInfo(packageName, 0, userHandle); 227 if (pi != null && pi.applicationInfo.flags != 0) { 228 return true; 229 } 230 } catch (RemoteException re) { 231 throw new RuntimeException("Package manager has died", re); 232 } 233 234 return false; 235 } 236 237 @VisibleForTesting 238 void readOwnerFile() { 239 try { 240 InputStream input = openRead(); 241 XmlPullParser parser = Xml.newPullParser(); 242 parser.setInput(input, StandardCharsets.UTF_8.name()); 243 int type; 244 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT) { 245 if (type!=XmlPullParser.START_TAG) { 246 continue; 247 } 248 249 String tag = parser.getName(); 250 if (tag.equals(TAG_DEVICE_OWNER)) { 251 String name = parser.getAttributeValue(null, ATTR_NAME); 252 String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 253 mDeviceOwner = new OwnerInfo(name, packageName); 254 } else if (tag.equals(TAG_DEVICE_INITIALIZER)) { 255 String packageName = parser.getAttributeValue(null, ATTR_PACKAGE); 256 String initializerComponentStr = 257 parser.getAttributeValue(null, ATTR_COMPONENT_NAME); 258 ComponentName admin = 259 ComponentName.unflattenFromString(initializerComponentStr); 260 if (admin != null) { 261 mDeviceInitializer = new OwnerInfo(null, admin); 262 } else { 263 mDeviceInitializer = new OwnerInfo(null, packageName); 264 Slog.e(TAG, "Error parsing device-owner file. Bad component name " + 265 initializerComponentStr); 266 } 267 } else if (tag.equals(TAG_PROFILE_OWNER)) { 268 String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); 269 String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME); 270 String profileOwnerComponentStr = 271 parser.getAttributeValue(null, ATTR_COMPONENT_NAME); 272 int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID)); 273 OwnerInfo profileOwnerInfo = null; 274 if (profileOwnerComponentStr != null) { 275 ComponentName admin = ComponentName.unflattenFromString( 276 profileOwnerComponentStr); 277 if (admin != null) { 278 profileOwnerInfo = new OwnerInfo(profileOwnerName, admin); 279 } else { 280 // This shouldn't happen but switch from package name -> component name 281 // might have written bad device owner files. b/17652534 282 Slog.e(TAG, "Error parsing device-owner file. Bad component name " + 283 profileOwnerComponentStr); 284 } 285 } 286 if (profileOwnerInfo == null) { 287 profileOwnerInfo = new OwnerInfo(profileOwnerName, profileOwnerPackageName); 288 } 289 mProfileOwners.put(userId, profileOwnerInfo); 290 } else if (TAG_SYSTEM_UPDATE_POLICY.equals(tag)) { 291 mSystemUpdatePolicy = SystemUpdatePolicy.restoreFromXml(parser); 292 } else { 293 throw new XmlPullParserException( 294 "Unexpected tag in device owner file: " + tag); 295 } 296 } 297 input.close(); 298 } catch (XmlPullParserException xppe) { 299 Slog.e(TAG, "Error parsing device-owner file\n" + xppe); 300 } catch (IOException ioe) { 301 Slog.e(TAG, "IO Exception when reading device-owner file\n" + ioe); 302 } 303 } 304 305 @VisibleForTesting 306 void writeOwnerFile() { 307 synchronized (this) { 308 writeOwnerFileLocked(); 309 } 310 } 311 312 private void writeOwnerFileLocked() { 313 try { 314 OutputStream outputStream = startWrite(); 315 XmlSerializer out = new FastXmlSerializer(); 316 out.setOutput(outputStream, StandardCharsets.UTF_8.name()); 317 out.startDocument(null, true); 318 319 // Write device owner tag 320 if (mDeviceOwner != null) { 321 out.startTag(null, TAG_DEVICE_OWNER); 322 out.attribute(null, ATTR_PACKAGE, mDeviceOwner.packageName); 323 if (mDeviceOwner.name != null) { 324 out.attribute(null, ATTR_NAME, mDeviceOwner.name); 325 } 326 out.endTag(null, TAG_DEVICE_OWNER); 327 } 328 329 // Write device initializer tag 330 if (mDeviceInitializer != null) { 331 out.startTag(null, TAG_DEVICE_INITIALIZER); 332 out.attribute(null, ATTR_PACKAGE, mDeviceInitializer.packageName); 333 if (mDeviceInitializer.admin != null) { 334 out.attribute( 335 null, ATTR_COMPONENT_NAME, mDeviceInitializer.admin.flattenToString()); 336 } 337 out.endTag(null, TAG_DEVICE_INITIALIZER); 338 } 339 340 // Write profile owner tags 341 if (mProfileOwners.size() > 0) { 342 for (HashMap.Entry<Integer, OwnerInfo> owner : mProfileOwners.entrySet()) { 343 out.startTag(null, TAG_PROFILE_OWNER); 344 OwnerInfo ownerInfo = owner.getValue(); 345 out.attribute(null, ATTR_PACKAGE, ownerInfo.packageName); 346 out.attribute(null, ATTR_NAME, ownerInfo.name); 347 out.attribute(null, ATTR_USERID, Integer.toString(owner.getKey())); 348 if (ownerInfo.admin != null) { 349 out.attribute(null, ATTR_COMPONENT_NAME, ownerInfo.admin.flattenToString()); 350 } 351 out.endTag(null, TAG_PROFILE_OWNER); 352 } 353 } 354 355 // Write system update policy tag 356 if (mSystemUpdatePolicy != null) { 357 out.startTag(null, TAG_SYSTEM_UPDATE_POLICY); 358 mSystemUpdatePolicy.saveToXml(out); 359 out.endTag(null, TAG_SYSTEM_UPDATE_POLICY); 360 } 361 out.endDocument(); 362 out.flush(); 363 finishWrite(outputStream); 364 } catch (IOException ioe) { 365 Slog.e(TAG, "IO Exception when writing device-owner file\n" + ioe); 366 } 367 } 368 369 private InputStream openRead() throws IOException { 370 if (mInputStreamForTest != null) { 371 return mInputStreamForTest; 372 } 373 374 return new AtomicFile(new File(Environment.getSystemSecureDirectory(), 375 DEVICE_OWNER_XML)).openRead(); 376 } 377 378 private OutputStream startWrite() throws IOException { 379 if (mOutputStreamForTest != null) { 380 return mOutputStreamForTest; 381 } 382 383 fileForWriting = new AtomicFile(new File(Environment.getSystemSecureDirectory(), 384 DEVICE_OWNER_XML)); 385 return fileForWriting.startWrite(); 386 } 387 388 private void finishWrite(OutputStream stream) { 389 if (fileForWriting != null) { 390 fileForWriting.finishWrite((FileOutputStream) stream); 391 } 392 } 393 394 private static class OwnerInfo { 395 public final String name; 396 public final String packageName; 397 public final ComponentName admin; 398 399 public OwnerInfo(String name, String packageName) { 400 this.name = name; 401 this.packageName = packageName; 402 this.admin = new ComponentName(packageName, ""); 403 } 404 405 public OwnerInfo(String name, ComponentName admin) { 406 this.name = name; 407 this.admin = admin; 408 this.packageName = admin.getPackageName(); 409 } 410 public void dump(String prefix, PrintWriter pw) { 411 pw.println(prefix + "admin=" + admin); 412 pw.println(prefix + "name=" + name); 413 pw.println(); 414 } 415 } 416 417 public void dump(String prefix, PrintWriter pw) { 418 if (mDeviceOwner != null) { 419 pw.println(prefix + "Device Owner: "); 420 mDeviceOwner.dump(prefix + " ", pw); 421 } 422 if (mProfileOwners != null) { 423 for (Map.Entry<Integer, OwnerInfo> entry : mProfileOwners.entrySet()) { 424 pw.println(prefix + "Profile Owner (User " + entry.getKey() + "): "); 425 entry.getValue().dump(prefix + " ", pw); 426 } 427 } 428 } 429 } 430