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.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