diff options
Diffstat (limited to 'services/java/com/android/server/usb/UsbSettingsManager.java')
-rw-r--r-- | services/java/com/android/server/usb/UsbSettingsManager.java | 147 |
1 files changed, 108 insertions, 39 deletions
diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java index a8453d3..4b2bbfe 100644 --- a/services/java/com/android/server/usb/UsbSettingsManager.java +++ b/services/java/com/android/server/usb/UsbSettingsManager.java @@ -33,9 +33,10 @@ import android.hardware.usb.UsbDevice; import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.os.Binder; -import android.os.FileUtils; -import android.os.Process; +import android.os.Environment; import android.os.UserHandle; +import android.util.AtomicFile; +import android.util.Log; import android.util.Slog; import android.util.SparseBooleanArray; import android.util.Xml; @@ -48,7 +49,6 @@ import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlSerializer; -import java.io.BufferedOutputStream; import java.io.File; import java.io.FileDescriptor; import java.io.FileInputStream; @@ -60,13 +60,21 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -class UsbSettingsManager { +import libcore.io.IoUtils; +class UsbSettingsManager { private static final String TAG = "UsbSettingsManager"; private static final boolean DEBUG = false; - private static final File sSettingsFile = new File("/data/system/usb_device_manager.xml"); + + /** Legacy settings file, before multi-user */ + private static final File sSingleUserSettingsFile = new File( + "/data/system/usb_device_manager.xml"); + + private final UserHandle mUser; + private final AtomicFile mSettingsFile; private final Context mContext; + private final Context mUserContext; private final PackageManager mPackageManager; // Temporary mapping USB device name to list of UIDs with permissions for the device @@ -350,28 +358,49 @@ class UsbSettingsManager { } private class MyPackageMonitor extends PackageMonitor { - + @Override public void onPackageAdded(String packageName, int uid) { handlePackageUpdate(packageName); } + @Override public void onPackageChanged(String packageName, int uid, String[] components) { handlePackageUpdate(packageName); } + @Override public void onPackageRemoved(String packageName, int uid) { clearDefaults(packageName); } } + MyPackageMonitor mPackageMonitor = new MyPackageMonitor(); - public UsbSettingsManager(Context context) { + public UsbSettingsManager(Context context, UserHandle user) { + if (DEBUG) Slog.v(TAG, "Creating settings for " + user); + + try { + mUserContext = context.createPackageContextAsUser("android", 0, user); + } catch (NameNotFoundException e) { + throw new RuntimeException("Missing android package"); + } + mContext = context; - mPackageManager = context.getPackageManager(); + mPackageManager = mUserContext.getPackageManager(); + + mUser = user; + mSettingsFile = new AtomicFile(new File( + Environment.getUserSystemDirectory(user.getIdentifier()), + "usb_device_manager.xml")); + synchronized (mLock) { + if (UserHandle.OWNER.equals(user)) { + upgradeSingleUserLocked(); + } readSettingsLocked(); } - mPackageMonitor.register(context, null, true); + + mPackageMonitor.register(mUserContext, null, true); } private void readPreference(XmlPullParser parser) @@ -395,10 +424,54 @@ class UsbSettingsManager { XmlUtils.nextElement(parser); } + /** + * Upgrade any single-user settings from {@link #sSingleUserSettingsFile}. + * Should only by called by owner. + */ + private void upgradeSingleUserLocked() { + if (sSingleUserSettingsFile.exists()) { + mDevicePreferenceMap.clear(); + mAccessoryPreferenceMap.clear(); + + FileInputStream fis = null; + try { + fis = new FileInputStream(sSingleUserSettingsFile); + XmlPullParser parser = Xml.newPullParser(); + parser.setInput(fis, null); + + XmlUtils.nextElement(parser); + while (parser.getEventType() != XmlPullParser.END_DOCUMENT) { + final String tagName = parser.getName(); + if ("preference".equals(tagName)) { + readPreference(parser); + } else { + XmlUtils.nextElement(parser); + } + } + } catch (IOException e) { + Log.wtf(TAG, "Failed to read single-user settings", e); + } catch (XmlPullParserException e) { + Log.wtf(TAG, "Failed to read single-user settings", e); + } finally { + IoUtils.closeQuietly(fis); + } + + writeSettingsLocked(); + + // Success or failure, we delete single-user file + sSingleUserSettingsFile.delete(); + } + } + private void readSettingsLocked() { + if (DEBUG) Slog.v(TAG, "readSettingsLocked()"); + + mDevicePreferenceMap.clear(); + mAccessoryPreferenceMap.clear(); + FileInputStream stream = null; try { - stream = new FileInputStream(sSettingsFile); + stream = mSettingsFile.openRead(); XmlPullParser parser = Xml.newPullParser(); parser.setInput(stream, null); @@ -407,7 +480,7 @@ class UsbSettingsManager { String tagName = parser.getName(); if ("preference".equals(tagName)) { readPreference(parser); - } else { + } else { XmlUtils.nextElement(parser); } } @@ -415,25 +488,21 @@ class UsbSettingsManager { if (DEBUG) Slog.d(TAG, "settings file not found"); } catch (Exception e) { Slog.e(TAG, "error reading settings file, deleting to start fresh", e); - sSettingsFile.delete(); + mSettingsFile.delete(); } finally { - if (stream != null) { - try { - stream.close(); - } catch (IOException e) { - } - } + IoUtils.closeQuietly(stream); } } private void writeSettingsLocked() { + if (DEBUG) Slog.v(TAG, "writeSettingsLocked()"); + FileOutputStream fos = null; try { - FileOutputStream fstr = new FileOutputStream(sSettingsFile); - if (DEBUG) Slog.d(TAG, "writing settings to " + fstr); - BufferedOutputStream str = new BufferedOutputStream(fstr); + fos = mSettingsFile.startWrite(); + FastXmlSerializer serializer = new FastXmlSerializer(); - serializer.setOutput(str, "utf-8"); + serializer.setOutput(fos, "utf-8"); serializer.startDocument(null, true); serializer.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true); serializer.startTag(null, "settings"); @@ -455,12 +524,12 @@ class UsbSettingsManager { serializer.endTag(null, "settings"); serializer.endDocument(); - str.flush(); - FileUtils.sync(fstr); - str.close(); - } catch (Exception e) { - Slog.e(TAG, "error writing settings file, deleting to start fresh", e); - sSettingsFile.delete(); + mSettingsFile.finishWrite(fos); + } catch (IOException e) { + Slog.e(TAG, "Failed to write settings", e); + if (fos != null) { + mSettingsFile.failWrite(fos); + } } } @@ -547,7 +616,7 @@ class UsbSettingsManager { } // Send broadcast to running activity with registered intent - mContext.sendBroadcastAsUser(intent, UserHandle.ALL); + mUserContext.sendBroadcast(intent); // Start activity with registered intent resolveActivity(intent, matches, defaultPackage, device, null); @@ -608,7 +677,7 @@ class UsbSettingsManager { dialogIntent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); dialogIntent.putExtra("uri", uri); try { - mContext.startActivity(dialogIntent); + mUserContext.startActivityAsUser(dialogIntent, mUser); } catch (ActivityNotFoundException e) { Slog.e(TAG, "unable to start UsbAccessoryUriActivity"); } @@ -656,7 +725,7 @@ class UsbSettingsManager { intent.setComponent( new ComponentName(defaultRI.activityInfo.packageName, defaultRI.activityInfo.name)); - mContext.startActivity(intent); + mUserContext.startActivityAsUser(intent, mUser); } catch (ActivityNotFoundException e) { Slog.e(TAG, "startActivity failed", e); } @@ -683,7 +752,7 @@ class UsbSettingsManager { resolverIntent.putExtra(Intent.EXTRA_INTENT, intent); } try { - mContext.startActivity(resolverIntent); + mUserContext.startActivityAsUser(resolverIntent, mUser); } catch (ActivityNotFoundException e) { Slog.e(TAG, "unable to start activity " + resolverIntent); } @@ -814,7 +883,7 @@ class UsbSettingsManager { } private void requestPermissionDialog(Intent intent, String packageName, PendingIntent pi) { - int uid = Binder.getCallingUid(); + final int uid = Binder.getCallingUid(); // compare uid with packageName to foil apps pretending to be someone else try { @@ -833,9 +902,9 @@ class UsbSettingsManager { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(Intent.EXTRA_INTENT, pi); intent.putExtra("package", packageName); - intent.putExtra("uid", uid); + intent.putExtra(Intent.EXTRA_UID, uid); try { - mContext.startActivity(intent); + mUserContext.startActivityAsUser(intent, mUser); } catch (ActivityNotFoundException e) { Slog.e(TAG, "unable to start UsbPermissionActivity"); } finally { @@ -851,7 +920,7 @@ class UsbSettingsManager { intent.putExtra(UsbManager.EXTRA_DEVICE, device); intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true); try { - pi.send(mContext, 0, intent); + pi.send(mUserContext, 0, intent); } catch (PendingIntent.CanceledException e) { if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled"); } @@ -864,14 +933,14 @@ class UsbSettingsManager { } public void requestPermission(UsbAccessory accessory, String packageName, PendingIntent pi) { - Intent intent = new Intent(); + Intent intent = new Intent(); // respond immediately if permission has already been granted if (hasPermission(accessory)) { intent.putExtra(UsbManager.EXTRA_ACCESSORY, accessory); intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, true); - try { - pi.send(mContext, 0, intent); + try { + pi.send(mUserContext, 0, intent); } catch (PendingIntent.CanceledException e) { if (DEBUG) Slog.d(TAG, "requestPermission PendingIntent was cancelled"); } |