diff options
65 files changed, 993 insertions, 321 deletions
diff --git a/api/current.txt b/api/current.txt index d1a904a..cb4a7db 100644 --- a/api/current.txt +++ b/api/current.txt @@ -858,6 +858,7 @@ package android { field public static final int resource = 16842789; // 0x1010025 field public static final int restoreAnyVersion = 16843450; // 0x10102ba field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d + field public static final int restrictedAccountType = 16843733; // 0x10103d5 field public static final int right = 16843183; // 0x10101af field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093 field public static final int ringtoneType = 16843257; // 0x10101f9 @@ -6716,6 +6717,7 @@ package android.content.pm { method public abstract java.util.List<android.content.pm.PermissionInfo> queryPermissionsByGroup(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException; method public abstract deprecated void removePackageFromPreferred(java.lang.String); method public abstract void removePermission(java.lang.String); + method public android.content.Intent buildPermissionRequestIntent(java.lang.String...); method public abstract android.content.pm.ResolveInfo resolveActivity(android.content.Intent, int); method public abstract android.content.pm.ProviderInfo resolveContentProvider(java.lang.String, int); method public abstract android.content.pm.ResolveInfo resolveService(android.content.Intent, int); @@ -10305,10 +10307,12 @@ package android.hardware.usb { } public class UsbDeviceConnection { - method public int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int); + method public deprecated int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int); + method public int bulkTransfer(android.hardware.usb.UsbEndpoint, byte[], int, int, int); method public boolean claimInterface(android.hardware.usb.UsbInterface, boolean); method public void close(); - method public int controlTransfer(int, int, int, int, byte[], int, int); + method public deprecated int controlTransfer(int, int, int, int, byte[], int, int); + method public int controlTransfer(int, int, int, int, byte[], int, int, int); method public int getFileDescriptor(); method public byte[] getRawDescriptors(); method public java.lang.String getSerial(); @@ -16811,6 +16815,9 @@ package android.os { field public static final java.lang.String DISALLOW_MODIFY_ACCOUNTS = "no_modify_accounts"; field public static final java.lang.String DISALLOW_SHARE_LOCATION = "no_share_location"; field public static final java.lang.String DISALLOW_UNINSTALL_APPS = "no_uninstall_apps"; + field public static final java.lang.String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources"; + field public static final java.lang.String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; + field public static final java.lang.String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer"; } public abstract class Vibrator { diff --git a/cmds/interrupter/Android.mk b/cmds/interrupter/Android.mk new file mode 100644 index 0000000..e324627 --- /dev/null +++ b/cmds/interrupter/Android.mk @@ -0,0 +1,21 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + interrupter.c +LOCAL_MODULE := interrupter +LOCAL_MODULE_TAGS := eng tests +LOCAL_LDFLAGS := -ldl + +include $(BUILD_SHARED_LIBRARY) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + interrupter.c +LOCAL_MODULE := interrupter +LOCAL_MODULE_TAGS := eng tests +LOCAL_LDFLAGS := -ldl + +include $(BUILD_HOST_SHARED_LIBRARY)
\ No newline at end of file diff --git a/cmds/interrupter/interrupter.c b/cmds/interrupter/interrupter.c new file mode 100644 index 0000000..ae55515 --- /dev/null +++ b/cmds/interrupter/interrupter.c @@ -0,0 +1,53 @@ +/* + * Copyright 2012, 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. + */ + + +/** + * The probability of a syscall failing from 0.0 to 1.0 + */ +#define PROBABILITY 0.9 + + + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> + +/* for various intercepted calls */ +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <fcntl.h> + +/* For builds on glibc */ +#define __USE_GNU +#include <dlfcn.h> + +#include "interrupter.h" + +static int probability = PROBABILITY * RAND_MAX; + +static int maybe_interrupt() { + if (rand() < probability) { + return 1; + } + return 0; +} + +DEFINE_INTERCEPT(read, ssize_t, int, void*, size_t); +DEFINE_INTERCEPT(write, ssize_t, int, const void*, size_t); +DEFINE_INTERCEPT(accept, int, int, struct sockaddr*, socklen_t*); +DEFINE_INTERCEPT(creat, int, const char*, mode_t); diff --git a/cmds/interrupter/interrupter.h b/cmds/interrupter/interrupter.h new file mode 100644 index 0000000..9ad0277 --- /dev/null +++ b/cmds/interrupter/interrupter.h @@ -0,0 +1,79 @@ +/* + * Copyright 2012, 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. + */ + +#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2) +#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2) +#define CONCATENATE2(arg1, arg2) arg1##arg2 + +#define INTERRUPTER(sym) \ + if (real_##sym == NULL) \ + __init_##sym(); \ + if (maybe_interrupt()) { \ + errno = EINTR; \ + return -1; \ + } + +#define CALL_FUNCTION_1(sym, ret, type1) \ +ret (*real_##sym)(type1) = NULL; \ +ret sym(type1 arg1) { \ + INTERRUPTER(sym) \ + return real_##sym(arg1); \ +} + +#define CALL_FUNCTION_2(sym, ret, type1, type2) \ +ret (*real_##sym)(type1, type2) = NULL; \ +ret sym(type1 arg1, type2 arg2) { \ + INTERRUPTER(sym) \ + return real_##sym(arg1, arg2); \ +} + +#define CALL_FUNCTION_3(sym, ret, type1, type2, type3) \ +ret (*real_##sym)(type1, type2, type3) = NULL; \ +ret sym(type1 arg1, type2 arg2, type3 arg3) { \ + INTERRUPTER(sym) \ + return real_##sym(arg1, arg2, arg3); \ +} + +#define CALL_FUNCTION_4(sym, ret, type1, type2, type3, type4) \ +ret (*real_##sym)(type1, type2, type3, type4) = NULL; \ +ret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \ + INTERRUPTER(sym) \ + return real_##sym(arg1, arg2, arg3, arg4); \ +} + +#define CALL_FUNCTION_5(sym, ret, type1, type2, type3, type4, type5) \ +ret (*real_##sym)(type1, type2, type3, type4, type5) = NULL; \ +ret sym(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \ + INTERRUPTER(sym) \ + return real_##sym(arg1, arg2, arg3, arg4, arg5); \ +} + +#define DEFINE_INTERCEPT_N(N, sym, ret, ...) \ +static void __init_##sym(void); \ +CONCATENATE(CALL_FUNCTION_, N)(sym, ret, __VA_ARGS__) \ +static void __init_##sym(void) { \ + real_##sym = dlsym(RTLD_NEXT, #sym); \ + if (real_##sym == NULL) { \ + fprintf(stderr, "Error hooking " #sym ": %s\n", dlerror()); \ + } \ +} + +#define INTERCEPT_NARG(...) INTERCEPT_NARG_N(__VA_ARGS__, INTERCEPT_RSEQ_N()) +#define INTERCEPT_NARG_N(...) INTERCEPT_ARG_N(__VA_ARGS__) +#define INTERCEPT_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N +#define INTERCEPT_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0 + +#define DEFINE_INTERCEPT(sym, ret, ...) DEFINE_INTERCEPT_N(INTERCEPT_NARG(__VA_ARGS__), sym, ret, __VA_ARGS__) diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java index 98c82b5..224945a 100644 --- a/cmds/pm/src/com/android/commands/pm/Pm.java +++ b/cmds/pm/src/com/android/commands/pm/Pm.java @@ -1218,7 +1218,8 @@ public final class Pm { ComponentName cn = ComponentName.unflattenFromString(pkg); if (cn == null) { try { - mPm.setApplicationEnabledSetting(pkg, state, 0, userId); + mPm.setApplicationEnabledSetting(pkg, state, 0, userId, + "shell:" + android.os.Process.myUid()); System.err.println("Package " + pkg + " new state: " + enabledSettingToString( mPm.getApplicationEnabledSetting(pkg, userId))); diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java index 944a533..bb9e19f 100644 --- a/core/java/android/app/ActivityManager.java +++ b/core/java/android/app/ActivityManager.java @@ -896,7 +896,7 @@ public class ActivityManager { * @param taskId The identifier of the task to be moved, as found in * {@link RunningTaskInfo} or {@link RecentTaskInfo}. * @param flags Additional operational flags, 0 or more of - * {@link #MOVE_TASK_WITH_HOME}. + * {@link #MOVE_TASK_WITH_HOME}, {@link #MOVE_TASK_NO_USER_ACTION}. */ public void moveTaskToFront(int taskId, int flags) { moveTaskToFront(taskId, flags, null); @@ -911,7 +911,7 @@ public class ActivityManager { * @param taskId The identifier of the task to be moved, as found in * {@link RunningTaskInfo} or {@link RecentTaskInfo}. * @param flags Additional operational flags, 0 or more of - * {@link #MOVE_TASK_WITH_HOME}. + * {@link #MOVE_TASK_WITH_HOME}, {@link #MOVE_TASK_NO_USER_ACTION}. * @param options Additional options for the operation, either null or * as per {@link Context#startActivity(Intent, android.os.Bundle) * Context.startActivity(Intent, Bundle)}. diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java index 6d55dd5..271494f 100644 --- a/core/java/android/app/ApplicationPackageManager.java +++ b/core/java/android/app/ApplicationPackageManager.java @@ -1279,7 +1279,8 @@ final class ApplicationPackageManager extends PackageManager { public void setApplicationEnabledSetting(String packageName, int newState, int flags) { try { - mPM.setApplicationEnabledSetting(packageName, newState, flags, mContext.getUserId()); + mPM.setApplicationEnabledSetting(packageName, newState, flags, + mContext.getUserId(), mContext.getBasePackageName()); } catch (RemoteException e) { // Should never happen! } diff --git a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java index 43c2392..81c0a6a 100644 --- a/core/java/android/bluetooth/BluetoothTetheringDataTracker.java +++ b/core/java/android/bluetooth/BluetoothTetheringDataTracker.java @@ -21,6 +21,7 @@ import android.os.ServiceManager; import android.os.INetworkManagementService; import android.content.Context; import android.net.ConnectivityManager; +import android.net.DhcpResults; import android.net.LinkCapabilities; import android.net.LinkProperties; import android.net.NetworkInfo; @@ -28,7 +29,10 @@ import android.net.NetworkInfo.DetailedState; import android.net.NetworkStateTracker; import android.net.NetworkUtils; import android.os.Handler; +import android.os.Looper; import android.os.Message; +import android.os.Messenger; +import android.text.TextUtils; import android.util.Log; import java.net.InterfaceAddress; import android.net.LinkAddress; @@ -36,8 +40,11 @@ import android.net.RouteInfo; import java.net.Inet4Address; import android.os.SystemProperties; +import com.android.internal.util.AsyncChannel; + import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; /** * This class tracks the data connection associated with Bluetooth @@ -51,24 +58,29 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker { private static final String NETWORKTYPE = "BLUETOOTH_TETHER"; private static final String TAG = "BluetoothTethering"; private static final boolean DBG = true; - private static final boolean VDBG = false; + private static final boolean VDBG = true; private AtomicBoolean mTeardownRequested = new AtomicBoolean(false); private AtomicBoolean mPrivateDnsRouteSet = new AtomicBoolean(false); private AtomicInteger mDefaultGatewayAddr = new AtomicInteger(0); private AtomicBoolean mDefaultRouteSet = new AtomicBoolean(false); + private final Object mLinkPropertiesLock = new Object(); private LinkProperties mLinkProperties; + private LinkCapabilities mLinkCapabilities; + + private final Object mNetworkInfoLock = new Object(); private NetworkInfo mNetworkInfo; private BluetoothPan mBluetoothPan; - private static String mIface; - private Thread mDhcpThread; + private static String mRevTetheredIface; /* For sending events to connectivity service handler */ private Handler mCsHandler; - private Context mContext; - public static BluetoothTetheringDataTracker sInstance; + protected Context mContext; + private static BluetoothTetheringDataTracker sInstance; + private BtdtHandler mBtdtHandler; + private AtomicReference<AsyncChannel> mAsyncChannel = new AtomicReference<AsyncChannel>(null); private BluetoothTetheringDataTracker() { mNetworkInfo = new NetworkInfo(ConnectivityManager.TYPE_BLUETOOTH, 0, NETWORKTYPE, ""); @@ -108,6 +120,7 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker { if (adapter != null) { adapter.getProfileProxy(mContext, mProfileServiceListener, BluetoothProfile.PAN); } + mBtdtHandler = new BtdtHandler(target.getLooper(), this); } private BluetoothProfile.ServiceListener mProfileServiceListener = @@ -224,15 +237,19 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker { /** * Fetch NetworkInfo for the network */ - public synchronized NetworkInfo getNetworkInfo() { - return mNetworkInfo; + public NetworkInfo getNetworkInfo() { + synchronized (mNetworkInfoLock) { + return new NetworkInfo(mNetworkInfo); + } } /** * Fetch LinkProperties for the network */ - public synchronized LinkProperties getLinkProperties() { - return new LinkProperties(mLinkProperties); + public LinkProperties getLinkProperties() { + synchronized (mLinkPropertiesLock) { + return new LinkProperties(mLinkProperties); + } } /** @@ -286,88 +303,68 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker { return count; } - - private boolean readLinkProperty(String iface) { - String DhcpPrefix = "dhcp." + iface + "."; - String ip = SystemProperties.get(DhcpPrefix + "ipaddress"); - String dns1 = SystemProperties.get(DhcpPrefix + "dns1"); - String dns2 = SystemProperties.get(DhcpPrefix + "dns2"); - String gateway = SystemProperties.get(DhcpPrefix + "gateway"); - String mask = SystemProperties.get(DhcpPrefix + "mask"); - if(ip.isEmpty() || gateway.isEmpty()) { - Log.e(TAG, "readLinkProperty, ip: " + ip + ", gateway: " + gateway + ", can not be empty"); - return false; + void startReverseTether(final LinkProperties linkProperties) { + if (linkProperties == null || TextUtils.isEmpty(linkProperties.getInterfaceName())) { + Log.e(TAG, "attempted to reverse tether with empty interface"); + return; } - int PrefixLen = countPrefixLength(NetworkUtils.numericToInetAddress(mask).getAddress()); - mLinkProperties.addLinkAddress(new LinkAddress(NetworkUtils.numericToInetAddress(ip), PrefixLen)); - RouteInfo ri = new RouteInfo(NetworkUtils.numericToInetAddress(gateway)); - mLinkProperties.addRoute(ri); - if(!dns1.isEmpty()) - mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns1)); - if(!dns2.isEmpty()) - mLinkProperties.addDns(NetworkUtils.numericToInetAddress(dns2)); - mLinkProperties.setInterfaceName(iface); - return true; - } - public synchronized void startReverseTether(String iface) { - mIface = iface; - if (DBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler); - mDhcpThread = new Thread(new Runnable() { + synchronized (mLinkPropertiesLock) { + if (mLinkProperties.getInterfaceName() != null) { + Log.e(TAG, "attempted to reverse tether while already in process"); + return; + } + mLinkProperties = linkProperties; + } + Thread dhcpThread = new Thread(new Runnable() { public void run() { - //TODO(): Add callbacks for failure and success case. //Currently this thread runs independently. - if (DBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler); - String DhcpResultName = "dhcp." + mIface + ".result";; - String result = ""; - if (VDBG) Log.d(TAG, "waiting for change of sys prop dhcp result: " + DhcpResultName); - for(int i = 0; i < 30*5; i++) { - try { Thread.sleep(200); } catch (InterruptedException ie) { return;} - result = SystemProperties.get(DhcpResultName); - if (VDBG) Log.d(TAG, "read " + DhcpResultName + ": " + result); - if(result.equals("failed")) { - Log.e(TAG, "startReverseTether, failed to start dhcp service"); + DhcpResults dhcpResults = new DhcpResults(); + boolean success = NetworkUtils.runDhcp(linkProperties.getInterfaceName(), + dhcpResults); + synchronized (mLinkPropertiesLock) { + if (linkProperties.getInterfaceName() != mLinkProperties.getInterfaceName()) { + Log.e(TAG, "obsolete DHCP run aborted"); return; } - if(result.equals("ok")) { - if (VDBG) Log.d(TAG, "startReverseTether, dhcp resut: " + result); - if(readLinkProperty(mIface)) { - - mNetworkInfo.setIsAvailable(true); - mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); - - if (VDBG) Log.d(TAG, "startReverseTether mCsHandler: " + mCsHandler); - if(mCsHandler != null) { - Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); - msg.sendToTarget(); - - msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); - msg.sendToTarget(); - } - } + if (!success) { + Log.e(TAG, "DHCP request error:" + NetworkUtils.getDhcpError()); return; } + mLinkProperties = dhcpResults.linkProperties; + synchronized (mNetworkInfoLock) { + mNetworkInfo.setIsAvailable(true); + mNetworkInfo.setDetailedState(DetailedState.CONNECTED, null, null); + if (mCsHandler != null) { + Message msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, + new NetworkInfo(mNetworkInfo)); + msg.sendToTarget(); + } + } + return; } - Log.e(TAG, "startReverseTether, dhcp failed, resut: " + result); } }); - mDhcpThread.start(); + dhcpThread.start(); } - public synchronized void stopReverseTether() { - //NetworkUtils.stopDhcp(iface); - if(mDhcpThread != null && mDhcpThread.isAlive()) { - mDhcpThread.interrupt(); - try { mDhcpThread.join(); } catch (InterruptedException ie) { return; } + void stopReverseTether() { + synchronized (mLinkPropertiesLock) { + if (TextUtils.isEmpty(mLinkProperties.getInterfaceName())) { + Log.e(TAG, "attempted to stop reverse tether with nothing tethered"); + return; + } + NetworkUtils.stopDhcp(mLinkProperties.getInterfaceName()); + mLinkProperties.clear(); + synchronized (mNetworkInfoLock) { + mNetworkInfo.setIsAvailable(false); + mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); + + if (mCsHandler != null) { + mCsHandler.obtainMessage(EVENT_STATE_CHANGED, new NetworkInfo(mNetworkInfo)). + sendToTarget(); + } + } } - mLinkProperties.clear(); - mNetworkInfo.setIsAvailable(false); - mNetworkInfo.setDetailedState(DetailedState.DISCONNECTED, null, null); - - Message msg = mCsHandler.obtainMessage(EVENT_CONFIGURATION_CHANGED, mNetworkInfo); - msg.sendToTarget(); - - msg = mCsHandler.obtainMessage(EVENT_STATE_CHANGED, mNetworkInfo); - msg.sendToTarget(); } public void setDependencyMet(boolean met) { @@ -383,4 +380,54 @@ public class BluetoothTetheringDataTracker implements NetworkStateTracker { public void removeStackedLink(LinkProperties link) { mLinkProperties.removeStackedLink(link); } + + static class BtdtHandler extends Handler { + private AsyncChannel mStackChannel; + private final BluetoothTetheringDataTracker mBtdt; + + BtdtHandler(Looper looper, BluetoothTetheringDataTracker parent) { + super(looper); + mBtdt = parent; + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: + if (VDBG) Log.d(TAG, "got CMD_CHANNEL_HALF_CONNECTED"); + if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { + AsyncChannel ac = (AsyncChannel)msg.obj; + if (mBtdt.mAsyncChannel.compareAndSet(null, ac) == false) { + Log.e(TAG, "Trying to set mAsyncChannel twice!"); + } else { + ac.sendMessage( + AsyncChannel.CMD_CHANNEL_FULL_CONNECTION); + } + } + break; + case AsyncChannel.CMD_CHANNEL_DISCONNECTED: + if (VDBG) Log.d(TAG, "got CMD_CHANNEL_DISCONNECTED"); + mBtdt.stopReverseTether(); + mBtdt.mAsyncChannel.set(null); + break; + case NetworkStateTracker.EVENT_NETWORK_CONNECTED: + LinkProperties linkProperties = (LinkProperties)(msg.obj); + if (VDBG) Log.d(TAG, "got EVENT_NETWORK_CONNECTED, " + linkProperties); + mBtdt.startReverseTether(linkProperties); + break; + case NetworkStateTracker.EVENT_NETWORK_DISCONNECTED: + linkProperties = (LinkProperties)(msg.obj); + if (VDBG) Log.d(TAG, "got EVENT_NETWORK_DISCONNECTED, " + linkProperties); + mBtdt.stopReverseTether(); + break; + } + } + } + + @Override + public void supplyMessenger(Messenger messenger) { + if (messenger != null) { + new AsyncChannel().connect(mContext, mBtdtHandler, messenger); + } + } } diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl index a32a201..a0e1555 100644 --- a/core/java/android/content/pm/IPackageManager.aidl +++ b/core/java/android/content/pm/IPackageManager.aidl @@ -239,7 +239,8 @@ interface IPackageManager { /** * As per {@link android.content.pm.PackageManager#setApplicationEnabledSetting}. */ - void setApplicationEnabledSetting(in String packageName, in int newState, int flags, int userId); + void setApplicationEnabledSetting(in String packageName, in int newState, int flags, + int userId, String callingPackage); /** * As per {@link android.content.pm.PackageManager#getApplicationEnabledSetting}. diff --git a/core/java/android/content/pm/PackageInfo.java b/core/java/android/content/pm/PackageInfo.java index 77ca7f6..fb539c5 100644 --- a/core/java/android/content/pm/PackageInfo.java +++ b/core/java/android/content/pm/PackageInfo.java @@ -154,7 +154,7 @@ public class PackageInfo implements Parcelable { /** * Flag for {@link #requestedPermissionsFlags}: the requested permission * is required for the application to run; the user can not optionally - * disable it. Currently all permissions are required. + * disable it. */ public static final int REQUESTED_PERMISSION_REQUIRED = 1<<0; @@ -221,6 +221,9 @@ public class PackageInfo implements Parcelable { /** @hide */ public boolean requiredForAllUsers; + /** @hide */ + public String restrictedAccountType; + public PackageInfo() { } @@ -262,6 +265,7 @@ public class PackageInfo implements Parcelable { dest.writeTypedArray(reqFeatures, parcelableFlags); dest.writeInt(installLocation); dest.writeInt(requiredForAllUsers ? 1 : 0); + dest.writeString(restrictedAccountType); } public static final Parcelable.Creator<PackageInfo> CREATOR @@ -301,5 +305,6 @@ public class PackageInfo implements Parcelable { reqFeatures = source.createTypedArray(FeatureInfo.CREATOR); installLocation = source.readInt(); requiredForAllUsers = source.readInt() != 0; + restrictedAccountType = source.readString(); } } diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 0bea138..9afbe6f 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -45,7 +45,7 @@ public abstract class PackageManager { /** * This exception is thrown when a given package, application, or component - * name can not be found. + * name cannot be found. */ public static class NameNotFoundException extends AndroidException { public NameNotFoundException() { @@ -267,7 +267,7 @@ public abstract class PackageManager { * user has explicitly disabled the application, regardless of what it has * specified in its manifest. Because this is due to the user's request, * they may re-enable it if desired through the appropriate system UI. This - * option currently <strong>can not</strong> be used with + * option currently <strong>cannot</strong> be used with * {@link #setComponentEnabledSetting(ComponentName, int, int)}. */ public static final int COMPONENT_ENABLED_STATE_DISABLED_USER = 3; @@ -1264,6 +1264,23 @@ public abstract class PackageManager { = "android.content.pm.extra.VERIFICATION_VERSION_CODE"; /** + * The action used to request that the user approve a permission request + * from the application. + * + * @hide + */ + public static final String ACTION_REQUEST_PERMISSION + = "android.content.pm.action.REQUEST_PERMISSION"; + + /** + * Extra field name for the list of permissions, which the user must approve. + * + * @hide + */ + public static final String EXTRA_REQUEST_PERMISSION_PERMISSION_LIST + = "android.content.pm.extra.PERMISSION_LIST"; + + /** * Retrieve overall information about an application package that is * installed on the system. * <p> @@ -1283,9 +1300,9 @@ public abstract class PackageManager { * package. If flag GET_UNINSTALLED_PACKAGES is set and if the * package is not found in the list of installed applications, the * package information is retrieved from the list of uninstalled - * applications(which includes installed applications as well as - * applications with data directory ie applications which had been - * deleted with DONT_DELTE_DATA flag set). + * applications (which includes installed applications as well as + * applications with data directory i.e. applications which had been + * deleted with {@code DONT_DELETE_DATA} flag set). * @see #GET_ACTIVITIES * @see #GET_GIDS * @see #GET_CONFIGURATIONS @@ -1326,7 +1343,7 @@ public abstract class PackageManager { * null if neither are found. * * <p>Throws {@link NameNotFoundException} if a package with the given - * name can not be found on the system. + * name cannot be found on the system. * * @param packageName The name of the package to inspect. * @@ -1341,7 +1358,7 @@ public abstract class PackageManager { * assigned to a package. * * <p>Throws {@link NameNotFoundException} if a package with the given - * name can not be found on the system. + * name cannot be found on the system. * * @param packageName The full name (i.e. com.google.apps.contacts) of the * desired package. @@ -1372,7 +1389,7 @@ public abstract class PackageManager { * Retrieve all of the information we know about a particular permission. * * <p>Throws {@link NameNotFoundException} if a permission with the given - * name can not be found on the system. + * name cannot be found on the system. * * @param name The fully qualified name (i.e. com.google.permission.LOGIN) * of the permission you are interested in. @@ -1408,7 +1425,7 @@ public abstract class PackageManager { * permissions. * * <p>Throws {@link NameNotFoundException} if a permission group with the given - * name can not be found on the system. + * name cannot be found on the system. * * @param name The fully qualified name (i.e. com.google.permission_group.APPS) * of the permission you are interested in. @@ -1437,7 +1454,7 @@ public abstract class PackageManager { * package/application. * * <p>Throws {@link NameNotFoundException} if an application with the given - * package name can not be found on the system. + * package name cannot be found on the system. * * @param packageName The full name (i.e. com.google.apps.contacts) of an * application. @@ -1453,7 +1470,7 @@ public abstract class PackageManager { * list of uninstalled applications(which includes * installed applications as well as applications * with data directory ie applications which had been - * deleted with DONT_DELTE_DATA flag set). + * deleted with {@code DONT_DELETE_DATA} flag set). * * @see #GET_META_DATA * @see #GET_SHARED_LIBRARY_FILES @@ -1467,7 +1484,7 @@ public abstract class PackageManager { * class. * * <p>Throws {@link NameNotFoundException} if an activity with the given - * class name can not be found on the system. + * class name cannot be found on the system. * * @param component The full component name (i.e. * com.google.apps.contacts/com.google.apps.contacts.ContactsList) of an Activity @@ -1490,7 +1507,7 @@ public abstract class PackageManager { * class. * * <p>Throws {@link NameNotFoundException} if a receiver with the given - * class name can not be found on the system. + * class name cannot be found on the system. * * @param component The full component name (i.e. * com.google.apps.calendar/com.google.apps.calendar.CalendarAlarm) of a Receiver @@ -1513,7 +1530,7 @@ public abstract class PackageManager { * class. * * <p>Throws {@link NameNotFoundException} if a service with the given - * class name can not be found on the system. + * class name cannot be found on the system. * * @param component The full component name (i.e. * com.google.apps.media/com.google.apps.media.BackgroundPlayback) of a Service @@ -1535,7 +1552,7 @@ public abstract class PackageManager { * provider class. * * <p>Throws {@link NameNotFoundException} if a provider with the given - * class name can not be found on the system. + * class name cannot be found on the system. * * @param component The full component name (i.e. * com.google.providers.media/com.google.providers.media.MediaProvider) of a @@ -1572,7 +1589,7 @@ public abstract class PackageManager { * installed on the device. In the unlikely case of there being no * installed packages, an empty list is returned. * If flag GET_UNINSTALLED_PACKAGES is set, a list of all - * applications including those deleted with DONT_DELETE_DATA + * applications including those deleted with {@code DONT_DELETE_DATA} * (partially installed apps with data directory) will be returned. * * @see #GET_ACTIVITIES @@ -1642,7 +1659,7 @@ public abstract class PackageManager { * installed on the device. In the unlikely case of there being no * installed packages, an empty list is returned. * If flag GET_UNINSTALLED_PACKAGES is set, a list of all - * applications including those deleted with DONT_DELETE_DATA + * applications including those deleted with {@code DONT_DELETE_DATA} * (partially installed apps with data directory) will be returned. * * @see #GET_ACTIVITIES @@ -1735,6 +1752,29 @@ public abstract class PackageManager { public abstract void removePermission(String name); /** + * Returns an {@link Intent} suitable for passing to {@code startActivityForResult} + * which prompts the user to grant {@code permissions} to this application. + * + * @throws NullPointerException if {@code permissions} is {@code null}. + * @throws IllegalArgumentException if {@code permissions} contains {@code null}. + */ + public Intent buildPermissionRequestIntent(String... permissions) { + if (permissions == null) { + throw new NullPointerException("permissions cannot be null"); + } + for (String permission : permissions) { + if (permission == null) { + throw new IllegalArgumentException("permissions cannot contain null"); + } + } + + Intent i = new Intent(ACTION_REQUEST_PERMISSION); + i.putExtra(EXTRA_REQUEST_PERMISSION_PERMISSION_LIST, permissions); + i.setPackage("com.android.packageinstaller"); + return i; + } + + /** * Grant a permission to an application which the application does not * already have. The permission must have been requested by the application, * but as an optional permission. If the application is not allowed to @@ -1847,7 +1887,7 @@ public abstract class PackageManager { /** * Return a List of all application packages that are installed on the * device. If flag GET_UNINSTALLED_PACKAGES has been set, a list of all - * applications including those deleted with DONT_DELETE_DATA (partially + * applications including those deleted with {@code DONT_DELETE_DATA} (partially * installed apps with data directory) will be returned. * * @param flags Additional option flags. Use any combination of @@ -1858,7 +1898,7 @@ public abstract class PackageManager { * is installed on the device. In the unlikely case of there being * no installed applications, an empty list is returned. * If flag GET_UNINSTALLED_PACKAGES is set, a list of all - * applications including those deleted with DONT_DELETE_DATA + * applications including those deleted with {@code DONT_DELETE_DATA} * (partially installed apps with data directory) will be returned. * * @see #GET_META_DATA @@ -2164,7 +2204,7 @@ public abstract class PackageManager { * instrumentation class. * * <p>Throws {@link NameNotFoundException} if instrumentation with the - * given class name can not be found on the system. + * given class name cannot be found on the system. * * @param className The full name (i.e. * com.google.apps.contacts.InstrumentList) of an @@ -2201,8 +2241,8 @@ public abstract class PackageManager { * icon. * * @param packageName The name of the package that this icon is coming from. - * Can not be null. - * @param resid The resource identifier of the desired image. Can not be 0. + * Cannot be null. + * @param resid The resource identifier of the desired image. Cannot be 0. * @param appInfo Overall information about <var>packageName</var>. This * may be null, in which case the application information will be retrieved * for you if needed; if you already have this information around, it can @@ -2218,7 +2258,7 @@ public abstract class PackageManager { * Retrieve the icon associated with an activity. Given the full name of * an activity, retrieves the information about it and calls * {@link ComponentInfo#loadIcon ComponentInfo.loadIcon()} to return its icon. - * If the activity can not be found, NameNotFoundException is thrown. + * If the activity cannot be found, NameNotFoundException is thrown. * * @param activityName Name of the activity whose icon is to be retrieved. * @@ -2237,7 +2277,7 @@ public abstract class PackageManager { * set, this simply returns the result of * getActivityIcon(intent.getClassName()). Otherwise it resolves the intent's * component and returns the icon associated with the resolved component. - * If intent.getClassName() can not be found or the Intent can not be resolved + * If intent.getClassName() cannot be found or the Intent cannot be resolved * to a component, NameNotFoundException is thrown. * * @param intent The intent for which you would like to retrieve an icon. @@ -2276,7 +2316,7 @@ public abstract class PackageManager { /** * Retrieve the icon associated with an application. Given the name of the * application's package, retrieves the information about it and calls - * getApplicationIcon() to return its icon. If the application can not be + * getApplicationIcon() to return its icon. If the application cannot be * found, NameNotFoundException is thrown. * * @param packageName Name of the package whose application icon is to be @@ -2296,7 +2336,7 @@ public abstract class PackageManager { * Retrieve the logo associated with an activity. Given the full name of * an activity, retrieves the information about it and calls * {@link ComponentInfo#loadLogo ComponentInfo.loadLogo()} to return its logo. - * If the activity can not be found, NameNotFoundException is thrown. + * If the activity cannot be found, NameNotFoundException is thrown. * * @param activityName Name of the activity whose logo is to be retrieved. * @@ -2316,7 +2356,7 @@ public abstract class PackageManager { * set, this simply returns the result of * getActivityLogo(intent.getClassName()). Otherwise it resolves the intent's * component and returns the logo associated with the resolved component. - * If intent.getClassName() can not be found or the Intent can not be resolved + * If intent.getClassName() cannot be found or the Intent cannot be resolved * to a component, NameNotFoundException is thrown. * * @param intent The intent for which you would like to retrieve a logo. @@ -2348,7 +2388,7 @@ public abstract class PackageManager { /** * Retrieve the logo associated with an application. Given the name of the * application's package, retrieves the information about it and calls - * getApplicationLogo() to return its logo. If the application can not be + * getApplicationLogo() to return its logo. If the application cannot be * found, NameNotFoundException is thrown. * * @param packageName Name of the package whose application logo is to be @@ -2372,8 +2412,8 @@ public abstract class PackageManager { * labels and other text. * * @param packageName The name of the package that this text is coming from. - * Can not be null. - * @param resid The resource identifier of the desired text. Can not be 0. + * Cannot be null. + * @param resid The resource identifier of the desired text. Cannot be 0. * @param appInfo Overall information about <var>packageName</var>. This * may be null, in which case the application information will be retrieved * for you if needed; if you already have this information around, it can @@ -2390,8 +2430,8 @@ public abstract class PackageManager { * retrieve XML meta data. * * @param packageName The name of the package that this xml is coming from. - * Can not be null. - * @param resid The resource identifier of the desired xml. Can not be 0. + * Cannot be null. + * @param resid The resource identifier of the desired xml. Cannot be 0. * @param appInfo Overall information about <var>packageName</var>. This * may be null, in which case the application information will be retrieved * for you if needed; if you already have this information around, it can @@ -2409,7 +2449,7 @@ public abstract class PackageManager { * * @return Returns the label associated with this application, or null if * it could not be found for any reason. - * @param info The application to get the label of + * @param info The application to get the label of. */ public abstract CharSequence getApplicationLabel(ApplicationInfo info); @@ -2417,7 +2457,7 @@ public abstract class PackageManager { * Retrieve the resources associated with an activity. Given the full * name of an activity, retrieves the information about it and calls * getResources() to return its application's resources. If the activity - * can not be found, NameNotFoundException is thrown. + * cannot be found, NameNotFoundException is thrown. * * @param activityName Name of the activity whose resources are to be * retrieved. @@ -2448,7 +2488,7 @@ public abstract class PackageManager { * Retrieve the resources associated with an application. Given the full * package name of an application, retrieves the information about it and * calls getResources() to return its application's resources. If the - * appPackageName can not be found, NameNotFoundException is thrown. + * appPackageName cannot be found, NameNotFoundException is thrown. * * @param appPackageName Package name of the application whose resources * are to be retrieved. @@ -2617,7 +2657,7 @@ public abstract class PackageManager { * {@link PackageManager#VERIFICATION_REJECT}. * * @param id pending package identifier as passed via the - * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra + * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra. * @param verificationCode either {@link PackageManager#VERIFICATION_ALLOW} * or {@link PackageManager#VERIFICATION_REJECT}. * @throws SecurityException if the caller does not have the @@ -2638,7 +2678,7 @@ public abstract class PackageManager { * will have no effect. * * @param id pending package identifier as passed via the - * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra + * {@link PackageManager#EXTRA_VERIFICATION_ID} Intent extra. * @param verificationCodeAtTimeout either * {@link PackageManager#VERIFICATION_ALLOW} or * {@link PackageManager#VERIFICATION_REJECT}. If @@ -2870,7 +2910,7 @@ public abstract class PackageManager { /** * @deprecated This is a protected API that should not have been available * to third party applications. It is the platform's responsibility for - * assigning preferred activities and this can not be directly modified. + * assigning preferred activities and this cannot be directly modified. * * Add a new preferred activity mapping to the system. This will be used * to automatically select the given activity component when @@ -2904,7 +2944,7 @@ public abstract class PackageManager { /** * @deprecated This is a protected API that should not have been available * to third party applications. It is the platform's responsibility for - * assigning preferred activities and this can not be directly modified. + * assigning preferred activities and this cannot be directly modified. * * Replaces an existing preferred activity mapping to the system, and if that were not present * adds a new preferred activity. This will be used diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index 149b8e5..11f9be9 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -290,6 +290,7 @@ public class PackageParser { pi.applicationInfo = generateApplicationInfo(p, flags, state, userId); pi.installLocation = p.installLocation; pi.requiredForAllUsers = p.mRequiredForAllUsers; + pi.restrictedAccountType = p.mRestrictedAccountType; pi.firstInstallTime = firstInstallTime; pi.lastUpdateTime = lastUpdateTime; if ((flags&PackageManager.GET_GIDS) != 0) { @@ -1023,16 +1024,14 @@ public class PackageParser { // that may change. String name = sa.getNonResourceString( com.android.internal.R.styleable.AndroidManifestUsesPermission_name); - /* Not supporting optional permissions yet. boolean required = sa.getBoolean( com.android.internal.R.styleable.AndroidManifestUsesPermission_required, true); - */ sa.recycle(); if (name != null && !pkg.requestedPermissions.contains(name)) { pkg.requestedPermissions.add(name.intern()); - pkg.requestedPermissionsRequired.add(Boolean.TRUE); + pkg.requestedPermissionsRequired.add(required ? Boolean.TRUE : Boolean.FALSE); } XmlUtils.skipCurrentTag(parser); @@ -1766,6 +1765,11 @@ public class PackageParser { false)) { owner.mRequiredForAllUsers = true; } + String accountType = sa.getString(com.android.internal.R.styleable + .AndroidManifestApplication_restrictedAccountType); + if (accountType != null && accountType.length() > 0) { + owner.mRestrictedAccountType = accountType; + } } if (sa.getBoolean( @@ -3193,6 +3197,7 @@ public class PackageParser { } public final static class Package { + public String packageName; // For now we only support one application per package. @@ -3280,6 +3285,9 @@ public class PackageParser { /* An app that's required for all users and cannot be uninstalled for a user */ public boolean mRequiredForAllUsers; + /* The restricted account authenticator type that is used by this application */ + public String mRestrictedAccountType; + /** * Digest suitable for comparing whether this package's manifest is the * same as another. diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java index 3579977..dcd54fc 100644 --- a/core/java/android/content/pm/PackageUserState.java +++ b/core/java/android/content/pm/PackageUserState.java @@ -30,6 +30,8 @@ public class PackageUserState { public boolean installed; public int enabled; + public String lastDisableAppCaller; + public HashSet<String> disabledComponents; public HashSet<String> enabledComponents; @@ -43,6 +45,7 @@ public class PackageUserState { stopped = o.stopped; notLaunched = o.notLaunched; enabled = o.enabled; + lastDisableAppCaller = o.lastDisableAppCaller; disabledComponents = o.disabledComponents != null ? new HashSet<String>(o.disabledComponents) : null; enabledComponents = o.enabledComponents != null diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java index b536490..3358f8c 100644 --- a/core/java/android/hardware/usb/UsbDeviceConnection.java +++ b/core/java/android/hardware/usb/UsbDeviceConnection.java @@ -17,7 +17,6 @@ package android.hardware.usb; import android.os.ParcelFileDescriptor; -import android.util.Log; import java.io.FileDescriptor; @@ -119,10 +118,41 @@ public class UsbDeviceConnection { * @param timeout in milliseconds * @return length of data transferred (or zero) for success, * or negative value for failure + * + * @deprecate Use {@link #controlTransfer(int, int, int, int, byte[], int, int, int)} + * which accepts a buffer start index. */ + @Deprecated public int controlTransfer(int requestType, int request, int value, int index, byte[] buffer, int length, int timeout) { - return native_control_request(requestType, request, value, index, buffer, length, timeout); + return controlTransfer(requestType, request, value, index, buffer, 0, length, timeout); + } + + /** + * Performs a control transaction on endpoint zero for this device. + * The direction of the transfer is determined by the request type. + * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is + * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write, + * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer + * is a read. + * + * @param requestType request type for this transaction + * @param request request ID for this transaction + * @param value value field for this transaction + * @param index index field for this transaction + * @param buffer buffer for data portion of transaction, + * or null if no data needs to be sent or received + * @param start the index of the first byte in the buffer to send or receive + * @param length the length of the data to send or receive + * @param timeout in milliseconds + * @return length of data transferred (or zero) for success, + * or negative value for failure + */ + public int controlTransfer(int requestType, int request, int value, int index, + byte[] buffer, int start, int length, int timeout) { + checkBounds(buffer, start, length); + return native_control_request(requestType, request, value, index, + buffer, start, length, timeout); } /** @@ -130,14 +160,37 @@ public class UsbDeviceConnection { * The direction of the transfer is determined by the direction of the endpoint * * @param endpoint the endpoint for this transaction - * @param buffer buffer for data to send or receive, + * @param buffer buffer for data to send or receive * @param length the length of the data to send or receive * @param timeout in milliseconds * @return length of data transferred (or zero) for success, * or negative value for failure + * + * @deprecate Use {@link #bulkTransfer(UsbEndpoint, byte[], int, int, int)} + * which accepts a buffer start index. */ - public int bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) { - return native_bulk_request(endpoint.getAddress(), buffer, length, timeout); + @Deprecated + public int bulkTransfer(UsbEndpoint endpoint, + byte[] buffer, int length, int timeout) { + return bulkTransfer(endpoint, buffer, 0, length, timeout); + } + + /** + * Performs a bulk transaction on the given endpoint. + * The direction of the transfer is determined by the direction of the endpoint + * + * @param endpoint the endpoint for this transaction + * @param buffer buffer for data to send or receive + * @param start the index of the first byte in the buffer to send or receive + * @param length the length of the data to send or receive + * @param timeout in milliseconds + * @return length of data transferred (or zero) for success, + * or negative value for failure + */ + public int bulkTransfer(UsbEndpoint endpoint, + byte[] buffer, int start, int length, int timeout) { + checkBounds(buffer, start, length); + return native_bulk_request(endpoint.getAddress(), buffer, start, length, timeout); } /** @@ -168,6 +221,13 @@ public class UsbDeviceConnection { return native_get_serial(); } + private static void checkBounds(byte[] buffer, int start, int length) { + final int bufferLength = (buffer != null ? buffer.length : 0); + if (start < 0 || start + length > bufferLength) { + throw new IllegalArgumentException("Buffer start or length out of bounds."); + } + } + private native boolean native_open(String deviceName, FileDescriptor pfd); private native void native_close(); private native int native_get_fd(); @@ -175,8 +235,9 @@ public class UsbDeviceConnection { private native boolean native_claim_interface(int interfaceID, boolean force); private native boolean native_release_interface(int interfaceID); private native int native_control_request(int requestType, int request, int value, - int index, byte[] buffer, int length, int timeout); - private native int native_bulk_request(int endpoint, byte[] buffer, int length, int timeout); + int index, byte[] buffer, int start, int length, int timeout); + private native int native_bulk_request(int endpoint, byte[] buffer, + int start, int length, int timeout); private native UsbRequest native_request_wait(); private native String native_get_serial(); } diff --git a/core/java/android/net/BaseNetworkStateTracker.java b/core/java/android/net/BaseNetworkStateTracker.java index a554611..1165281 100644 --- a/core/java/android/net/BaseNetworkStateTracker.java +++ b/core/java/android/net/BaseNetworkStateTracker.java @@ -18,6 +18,7 @@ package android.net; import android.content.Context; import android.os.Handler; +import android.os.Messenger; import com.android.internal.util.Preconditions; @@ -165,4 +166,9 @@ public abstract class BaseNetworkStateTracker implements NetworkStateTracker { public void removeStackedLink(LinkProperties link) { mLinkProperties.removeStackedLink(link); } + + @Override + public void supplyMessenger(Messenger messenger) { + // not supported on this network + } } diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java index 3a04c27..4e4980d 100644 --- a/core/java/android/net/ConnectivityManager.java +++ b/core/java/android/net/ConnectivityManager.java @@ -23,6 +23,7 @@ import android.annotation.SdkConstant.SdkConstantType; import android.content.Context; import android.os.Binder; import android.os.Build.VERSION_CODES; +import android.os.Messenger; import android.os.RemoteException; import android.provider.Settings; @@ -1280,4 +1281,17 @@ public class ConnectivityManager { } } + /** + * Supply the backend messenger for a network tracker + * + * @param type NetworkType to set + * @param messenger {@link Messenger} + * {@hide} + */ + public void supplyMessenger(int networkType, Messenger messenger) { + try { + mService.supplyMessenger(networkType, messenger); + } catch (RemoteException e) { + } + } } diff --git a/core/java/android/net/DummyDataStateTracker.java b/core/java/android/net/DummyDataStateTracker.java index db8f0bc..15a81f3 100644 --- a/core/java/android/net/DummyDataStateTracker.java +++ b/core/java/android/net/DummyDataStateTracker.java @@ -19,6 +19,7 @@ package android.net; import android.content.Context; import android.os.Handler; import android.os.Message; +import android.os.Messenger; import android.util.Slog; /** @@ -213,6 +214,11 @@ public class DummyDataStateTracker implements NetworkStateTracker { mLinkProperties.removeStackedLink(link); } + @Override + public void supplyMessenger(Messenger messenger) { + // not supported on this network + } + static private void log(String s) { Slog.d(TAG, s); } diff --git a/core/java/android/net/EthernetDataTracker.java b/core/java/android/net/EthernetDataTracker.java index b744a47..27d5a58 100644 --- a/core/java/android/net/EthernetDataTracker.java +++ b/core/java/android/net/EthernetDataTracker.java @@ -22,6 +22,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.Message; +import android.os.Messenger; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; @@ -417,4 +418,9 @@ public class EthernetDataTracker implements NetworkStateTracker { public void removeStackedLink(LinkProperties link) { mLinkProperties.removeStackedLink(link); } + + @Override + public void supplyMessenger(Messenger messenger) { + // not supported on this network + } } diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index 056fa03..9e9b43d 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -22,6 +22,7 @@ import android.net.NetworkQuotaInfo; import android.net.NetworkState; import android.net.ProxyProperties; import android.os.IBinder; +import android.os.Messenger; import android.os.ParcelFileDescriptor; import com.android.internal.net.LegacyVpnInfo; @@ -126,4 +127,6 @@ interface IConnectivityManager boolean updateLockdownVpn(); void captivePortalCheckComplete(in NetworkInfo info); + + void supplyMessenger(int networkType, in Messenger messenger); } diff --git a/core/java/android/net/LinkCapabilities.java b/core/java/android/net/LinkCapabilities.java index eb9166f..fb444ea 100644 --- a/core/java/android/net/LinkCapabilities.java +++ b/core/java/android/net/LinkCapabilities.java @@ -314,8 +314,8 @@ public class LinkCapabilities implements Parcelable { sb.append(":\""); sb.append(entry.getValue()); sb.append("\""); - return mCapabilities.toString(); } + sb.append("}"); return sb.toString(); } diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java index eedc372..52b238f 100644 --- a/core/java/android/net/LinkProperties.java +++ b/core/java/android/net/LinkProperties.java @@ -290,7 +290,7 @@ public class LinkProperties implements Parcelable { } stacked += "] "; } - return ifaceName + linkAddresses + routes + dns + domainName + proxy + stacked; + return "{" + ifaceName + linkAddresses + routes + dns + domainName + proxy + stacked + "}"; } /** diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java index faf739b..e85dbcd 100644 --- a/core/java/android/net/MobileDataStateTracker.java +++ b/core/java/android/net/MobileDataStateTracker.java @@ -74,7 +74,6 @@ public class MobileDataStateTracker implements NetworkStateTracker { private Handler mHandler; private AsyncChannel mDataConnectionTrackerAc; - private Messenger mMessenger; /** * Create a new MobileDataStateTracker @@ -103,7 +102,6 @@ public class MobileDataStateTracker implements NetworkStateTracker { IntentFilter filter = new IntentFilter(); filter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED); - filter.addAction(DctConstants.ACTION_DATA_CONNECTION_TRACKER_MESSENGER); mContext.registerReceiver(new MobileDataStateReceiver(), filter); mMobileDataState = PhoneConstants.DataState.DISCONNECTED; @@ -285,13 +283,6 @@ public class MobileDataStateTracker implements NetworkStateTracker { " broadcast" + reason == null ? "" : "(" + reason + ")"); } setDetailedState(DetailedState.FAILED, reason, apnName); - } else if (intent.getAction().equals(DctConstants - .ACTION_DATA_CONNECTION_TRACKER_MESSENGER)) { - if (VDBG) log(mApnType + " got ACTION_DATA_CONNECTION_TRACKER_MESSENGER"); - mMessenger = - intent.getParcelableExtra(DctConstants.EXTRA_MESSENGER); - AsyncChannel ac = new AsyncChannel(); - ac.connect(mContext, MobileDataStateTracker.this.mHandler, mMessenger); } else { if (DBG) log("Broadcast received: ignore " + intent.getAction()); } @@ -613,6 +604,12 @@ public class MobileDataStateTracker implements NetworkStateTracker { return new LinkCapabilities(mLinkCapabilities); } + public void supplyMessenger(Messenger messenger) { + if (VDBG) log(mApnType + " got supplyMessenger"); + AsyncChannel ac = new AsyncChannel(); + ac.connect(mContext, MobileDataStateTracker.this.mHandler, messenger); + } + private void log(String s) { Slog.d(TAG, mApnType + ": " + s); } diff --git a/core/java/android/net/NetworkStateTracker.java b/core/java/android/net/NetworkStateTracker.java index b22159c..cf77a1c 100644 --- a/core/java/android/net/NetworkStateTracker.java +++ b/core/java/android/net/NetworkStateTracker.java @@ -18,6 +18,9 @@ package android.net; import android.content.Context; import android.os.Handler; +import android.os.Messenger; + +import static com.android.internal.util.Protocol.BASE_NETWORK_STATE_TRACKER; /** * Interface provides the {@link com.android.server.ConnectivityService} @@ -48,25 +51,38 @@ public interface NetworkStateTracker { * msg.what = EVENT_STATE_CHANGED * msg.obj = NetworkInfo object */ - public static final int EVENT_STATE_CHANGED = 1; + public static final int EVENT_STATE_CHANGED = BASE_NETWORK_STATE_TRACKER; /** * msg.what = EVENT_CONFIGURATION_CHANGED * msg.obj = NetworkInfo object */ - public static final int EVENT_CONFIGURATION_CHANGED = 3; + public static final int EVENT_CONFIGURATION_CHANGED = BASE_NETWORK_STATE_TRACKER + 1; /** * msg.what = EVENT_RESTORE_DEFAULT_NETWORK * msg.obj = FeatureUser object */ - public static final int EVENT_RESTORE_DEFAULT_NETWORK = 6; + public static final int EVENT_RESTORE_DEFAULT_NETWORK = BASE_NETWORK_STATE_TRACKER + 2; /** * msg.what = EVENT_NETWORK_SUBTYPE_CHANGED * msg.obj = NetworkInfo object */ - public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 7; + public static final int EVENT_NETWORK_SUBTYPE_CHANGED = BASE_NETWORK_STATE_TRACKER + 3; + + /** + * msg.what = EVENT_NETWORK_CONNECTED + * msg.obj = LinkProperties object + */ + public static final int EVENT_NETWORK_CONNECTED = BASE_NETWORK_STATE_TRACKER + 4; + + /** + * msg.what = EVENT_NETWORK_CONNECTION_DISCONNECTED + * msg.obj = LinkProperties object, same iface name + */ + public static final int EVENT_NETWORK_DISCONNECTED = BASE_NETWORK_STATE_TRACKER + 5; + /** * ------------------------------------------------------------- @@ -207,4 +223,10 @@ public interface NetworkStateTracker { * Informs the state tracker that a stacked interface has been removed. **/ public void removeStackedLink(LinkProperties link); + + /* + * Called once to setup async channel between this and + * the underlying network specific code. + */ + public void supplyMessenger(Messenger messenger); } diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java index 3a7abc0..cc3c5f7 100644 --- a/core/java/android/net/RouteInfo.java +++ b/core/java/android/net/RouteInfo.java @@ -132,7 +132,10 @@ public class RouteInfo implements Parcelable { } private boolean isHost() { - return (mGateway.equals(Inet4Address.ANY) || mGateway.equals(Inet6Address.ANY)); + return (mDestination.getAddress() instanceof Inet4Address && + mDestination.getNetworkPrefixLength() == 32) || + (mDestination.getAddress() instanceof Inet6Address && + mDestination.getNetworkPrefixLength() == 128); } private boolean isDefault() { diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl index 4b83611..45524c8 100644 --- a/core/java/android/os/INetworkManagementService.aidl +++ b/core/java/android/os/INetworkManagementService.aidl @@ -152,16 +152,6 @@ interface INetworkManagementService boolean isTetheringStarted(); /** - * Start bluetooth reverse tethering services - */ - void startReverseTethering(in String iface); - - /** - * Stop currently running bluetooth reserse tethering services - */ - void stopReverseTethering(); - - /** * Tethers the specified interface */ void tetherInterface(String iface); diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index 622308f..1ba16bd 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -86,8 +86,42 @@ public class UserManager { * @see #setUserRestrictions(Bundle) * @see #getUserRestrictions() */ + public static final String DISALLOW_SHARE_LOCATION = "no_share_location"; + /** + * Key for user restrictions. Specifies if a user is disallowed from enabling the + * "Unknown Sources" setting, that allows installation of apps from unknown sources. + * The default value is <code>false</code>. + * <p/> + * Type: Boolean + * @see #setUserRestrictions(Bundle) + * @see #getUserRestrictions() + */ + public static final String DISALLOW_INSTALL_UNKNOWN_SOURCES = "no_install_unknown_sources"; + + /** + * Key for user restrictions. Specifies if a user is disallowed from configuring bluetooth. + * The default value is <code>false</code>. + * <p/> + * Type: Boolean + * @see #setUserRestrictions(Bundle) + * @see #getUserRestrictions() + */ + public static final String DISALLOW_CONFIG_BLUETOOTH = "no_config_bluetooth"; + + + /** + * Key for user restrictions. Specifies if a user is disallowed from transferring files over + * USB. The default value is <code>false</code>. + * <p/> + * Type: Boolean + * @see #setUserRestrictions(Bundle) + * @see #getUserRestrictions() + */ + public static final String DISALLOW_USB_FILE_TRANSFER = "no_usb_file_transfer"; + + /** @hide */ public UserManager(Context context, IUserManager service) { mService = service; @@ -130,7 +164,7 @@ public class UserManager { /** * Used to determine whether the user making this call is subject to * teleportations. - * @return whether the user making this call is a goat + * @return whether the user making this call is a goat */ public boolean isUserAGoat() { return false; @@ -272,6 +306,16 @@ public class UserManager { } /** + * @hide + * Returns whether the current user has been disallowed from performing certain actions + * or setting certain settings. + * @param restrictionKey the string key representing the restriction + */ + public boolean hasUserRestriction(String restrictionKey) { + return getUserRestrictions().getBoolean(restrictionKey, false); + } + + /** * Return the serial number for a user. This is a device-unique * number assigned to that user; if the user is deleted and then a new * user created, the new users will not be given the same serial number. @@ -465,7 +509,7 @@ public class UserManager { * Returns the maximum number of users that can be created on this device. A return value * of 1 means that it is a single user device. * @hide - * @return a value greater than or equal to 1 + * @return a value greater than or equal to 1 */ public static int getMaxSupportedUsers() { // Don't allow multiple users on certain builds @@ -508,13 +552,6 @@ public class UserManager { return -1; } - /** - * Returns whether the current user is allowed to toggle location sharing settings. - * @hide - */ - public boolean isLocationSharingToggleAllowed() { - return !getUserRestrictions().getBoolean(DISALLOW_SHARE_LOCATION, false); - } /** * @hide diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index 98edeae..dd36022 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -5890,6 +5890,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager private boolean mNeedResolution = false; private boolean mIsRtlCompatibilityMode = true; + private static int UNDEFINED_MARGIN = DEFAULT_MARGIN_RELATIVE; + + private boolean mLeftMarginUndefined = false; + private boolean mRightMarginUndefined = false; + /** * Creates a new set of layout parameters. The values are extracted from * the supplied attributes set and context. @@ -5916,16 +5921,26 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } else { leftMargin = a.getDimensionPixelSize( R.styleable.ViewGroup_MarginLayout_layout_marginLeft, - DEFAULT_MARGIN_RESOLVED); - topMargin = a.getDimensionPixelSize( - R.styleable.ViewGroup_MarginLayout_layout_marginTop, - DEFAULT_MARGIN_RESOLVED); + UNDEFINED_MARGIN); + if (leftMargin == UNDEFINED_MARGIN) { + mLeftMarginUndefined = true; + leftMargin = DEFAULT_MARGIN_RESOLVED; + } rightMargin = a.getDimensionPixelSize( R.styleable.ViewGroup_MarginLayout_layout_marginRight, + UNDEFINED_MARGIN); + if (rightMargin == UNDEFINED_MARGIN) { + mRightMarginUndefined = true; + rightMargin = DEFAULT_MARGIN_RESOLVED; + } + + topMargin = a.getDimensionPixelSize( + R.styleable.ViewGroup_MarginLayout_layout_marginTop, DEFAULT_MARGIN_RESOLVED); bottomMargin = a.getDimensionPixelSize( R.styleable.ViewGroup_MarginLayout_layout_marginBottom, DEFAULT_MARGIN_RESOLVED); + startMargin = a.getDimensionPixelSize( R.styleable.ViewGroup_MarginLayout_layout_marginStart, DEFAULT_MARGIN_RELATIVE); @@ -5949,6 +5964,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public MarginLayoutParams(int width, int height) { super(width, height); + mLeftMarginUndefined = true; + mRightMarginUndefined = true; + mNeedResolution = false; mIsRtlCompatibilityMode = false; } @@ -5969,6 +5987,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager this.startMargin = source.startMargin; this.endMargin = source.endMargin; + this.mLeftMarginUndefined = source.mLeftMarginUndefined; + this.mRightMarginUndefined = source.mRightMarginUndefined; + this.mNeedResolution = source.mNeedResolution; this.mIsRtlCompatibilityMode = source.mIsRtlCompatibilityMode; @@ -5981,6 +6002,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager public MarginLayoutParams(LayoutParams source) { super(source); + mLeftMarginUndefined = true; + mRightMarginUndefined = true; + mNeedResolution = false; mIsRtlCompatibilityMode = false; } @@ -6005,6 +6029,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager topMargin = top; rightMargin = right; bottomMargin = bottom; + mLeftMarginUndefined = false; + mRightMarginUndefined = false; mNeedResolution = isMarginRelative(); } @@ -6147,30 +6173,42 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager // No relative margin or pre JB-MR1 case or no need to resolve, just dont do anything // Will use the left and right margins if no relative margin is defined. - if (!isMarginRelative() || !mNeedResolution || mIsRtlCompatibilityMode) return; + if (!isMarginRelative() || !mNeedResolution) return; // Proceed with resolution doResolveMargins(); } private void doResolveMargins() { - // We have some relative margins (either the start one or the end one or both). So use - // them and override what has been defined for left and right margins. If either start - // or end margin is not defined, just set it to default "0". - switch(mLayoutDirection) { - case View.LAYOUT_DIRECTION_RTL: - leftMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ? - endMargin : DEFAULT_MARGIN_RESOLVED; - rightMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ? - startMargin : DEFAULT_MARGIN_RESOLVED; - break; - case View.LAYOUT_DIRECTION_LTR: - default: - leftMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ? - startMargin : DEFAULT_MARGIN_RESOLVED; - rightMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ? - endMargin : DEFAULT_MARGIN_RESOLVED; - break; + + if (mIsRtlCompatibilityMode) { + // if left or right margins are not defined and if we have some start or end margin + // defined then use those start and end margins. + if (mLeftMarginUndefined && startMargin > DEFAULT_MARGIN_RELATIVE) { + leftMargin = startMargin; + } + if (mRightMarginUndefined && endMargin > DEFAULT_MARGIN_RELATIVE) { + rightMargin = endMargin; + } + } else { + // We have some relative margins (either the start one or the end one or both). So use + // them and override what has been defined for left and right margins. If either start + // or end margin is not defined, just set it to default "0". + switch(mLayoutDirection) { + case View.LAYOUT_DIRECTION_RTL: + leftMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ? + endMargin : DEFAULT_MARGIN_RESOLVED; + rightMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ? + startMargin : DEFAULT_MARGIN_RESOLVED; + break; + case View.LAYOUT_DIRECTION_LTR: + default: + leftMargin = (startMargin > DEFAULT_MARGIN_RELATIVE) ? + startMargin : DEFAULT_MARGIN_RESOLVED; + rightMargin = (endMargin > DEFAULT_MARGIN_RELATIVE) ? + endMargin : DEFAULT_MARGIN_RESOLVED; + break; + } } mNeedResolution = false; } diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java index 91b109e..b380403 100644 --- a/core/java/com/android/internal/util/Protocol.java +++ b/core/java/com/android/internal/util/Protocol.java @@ -52,5 +52,6 @@ public class Protocol { public static final int BASE_DATA_CONNECTION_TRACKER = 0x00042000; public static final int BASE_DNS_PINGER = 0x00050000; public static final int BASE_NSD_MANAGER = 0x00060000; + public static final int BASE_NETWORK_STATE_TRACKER = 0x00070000; //TODO: define all used protocols } diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp index 923781e..cea5bbf 100644 --- a/core/jni/android_hardware_UsbDeviceConnection.cpp +++ b/core/jni/android_hardware_UsbDeviceConnection.cpp @@ -142,7 +142,7 @@ android_hardware_UsbDeviceConnection_release_interface(JNIEnv *env, jobject thiz static jint android_hardware_UsbDeviceConnection_control_request(JNIEnv *env, jobject thiz, jint requestType, jint request, jint value, jint index, - jbyteArray buffer, jint length, jint timeout) + jbyteArray buffer, jint start, jint length, jint timeout) { struct usb_device* device = get_device_from_object(env, thiz); if (!device) { @@ -152,25 +152,22 @@ android_hardware_UsbDeviceConnection_control_request(JNIEnv *env, jobject thiz, jbyte* bufferBytes = NULL; if (buffer) { - if (env->GetArrayLength(buffer) < length) { - jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); - return -1; - } - bufferBytes = env->GetByteArrayElements(buffer, 0); + bufferBytes = (jbyte*)env->GetPrimitiveArrayCritical(buffer, NULL); } jint result = usb_device_control_transfer(device, requestType, request, - value, index, bufferBytes, length, timeout); + value, index, bufferBytes + start, length, timeout); - if (bufferBytes) - env->ReleaseByteArrayElements(buffer, bufferBytes, 0); + if (bufferBytes) { + env->ReleasePrimitiveArrayCritical(buffer, bufferBytes, 0); + } return result; } static jint android_hardware_UsbDeviceConnection_bulk_request(JNIEnv *env, jobject thiz, - jint endpoint, jbyteArray buffer, jint length, jint timeout) + jint endpoint, jbyteArray buffer, jint start, jint length, jint timeout) { struct usb_device* device = get_device_from_object(env, thiz); if (!device) { @@ -180,17 +177,14 @@ android_hardware_UsbDeviceConnection_bulk_request(JNIEnv *env, jobject thiz, jbyte* bufferBytes = NULL; if (buffer) { - if (env->GetArrayLength(buffer) < length) { - jniThrowException(env, "java/lang/ArrayIndexOutOfBoundsException", NULL); - return -1; - } - bufferBytes = env->GetByteArrayElements(buffer, 0); + bufferBytes = (jbyte*)env->GetPrimitiveArrayCritical(buffer, NULL); } - jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout); + jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes + start, length, timeout); - if (bufferBytes) - env->ReleaseByteArrayElements(buffer, bufferBytes, 0); + if (bufferBytes) { + env->ReleasePrimitiveArrayCritical(buffer, bufferBytes, 0); + } return result; } @@ -235,9 +229,9 @@ static JNINativeMethod method_table[] = { {"native_get_desc", "()[B", (void *)android_hardware_UsbDeviceConnection_get_desc}, {"native_claim_interface", "(IZ)Z",(void *)android_hardware_UsbDeviceConnection_claim_interface}, {"native_release_interface","(I)Z", (void *)android_hardware_UsbDeviceConnection_release_interface}, - {"native_control_request", "(IIII[BII)I", + {"native_control_request", "(IIII[BIII)I", (void *)android_hardware_UsbDeviceConnection_control_request}, - {"native_bulk_request", "(I[BII)I", + {"native_bulk_request", "(I[BIII)I", (void *)android_hardware_UsbDeviceConnection_bulk_request}, {"native_request_wait", "()Landroid/hardware/usb/UsbRequest;", (void *)android_hardware_UsbDeviceConnection_request_wait}, diff --git a/core/jni/android_view_InputEventReceiver.cpp b/core/jni/android_view_InputEventReceiver.cpp index 9501cf2..198814a 100644 --- a/core/jni/android_view_InputEventReceiver.cpp +++ b/core/jni/android_view_InputEventReceiver.cpp @@ -118,8 +118,13 @@ status_t NativeInputEventReceiver::finishInputEvent(uint32_t seq, bool handled) int NativeInputEventReceiver::handleEvent(int receiveFd, int events, void* data) { if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { - ALOGE("channel '%s' ~ Publisher closed input channel or an error occurred. " +#if DEBUG_DISPATCH_CYCLE + // This error typically occurs when the publisher has closed the input channel + // as part of removing a window or finishing an IME session, in which case + // the consumer will soon be disposed as well. + ALOGD("channel '%s' ~ Publisher closed input channel or an error occurred. " "events=0x%x", getInputChannelName(), events); +#endif return 0; // remove the callback } diff --git a/core/jni/android_view_InputEventSender.cpp b/core/jni/android_view_InputEventSender.cpp index bd1d103..2306cf2 100644 --- a/core/jni/android_view_InputEventSender.cpp +++ b/core/jni/android_view_InputEventSender.cpp @@ -151,8 +151,13 @@ status_t NativeInputEventSender::sendMotionEvent(uint32_t seq, const MotionEvent int NativeInputEventSender::handleEvent(int receiveFd, int events, void* data) { if (events & (ALOOPER_EVENT_ERROR | ALOOPER_EVENT_HANGUP)) { - ALOGE("channel '%s' ~ Consumer closed input channel or an error occurred. " +#if DEBUG_DISPATCH_CYCLE + // This error typically occurs when the consumer has closed the input channel + // as part of finishing an IME session, in which case the publisher will + // soon be disposed as well. + ALOGD("channel '%s' ~ Consumer closed input channel or an error occurred. " "events=0x%x", getInputChannelName(), events); +#endif return 0; // remove the callback } diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 6f59817..0afe4c1 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -889,6 +889,11 @@ <!-- Declare that your application will be able to deal with RTL (right to left) layouts. If set to false (default value), your application will not care about RTL layouts. --> <attr name="supportsRtl" format="boolean" /> + <!-- Declare that this application requires access to restricted accounts of a certain + type. The default value is null and restricted accounts won\'t be visible to this + application. The type should correspond to the account authenticator type, such as + "com.google" --> + <attr name="restrictedAccountType" format="string"/> </declare-styleable> <!-- The <code>permission</code> tag declares a security permission that can be @@ -991,9 +996,8 @@ permission, and it must always be granted when it is installed. If you set this to false, then in some cases the application may be installed with it being granted the permission, and it will - need to request the permission later if it needs it. + need to request the permission later if it needs it. --> <attr name="required" format="boolean" /> - --> </declare-styleable> <!-- The <code>uses-configuration</code> tag specifies @@ -1036,7 +1040,7 @@ don't support it. If you set this to false, then this will not impose a restriction on where the application can be installed. --> - <attr name="required" format="boolean" /> + <attr name="required" /> </declare-styleable> <!-- The <code>uses-sdk</code> tag describes the SDK features that the diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index 489a947..42d692f 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -2041,6 +2041,7 @@ <public type="attr" name="indicatorEnd" /> <public type="attr" name="childIndicatorStart" /> <public type="attr" name="childIndicatorEnd" /> + <public type="attr" name="restrictedAccountType" /> <public type="style" name="Theme.NoTitleBar.Overscan" /> <public type="style" name="Theme.Light.NoTitleBar.Overscan" /> diff --git a/core/tests/coretests/src/android/net/RouteInfoTest.java b/core/tests/coretests/src/android/net/RouteInfoTest.java index 59eb601..55d6592 100644 --- a/core/tests/coretests/src/android/net/RouteInfoTest.java +++ b/core/tests/coretests/src/android/net/RouteInfoTest.java @@ -149,6 +149,40 @@ public class RouteInfoTest extends TestCase { assertAreNotEqual(r1, r3); } + public void testHostRoute() { + RouteInfo r; + + r = new RouteInfo(Prefix("0.0.0.0/0"), Address("0.0.0.0"), "wlan0"); + assertFalse(r.isHostRoute()); + + r = new RouteInfo(Prefix("::/0"), Address("::"), "wlan0"); + assertFalse(r.isHostRoute()); + + r = new RouteInfo(Prefix("192.0.2.0/24"), null, "wlan0"); + assertFalse(r.isHostRoute()); + + r = new RouteInfo(Prefix("2001:db8::/48"), null, "wlan0"); + assertFalse(r.isHostRoute()); + + r = new RouteInfo(Prefix("192.0.2.0/32"), Address("0.0.0.0"), "wlan0"); + assertTrue(r.isHostRoute()); + + r = new RouteInfo(Prefix("2001:db8::/128"), Address("::"), "wlan0"); + assertTrue(r.isHostRoute()); + + r = new RouteInfo(Prefix("192.0.2.0/32"), null, "wlan0"); + assertTrue(r.isHostRoute()); + + r = new RouteInfo(Prefix("2001:db8::/128"), null, "wlan0"); + assertTrue(r.isHostRoute()); + + r = new RouteInfo(Prefix("::/128"), Address("fe80::"), "wlan0"); + assertTrue(r.isHostRoute()); + + r = new RouteInfo(Prefix("0.0.0.0/32"), Address("192.0.2.1"), "wlan0"); + assertTrue(r.isHostRoute()); + } + public RouteInfo passThroughParcel(RouteInfo r) { Parcel p = Parcel.obtain(); RouteInfo r2 = null; diff --git a/docs/html/guide/practices/index.jd b/docs/html/guide/practices/index.jd index 04a43c5..48a849a 100644 --- a/docs/html/guide/practices/index.jd +++ b/docs/html/guide/practices/index.jd @@ -19,7 +19,7 @@ of fueling the impression-install-ranking cycle: improve the product!</p> <a href="http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html"> <h4>Say Goodbye to the Menu Button</h4> - <p>As Ice Cream Sandwich rolls out to more devices, it?s important that you begin to migrate + <p>As Ice Cream Sandwich rolls out to more devices, it's important that you begin to migrate your designs to the action bar in order to promote a consistent Android user experience.</p> </a> @@ -49,4 +49,4 @@ make mistakes in the way they interact with the Android system and with other ap </div> -</div>
\ No newline at end of file +</div> diff --git a/docs/html/training/basics/intents/result.jd b/docs/html/training/basics/intents/result.jd index 0086913..24ecc46 100644 --- a/docs/html/training/basics/intents/result.jd +++ b/docs/html/training/basics/intents/result.jd @@ -62,7 +62,7 @@ app can properly identify the result and determine how to handle it.</p> static final int PICK_CONTACT_REQUEST = 1; // The request code ... private void pickContact() { - Intent pickContactIntent = new Intent(Intent.ACTION_PICK, new Uri("content://contacts")); + Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts")); pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST); } diff --git a/docs/html/training/in-app-billing/purchase-iab-products.jd b/docs/html/training/in-app-billing/purchase-iab-products.jd index 7fa77d3..4e6e035 100644 --- a/docs/html/training/in-app-billing/purchase-iab-products.jd +++ b/docs/html/training/in-app-billing/purchase-iab-products.jd @@ -104,7 +104,7 @@ IabHelper.QueryInventoryFinishedListener mGotInventoryListener </pre> <h2 id="Consume">Consume a Purchase</h2> -<p>You can use the In-app Billing Version 3 API to track the ownership of purchased items in Google Play. Once an item is purchased, it is considered to be "owned" and cannot be purchased again from Google Play while in that state. You must send a consumption request for the item before Google Play makes it available for purchase again. All managed in-app products are consumable. How you use the consumption mechanism in your app is up to you. Typically, you would implement consumption for products with temporary benefits that users may want to purchase multiple times (for example, in-game currency or replensihable game tokens). You would typically not want to implement consumption for products that are purchased once and provide a permanent effect (for example, a premium upgrade).</p> +<p>You can use the In-app Billing Version 3 API to track the ownership of purchased items in Google Play. Once an item is purchased, it is considered to be "owned" and cannot be purchased again from Google Play while in that state. You must send a consumption request for the item before Google Play makes it available for purchase again. All managed in-app products are consumable. How you use the consumption mechanism in your app is up to you. Typically, you would implement consumption for products with temporary benefits that users may want to purchase multiple times (for example, in-game currency or replenishable game tokens). You would typically not want to implement consumption for products that are purchased once and provide a permanent effect (for example, a premium upgrade).</p> <p>It's your responsibility to control and track how the in-app product is provisioned to the user. For example, if the user purchased in-game currency, you should update the player's inventory with the amount of currency purchased.</p> <p class="note"><strong>Security Recommendation:</strong> You must send a consumption request before provisioning the benefit of the consumable in-app purchase to the user. Make sure that you have received a successful consumption response from Google Play before you provision the item.</p> <p>To record a purchase consumption, call {@code consumeAsync(Purchase, OnConsumeFinishedListener)} on your {@code IabHelper} instance. The first argument that the method takes is the {@code Purchase} object representing the item to consume. The second argument is a {@code OnConsumeFinishedListener} that is notified when the consumption operation has completed and handles the consumption response from Google Play. It is safe to make this call fom your main thread.</p> diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 07daa3b..0b8f7e6 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -248,9 +248,7 @@ status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList, } status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) { - mLayers.add(layer); - mCaches.resourceCache.incrementRefcount(layer); - + layer = refLayer(layer); addDrawOp(new (alloc()) DrawLayerOp(layer, x, y)); return DrawGlInfo::kStatusDone; } diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 50e552f..19f7eb6 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -271,6 +271,12 @@ private: return copy; } + inline Layer* refLayer(Layer* layer) { + mLayers.add(layer); + mCaches.resourceCache.incrementRefcount(layer); + return layer; + } + inline SkBitmap* refBitmap(SkBitmap* bitmap) { // Note that this assumes the bitmap is immutable. There are cases this won't handle // correctly, such as creating the bitmap from scratch, drawing with it, changing its diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 2998535..7f4977a 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -75,6 +75,13 @@ bool Layer::resize(const uint32_t width, const uint32_t height) { return true; } + const uint32_t maxTextureSize = Caches::getInstance().maxTextureSize; + if (desiredWidth > maxTextureSize || desiredHeight > maxTextureSize) { + ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)", + desiredWidth, desiredHeight, maxTextureSize, maxTextureSize); + return false; + } + uint32_t oldWidth = getWidth(); uint32_t oldHeight = getHeight(); diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index bb02286..8451048 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -222,6 +222,21 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque return NULL; } + // We first obtain a layer before comparing against the max texture size + // because layers are not allocated at the exact desired size. They are + // always created slighly larger to improve recycling + const uint32_t maxTextureSize = caches.maxTextureSize; + if (layer->getWidth() > maxTextureSize || layer->getHeight() > maxTextureSize) { + ALOGW("Layer exceeds max. dimensions supported by the GPU (%dx%d, max=%dx%d)", + width, height, maxTextureSize, maxTextureSize); + + // Creating a new layer always increment its refcount by 1, this allows + // us to destroy the layer object if one was created for us + Caches::getInstance().resourceCache.decrementRefcount(layer); + + return NULL; + } + layer->setFbo(fbo); layer->layer.set(0.0f, 0.0f, width, height); layer->texCoords.set(0.0f, height / float(layer->getHeight()), @@ -243,14 +258,11 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque layer->setEmpty(false); layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE); + // This should only happen if we run out of memory if (glGetError() != GL_NO_ERROR) { - ALOGD("Could not allocate texture for layer (fbo=%d %dx%d)", - fbo, width, height); - + ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height); glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); - - Caches::getInstance().resourceCache.decrementRefcount(layer); - + caches.resourceCache.decrementRefcount(layer); return NULL; } } @@ -272,7 +284,6 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { layer->texCoords.set(0.0f, height / float(layer->getHeight()), width / float(layer->getWidth()), 0.0f); } else { - Caches::getInstance().resourceCache.decrementRefcount(layer); return false; } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index 4a67997..a446e40 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -98,11 +98,11 @@ public class SettingsHelper { private void setGpsLocation(String value) { UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE); - if (! um.isLocationSharingToggleAllowed()) { + if (um.hasUserRestriction(UserManager.DISALLOW_SHARE_LOCATION)) { return; } final String GPS = LocationManager.GPS_PROVIDER; - boolean enabled = + boolean enabled = GPS.equals(value) || value.startsWith(GPS + ",") || value.endsWith("," + GPS) || diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java index 5ad305c..ad5e20b 100644 --- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java +++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java @@ -989,6 +989,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback { final Callback cb = getCallback(); if (!mActionBar.isOverflowMenuShowing() || !toggleMenuMode) { if (cb != null && !isDestroyed() && mActionBar.getVisibility() == View.VISIBLE) { + // If we have a menu invalidation pending, do it now. + if (mInvalidatePanelMenuPosted && + (mInvalidatePanelMenuFeatures & (1 << FEATURE_OPTIONS_PANEL)) != 0) { + mDecor.removeCallbacks(mInvalidatePanelMenuRunnable); + mInvalidatePanelMenuRunnable.run(); + } + final PanelFeatureState st = getPanelState(FEATURE_OPTIONS_PANEL, true); // If we don't have a menu or we're waiting for a full content refresh, diff --git a/services/java/com/android/server/BluetoothManagerService.java b/services/java/com/android/server/BluetoothManagerService.java index 33e712a..924b9df 100755 --- a/services/java/com/android/server/BluetoothManagerService.java +++ b/services/java/com/android/server/BluetoothManagerService.java @@ -1081,9 +1081,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) return true; } else if (off) { if (mBluetooth.getState() == BluetoothAdapter.STATE_OFF) return true; - } else { + } else { if (mBluetooth.getState() != BluetoothAdapter.STATE_ON) return true; - } + } } catch (RemoteException e) { Log.e(TAG, "getState()", e); break; @@ -1091,9 +1091,9 @@ class BluetoothManagerService extends IBluetoothManager.Stub { } if (on || off) { SystemClock.sleep(300); - } else { + } else { SystemClock.sleep(50); - } + } i++; } Log.e(TAG,"waitForOnOff time out"); diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java index 6dcb403..0bb0366 100644 --- a/services/java/com/android/server/ConnectivityService.java +++ b/services/java/com/android/server/ConnectivityService.java @@ -74,6 +74,7 @@ import android.os.IBinder; import android.os.INetworkManagementService; import android.os.Looper; import android.os.Message; +import android.os.Messenger; import android.os.ParcelFileDescriptor; import android.os.PowerManager; import android.os.Process; @@ -3220,7 +3221,7 @@ public class ConnectivityService extends IConnectivityManager.Stub { throwIfLockdownEnabled(); try { int type = mActiveDefaultNetwork; - if (ConnectivityManager.isNetworkTypeValid(type)) { + if (ConnectivityManager.isNetworkTypeValid(type) && mNetTrackers[type] != null) { mVpn.protect(socket, mNetTrackers[type].getLinkProperties().getInterfaceName()); return true; } @@ -3425,4 +3426,12 @@ public class ConnectivityService extends IConnectivityManager.Stub { throw new IllegalStateException("Unavailable in lockdown mode"); } } + + public void supplyMessenger(int networkType, Messenger messenger) { + enforceConnectivityInternalPermission(); + + if (isNetworkTypeValid(networkType) && mNetTrackers[networkType] != null) { + mNetTrackers[networkType].supplyMessenger(messenger); + } + } } diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java index d3e7c24..ab70e6f 100644 --- a/services/java/com/android/server/DevicePolicyManagerService.java +++ b/services/java/com/android/server/DevicePolicyManagerService.java @@ -2443,7 +2443,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub { == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { ipm.setApplicationEnabledSetting(packageName, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, - PackageManager.DONT_KILL_APP, userId); + PackageManager.DONT_KILL_APP, userId, "DevicePolicyManager"); } } catch (RemoteException e) { } diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java index 2d53023..3b541ec 100644 --- a/services/java/com/android/server/InputMethodManagerService.java +++ b/services/java/com/android/server/InputMethodManagerService.java @@ -1598,7 +1598,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) { mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(), PackageManager.COMPONENT_ENABLED_STATE_DEFAULT, - PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId()); + PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(), + mContext.getBasePackageName()); } } catch (RemoteException e) { } diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java index 2210a18..d2acb40 100644 --- a/services/java/com/android/server/NetworkManagementService.java +++ b/services/java/com/android/server/NetworkManagementService.java @@ -839,33 +839,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub return event.getMessage().endsWith("started"); } - // TODO(BT) Remove - @Override - public void startReverseTethering(String iface) { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - // cmd is "tether start first_start first_stop second_start second_stop ..." - // an odd number of addrs will fail - try { - mConnector.execute("tether", "start-reverse", iface); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - BluetoothTetheringDataTracker.getInstance().startReverseTether(iface); - - } - - // TODO(BT) Remove - @Override - public void stopReverseTethering() { - mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); - try { - mConnector.execute("tether", "stop-reverse"); - } catch (NativeDaemonConnectorException e) { - throw e.rethrowAsParcelableException(); - } - BluetoothTetheringDataTracker.getInstance().stopReverseTether(); - } - @Override public void tetherInterface(String iface) { mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index c4b98ad..03679a5 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -906,6 +906,7 @@ public class AccountManagerService } } + @Override public void invalidateAuthToken(String accountType, String authToken) { if (Log.isLoggable(TAG, Log.VERBOSE)) { Log.v(TAG, "invalidateAuthToken: accountType " + accountType @@ -1351,7 +1352,7 @@ public class AccountManagerService String subtitle = ""; if (index > 0) { title = titleAndSubtitle.substring(0, index); - subtitle = titleAndSubtitle.substring(index + 1); + subtitle = titleAndSubtitle.substring(index + 1); } UserHandle user = new UserHandle(userId); n.setLatestEventInfo(mContext, title, subtitle, @@ -1426,8 +1427,7 @@ public class AccountManagerService checkManageAccountsPermission(); // Is user disallowed from modifying accounts? - if (getUserManager().getUserRestrictions(Binder.getCallingUserHandle()) - .getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { + if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { try { response.onError(AccountManager.ERROR_CODE_USER_RESTRICTED, "User is not allowed to add an account!"); @@ -2570,9 +2570,7 @@ public class AccountManagerService private boolean canUserModifyAccounts(int callingUid) { if (callingUid != android.os.Process.myUid()) { - Bundle restrictions = getUserManager().getUserRestrictions( - new UserHandle(UserHandle.getUserId(callingUid))); - if (restrictions.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS, false)) { + if (getUserManager().hasUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS)) { return false; } } @@ -2710,7 +2708,7 @@ public class AccountManagerService } if (mUserManager.getUserInfo(userAccounts.userId).isRestricted()) { String[] packages = mPackageManager.getPackagesForUid(callingUid); - // If any of the packages includes a white listed package, return the full set, + // If any of the packages is a white listed package, return the full set, // otherwise return non-shared accounts only. // This might be a temporary way to specify a whitelist String whiteList = mContext.getResources().getString( @@ -2723,16 +2721,30 @@ public class AccountManagerService ArrayList<Account> allowed = new ArrayList<Account>(); Account[] sharedAccounts = getSharedAccountsAsUser(userAccounts.userId); if (sharedAccounts == null || sharedAccounts.length == 0) return unfiltered; - for (Account account : unfiltered) { - boolean found = false; - for (Account shared : sharedAccounts) { - if (shared.equals(account)) { - found = true; - break; + String requiredAccountType = ""; + try { + for (String packageName : packages) { + PackageInfo pi = mPackageManager.getPackageInfo(packageName, 0); + if (pi != null && pi.restrictedAccountType != null) { + requiredAccountType = pi.restrictedAccountType; } } - if (!found) { + } catch (NameNotFoundException nnfe) { + } + for (Account account : unfiltered) { + if (account.type.equals(requiredAccountType)) { allowed.add(account); + } else { + boolean found = false; + for (Account shared : sharedAccounts) { + if (shared.equals(account)) { + found = true; + break; + } + } + if (!found) { + allowed.add(account); + } } } Account[] filtered = new Account[allowed.size()]; diff --git a/services/java/com/android/server/am/ProcessList.java b/services/java/com/android/server/am/ProcessList.java index 9e25e30..1a635a9 100644 --- a/services/java/com/android/server/am/ProcessList.java +++ b/services/java/com/android/server/am/ProcessList.java @@ -144,8 +144,8 @@ class ProcessList { // These are the high-end OOM level limits. This is appropriate for a // 1280x800 or larger screen with around 1GB RAM. Values are in KB. private final long[] mOomMinFreeHigh = new long[] { - 32768, 40960, 49152, - 57344, 65536, 81920 + 49152, 61440, 73728, + 86016, 98304, 122880 }; // The actual OOM killer memory levels we are using. private final long[] mOomMinFree = new long[mOomAdj.length]; diff --git a/services/java/com/android/server/content/ContentService.java b/services/java/com/android/server/content/ContentService.java index 545ec93..68cf5fc 100644 --- a/services/java/com/android/server/content/ContentService.java +++ b/services/java/com/android/server/content/ContentService.java @@ -37,7 +37,6 @@ import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; -import android.text.format.DateUtils; import android.util.Log; import android.util.Slog; import android.util.SparseIntArray; @@ -408,10 +407,10 @@ public final class ContentService extends IContentService.Stub { "no permission to write the sync settings"); int userId = UserHandle.getCallingUserId(); - if (pollFrequency <= DateUtils.MINUTE_IN_MILLIS) { + if (pollFrequency < 60) { Slog.w(TAG, "Requested poll frequency of " + pollFrequency - + "ms being rounded up to 60 seconds."); - pollFrequency = DateUtils.MINUTE_IN_MILLIS; + + " seconds being rounded up to 60 seconds."); + pollFrequency = 60; } long identityToken = clearCallingIdentity(); diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java index afdd294..dc5916b 100644 --- a/services/java/com/android/server/pm/PackageManagerService.java +++ b/services/java/com/android/server/pm/PackageManagerService.java @@ -8733,7 +8733,7 @@ public class PackageManagerService extends IPackageManager.Stub { false, //installed true, //stopped true, //notLaunched - null, null); + null, null, null); if (!isSystemApp(ps)) { if (ps.isAnyInstalled(sUserManager.getUserIds())) { // Other user still have this package installed, so all @@ -9306,9 +9306,12 @@ public class PackageManagerService extends IPackageManager.Stub { @Override public void setApplicationEnabledSetting(String appPackageName, - int newState, int flags, int userId) { + int newState, int flags, int userId, String callingPackage) { if (!sUserManager.exists(userId)) return; - setEnabledSetting(appPackageName, null, newState, flags, userId); + if (callingPackage == null) { + callingPackage = Integer.toString(Binder.getCallingUid()); + } + setEnabledSetting(appPackageName, null, newState, flags, userId, callingPackage); } @Override @@ -9316,11 +9319,11 @@ public class PackageManagerService extends IPackageManager.Stub { int newState, int flags, int userId) { if (!sUserManager.exists(userId)) return; setEnabledSetting(componentName.getPackageName(), - componentName.getClassName(), newState, flags, userId); + componentName.getClassName(), newState, flags, userId, null); } - private void setEnabledSetting( - final String packageName, String className, int newState, final int flags, int userId) { + private void setEnabledSetting(final String packageName, String className, int newState, + final int flags, int userId, String callingPackage) { if (!(newState == COMPONENT_ENABLED_STATE_DEFAULT || newState == COMPONENT_ENABLED_STATE_ENABLED || newState == COMPONENT_ENABLED_STATE_DISABLED @@ -9366,7 +9369,12 @@ public class PackageManagerService extends IPackageManager.Stub { // Nothing to do return; } - pkgSetting.setEnabled(newState, userId); + if (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT + || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) { + // Don't care about who enables an app. + callingPackage = null; + } + pkgSetting.setEnabled(newState, userId, callingPackage); // pkgSetting.pkg.mSetEnabled = newState; } else { // We're dealing with a component level state change diff --git a/services/java/com/android/server/pm/PackageSettingBase.java b/services/java/com/android/server/pm/PackageSettingBase.java index ae1b213..e64ec6d 100644 --- a/services/java/com/android/server/pm/PackageSettingBase.java +++ b/services/java/com/android/server/pm/PackageSettingBase.java @@ -189,14 +189,20 @@ class PackageSettingBase extends GrantedPermissions { return DEFAULT_USER_STATE; } - void setEnabled(int state, int userId) { - modifyUserState(userId).enabled = state; + void setEnabled(int state, int userId, String callingPackage) { + PackageUserState st = modifyUserState(userId); + st.enabled = state; + st.lastDisableAppCaller = callingPackage; } int getEnabled(int userId) { return readUserState(userId).enabled; } + String getLastDisabledAppCaller(int userId) { + return readUserState(userId).lastDisableAppCaller; + } + void setInstalled(boolean inst, int userId) { modifyUserState(userId).installed = inst; } @@ -249,13 +255,14 @@ class PackageSettingBase extends GrantedPermissions { } void setUserState(int userId, int enabled, boolean installed, boolean stopped, - boolean notLaunched, HashSet<String> enabledComponents, + boolean notLaunched, String lastDisableAppCaller, HashSet<String> enabledComponents, HashSet<String> disabledComponents) { PackageUserState state = modifyUserState(userId); state.enabled = enabled; state.installed = installed; state.stopped = stopped; state.notLaunched = notLaunched; + state.lastDisableAppCaller = lastDisableAppCaller; state.enabledComponents = enabledComponents; state.disabledComponents = disabledComponents; } diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java index e645078..e13a17b 100644 --- a/services/java/com/android/server/pm/Settings.java +++ b/services/java/com/android/server/pm/Settings.java @@ -104,6 +104,7 @@ final class Settings { private static final String ATTR_CODE = "code"; private static final String ATTR_NOT_LAUNCHED = "nl"; private static final String ATTR_ENABLED = "enabled"; + private static final String ATTR_ENABLED_CALLER = "enabledCaller"; private static final String ATTR_STOPPED = "stopped"; private static final String ATTR_INSTALLED = "inst"; @@ -453,7 +454,7 @@ final class Settings { installed, true, // stopped, true, // notLaunched - null, null); + null, null, null); writePackageRestrictionsLPr(user.id); } } @@ -850,7 +851,7 @@ final class Settings { true, // installed false, // stopped false, // notLaunched - null, null); + null, null, null); } return; } @@ -895,6 +896,8 @@ final class Settings { final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED); final int enabled = enabledStr == null ? COMPONENT_ENABLED_STATE_DEFAULT : Integer.parseInt(enabledStr); + final String enabledCaller = parser.getAttributeValue(null, + ATTR_ENABLED_CALLER); final String installedStr = parser.getAttributeValue(null, ATTR_INSTALLED); final boolean installed = installedStr == null ? true : Boolean.parseBoolean(installedStr); @@ -925,7 +928,7 @@ final class Settings { } ps.setUserState(userId, enabled, installed, stopped, notLaunched, - enabledComponents, disabledComponents); + enabledCaller, enabledComponents, disabledComponents); } else if (tagName.equals("preferred-activities")) { readPreferredActivitiesLPw(parser, userId); } else { @@ -1052,6 +1055,10 @@ final class Settings { if (ustate.enabled != COMPONENT_ENABLED_STATE_DEFAULT) { serializer.attribute(null, ATTR_ENABLED, Integer.toString(ustate.enabled)); + if (ustate.lastDisableAppCaller != null) { + serializer.attribute(null, ATTR_ENABLED_CALLER, + ustate.lastDisableAppCaller); + } } if (ustate.enabledComponents != null && ustate.enabledComponents.size() > 0) { @@ -2239,14 +2246,14 @@ final class Settings { final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED); if (enabledStr != null) { try { - packageSetting.setEnabled(Integer.parseInt(enabledStr), 0 /* userId */); + packageSetting.setEnabled(Integer.parseInt(enabledStr), 0 /* userId */, null); } catch (NumberFormatException e) { if (enabledStr.equalsIgnoreCase("true")) { - packageSetting.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 0); + packageSetting.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 0, null); } else if (enabledStr.equalsIgnoreCase("false")) { - packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0); + packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null); } else if (enabledStr.equalsIgnoreCase("default")) { - packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0); + packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0, null); } else { PackageManagerService.reportSettingsProblem(Log.WARN, "Error in package manager settings: package " + name @@ -2255,7 +2262,7 @@ final class Settings { } } } else { - packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0); + packageSetting.setEnabled(COMPONENT_ENABLED_STATE_DEFAULT, 0, null); } final String installStatusStr = parser.getAttributeValue(null, "installStatus"); @@ -2789,6 +2796,11 @@ final class Settings { pw.print(ps.getNotLaunched(user.id)); pw.print(" enabled="); pw.println(ps.getEnabled(user.id)); + String lastDisabledAppCaller = ps.getLastDisabledAppCaller(user.id); + if (lastDisabledAppCaller != null) { + pw.print(prefix); pw.print(" lastDisabledCaller: "); + pw.println(lastDisabledAppCaller); + } HashSet<String> cmp = ps.getDisabledComponents(user.id); if (cmp != null && cmp.size() > 0) { pw.print(prefix); pw.println(" disabledComponents:"); diff --git a/services/java/com/android/server/pm/UserManagerService.java b/services/java/com/android/server/pm/UserManagerService.java index fecc2df..01ea1a2 100644 --- a/services/java/com/android/server/pm/UserManagerService.java +++ b/services/java/com/android/server/pm/UserManagerService.java @@ -26,7 +26,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.RestrictionEntry; -import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.UserInfo; @@ -619,6 +618,10 @@ public class UserManagerService extends IUserManager.Stub { writeBoolean(serializer, restrictions, UserManager.DISALLOW_INSTALL_APPS); writeBoolean(serializer, restrictions, UserManager.DISALLOW_UNINSTALL_APPS); writeBoolean(serializer, restrictions, UserManager.DISALLOW_SHARE_LOCATION); + writeBoolean(serializer, restrictions, + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH); + writeBoolean(serializer, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER); serializer.endTag(null, TAG_RESTRICTIONS); } serializer.endTag(null, TAG_USER); @@ -735,6 +738,10 @@ public class UserManagerService extends IUserManager.Stub { readBoolean(parser, restrictions, UserManager.DISALLOW_INSTALL_APPS); readBoolean(parser, restrictions, UserManager.DISALLOW_UNINSTALL_APPS); readBoolean(parser, restrictions, UserManager.DISALLOW_SHARE_LOCATION); + readBoolean(parser, restrictions, + UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES); + readBoolean(parser, restrictions, UserManager.DISALLOW_CONFIG_BLUETOOTH); + readBoolean(parser, restrictions, UserManager.DISALLOW_USB_FILE_TRANSFER); } } } diff --git a/services/java/com/android/server/usb/UsbSettingsManager.java b/services/java/com/android/server/usb/UsbSettingsManager.java index f9aaa17..9b5b312 100644 --- a/services/java/com/android/server/usb/UsbSettingsManager.java +++ b/services/java/com/android/server/usb/UsbSettingsManager.java @@ -34,6 +34,7 @@ import android.hardware.usb.UsbInterface; import android.hardware.usb.UsbManager; import android.os.Binder; import android.os.Environment; +import android.os.Process; import android.os.UserHandle; import android.util.AtomicFile; import android.util.Log; @@ -853,21 +854,29 @@ class UsbSettingsManager { public boolean hasPermission(UsbDevice device) { synchronized (mLock) { + int uid = Binder.getCallingUid(); + if (uid == Process.SYSTEM_UID) { + return true; + } SparseBooleanArray uidList = mDevicePermissionMap.get(device.getDeviceName()); if (uidList == null) { return false; } - return uidList.get(Binder.getCallingUid()); + return uidList.get(uid); } } public boolean hasPermission(UsbAccessory accessory) { synchronized (mLock) { + int uid = Binder.getCallingUid(); + if (uid == Process.SYSTEM_UID) { + return true; + } SparseBooleanArray uidList = mAccessoryPermissionMap.get(accessory); if (uidList == null) { return false; } - return uidList.get(Binder.getCallingUid()); + return uidList.get(uid); } } diff --git a/services/java/com/android/server/wifi/README.txt b/services/java/com/android/server/wifi/README.txt index c03bff5..39e1475 100644 --- a/services/java/com/android/server/wifi/README.txt +++ b/services/java/com/android/server/wifi/README.txt @@ -10,3 +10,10 @@ WifiNotificationController: Controls whether the open network notification is di WifiStateMachine: Tracks the various states on STA and AP connectivity and handles bring up and shut down. + +Feature description: + +Scan-only mode with Wi-Fi turned off: + - Setup wizard opts user into allowing scanning for improved location. We show no further dialogs in setup wizard since the user has just opted into the feature. This is the reason WifiService listens to DEVICE_PROVISIONED setting. + - Once the user has his device provisioned, turning off Wi-Fi from settings or from a third party app will show up a dialog reminding the user that scan mode will be on even though Wi-Fi is being turned off. The user has the choice to turn this notification off. + - In the scan mode, the device continues to allow scanning from any app with Wi-Fi turned off. This is done by disabling all networks and allowing only scans to be passed. diff --git a/services/java/com/android/server/wifi/WifiService.java b/services/java/com/android/server/wifi/WifiService.java index 9dde58f..f8d5d2e 100644 --- a/services/java/com/android/server/wifi/WifiService.java +++ b/services/java/com/android/server/wifi/WifiService.java @@ -58,6 +58,7 @@ import java.net.InetAddress; import java.net.Inet4Address; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; import com.android.internal.R; import com.android.internal.app.IBatteryStats; @@ -101,6 +102,9 @@ public final class WifiService extends IWifiManager.Stub { private int mMulticastEnabled; private int mMulticastDisabled; + private AtomicBoolean mDeviceProvisioned = new AtomicBoolean(); + private AtomicBoolean mNotifyScanMode = new AtomicBoolean(); + private final IBatteryStats mBatteryStats; private final AppOpsManager mAppOps; @@ -245,6 +249,8 @@ public final class WifiService extends IWifiManager.Stub { mWifiController.start(); registerForScanModeChange(); + registerForDeviceProvisionedChange(); + registerForNotifyUserOnScanModeChange(); mContext.registerReceiver( new BroadcastReceiver() { @Override @@ -399,10 +405,8 @@ public final class WifiService extends IWifiManager.Stub { /* Turning off Wi-Fi when scans are still available */ if (!enable && isScanningAlwaysAvailable()) { - /* This can be changed by user in the app to not be notified again */ - boolean notifyUser = (Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.WIFI_NOTIFY_SCAN_ALWAYS_AVAILABLE, 1) == 1); - if (notifyUser) { + /* Notify if device is provisioned and user has not opted out of the notification */ + if (mNotifyScanMode.get() && mDeviceProvisioned.get()) { Intent intent = new Intent(WifiManager.ACTION_NOTIFY_SCAN_ALWAYS_AVAILABLE); mContext.startActivityAsUser(intent, null, UserHandle.CURRENT); } @@ -875,6 +879,51 @@ public final class WifiService extends IWifiManager.Stub { false, contentObserver); } + private void getPersistedDeviceProvisioned() { + mDeviceProvisioned.set(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.DEVICE_PROVISIONED, 0) != 0); + } + + private void getPersistedNotifyScanMode() { + mNotifyScanMode.set(Settings.Global.getInt(mContext.getContentResolver(), + Settings.Global.WIFI_NOTIFY_SCAN_ALWAYS_AVAILABLE, 1) == 1); + } + + /** + * Observes settings changes to notify the user when scan mode is active and + * Wi-Fi is turned off + */ + private void registerForNotifyUserOnScanModeChange() { + ContentObserver contentObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + getPersistedNotifyScanMode(); + } + }; + + getPersistedNotifyScanMode(); + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.WIFI_NOTIFY_SCAN_ALWAYS_AVAILABLE), + false, contentObserver); + } + + /* + * Observes settings changes device provisioned status + */ + private void registerForDeviceProvisionedChange() { + ContentObserver contentObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + getPersistedDeviceProvisioned(); + } + }; + + getPersistedDeviceProvisioned(); + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), + false, contentObserver); + } + private void registerForBroadcasts() { IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_SCREEN_ON); @@ -899,6 +948,8 @@ public final class WifiService extends IWifiManager.Stub { pw.println("Stay-awake conditions: " + Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.STAY_ON_WHILE_PLUGGED_IN, 0)); + pw.println("mDeviceProvisioned " + mDeviceProvisioned.get()); + pw.println("mNotifyScanMode " + mNotifyScanMode.get()); pw.println("mMulticastEnabled " + mMulticastEnabled); pw.println("mMulticastDisabled " + mMulticastDisabled); mWifiController.dump(fd, pw, args); diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java index 1ab5f45..c501553 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java @@ -176,8 +176,8 @@ public class PackageManagerSettingsTests extends AndroidTestCase { // Enable/Disable a package PackageSetting ps = settings.peekPackageLPr(PACKAGE_NAME_1); - ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0); - ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1); + ps.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, 0, null); + ps.setEnabled(COMPONENT_ENABLED_STATE_ENABLED, 1, null); assertEquals(COMPONENT_ENABLED_STATE_DISABLED, ps.getEnabled(0)); assertEquals(COMPONENT_ENABLED_STATE_ENABLED, ps.getEnabled(1)); diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java index cacafd4..9d556c0 100644 --- a/telephony/java/com/android/internal/telephony/DctConstants.java +++ b/telephony/java/com/android/internal/telephony/DctConstants.java @@ -111,7 +111,4 @@ public class DctConstants { public static final int ENABLED = 1; public static final String APN_TYPE_KEY = "apnType"; - public static String ACTION_DATA_CONNECTION_TRACKER_MESSENGER = - "com.android.internal.telephony"; - public static String EXTRA_MESSENGER = "EXTRA_MESSENGER"; } diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java index 32cd2f6..f637e89 100644 --- a/wifi/java/android/net/wifi/WifiNative.java +++ b/wifi/java/android/net/wifi/WifiNative.java @@ -793,4 +793,14 @@ public class WifiNative { public boolean p2pServDiscCancelReq(String id) { return doBooleanCommand("P2P_SERV_DISC_CANCEL_REQ " + id); } + + /* Set the current mode of miracast operation. + * 0 = disabled + * 1 = operating as source + * 2 = operating as sink + */ + public void setMiracastMode(int mode) { + // Note: optional feature on the driver. It is ok for this to fail. + doBooleanCommand("DRIVER MIRACAST " + mode); + } } diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index 81d2e11..cf75381 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -27,6 +27,7 @@ import android.net.NetworkInfo.DetailedState; import android.net.NetworkStateTracker; import android.os.Handler; import android.os.Message; +import android.os.Messenger; import android.util.Slog; import java.util.concurrent.atomic.AtomicBoolean; @@ -262,4 +263,9 @@ public class WifiStateTracker implements NetworkStateTracker { public void removeStackedLink(LinkProperties link) { mLinkProperties.removeStackedLink(link); } + + @Override + public void supplyMessenger(Messenger messenger) { + // not supported on this network + } } diff --git a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl index 381a450..1c9c40d 100644 --- a/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl +++ b/wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl @@ -26,5 +26,6 @@ import android.os.Messenger; interface IWifiP2pManager { Messenger getMessenger(); + void setMiracastMode(int mode); } diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java index 2e80064..737ab91 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pManager.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pManager.java @@ -1258,6 +1258,21 @@ public class WifiP2pManager { c.mAsyncChannel.sendMessage(REQUEST_PERSISTENT_GROUP_INFO, 0, c.putListener(listener)); } + /** @hide */ + public static final int MIRACAST_DISABLED = 0; + /** @hide */ + public static final int MIRACAST_SOURCE = 1; + /** @hide */ + public static final int MIRACAST_SINK = 2; + /** Internal use only @hide */ + public void setMiracastMode(int mode) { + try { + mService.setMiracastMode(mode); + } catch(RemoteException e) { + // ignore + } + } + /** * Get a reference to WifiP2pService handler. This is used to establish * an AsyncChannel communication with WifiService diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java index e6a1df1..447ddb0 100644 --- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java +++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java @@ -164,6 +164,8 @@ public class WifiP2pService extends IWifiP2pManager.Stub { public static final int DISCONNECT_WIFI_REQUEST = BASE + 12; public static final int DISCONNECT_WIFI_RESPONSE = BASE + 13; + public static final int SET_MIRACAST_MODE = BASE + 14; + private final boolean mP2pSupported; private WifiP2pDevice mThisDevice = new WifiP2pDevice(); @@ -310,6 +312,12 @@ public class WifiP2pService extends IWifiP2pManager.Stub { "WifiP2pService"); } + private void enforceConnectivityInternalPermission() { + mContext.enforceCallingOrSelfPermission( + android.Manifest.permission.CONNECTIVITY_INTERNAL, + "WifiP2pService"); + } + /** * Get a reference to handler. This is used by a client to establish * an AsyncChannel communication with WifiP2pService @@ -320,6 +328,20 @@ public class WifiP2pService extends IWifiP2pManager.Stub { return new Messenger(mP2pStateMachine.getHandler()); } + /** This is used to provide information to drivers to optimize performance depending + * on the current mode of operation. + * 0 - disabled + * 1 - source operation + * 2 - sink operation + * + * As an example, the driver could reduce the channel dwell time during scanning + * when acting as a source or sink to minimize impact on miracast. + */ + public void setMiracastMode(int mode) { + enforceConnectivityInternalPermission(); + mP2pStateMachine.sendMessage(SET_MIRACAST_MODE, mode); + } + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP) @@ -572,6 +594,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { case DhcpStateMachine.CMD_POST_DHCP_ACTION: case DhcpStateMachine.CMD_ON_QUIT: case WifiMonitor.P2P_PROV_DISC_FAILURE_EVENT: + case SET_MIRACAST_MODE: break; case WifiStateMachine.CMD_ENABLE_P2P: // Enable is lazy and has no response @@ -878,7 +901,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { sendPeersChangedBroadcast(); } break; - case WifiP2pManager.ADD_LOCAL_SERVICE: + case WifiP2pManager.ADD_LOCAL_SERVICE: if (DBG) logd(getName() + " add service"); WifiP2pServiceInfo servInfo = (WifiP2pServiceInfo)message.obj; if (addLocalService(message.replyTo, servInfo)) { @@ -916,7 +939,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub { clearServiceRequests(message.replyTo); replyToMessage(message, WifiP2pManager.CLEAR_SERVICE_REQUESTS_SUCCEEDED); break; - case WifiMonitor.P2P_SERV_DISC_RESP_EVENT: + case WifiMonitor.P2P_SERV_DISC_RESP_EVENT: if (DBG) logd(getName() + " receive service response"); List<WifiP2pServiceResponse> sdRespList = (List<WifiP2pServiceResponse>) message.obj; @@ -927,13 +950,16 @@ public class WifiP2pService extends IWifiP2pManager.Stub { sendServiceResponse(resp); } break; - case WifiP2pManager.DELETE_PERSISTENT_GROUP: + case WifiP2pManager.DELETE_PERSISTENT_GROUP: if (DBG) logd(getName() + " delete persistent group"); mGroups.remove(message.arg1); replyToMessage(message, WifiP2pManager.DELETE_PERSISTENT_GROUP_SUCCEEDED); break; + case SET_MIRACAST_MODE: + mWifiNative.setMiracastMode(message.arg1); + break; default: - return NOT_HANDLED; + return NOT_HANDLED; } return HANDLED; } |