1 /*
2  * Copyright (C) 2009 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.cts.usespermissiondiffcertapp;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.ComponentName;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.pm.PackageManager;
24 import android.net.Uri;
25 import android.os.SystemClock;
26 import android.test.AndroidTestCase;
27 import android.util.Log;
28 
29 /**
30  * Tests that one application can and can not modify the installer package
31  * of another application is appropriate.
32  *
33  * Accesses app cts/tests/appsecurity-tests/test-apps/PermissionDeclareApp/...
34  */
35 public class ModifyInstallerPackageTest extends AndroidTestCase {
36     static final ComponentName SET_INSTALLER_PACKAGE_COMP
37             = new ComponentName("com.android.cts.permissiondeclareapp",
38                     "com.android.cts.permissiondeclareapp.SetInstallerPackage");
39     static final String OTHER_PACKAGE = "com.android.cts.permissiondeclareapp";
40     static final String MY_PACKAGE = "com.android.cts.usespermissiondiffcertapp";
41 
42     static class SetInstallerPackageReceiver extends BroadcastReceiver {
43         boolean mHaveResult = false;
44         boolean mGoodResult = false;
45         boolean mSucceeded = false;
46 
47         @Override
onReceive(Context context, Intent intent)48         public void onReceive(Context context, Intent intent) {
49             synchronized (this) {
50                 mHaveResult = true;
51                 switch (getResultCode()) {
52                     case 100:
53                         mGoodResult = true;
54                         mSucceeded = false;
55                         break;
56                     case 101:
57                         mGoodResult = true;
58                         mSucceeded = true;
59                         break;
60                     default:
61                         mGoodResult = false;
62                         break;
63                 }
64                 notifyAll();
65             }
66         }
67 
assertSuccess(String failureMessage)68         void assertSuccess(String failureMessage) {
69             synchronized (this) {
70                 final long startTime = SystemClock.uptimeMillis();
71                 while (!mHaveResult) {
72                     try {
73                         wait(5000);
74                     } catch (InterruptedException e) {
75                     }
76                     if (SystemClock.uptimeMillis() >= (startTime+5000)) {
77                         throw new RuntimeException("Timeout");
78                     }
79                 }
80                 if (!mGoodResult) {
81                     fail("Broadcast receiver did not return good result");
82                 }
83                 if (!mSucceeded) {
84                     fail(failureMessage);
85                 }
86             }
87         }
88 
assertFailure(String failureMessage)89         void assertFailure(String failureMessage) {
90             synchronized (this) {
91                 final long startTime = SystemClock.uptimeMillis();
92                 while (!mHaveResult) {
93                     try {
94                         wait(5000);
95                     } catch (InterruptedException e) {
96                     }
97                     if (SystemClock.uptimeMillis() >= (startTime+5000)) {
98                         throw new RuntimeException("Timeout");
99                     }
100                 }
101                 if (!mGoodResult) {
102                     fail("Broadcast receiver did not return good result");
103                 }
104                 if (mSucceeded) {
105                     fail(failureMessage);
106                 }
107             }
108         }
109     }
110 
getPackageManager()111     PackageManager getPackageManager() {
112         return getContext().getPackageManager();
113     }
114 
115     /**
116      * Test that we can set the installer package name.
117      */
testSetInstallPackage()118     public void testSetInstallPackage() {
119         // Pre-condition.
120         assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
121 
122         getPackageManager().setInstallerPackageName(OTHER_PACKAGE, MY_PACKAGE);
123         assertEquals(MY_PACKAGE, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
124 
125         // Clean up.
126         getPackageManager().setInstallerPackageName(OTHER_PACKAGE, null);
127         assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
128     }
129 
130     /**
131      * Test that we fail if trying to set an installer package with an unknown
132      * target package name.
133      */
testSetInstallPackageBadTarget()134     public void testSetInstallPackageBadTarget() {
135         try {
136             getPackageManager().setInstallerPackageName("thisdoesnotexistihope!", MY_PACKAGE);
137             fail("setInstallerPackageName did not throw IllegalArgumentException");
138         } catch (IllegalArgumentException e) {
139             // That's what we want!
140         }
141     }
142 
143     /**
144      * Test that we fail if trying to set an installer package with an unknown
145      * installer package name.
146      */
testSetInstallPackageBadInstaller()147     public void testSetInstallPackageBadInstaller() {
148         try {
149             getPackageManager().setInstallerPackageName(OTHER_PACKAGE, "thisdoesnotexistihope!");
150             fail("setInstallerPackageName did not throw IllegalArgumentException");
151         } catch (IllegalArgumentException e) {
152             // That's what we want!
153         }
154         assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
155     }
156 
157     /**
158      * Test that we fail if trying to set an installer package that is not
159      * signed with our cert.
160      */
testSetInstallPackageWrongCertificate()161     public void testSetInstallPackageWrongCertificate() {
162         // Pre-condition.
163         assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
164 
165         try {
166             getPackageManager().setInstallerPackageName(OTHER_PACKAGE, OTHER_PACKAGE);
167             fail("setInstallerPackageName did not throw SecurityException");
168         } catch (SecurityException e) {
169             // That's what we want!
170         }
171 
172         assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
173     }
174 
175     /**
176      * Test that we fail if trying to set an installer package that is not
177      * signed with the same cert as the currently set installer.
178      */
testSetInstallPackageConflictingInstaller()179     public void testSetInstallPackageConflictingInstaller() {
180         // Pre-condition.
181         assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
182 
183         // Have the other package set the installer, under its cert.
184         Intent intent = new Intent();
185         intent.setComponent(SET_INSTALLER_PACKAGE_COMP);
186         intent.putExtra("target", OTHER_PACKAGE);
187         intent.putExtra("installer", OTHER_PACKAGE);
188         SetInstallerPackageReceiver receiver = new SetInstallerPackageReceiver();
189         getContext().sendOrderedBroadcast(intent, null, receiver, null, 0, null, null);
190         receiver.assertSuccess("Failure initializing with other installer");
191 
192         assertEquals(OTHER_PACKAGE, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
193 
194         try {
195             getPackageManager().setInstallerPackageName(OTHER_PACKAGE, MY_PACKAGE);
196             fail("setInstallerPackageName did not throw SecurityException");
197         } catch (SecurityException e) {
198             // That's what we want!
199         }
200 
201         assertEquals(OTHER_PACKAGE, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
202 
203         // Now clear the installer
204         intent.putExtra("target", OTHER_PACKAGE);
205         intent.putExtra("installer", (String)null);
206         receiver = new SetInstallerPackageReceiver();
207         getContext().sendOrderedBroadcast(intent, null, receiver, null, 0, null, null);
208         receiver.assertSuccess("Failure clearing other installer");
209 
210         assertEquals(null, getPackageManager().getInstallerPackageName(OTHER_PACKAGE));
211     }
212 }
213