summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/os/IUserManager.aidl1
-rw-r--r--core/java/android/os/UserManager.java9
-rw-r--r--core/java/com/android/internal/app/RestrictionsPinActivity.java92
-rw-r--r--core/java/com/android/internal/app/RestrictionsPinSetupActivity.java104
-rw-r--r--core/res/res/layout/restrictions_pin_challenge.xml59
-rw-r--r--core/res/res/layout/restrictions_pin_setup.xml (renamed from core/res/res/layout/pin_challenge.xml)27
-rw-r--r--core/res/res/values/strings.xml12
-rwxr-xr-xcore/res/res/values/symbols.xml8
-rwxr-xr-xservices/java/com/android/server/pm/PackageManagerService.java7
-rw-r--r--services/java/com/android/server/pm/UserManagerService.java107
10 files changed, 334 insertions, 92 deletions
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 7589a5a..bd2d9ac 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -49,4 +49,5 @@ interface IUserManager {
boolean changeRestrictionsPin(in String newPin);
int checkRestrictionsPin(in String pin);
boolean hasRestrictionsPin();
+ void removeRestrictions();
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index c33a28a..cdaa868 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -678,4 +678,13 @@ public class UserManager {
}
return false;
}
+
+ /** @hide */
+ public void removeRestrictions() {
+ try {
+ mService.removeRestrictions();
+ } catch (RemoteException re) {
+ Log.w(TAG, "Could not change restrictions pin");
+ }
+ }
}
diff --git a/core/java/com/android/internal/app/RestrictionsPinActivity.java b/core/java/com/android/internal/app/RestrictionsPinActivity.java
index 57436f7..f8ce108 100644
--- a/core/java/com/android/internal/app/RestrictionsPinActivity.java
+++ b/core/java/com/android/internal/app/RestrictionsPinActivity.java
@@ -26,6 +26,7 @@ import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.WindowManager;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
@@ -39,17 +40,24 @@ import com.android.internal.R;
public class RestrictionsPinActivity extends AlertActivity
implements DialogInterface.OnClickListener, TextWatcher, OnEditorActionListener {
- private UserManager mUserManager;
+ protected UserManager mUserManager;
+ protected boolean mHasRestrictionsPin;
- private EditText mPin1Text;
- private EditText mPin2Text;
- private TextView mPinErrorMessage;
- private TextView mPinMessage;
+ protected EditText mPinText;
+ protected TextView mPinErrorMessage;
+ protected TextView mPinMessage;
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
+ mHasRestrictionsPin = mUserManager.hasRestrictionsPin();
+ initUi();
+ setupAlert();
+ }
+
+ protected void initUi() {
AlertController.AlertParams ap = mAlertParams;
ap.mTitle = getString(R.string.restr_pin_enter_pin);
ap.mPositiveButtonText = getString(R.string.ok);
@@ -58,18 +66,12 @@ public class RestrictionsPinActivity extends AlertActivity
ap.mNegativeButtonListener = this;
LayoutInflater inflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- ap.mView = inflater.inflate(R.layout.pin_challenge, null);
+ ap.mView = inflater.inflate(R.layout.restrictions_pin_challenge, null);
mPinMessage = (TextView) ap.mView.findViewById(R.id.pin_message);
- mPin1Text = (EditText) ap.mView.findViewById(R.id.pin1_text);
- mPin2Text = (EditText) ap.mView.findViewById(R.id.pin2_text);
+ mPinText = (EditText) ap.mView.findViewById(R.id.pin_text);
mPinErrorMessage = (TextView) ap.mView.findViewById(R.id.pin_error_message);
- mPin1Text.addTextChangedListener(this);
- mPin2Text.addTextChangedListener(this);
-
- mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
-
- setupAlert();
+ mPinText.addTextChangedListener(this);
}
protected boolean verifyingPin() {
@@ -81,19 +83,12 @@ public class RestrictionsPinActivity extends AlertActivity
setPositiveButtonState(false);
boolean hasPin = mUserManager.hasRestrictionsPin();
- if (verifyingPin()) {
- if (hasPin) {
- mPinMessage.setVisibility(View.GONE);
- mPinErrorMessage.setVisibility(View.GONE);
- mPin2Text.setVisibility(View.GONE);
- mPin1Text.setOnEditorActionListener(this);
- updatePinTimer(-1);
- } else {
- setResult(RESULT_OK);
- finish();
- }
- } else if (hasPin) {
- // Shouldn't really be in this state, exit
+ if (hasPin) {
+ mPinMessage.setVisibility(View.GONE);
+ mPinErrorMessage.setVisibility(View.GONE);
+ mPinText.setOnEditorActionListener(this);
+ updatePinTimer(-1);
+ } else if (verifyingPin()) {
setResult(RESULT_OK);
finish();
}
@@ -114,14 +109,14 @@ public class RestrictionsPinActivity extends AlertActivity
seconds);
mPinErrorMessage.setText(String.format(formatString, seconds));
mPinErrorMessage.setVisibility(View.VISIBLE);
- mPin1Text.setEnabled(false);
- mPin1Text.setText("");
+ mPinText.setEnabled(false);
+ mPinText.setText("");
setPositiveButtonState(false);
- mPin1Text.postDelayed(mCountdownRunnable, Math.min(1000, pinTimerMs));
+ mPinText.postDelayed(mCountdownRunnable, Math.min(1000, pinTimerMs));
} else {
mPinErrorMessage.setVisibility(View.INVISIBLE);
- mPin1Text.setEnabled(true);
- mPin1Text.setText("");
+ mPinText.setEnabled(true);
+ mPinText.setText("");
}
}
@@ -134,20 +129,13 @@ public class RestrictionsPinActivity extends AlertActivity
}
}
- private void performPositiveButtonAction() {
- if (verifyingPin()) {
- int result = mUserManager.checkRestrictionsPin(mPin1Text.getText().toString());
- if (result == UserManager.PIN_VERIFICATION_SUCCESS) {
- setResult(RESULT_OK);
- finish();
- } else if (result >= 0) {
- updatePinTimer(result);
- }
- } else {
- if (mUserManager.changeRestrictionsPin(mPin1Text.getText().toString())) {
- setResult(RESULT_OK);
- finish();
- }
+ protected void performPositiveButtonAction() {
+ int result = mUserManager.checkRestrictionsPin(mPinText.getText().toString());
+ if (result == UserManager.PIN_VERIFICATION_SUCCESS) {
+ setResult(RESULT_OK);
+ finish();
+ } else if (result >= 0) {
+ updatePinTimer(result);
}
}
@@ -157,16 +145,8 @@ public class RestrictionsPinActivity extends AlertActivity
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
- CharSequence pin1 = mPin1Text.getText();
- if (!verifyingPin()) {
- CharSequence pin2 = mPin2Text.getText();
- boolean match = pin1 != null && pin2 != null && pin1.length() >= 4
- && pin1.toString().equals(pin2.toString());
- setPositiveButtonState(match);
- mPinErrorMessage.setVisibility(match ? View.INVISIBLE : View.VISIBLE);
- } else {
- setPositiveButtonState(pin1 != null && pin1.length() >= 4);
- }
+ CharSequence pin = mPinText.getText();
+ setPositiveButtonState(pin != null && pin.length() >= 4);
}
@Override
diff --git a/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java b/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java
index 35f2967..1d09292 100644
--- a/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java
+++ b/core/java/com/android/internal/app/RestrictionsPinSetupActivity.java
@@ -16,13 +16,115 @@
package com.android.internal.app;
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.UserManager;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import com.android.internal.R;
+
/**
* This activity is launched by Settings and other apps to either create a new PIN or
- * challenge for an existing PIN. The PIN is maintained by UserManager.
+ * change an existing PIN. The PIN is maintained by UserManager.
*/
public class RestrictionsPinSetupActivity extends RestrictionsPinActivity {
+ private EditText mNewPinText;
+ private EditText mConfirmPinText;
+
+ protected void initUi() {
+ AlertController.AlertParams ap = mAlertParams;
+ ap.mTitle = getString(R.string.restr_pin_enter_pin);
+ ap.mPositiveButtonText = getString(R.string.ok);
+ ap.mNegativeButtonText = getString(R.string.cancel);
+ ap.mPositiveButtonListener = this;
+ ap.mNegativeButtonListener = this;
+ LayoutInflater inflater =
+ (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ ap.mView = inflater.inflate(R.layout.restrictions_pin_setup, null);
+
+ mPinText = (EditText) ap.mView.findViewById(R.id.pin_text);
+ mPinMessage = (TextView) ap.mView.findViewById(R.id.pin_message);
+ mNewPinText = (EditText) ap.mView.findViewById(R.id.pin_new_text);
+ mConfirmPinText = (EditText) ap.mView.findViewById(R.id.pin_confirm_text);
+ mPinErrorMessage = (TextView) ap.mView.findViewById(R.id.pin_error_message);
+ mNewPinText.addTextChangedListener(this);
+ mConfirmPinText.addTextChangedListener(this);
+
+ if (!mHasRestrictionsPin) {
+ mPinText.setVisibility(View.GONE);
+ }
+ }
+
+ public void onResume() {
+ super.onResume();
+ setPositiveButtonState(false);
+ }
+
protected boolean verifyingPin() {
return false;
}
+
+ private void setPositiveButtonState(boolean enabled) {
+ mAlert.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(enabled);
+ }
+
+ public void onClick(DialogInterface dialog, int which) {
+ setResult(RESULT_CANCELED);
+ if (which == AlertDialog.BUTTON_POSITIVE) {
+ performPositiveButtonAction();
+ } else if (which == AlertDialog.BUTTON_NEGATIVE) {
+ finish();
+ }
+ }
+
+ protected void performPositiveButtonAction() {
+ if (mHasRestrictionsPin) {
+ int result = mUserManager.checkRestrictionsPin(mPinText.getText().toString());
+ if (result != UserManager.PIN_VERIFICATION_SUCCESS) {
+ // TODO: Set message that existing pin doesn't match
+ return;
+ }
+ }
+ if (mUserManager.changeRestrictionsPin(mNewPinText.getText().toString())) {
+ // TODO: Send message to PIN recovery agent about the recovery email address
+ setResult(RESULT_OK);
+ finish();
+ }
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ CharSequence pin = mPinText.getText();
+ CharSequence pin1 = mNewPinText.getText();
+ CharSequence pin2 = mConfirmPinText.getText();
+ boolean match = pin1 != null && pin2 != null && pin1.length() >= 4
+ && pin1.toString().equals(pin2.toString())
+ && (!mHasRestrictionsPin || (pin != null && pin.length() >= 4));
+ boolean showError = !TextUtils.isEmpty(pin1) && !TextUtils.isEmpty(pin2);
+ // TODO: Check recovery email address as well
+ setPositiveButtonState(match);
+ mPinErrorMessage.setVisibility((match || !showError) ? View.INVISIBLE : View.VISIBLE);
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ performPositiveButtonAction();
+ return true;
+ }
}
diff --git a/core/res/res/layout/restrictions_pin_challenge.xml b/core/res/res/layout/restrictions_pin_challenge.xml
new file mode 100644
index 0000000..954af92
--- /dev/null
+++ b/core/res/res/layout/restrictions_pin_challenge.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<!-- Layout used as the dialog's content View for EditTextPreference. -->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_marginTop="48dp"
+ android:layout_marginBottom="48dp"
+ android:overScrollMode="ifContentScrolls">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="8dip"
+ android:orientation="vertical">
+
+ <TextView android:id="@+id/pin_message"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_marginTop="16dp"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/restr_pin_create_pin"
+ android:textColor="?android:attr/textColorSecondary" />
+
+ <EditText android:id="@+id/pin_text"
+ style="?android:attr/textAppearanceMedium"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:hint="@string/restr_pin_enter_pin"
+ android:inputType="numberPassword"
+ android:textColor="?android:attr/textColorPrimary" />
+
+ <TextView android:id="@+id/pin_error_message"
+ style="?android:attr/textAppearanceSmall"
+ android:layout_marginBottom="16dp"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/restr_pin_error_doesnt_match"
+ android:textColor="#FFFF0000" />
+
+ </LinearLayout>
+
+</ScrollView>
diff --git a/core/res/res/layout/pin_challenge.xml b/core/res/res/layout/restrictions_pin_setup.xml
index 2cb14b4..03ed696 100644
--- a/core/res/res/layout/pin_challenge.xml
+++ b/core/res/res/layout/restrictions_pin_setup.xml
@@ -37,38 +37,31 @@
android:text="@string/restr_pin_create_pin"
android:textColor="?android:attr/textColorSecondary" />
- <!-- TextView android:id="@+id/pin1_label"
- style="?android:attr/textAppearanceSmall"
- android:layout_marginBottom="16dp"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/restr_pin_enter_pin"
- android:textColor="?android:attr/textColorSecondary" /-->
-
- <EditText android:id="@+id/pin1_text"
+ <EditText android:id="@+id/pin_text"
style="?android:attr/textAppearanceMedium"
android:layout_marginBottom="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:hint="@string/restr_pin_enter_pin"
- android:inputType="textPassword"
+ android:hint="@string/restr_pin_enter_old_pin"
+ android:inputType="numberPassword"
android:textColor="?android:attr/textColorPrimary" />
- <!-- TextView android:id="@+id/pin2_label"
- style="?android:attr/textAppearanceSmall"
+ <EditText android:id="@+id/pin_new_text"
+ style="?android:attr/textAppearanceMedium"
android:layout_marginBottom="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/restr_pin_confirm_pin"
- android:textColor="?android:attr/textColorSecondary" /-->
+ android:hint="@string/restr_pin_enter_new_pin"
+ android:inputType="numberPassword"
+ android:textColor="?android:attr/textColorPrimary" />
- <EditText android:id="@+id/pin2_text"
+ <EditText android:id="@+id/pin_confirm_text"
style="?android:attr/textAppearanceMedium"
android:layout_marginBottom="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/restr_pin_confirm_pin"
- android:inputType="textPassword"
+ android:inputType="numberPassword"
android:textColor="?android:attr/textColorPrimary" />
<TextView android:id="@+id/pin_error_message"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index eba3f42..b01b50e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4256,12 +4256,16 @@
<!-- Write fail reason: couldn't write the printed content. [CHAR LIMIT=none] -->
<string name="write_fail_reason_cannot_write">Error writing content</string>
+ <!-- PIN entry dialog label/hint for PIN [CHAR LIMIT=none] -->
+ <string name="restr_pin_enter_pin">Enter PIN</string>
+ <!-- PIN entry dialog label/hint for old PIN [CHAR LIMIT=none] -->
+ <string name="restr_pin_enter_old_pin">Current PIN</string>
+ <!-- PIN entry dialog label for new PIN [CHAR LIMIT=none] -->
+ <string name="restr_pin_enter_new_pin">New PIN</string>
+ <!-- PIN entry dialog label for new PIN confirmation [CHAR LIMIT=none] -->
+ <string name="restr_pin_confirm_pin">Confirm new PIN</string>
<!-- PIN creation dialog message [CHAR LIMIT=none] -->
<string name="restr_pin_create_pin">Create a PIN for modifying restrictions</string>
- <!-- PIN entry dialog label for PIN [CHAR LIMIT=none] -->
- <string name="restr_pin_enter_pin">Enter PIN</string>
- <!-- PIN entry dialog label for PIN confirmation [CHAR LIMIT=none] -->
- <string name="restr_pin_confirm_pin">Confirm PIN</string>
<!-- PIN entry dialog error when PINs are not the same [CHAR LIMIT=none] -->
<string name="restr_pin_error_doesnt_match">PINs don\'t match. Try again.</string>
<!-- PIN entry dialog error when PIN is too short [CHAR LIMIT=none] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index e29e82b..8a12ac8 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -214,8 +214,9 @@
<java-symbol type="id" name="breadcrumb_section" />
<java-symbol type="id" name="action_bar_spinner" />
<java-symbol type="id" name="pin_message" />
- <java-symbol type="id" name="pin1_text" />
- <java-symbol type="id" name="pin2_text" />
+ <java-symbol type="id" name="pin_text" />
+ <java-symbol type="id" name="pin_new_text" />
+ <java-symbol type="id" name="pin_confirm_text" />
<java-symbol type="id" name="pin_error_message" />
<java-symbol type="attr" name="actionModeShareDrawable" />
@@ -1157,7 +1158,8 @@
<java-symbol type="layout" name="sms_short_code_confirmation_dialog" />
<java-symbol type="layout" name="action_bar_up_container" />
<java-symbol type="layout" name="app_not_authorized" />
- <java-symbol type="layout" name="pin_challenge" />
+ <java-symbol type="layout" name="restrictions_pin_challenge" />
+ <java-symbol type="layout" name="restrictions_pin_setup" />
<java-symbol type="anim" name="slide_in_child_bottom" />
<java-symbol type="anim" name="slide_in_right" />
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 6f57261..7a01219 100755
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -6189,9 +6189,9 @@ public class PackageManagerService extends IPackageManager.Stub {
PackageSetting pkgSetting;
final int uid = Binder.getCallingUid();
if (UserHandle.getUserId(uid) != userId) {
- mContext.enforceCallingPermission(
+ mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
- "setApplicationBlocked for user " + userId);
+ "setApplicationBlockedSetting for user " + userId);
}
if (blocked && isPackageDeviceAdmin(packageName, userId)) {
@@ -6224,6 +6224,8 @@ public class PackageManagerService extends IPackageManager.Stub {
return true;
}
if (sendRemoved) {
+ killApplication(packageName, UserHandle.getUid(userId, pkgSetting.appId),
+ "blocking pkg");
sendPackageBlockedForUser(packageName, pkgSetting, userId);
}
} finally {
@@ -10016,6 +10018,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
+ sUserManager.systemReady();
}
public boolean isSafeMode() {
diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java
index 2901212..16c2fe7 100644
--- a/services/java/com/android/server/pm/UserManagerService.java
+++ b/services/java/com/android/server/pm/UserManagerService.java
@@ -21,11 +21,13 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
import android.app.IStopUserCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.RestrictionEntry;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
@@ -51,6 +53,7 @@ import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.Xml;
+import com.android.internal.content.PackageMonitor;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
@@ -229,6 +232,13 @@ public class UserManagerService extends IUserManager.Stub {
sInstance = this;
}
}
+
+ }
+
+ void systemReady() {
+ mUserPackageMonitor.register(ActivityThread.systemMain().getSystemContext(),
+ null, UserHandle.ALL, false);
+ userForeground(UserHandle.USER_OWNER);
}
@Override
@@ -822,11 +832,6 @@ public class UserManagerService extends IUserManager.Stub {
pinState.failedAttempts = failedAttempts;
pinState.lastAttemptTime = lastAttemptTime;
}
- // If this is not a restricted profile and there is no restrictions pin, clean up
- // any restrictions files that might have been left behind.
- if (!userInfo.isRestricted() && salt == 0) {
- cleanAppRestrictions(id);
- }
return userInfo;
} catch (IOException ioe) {
@@ -878,11 +883,22 @@ public class UserManagerService extends IUserManager.Stub {
}
}
+ private boolean isPackageInstalled(String pkg, int userId) {
+ final ApplicationInfo info = mPm.getApplicationInfo(pkg,
+ PackageManager.GET_UNINSTALLED_PACKAGES,
+ userId);
+ if (info == null || (info.flags&ApplicationInfo.FLAG_INSTALLED) == 0) {
+ return false;
+ }
+ return true;
+ }
+
/**
- * Removes all the restrictions files (res_<packagename>) for a given user.
+ * Removes all the restrictions files (res_<packagename>) for a given user, if all is true,
+ * else removes only those packages that have been uninstalled.
* Does not do any permissions checking.
*/
- private void cleanAppRestrictions(int userId) {
+ private void cleanAppRestrictions(int userId, boolean all) {
synchronized (mPackagesLock) {
File dir = Environment.getUserSystemDirectory(userId);
String[] files = dir.list();
@@ -891,13 +907,33 @@ public class UserManagerService extends IUserManager.Stub {
if (fileName.startsWith(RESTRICTIONS_FILE_PREFIX)) {
File resFile = new File(dir, fileName);
if (resFile.exists()) {
- resFile.delete();
+ if (all) {
+ resFile.delete();
+ } else {
+ String pkg = fileName.substring(RESTRICTIONS_FILE_PREFIX.length());
+ if (!isPackageInstalled(pkg, userId)) {
+ resFile.delete();
+ }
+ }
}
}
}
}
}
+ /**
+ * Removes the app restrictions file for a specific package and user id, if it exists.
+ */
+ private void cleanAppRestrictionsForPackage(String pkg, int userId) {
+ synchronized (mPackagesLock) {
+ File dir = Environment.getUserSystemDirectory(userId);
+ File resFile = new File(dir, RESTRICTIONS_FILE_PREFIX + pkg);
+ if (resFile.exists()) {
+ resFile.delete();
+ }
+ }
+ }
+
@Override
public UserInfo createUser(String name, int flags) {
checkManageUsersPermission("Only the system can create users");
@@ -1168,6 +1204,40 @@ public class UserManagerService extends IUserManager.Stub {
return true;
}
+ @Override
+ public void removeRestrictions() {
+ checkManageUsersPermission("Only system can remove restrictions");
+ final int userHandle = UserHandle.getCallingUserId();
+ synchronized (mPackagesLock) {
+ // Remove all user restrictions
+ setUserRestrictions(new Bundle(), userHandle);
+ // Remove restrictions pin
+ changeRestrictionsPin(null);
+ // Remove any app restrictions
+ cleanAppRestrictions(userHandle, true);
+ }
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ List<ApplicationInfo> apps =
+ mPm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES,
+ userHandle).getList();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ for (ApplicationInfo appInfo : apps) {
+ if ((appInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0
+ && (appInfo.flags & ApplicationInfo.FLAG_BLOCKED) != 0) {
+ mPm.setApplicationBlockedSettingAsUser(appInfo.packageName, false,
+ userHandle);
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+ });
+ }
+
/*
* Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
* Not the most secure, but it is at least a second level of protection. First level is that
@@ -1372,7 +1442,7 @@ public class UserManagerService extends IUserManager.Stub {
}
/**
- * Make a note of the last started time of a user.
+ * Make a note of the last started time of a user and do some cleanup.
* @param userId the user that was just foregrounded
*/
public void userForeground(int userId) {
@@ -1387,6 +1457,12 @@ public class UserManagerService extends IUserManager.Stub {
user.lastLoggedInTime = now;
writeUserLocked(user);
}
+ // If this is not a restricted profile and there is no restrictions pin, clean up
+ // all restrictions files that might have been left behind, else clean up just the
+ // ones with uninstalled packages
+ RestrictionsPinState pinState = mRestrictionsPinStates.get(userId);
+ final long salt = pinState == null ? 0 : pinState.salt;
+ cleanAppRestrictions(userId, (!user.isRestricted() && salt == 0));
}
}
@@ -1453,4 +1529,17 @@ public class UserManagerService extends IUserManager.Stub {
}
}
}
+
+ private PackageMonitor mUserPackageMonitor = new PackageMonitor() {
+ @Override
+ public void onPackageRemoved(String pkg, int uid) {
+ final int userId = this.getChangingUserId();
+ // Package could be disappearing because it is being blocked, so also check if
+ // it has been uninstalled.
+ final boolean uninstalled = isPackageDisappearing(pkg) == PACKAGE_PERMANENT_CHANGE;
+ if (uninstalled && userId >= 0 && !isPackageInstalled(pkg, userId)) {
+ cleanAppRestrictionsForPackage(pkg, userId);
+ }
+ }
+ };
}