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