diff options
6 files changed, 549 insertions, 118 deletions
diff --git a/api/current.txt b/api/current.txt index c0ed81a..740ec38 100644 --- a/api/current.txt +++ b/api/current.txt @@ -4771,6 +4771,7 @@ package android.app.admin { method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); method public boolean isDeviceOwnerApp(java.lang.String); + method public boolean isProfileOwnerApp(java.lang.String); method public void lockNow(); method public void removeActiveAdmin(android.content.ComponentName); method public boolean resetPassword(java.lang.String, int); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index ab82531..40bdb73 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -26,6 +26,7 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.os.Handler; +import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.ServiceManager; @@ -1681,4 +1682,88 @@ public class DevicePolicyManager { } return null; } + + /** + * @hide + * Sets the given package as the profile owner of the given user profile. The package must + * already be installed and there shouldn't be an existing profile owner registered for this + * user. Also, this method must be called before the user has been used for the first time. + * @param packageName the package name of the application to be registered as profile owner. + * @param ownerName the human readable name of the organisation associated with this DPM. + * @return whether the package was successfully registered as the profile owner. + * @throws IllegalArgumentException if packageName is null, the package isn't installed, or + * the user has already been set up. + */ + public boolean setProfileOwner(String packageName, String ownerName) + throws IllegalArgumentException { + if (mService != null) { + try { + return mService.setProfileOwner(packageName, ownerName, + Process.myUserHandle().getIdentifier()); + } catch (RemoteException re) { + Log.w(TAG, "Failed to set profile owner", re); + throw new IllegalArgumentException("Couldn't set profile owner.", re); + } + } + return false; + } + + /** + * Used to determine if a particular package is registered as the Profile Owner for the + * current user. A profile owner is a special device admin that has additional priviledges + * within the managed profile. + * + * @param packageName The package name of the app to compare with the registered profile owner. + * @return Whether or not the package is registered as the profile owner. + */ + public boolean isProfileOwnerApp(String packageName) { + if (mService != null) { + try { + String profileOwnerPackage = mService.getProfileOwner( + Process.myUserHandle().getIdentifier()); + return profileOwnerPackage != null && profileOwnerPackage.equals(packageName); + } catch (RemoteException re) { + Log.w(TAG, "Failed to check profile owner"); + } + } + return false; + } + + /** + * @hide + * @return the packageName of the owner of the given user profile or null if no profile + * owner has been set for that user. + * @throws IllegalArgumentException if the userId is invalid. + */ + public String getProfileOwner() throws IllegalArgumentException { + if (mService != null) { + try { + return mService.getProfileOwner(Process.myUserHandle().getIdentifier()); + } catch (RemoteException re) { + Log.w(TAG, "Failed to get profile owner"); + throw new IllegalArgumentException( + "Requested profile owner for invalid userId", re); + } + } + return null; + } + + /** + * @hide + * @return the human readable name of the organisation associated with this DPM or null if + * one is not set. + * @throws IllegalArgumentException if the userId is invalid. + */ + public String getProfileOwnerName() throws IllegalArgumentException { + if (mService != null) { + try { + return mService.getProfileOwnerName(Process.myUserHandle().getIdentifier()); + } catch (RemoteException re) { + Log.w(TAG, "Failed to get profile owner"); + throw new IllegalArgumentException( + "Requested profile owner for invalid userId", re); + } + } + return null; + } } diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 172c47c..9d189db 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -103,6 +103,10 @@ interface IDevicePolicyManager { String getDeviceOwner(); String getDeviceOwnerName(); + boolean setProfileOwner(String packageName, String ownerName, int userHandle); + String getProfileOwner(int userHandle); + String getProfileOwnerName(int userHandle); + boolean installCaCert(in byte[] certBuffer); void uninstallCaCert(in byte[] certBuffer); } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java new file mode 100644 index 0000000..1b048a1 --- /dev/null +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java @@ -0,0 +1,274 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.devicepolicy; + +import android.app.AppGlobals; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.content.pm.PackageManager.NameNotFoundException; +import android.os.Environment; +import android.os.RemoteException; +import android.util.AtomicFile; +import android.util.Slog; +import android.util.Xml; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.FastXmlSerializer; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.HashMap; + +/** + * Stores and restores state for the Device and Profile owners. By definition there can be + * only one device owner, but there may be a profile owner for each user. + */ +public class DeviceOwner { + private static final String TAG = "DevicePolicyManagerService"; + + private static final String DEVICE_OWNER_XML = "device_owner.xml"; + private static final String TAG_DEVICE_OWNER = "device-owner"; + private static final String TAG_PROFILE_OWNER = "profile-owner"; + private static final String ATTR_NAME = "name"; + private static final String ATTR_PACKAGE = "package"; + private static final String ATTR_USERID = "userId"; + + private AtomicFile fileForWriting; + + // Input/Output streams for testing. + private InputStream mInputStreamForTest; + private OutputStream mOutputStreamForTest; + + // Internal state for the device owner package. + private String mDeviceOwnerPackageName; + private String mDeviceOwnerName; + + // Internal state for the profile owner packages. + private final HashMap<Integer, String[]> mProfileOwners = new HashMap<Integer, String[]>(); + + // Private default constructor. + private DeviceOwner() { + } + + @VisibleForTesting + DeviceOwner(InputStream in, OutputStream out) { + mInputStreamForTest = in; + mOutputStreamForTest = out; + } + + /** + * Loads the device owner state from disk. + */ + static DeviceOwner load() { + DeviceOwner owner = new DeviceOwner(); + if (new File(Environment.getSystemSecureDirectory(), DEVICE_OWNER_XML).exists()) { + owner.readOwnerFile(); + return owner; + } else { + return null; + } + } + + /** + * Creates an instance of the device owner object with the device owner set. + */ + static DeviceOwner createWithDeviceOwner(String packageName, String ownerName) { + DeviceOwner owner = new DeviceOwner(); + owner.mDeviceOwnerPackageName = packageName; + owner.mDeviceOwnerName = ownerName; + return owner; + } + + /** + * Creates an instance of the device owner object with the profile owner set. + */ + static DeviceOwner createWithProfileOwner(String packageName, String ownerName, int userId) { + DeviceOwner owner = new DeviceOwner(); + owner.mProfileOwners.put(userId, new String[] { packageName, ownerName }); + return owner; + } + + String getDeviceOwnerPackageName() { + return mDeviceOwnerPackageName; + } + + String getDeviceOwnerName() { + return mDeviceOwnerName; + } + + void setDeviceOwner(String packageName, String ownerName) { + mDeviceOwnerPackageName = packageName; + mDeviceOwnerName = ownerName; + } + + void setProfileOwner(String packageName, String ownerName, int userId) { + mProfileOwners.put(userId, new String[] { packageName, ownerName }); + } + + void removeProfileOwner(int userId) { + mProfileOwners.remove(userId); + } + + String getProfileOwnerPackageName(int userId) { + String[] profileOwner = mProfileOwners.get(userId); + return profileOwner != null ? profileOwner[0] : null; + } + + String getProfileOwnerName(int userId) { + String[] profileOwner = mProfileOwners.get(userId); + return profileOwner != null ? profileOwner[1] : null; + } + + boolean hasDeviceOwner() { + return mDeviceOwnerPackageName != null; + } + + static boolean isInstalled(String packageName, PackageManager pm) { + try { + PackageInfo pi; + if ((pi = pm.getPackageInfo(packageName, 0)) != null) { + if ((pi.applicationInfo.flags) != 0) { + return true; + } + } + } catch (NameNotFoundException nnfe) { + Slog.w(TAG, "Device Owner package " + packageName + " not installed."); + } + return false; + } + + static boolean isInstalledForUser(String packageName, int userHandle) { + try { + PackageInfo pi = (AppGlobals.getPackageManager()) + .getPackageInfo(packageName, 0, userHandle); + if (pi != null && pi.applicationInfo.flags != 0) { + return true; + } + } catch (RemoteException re) { + throw new RuntimeException("Package manager has died", re); + } + + return false; + } + + void readOwnerFile() { + try { + InputStream input = openRead(); + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(input, null); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT) { + if (type!=XmlPullParser.START_TAG) { + continue; + } + + String tag = parser.getName(); + if (tag.equals(TAG_DEVICE_OWNER)) { + mDeviceOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); + mDeviceOwnerName = parser.getAttributeValue(null, ATTR_NAME); + } else if (tag.equals(TAG_PROFILE_OWNER)) { + String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); + String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME); + int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID)); + mProfileOwners.put(userId, + new String[] { profileOwnerPackageName, profileOwnerName }); + } else { + throw new XmlPullParserException( + "Unexpected tag in device owner file: " + tag); + } + } + input.close(); + } catch (XmlPullParserException xppe) { + Slog.e(TAG, "Error parsing device-owner file\n" + xppe); + } catch (IOException ioe) { + Slog.e(TAG, "IO Exception when reading device-owner file\n" + ioe); + } + } + + void writeOwnerFile() { + synchronized (this) { + writeOwnerFileLocked(); + } + } + + private void writeOwnerFileLocked() { + try { + OutputStream outputStream = startWrite(); + XmlSerializer out = new FastXmlSerializer(); + out.setOutput(outputStream, "utf-8"); + out.startDocument(null, true); + + // Write device owner tag + if (mDeviceOwnerPackageName != null) { + out.startTag(null, TAG_DEVICE_OWNER); + out.attribute(null, ATTR_PACKAGE, mDeviceOwnerPackageName); + if (mDeviceOwnerName != null) { + out.attribute(null, ATTR_NAME, mDeviceOwnerName); + } + out.endTag(null, TAG_DEVICE_OWNER); + } + + // Write profile owner tags + if (mProfileOwners.size() > 0) { + for (HashMap.Entry<Integer, String[]> owner : mProfileOwners.entrySet()) { + out.startTag(null, TAG_PROFILE_OWNER); + out.attribute(null, ATTR_PACKAGE, owner.getValue()[0]); + out.attribute(null, ATTR_NAME, owner.getValue()[1]); + out.attribute(null, ATTR_USERID, Integer.toString(owner.getKey())); + out.endTag(null, TAG_PROFILE_OWNER); + } + } + out.endDocument(); + out.flush(); + finishWrite(outputStream); + } catch (IOException ioe) { + Slog.e(TAG, "IO Exception when writing device-owner file\n" + ioe); + } + } + + private InputStream openRead() throws IOException { + if (mInputStreamForTest != null) { + return mInputStreamForTest; + } + + return new AtomicFile(new File(Environment.getSystemSecureDirectory(), + DEVICE_OWNER_XML)).openRead(); + } + + private OutputStream startWrite() throws IOException { + if (mOutputStreamForTest != null) { + return mOutputStreamForTest; + } + + fileForWriting = new AtomicFile(new File(Environment.getSystemSecureDirectory(), + DEVICE_OWNER_XML)); + return fileForWriting.startWrite(); + } + + private void finishWrite(OutputStream stream) { + if (fileForWriting != null) { + fileForWriting.finishWrite((FileOutputStream) stream); + } + } +}
\ No newline at end of file diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 186fbe1..a8f2df1 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -26,10 +26,6 @@ import com.android.internal.util.XmlUtils; import com.android.internal.widget.LockPatternUtils; import com.android.org.conscrypt.TrustedCertificateStore; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlSerializer; - import android.app.Activity; import android.app.ActivityManagerNative; import android.app.AlarmManager; @@ -49,9 +45,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ApplicationInfo; import android.content.pm.IPackageManager; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; -import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.ProxyProperties; @@ -75,7 +69,6 @@ import android.security.Credentials; import android.security.IKeyChainService; import android.security.KeyChain; import android.security.KeyChain.KeyChainConnection; -import android.util.AtomicFile; import android.util.Log; import android.util.PrintWriterPrinter; import android.util.Printer; @@ -84,6 +77,10 @@ import android.util.SparseArray; import android.util.Xml; import android.view.IWindowManager; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; +import org.xmlpull.v1.XmlSerializer; + import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileDescriptor; @@ -132,6 +129,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { IWindowManager mIWindowManager; NotificationManager mNotificationManager; + // Stores and loads state on device and profile owners. private DeviceOwner mDeviceOwner; /** @@ -601,6 +599,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring."); return; } + + mDeviceOwner.removeProfileOwner(userHandle); + mDeviceOwner.writeOwnerFile(); + DevicePolicyData policy = mUserData.get(userHandle); if (policy != null) { mUserData.remove(userHandle); @@ -614,9 +616,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { void loadDeviceOwner() { synchronized (this) { - if (DeviceOwner.isRegistered()) { - mDeviceOwner = new DeviceOwner(); - } + mDeviceOwner = DeviceOwner.load(); } } @@ -1294,7 +1294,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { if (admin.getUid() != Binder.getCallingUid()) { // If trying to remove device owner, refuse when the caller is not the owner. if (mDeviceOwner != null - && adminReceiver.getPackageName().equals(mDeviceOwner.getPackageName())) { + && adminReceiver.getPackageName().equals( + mDeviceOwner.getDeviceOwnerPackageName())) { return; } mContext.enforceCallingOrSelfPermission( @@ -2739,14 +2740,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { + " for device owner"); } synchronized (this) { - if (mDeviceOwner == null && !isDeviceProvisioned()) { - mDeviceOwner = new DeviceOwner(packageName, ownerName); + if (isDeviceProvisioned()) { + throw new IllegalStateException( + "Trying to set device owner but device is already provisioned."); + } + + if (mDeviceOwner != null && mDeviceOwner.hasDeviceOwner()) { + throw new IllegalStateException( + "Trying to set device owner but device owner is already set."); + } + + if (mDeviceOwner == null) { + // Device owner is not set and does not exist, set it. + mDeviceOwner = DeviceOwner.createWithDeviceOwner(packageName, ownerName); mDeviceOwner.writeOwnerFile(); return true; } else { - throw new IllegalStateException("Trying to set device owner to " + packageName - + ", owner=" + mDeviceOwner.getPackageName() - + ", device_provisioned=" + isDeviceProvisioned()); + // Device owner is not set but a profile owner exists, update Device owner state. + mDeviceOwner.setDeviceOwner(packageName, ownerName); + mDeviceOwner.writeOwnerFile(); + return true; } } } @@ -2758,7 +2771,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } synchronized (this) { return mDeviceOwner != null - && mDeviceOwner.getPackageName().equals(packageName); + && mDeviceOwner.getDeviceOwnerPackageName().equals(packageName); } } @@ -2769,7 +2782,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } synchronized (this) { if (mDeviceOwner != null) { - return mDeviceOwner.getPackageName(); + return mDeviceOwner.getDeviceOwnerPackageName(); } } return null; @@ -2783,7 +2796,67 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); synchronized (this) { if (mDeviceOwner != null) { - return mDeviceOwner.getName(); + return mDeviceOwner.getDeviceOwnerName(); + } + } + return null; + } + + @Override + public boolean setProfileOwner(String packageName, String ownerName, int userHandle) { + if (!mHasFeature) { + return false; + } + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); + if (packageName == null + || !DeviceOwner.isInstalledForUser(packageName, userHandle)) { + throw new IllegalArgumentException("Package name " + packageName + + " not installed for userId:" + userHandle); + } + synchronized (this) { + if (isUserSetupComplete(userHandle)) { + throw new IllegalStateException( + "Trying to set profile owner but user is already set-up."); + } + if (mDeviceOwner == null) { + // Device owner state does not exist, create it. + mDeviceOwner = DeviceOwner.createWithProfileOwner(packageName, ownerName, + userHandle); + mDeviceOwner.writeOwnerFile(); + return true; + } else { + // Device owner already exists, update it. + mDeviceOwner.setProfileOwner(packageName, ownerName, userHandle); + mDeviceOwner.writeOwnerFile(); + return true; + } + } + } + + @Override + public String getProfileOwner(int userHandle) { + if (!mHasFeature) { + return null; + } + + synchronized (this) { + if (mDeviceOwner != null) { + return mDeviceOwner.getProfileOwnerPackageName(userHandle); + } + } + return null; + } + + @Override + public String getProfileOwnerName(int userHandle) { + if (!mHasFeature) { + return null; + } + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null); + + synchronized (this) { + if (mDeviceOwner != null) { + return mDeviceOwner.getProfileOwnerName(userHandle); } } return null; @@ -2794,6 +2867,11 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { Settings.Global.DEVICE_PROVISIONED, 0) > 0; } + private boolean isUserSetupComplete(int userId) { + return Settings.Secure.getIntForUser(mContext.getContentResolver(), + Settings.Secure.USER_SETUP_COMPLETE, 0, userId) > 0; + } + private void enforceCrossUserPermission(int userHandle) { if (userHandle < 0) { throw new IllegalArgumentException("Invalid userId " + userHandle); @@ -2858,103 +2936,4 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { } } } - - static class DeviceOwner { - private static final String DEVICE_OWNER_XML = "device_owner.xml"; - private static final String TAG_DEVICE_OWNER = "device-owner"; - private static final String ATTR_NAME = "name"; - private static final String ATTR_PACKAGE = "package"; - private String mPackageName; - private String mOwnerName; - - DeviceOwner() { - readOwnerFile(); - } - - DeviceOwner(String packageName, String ownerName) { - this.mPackageName = packageName; - this.mOwnerName = ownerName; - } - - static boolean isRegistered() { - return new File(Environment.getSystemSecureDirectory(), - DEVICE_OWNER_XML).exists(); - } - - String getPackageName() { - return mPackageName; - } - - String getName() { - return mOwnerName; - } - - static boolean isInstalled(String packageName, PackageManager pm) { - try { - PackageInfo pi; - if ((pi = pm.getPackageInfo(packageName, 0)) != null) { - if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) { - return true; - } - } - } catch (NameNotFoundException nnfe) { - Slog.w(LOG_TAG, "Device Owner package " + packageName + " not installed."); - } - return false; - } - - void readOwnerFile() { - AtomicFile file = new AtomicFile(new File(Environment.getSystemSecureDirectory(), - DEVICE_OWNER_XML)); - try { - FileInputStream input = file.openRead(); - XmlPullParser parser = Xml.newPullParser(); - parser.setInput(input, null); - int type; - while ((type=parser.next()) != XmlPullParser.END_DOCUMENT - && type != XmlPullParser.START_TAG) { - } - String tag = parser.getName(); - if (!TAG_DEVICE_OWNER.equals(tag)) { - throw new XmlPullParserException( - "Device Owner file does not start with device-owner tag: found " + tag); - } - mPackageName = parser.getAttributeValue(null, ATTR_PACKAGE); - mOwnerName = parser.getAttributeValue(null, ATTR_NAME); - input.close(); - } catch (XmlPullParserException xppe) { - Slog.e(LOG_TAG, "Error parsing device-owner file\n" + xppe); - } catch (IOException ioe) { - Slog.e(LOG_TAG, "IO Exception when reading device-owner file\n" + ioe); - } - } - - void writeOwnerFile() { - synchronized (this) { - writeOwnerFileLocked(); - } - } - - private void writeOwnerFileLocked() { - AtomicFile file = new AtomicFile(new File(Environment.getSystemSecureDirectory(), - DEVICE_OWNER_XML)); - try { - FileOutputStream output = file.startWrite(); - XmlSerializer out = new FastXmlSerializer(); - out.setOutput(output, "utf-8"); - out.startDocument(null, true); - out.startTag(null, TAG_DEVICE_OWNER); - out.attribute(null, ATTR_PACKAGE, mPackageName); - if (mOwnerName != null) { - out.attribute(null, ATTR_NAME, mOwnerName); - } - out.endTag(null, TAG_DEVICE_OWNER); - out.endDocument(); - out.flush(); - file.finishWrite(output); - } catch (IOException ioe) { - Slog.e(LOG_TAG, "IO Exception when writing device-owner file\n" + ioe); - } - } - } } diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DeviceOwnerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DeviceOwnerTest.java new file mode 100644 index 0000000..f913b97 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DeviceOwnerTest.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.devicepolicy; + +import android.test.AndroidTestCase; +import android.test.suitebuilder.annotation.SmallTest; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +/** + * Tests for the DeviceOwner object that saves & loads device and policy owner information. + * run this test with: + * make -j FrameworksServicesTests + * runtest --path frameworks/base/services/tests/servicestests/ \ + * src/com/android/server/devicepolicy/DeviceOwnerTest.java + */ +public class DeviceOwnerTest extends AndroidTestCase { + + private ByteArrayInputStream mInputStreamForTest; + private ByteArrayOutputStream mOutputStreamForTest = new ByteArrayOutputStream(); + + @SmallTest + public void testDeviceOwnerOnly() throws Exception { + DeviceOwner out = new DeviceOwner(null, mOutputStreamForTest); + out.setDeviceOwner("some.device.owner.package", "owner"); + out.writeOwnerFile(); + + mInputStreamForTest = new ByteArrayInputStream(mOutputStreamForTest.toByteArray()); + DeviceOwner in = new DeviceOwner(mInputStreamForTest, null); + in.readOwnerFile(); + + assertEquals("some.device.owner.package", in.getDeviceOwnerPackageName()); + assertEquals("owner", in.getDeviceOwnerName()); + assertNull(in.getProfileOwnerPackageName(1)); + } + + @SmallTest + public void testProfileOwnerOnly() throws Exception { + DeviceOwner out = new DeviceOwner(null, mOutputStreamForTest); + out.setProfileOwner("some.profile.owner.package", "some-company", 1); + out.writeOwnerFile(); + + mInputStreamForTest = new ByteArrayInputStream(mOutputStreamForTest.toByteArray()); + DeviceOwner in = new DeviceOwner(mInputStreamForTest, null); + in.readOwnerFile(); + + assertNull(in.getDeviceOwnerPackageName()); + assertNull(in.getDeviceOwnerName()); + assertEquals("some.profile.owner.package", in.getProfileOwnerPackageName(1)); + assertEquals("some-company", in.getProfileOwnerName(1)); + } + + @SmallTest + public void testDeviceAndProfileOwners() throws Exception { + DeviceOwner out = new DeviceOwner(null, mOutputStreamForTest); + out.setDeviceOwner("some.device.owner.package", "owner"); + out.setProfileOwner("some.profile.owner.package", "some-company", 1); + out.setProfileOwner("some.other.profile.owner", "some-other-company", 2); + out.writeOwnerFile(); + + mInputStreamForTest = new ByteArrayInputStream(mOutputStreamForTest.toByteArray()); + + DeviceOwner in = new DeviceOwner(mInputStreamForTest, null); + in.readOwnerFile(); + + assertEquals("some.device.owner.package", in.getDeviceOwnerPackageName()); + assertEquals("owner", in.getDeviceOwnerName()); + assertEquals("some.profile.owner.package", in.getProfileOwnerPackageName(1)); + assertEquals("some-company", in.getProfileOwnerName(1)); + assertEquals("some.other.profile.owner", in.getProfileOwnerPackageName(2)); + assertEquals("some-other-company", in.getProfileOwnerName(2)); + } +}
\ No newline at end of file |