Home | History | Annotate | Download | only in devicepolicy
      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