diff options
19 files changed, 793 insertions, 181 deletions
diff --git a/cmds/uiautomator/library/Android.mk b/cmds/uiautomator/library/Android.mk index d65b0833aafa..af2e25a99ad5 100644 --- a/cmds/uiautomator/library/Android.mk +++ b/cmds/uiautomator/library/Android.mk @@ -18,7 +18,7 @@ LOCAL_PATH:= $(call my-dir) uiautomator.core_src_files := $(call all-java-files-under, core-src) \ $(call all-java-files-under, testrunner-src) -uiautomator.core_java_libraries := android.test.runner core-junit +uiautomator.core_java_libraries := android.test.runner junit uiautomator_internal_api_file := $(TARGET_OUT_COMMON_INTERMEDIATES)/PACKAGING/uiautomator_api.txt uiautomator_internal_removed_api_file := \ diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl index 59cbf6e93894..542a0a7d4040 100644 --- a/core/java/android/net/INetworkScoreService.aidl +++ b/core/java/android/net/INetworkScoreService.aidl @@ -56,17 +56,26 @@ interface INetworkScoreService void disableScoring(); /** - * Register a network subsystem for scoring. + * Register a cache to receive scoring updates. * * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. * @throws SecurityException if the caller is not the system. - * @throws IllegalArgumentException if a score cache is already registed for this type. * @hide */ void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); /** + * Unregister a cache to receive scoring updates. + * + * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. + * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. + * @throws SecurityException if the caller is not the system. + * @hide + */ + void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache); + + /** * Request a recommendation for the best network to connect to * taking into account the inputs from the {@link RecommendationRequest}. * diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java index c301fe3b73fe..af21cefce7ed 100644 --- a/core/java/android/net/NetworkScoreManager.java +++ b/core/java/android/net/NetworkScoreManager.java @@ -279,6 +279,24 @@ public class NetworkScoreManager { } /** + * Unregister a network score cache. + * + * @param networkType the type of network this cache can handle. See {@link NetworkKey#type}. + * @param scoreCache implementation of {@link INetworkScoreCache} to store the scores. + * @throws SecurityException if the caller does not hold the + * {@link android.Manifest.permission#BROADCAST_NETWORK_PRIVILEGED} permission. + * @throws IllegalArgumentException if a score cache is already registered for this type. + * @hide + */ + public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { + try { + mService.unregisterNetworkScoreCache(networkType, scoreCache); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Request a recommendation for which network to connect to. * * @param request a {@link RecommendationRequest} instance containing additional diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 1a8ba7455640..db7baac7fdd7 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7646,6 +7646,8 @@ public final class Settings { /** * Value to specify if Wi-Fi Wakeup feature is enabled. + * + * Type: int (0 for false, 1 for true) * @hide */ @SystemApi @@ -7654,6 +7656,8 @@ public final class Settings { /** * Value to specify if network recommendations from * {@link com.android.server.NetworkScoreService} are enabled. + * + * Type: int (0 for false, 1 for true) * @hide */ @SystemApi diff --git a/core/java/com/android/internal/os/TransferPipe.java b/core/java/com/android/internal/os/TransferPipe.java index e76b395e9e2d..f9041507ffdd 100644 --- a/core/java/com/android/internal/os/TransferPipe.java +++ b/core/java/com/android/internal/os/TransferPipe.java @@ -16,6 +16,7 @@ package com.android.internal.os; +import java.io.Closeable; import java.io.FileDescriptor; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -32,13 +33,13 @@ import android.util.Slog; /** * Helper for transferring data through a pipe from a client app. */ -public final class TransferPipe implements Runnable { +public final class TransferPipe implements Runnable, Closeable { static final String TAG = "TransferPipe"; static final boolean DEBUG = false; static final long DEFAULT_TIMEOUT = 5000; // 5 seconds - final Thread mThread;; + final Thread mThread; final ParcelFileDescriptor[] mFds; FileDescriptor mOutFd; @@ -54,8 +55,13 @@ public final class TransferPipe implements Runnable { } public TransferPipe() throws IOException { + this(null); + } + + public TransferPipe(String bufferPrefix) throws IOException { mThread = new Thread(this, "TransferPipe"); mFds = ParcelFileDescriptor.createPipe(); + mBufferPrefix = bufferPrefix; } ParcelFileDescriptor getReadFd() { @@ -70,6 +76,11 @@ public final class TransferPipe implements Runnable { mBufferPrefix = prefix; } + public static void dumpAsync(IBinder binder, FileDescriptor out, String[] args) + throws IOException, RemoteException { + goDump(binder, out, args); + } + static void go(Caller caller, IInterface iface, FileDescriptor out, String prefix, String[] args) throws IOException, RemoteException { go(caller, iface, out, prefix, args, DEFAULT_TIMEOUT); @@ -86,12 +97,9 @@ public final class TransferPipe implements Runnable { return; } - TransferPipe tp = new TransferPipe(); - try { + try (TransferPipe tp = new TransferPipe()) { caller.go(iface, tp.getWriteFd().getFileDescriptor(), prefix, args); tp.go(out, timeout); - } finally { - tp.kill(); } } @@ -111,12 +119,9 @@ public final class TransferPipe implements Runnable { return; } - TransferPipe tp = new TransferPipe(); - try { + try (TransferPipe tp = new TransferPipe()) { binder.dumpAsync(tp.getWriteFd().getFileDescriptor(), args); tp.go(out, timeout); - } finally { - tp.kill(); } } @@ -173,6 +178,11 @@ public final class TransferPipe implements Runnable { } } + @Override + public void close() { + kill(); + } + public void kill() { synchronized (this) { closeFd(0); diff --git a/legacy-test/Android.mk b/legacy-test/Android.mk index fe5d8ca66b6a..00110021584c 100644 --- a/legacy-test/Android.mk +++ b/legacy-test/Android.mk @@ -27,3 +27,15 @@ LOCAL_STATIC_JAVA_LIBRARIES := core-junit-static LOCAL_MODULE := legacy-test include $(BUILD_JAVA_LIBRARY) + +ifeq ($(HOST_OS),linux) +# Build the legacy-performance-test-hostdex library +# ================================================= +# This contains the android.test.PerformanceTestCase class only +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := ../core/java/android/test/PerformanceTestCase.java +LOCAL_MODULE := legacy-performance-test-hostdex + +include $(BUILD_HOST_DALVIK_JAVA_LIBRARY) +endif # HOST_OS == linux diff --git a/location/java/android/location/IFusedProvider.aidl b/location/java/android/location/IFusedProvider.aidl index 8870d2a2a420..e86ad1ac5147 100644 --- a/location/java/android/location/IFusedProvider.aidl +++ b/location/java/android/location/IFusedProvider.aidl @@ -22,11 +22,11 @@ import android.hardware.location.IFusedLocationHardware; * Interface definition for Location providers that require FLP services. * @hide */ -interface IFusedProvider { +oneway interface IFusedProvider { /** * Provides access to a FusedLocationHardware instance needed for the provider to work. * * @param instance The FusedLocationHardware available for the provider to use. */ void onFusedLocationHardwareChange(in IFusedLocationHardware instance); -}
\ No newline at end of file +} diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java index df1b6f51bc33..3ad264d38bb5 100644 --- a/services/core/java/com/android/server/InputMethodManagerService.java +++ b/services/core/java/com/android/server/InputMethodManagerService.java @@ -25,6 +25,7 @@ import com.android.internal.inputmethod.InputMethodUtils; import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings; import com.android.internal.os.HandlerCaller; import com.android.internal.os.SomeArgs; +import com.android.internal.os.TransferPipe; import com.android.internal.util.FastXmlSerializer; import com.android.internal.view.IInputContext; import com.android.internal.view.IInputMethod; @@ -4030,9 +4031,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (client != null) { pw.flush(); try { - client.client.asBinder().dump(fd, args); - } catch (RemoteException e) { - p.println("Input method client dead: " + e); + TransferPipe.dumpAsync(client.client.asBinder(), fd, args); + } catch (IOException | RemoteException e) { + p.println("Failed to dump input method client: " + e); } } else { p.println("No input method client."); @@ -4046,9 +4047,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub p.println(" "); pw.flush(); try { - focusedWindowClient.client.asBinder().dump(fd, args); - } catch (RemoteException e) { - p.println("Input method client in focused window dead: " + e); + TransferPipe.dumpAsync(focusedWindowClient.client.asBinder(), fd, args); + } catch (IOException | RemoteException e) { + p.println("Failed to dump input method client in focused window: " + e); } } @@ -4056,9 +4057,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub if (method != null) { pw.flush(); try { - method.asBinder().dump(fd, args); - } catch (RemoteException e) { - p.println("Input method service dead: " + e); + TransferPipe.dumpAsync(method.asBinder(), fd, args); + } catch (IOException | RemoteException e) { + p.println("Failed to dump input method service: " + e); } } else { p.println("No input method service."); diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java index 4e969bef864f..6412e01c1ff1 100644 --- a/services/core/java/com/android/server/NetworkScoreService.java +++ b/services/core/java/com/android/server/NetworkScoreService.java @@ -36,25 +36,29 @@ import android.net.ScoredNetwork; import android.net.wifi.WifiConfiguration; import android.os.Binder; import android.os.IBinder; +import android.os.RemoteCallbackList; import android.os.RemoteException; import android.os.UserHandle; import android.provider.Settings; import android.text.TextUtils; +import android.util.ArrayMap; import android.util.Log; import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.PackageMonitor; +import com.android.internal.os.TransferPipe; import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.function.Consumer; /** * Backing service for {@link android.net.NetworkScoreManager}. @@ -66,7 +70,8 @@ public class NetworkScoreService extends INetworkScoreService.Stub { private final Context mContext; private final NetworkScorerAppManager mNetworkScorerAppManager; - private final Map<Integer, INetworkScoreCache> mScoreCaches; + @GuardedBy("mScoreCaches") + private final Map<Integer, RemoteCallbackList<INetworkScoreCache>> mScoreCaches; /** Lock used to update mPackageMonitor when scorer package changes occur. */ private final Object mPackageMonitorLock = new Object[0]; @@ -164,7 +169,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { NetworkScoreService(Context context, NetworkScorerAppManager networkScoreAppManager) { mContext = context; mNetworkScorerAppManager = networkScoreAppManager; - mScoreCaches = new HashMap<>(); + mScoreCaches = new ArrayMap<>(); IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED); // TODO: Need to update when we support per-user scorers. http://b/23422763 mContext.registerReceiverAsUser( @@ -274,7 +279,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } // Separate networks by type. - Map<Integer, List<ScoredNetwork>> networksByType = new HashMap<>(); + Map<Integer, List<ScoredNetwork>> networksByType = new ArrayMap<>(); for (ScoredNetwork network : networks) { List<ScoredNetwork> networkList = networksByType.get(network.networkKey.type); if (networkList == null) { @@ -285,19 +290,32 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } // Pass the scores of each type down to the appropriate network scorer. - for (Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) { - INetworkScoreCache scoreCache = mScoreCaches.get(entry.getKey()); - if (scoreCache != null) { - try { - scoreCache.updateScores(entry.getValue()); - } catch (RemoteException e) { - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e); - } + for (final Map.Entry<Integer, List<ScoredNetwork>> entry : networksByType.entrySet()) { + final RemoteCallbackList<INetworkScoreCache> callbackList; + final boolean isEmpty; + synchronized (mScoreCaches) { + callbackList = mScoreCaches.get(entry.getKey()); + isEmpty = callbackList == null || callbackList.getRegisteredCallbackCount() == 0; + } + if (isEmpty) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding"); } - } else if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "No scorer registered for type " + entry.getKey() + ", discarding"); + continue; } + + sendCallback(new Consumer<INetworkScoreCache>() { + @Override + public void accept(INetworkScoreCache networkScoreCache) { + try { + networkScoreCache.updateScores(entry.getValue()); + } catch (RemoteException e) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "Unable to update scores of type " + entry.getKey(), e); + } + } + } + }, Collections.singleton(callbackList)); } return true; @@ -392,28 +410,52 @@ public class NetworkScoreService extends INetworkScoreService.Stub { /** Clear scores. Callers are responsible for checking permissions as appropriate. */ private void clearInternal() { - Set<INetworkScoreCache> cachesToClear = getScoreCaches(); + sendCallback(new Consumer<INetworkScoreCache>() { + @Override + public void accept(INetworkScoreCache networkScoreCache) { + try { + networkScoreCache.clearScores(); + } catch (RemoteException e) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "Unable to clear scores", e); + } + } + } + }, getScoreCacheLists()); + } - for (INetworkScoreCache scoreCache : cachesToClear) { - try { - scoreCache.clearScores(); - } catch (RemoteException e) { + @Override + public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { + mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); + synchronized (mScoreCaches) { + RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType); + if (callbackList == null) { + callbackList = new RemoteCallbackList<>(); + mScoreCaches.put(networkType, callbackList); + } + if (!callbackList.register(scoreCache)) { + if (callbackList.getRegisteredCallbackCount() == 0) { + mScoreCaches.remove(networkType); + } if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Unable to clear scores", e); + Log.v(TAG, "Unable to register NetworkScoreCache for type " + networkType); } } } } @Override - public void registerNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { + public void unregisterNetworkScoreCache(int networkType, INetworkScoreCache scoreCache) { mContext.enforceCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED, TAG); synchronized (mScoreCaches) { - if (mScoreCaches.containsKey(networkType)) { - throw new IllegalArgumentException( - "Score cache already registered for type " + networkType); + RemoteCallbackList<INetworkScoreCache> callbackList = mScoreCaches.get(networkType); + if (callbackList == null || !callbackList.unregister(scoreCache)) { + if (Log.isLoggable(TAG, Log.VERBOSE)) { + Log.v(TAG, "Unable to unregister NetworkScoreCache for type " + networkType); + } + } else if (callbackList.getRegisteredCallbackCount() == 0) { + mScoreCaches.remove(networkType); } - mScoreCaches.put(networkType, scoreCache); } } @@ -428,7 +470,7 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } @Override - protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { + protected void dump(final FileDescriptor fd, final PrintWriter writer, final String[] args) { mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG); NetworkScorerAppData currentScorer = mNetworkScorerAppManager.getActiveScorer(); if (currentScorer == null) { @@ -437,16 +479,17 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } writer.println("Current scorer: " + currentScorer.mPackageName); - for (INetworkScoreCache scoreCache : getScoreCaches()) { - try { - scoreCache.asBinder().dump(fd, args); - } catch (RemoteException e) { - writer.println("Unable to dump score cache"); - if (Log.isLoggable(TAG, Log.VERBOSE)) { - Log.v(TAG, "Unable to dump score cache", e); + sendCallback(new Consumer<INetworkScoreCache>() { + @Override + public void accept(INetworkScoreCache networkScoreCache) { + try { + TransferPipe.dumpAsync(networkScoreCache.asBinder(), fd, args); + } catch (IOException | RemoteException e) { + writer.println("Failed to dump score cache: " + e); } } - } + }, getScoreCacheLists()); + if (mServiceConnection != null) { mServiceConnection.dump(fd, writer, args); } else { @@ -456,14 +499,30 @@ public class NetworkScoreService extends INetworkScoreService.Stub { } /** - * Returns a set of all score caches that are currently active. + * Returns a {@link Collection} of all {@link RemoteCallbackList}s that are currently active. * * <p>May be used to perform an action on all score caches without potentially strange behavior * if a new scorer is registered during that action's execution. */ - private Set<INetworkScoreCache> getScoreCaches() { + private Collection<RemoteCallbackList<INetworkScoreCache>> getScoreCacheLists() { synchronized (mScoreCaches) { - return new HashSet<>(mScoreCaches.values()); + return new ArrayList<>(mScoreCaches.values()); + } + } + + private void sendCallback(Consumer<INetworkScoreCache> consumer, + Collection<RemoteCallbackList<INetworkScoreCache>> remoteCallbackLists) { + for (RemoteCallbackList<INetworkScoreCache> callbackList : remoteCallbackLists) { + synchronized (callbackList) { // Ensure only one active broadcast per RemoteCallbackList + final int count = callbackList.beginBroadcast(); + try { + for (int i = 0; i < count; i++) { + consumer.accept(callbackList.getBroadcastItem(i)); + } + } finally { + callbackList.finishBroadcast(); + } + } } } diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java index 5eb06ed20b42..b44087c07c16 100644 --- a/services/core/java/com/android/server/location/LocationProviderProxy.java +++ b/services/core/java/com/android/server/location/LocationProviderProxy.java @@ -17,6 +17,7 @@ package com.android.server.location; import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; import android.content.Context; @@ -30,6 +31,7 @@ import android.util.Log; import com.android.internal.location.ProviderProperties; import com.android.internal.location.ILocationProvider; import com.android.internal.location.ProviderRequest; +import com.android.internal.os.TransferPipe; import com.android.server.LocationManagerService; import com.android.server.ServiceWatcher; @@ -230,14 +232,9 @@ public class LocationProviderProxy implements LocationProviderInterface { pw.flush(); try { - service.asBinder().dump(fd, args); - } catch (RemoteException e) { - pw.println("service down (RemoteException)"); - Log.w(TAG, e); - } catch (Exception e) { - pw.println("service down (Exception)"); - // never let remote service crash system server - Log.e(TAG, "Exception from " + mServiceWatcher.getBestPackageName(), e); + TransferPipe.dumpAsync(service.asBinder(), fd, args); + } catch (IOException | RemoteException e) { + pw.println("Failed to dump location provider: " + e); } } diff --git a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java index 68b465aaf816..07d98bc0077a 100644 --- a/services/core/java/com/android/server/pm/EphemeralResolverConnection.java +++ b/services/core/java/com/android/server/pm/EphemeralResolverConnection.java @@ -32,7 +32,10 @@ import android.os.SystemClock; import android.os.UserHandle; import android.util.TimedRemoteCaller; +import com.android.internal.os.TransferPipe; + import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; @@ -85,13 +88,11 @@ final class EphemeralResolverConnection { .append((mRemoteInstance != null) ? "true" : "false").println(); pw.flush(); - try { - getRemoteInstanceLazy().asBinder().dump(fd, new String[] { prefix }); - } catch (TimeoutException te) { - /* ignore */ - } catch (RemoteException re) { - /* ignore */ + TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), fd, + new String[] { prefix }); + } catch (IOException | TimeoutException | RemoteException e) { + pw.println("Failed to dump remote instance: " + e); } } } diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java index d8f6b80970c0..bff68d85b4e5 100644 --- a/services/core/java/com/android/server/pm/Installer.java +++ b/services/core/java/com/android/server/pm/Installer.java @@ -204,35 +204,70 @@ public final class Installer extends SystemService { outputPath, dexFlags, compilerFilter, volumeUuid, sharedLibraries); } - public boolean mergeProfiles(int uid, String pkgName) throws InstallerException { - return mInstaller.mergeProfiles(uid, pkgName); + public boolean mergeProfiles(int uid, String packageName) throws InstallerException { + checkLock(); + try { + return mInstalld.mergeProfiles(uid, packageName); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } - public boolean dumpProfiles(String gid, String packageName, String codePaths) + public boolean dumpProfiles(int uid, String packageName, String codePaths) throws InstallerException { - return mInstaller.dumpProfiles(gid, packageName, codePaths); + checkLock(); + try { + return mInstalld.dumpProfiles(uid, packageName, codePaths); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void idmap(String targetApkPath, String overlayApkPath, int uid) throws InstallerException { - mInstaller.execute("idmap", targetApkPath, overlayApkPath, uid); + checkLock(); + try { + mInstalld.idmap(targetApkPath, overlayApkPath, uid); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void rmdex(String codePath, String instructionSet) throws InstallerException { assertValidInstructionSet(instructionSet); - mInstaller.execute("rmdex", codePath, instructionSet); + checkLock(); + try { + mInstalld.rmdex(codePath, instructionSet); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void rmPackageDir(String packageDir) throws InstallerException { - mInstaller.execute("rmpackagedir", packageDir); + checkLock(); + try { + mInstalld.rmPackageDir(packageDir); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } - public void clearAppProfiles(String pkgName) throws InstallerException { - mInstaller.execute("clear_app_profiles", pkgName); + public void clearAppProfiles(String packageName) throws InstallerException { + checkLock(); + try { + mInstalld.clearAppProfiles(packageName); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } - public void destroyAppProfiles(String pkgName) throws InstallerException { - mInstaller.execute("destroy_app_profiles", pkgName); + public void destroyAppProfiles(String packageName) throws InstallerException { + checkLock(); + try { + mInstalld.destroyAppProfiles(packageName); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void createUserData(String uuid, int userId, int userSerial, int flags) @@ -256,11 +291,21 @@ public final class Installer extends SystemService { public void markBootComplete(String instructionSet) throws InstallerException { assertValidInstructionSet(instructionSet); - mInstaller.execute("markbootcomplete", instructionSet); + checkLock(); + try { + mInstalld.markBootComplete(instructionSet); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void freeCache(String uuid, long freeStorageSize) throws InstallerException { - mInstaller.execute("freecache", uuid, freeStorageSize); + checkLock(); + try { + mInstalld.freeCache(uuid, freeStorageSize); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } /** @@ -268,29 +313,54 @@ public final class Installer extends SystemService { * directory to the real location for backward compatibility. Note that no * such symlink is created for 64 bit shared libraries. */ - public void linkNativeLibraryDirectory(String uuid, String dataPath, String nativeLibPath32, + public void linkNativeLibraryDirectory(String uuid, String packageName, String nativeLibPath32, int userId) throws InstallerException { - mInstaller.execute("linklib", uuid, dataPath, nativeLibPath32, userId); + checkLock(); + try { + mInstalld.linkNativeLibraryDirectory(uuid, packageName, nativeLibPath32, userId); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void createOatDir(String oatDir, String dexInstructionSet) throws InstallerException { - mInstaller.execute("createoatdir", oatDir, dexInstructionSet); + checkLock(); + try { + mInstalld.createOatDir(oatDir, dexInstructionSet); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void linkFile(String relativePath, String fromBase, String toBase) throws InstallerException { - mInstaller.execute("linkfile", relativePath, fromBase, toBase); + checkLock(); + try { + mInstalld.linkFile(relativePath, fromBase, toBase); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void moveAb(String apkPath, String instructionSet, String outputPath) throws InstallerException { - mInstaller.execute("move_ab", apkPath, instructionSet, outputPath); + checkLock(); + try { + mInstalld.moveAb(apkPath, instructionSet, outputPath); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } public void deleteOdex(String apkPath, String instructionSet, String outputPath) throws InstallerException { - mInstaller.execute("delete_odex", apkPath, instructionSet, outputPath); + checkLock(); + try { + mInstalld.deleteOdex(apkPath, instructionSet, outputPath); + } catch (RemoteException | ServiceSpecificException e) { + throw new InstallerException(e.getMessage()); + } } private static void assertValidInstructionSet(String instructionSet) diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 56a01737eac2..9102fee89422 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -7530,9 +7530,8 @@ public class PackageManagerService extends IPackageManager.Stub { final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); try { List<String> allCodePaths = pkg.getAllCodePathsExcludingResourceOnly(); - String gid = Integer.toString(sharedGid); String codePaths = TextUtils.join(";", allCodePaths); - mInstaller.dumpProfiles(gid, packageName, codePaths); + mInstaller.dumpProfiles(sharedGid, packageName, codePaths); } catch (InstallerException e) { Slog.w(TAG, "Failed to dump profiles", e); } diff --git a/services/print/java/com/android/server/print/RemotePrintSpooler.java b/services/print/java/com/android/server/print/RemotePrintSpooler.java index 07b26e83e934..6b919df290bb 100644 --- a/services/print/java/com/android/server/print/RemotePrintSpooler.java +++ b/services/print/java/com/android/server/print/RemotePrintSpooler.java @@ -43,9 +43,12 @@ import android.printservice.PrintService; import android.util.Slog; import android.util.TimedRemoteCaller; +import com.android.internal.os.TransferPipe; + import libcore.io.IoUtils; import java.io.FileDescriptor; +import java.io.IOException; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.List; @@ -572,13 +575,11 @@ final class RemotePrintSpooler { .append((mRemoteInstance != null) ? "true" : "false").println(); pw.flush(); - try { - getRemoteInstanceLazy().asBinder().dump(fd, new String[]{prefix}); - } catch (TimeoutException te) { - /* ignore */ - } catch (RemoteException re) { - /* ignore */ + TransferPipe.dumpAsync(getRemoteInstanceLazy().asBinder(), fd, + new String[] { prefix }); + } catch (IOException | TimeoutException | RemoteException e) { + pw.println("Failed to dump remote instance: " + e); } } } diff --git a/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java new file mode 100644 index 000000000000..0139671cc611 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/NetworkScoreServiceTest.java @@ -0,0 +1,422 @@ +/* + * Copyright (C) 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. + */ + +package com.android.server; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyInt; +import static org.mockito.Matchers.anyListOf; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import android.Manifest.permission; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.net.INetworkScoreCache; +import android.net.NetworkKey; +import android.net.NetworkScoreManager; +import android.net.NetworkScorerAppManager; +import android.net.NetworkScorerAppManager.NetworkScorerAppData; +import android.net.ScoredNetwork; +import android.net.WifiKey; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.UserHandle; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.MediumTest; +import android.support.test.runner.AndroidJUnit4; + +import com.android.internal.R; +import com.android.server.devicepolicy.MockUtils; + +import java.io.FileDescriptor; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +/** + * Tests for {@link NetworkScoreService}. + */ +@RunWith(AndroidJUnit4.class) +@MediumTest +public class NetworkScoreServiceTest { + private static final ScoredNetwork SCORED_NETWORK = + new ScoredNetwork(new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00")), + null /* rssiCurve*/); + private static final NetworkScorerAppData PREV_SCORER = new NetworkScorerAppData( + "prevPackageName", 0, "prevScorerName", null /* configurationActivityClassName */, + "prevScoringServiceClass"); + private static final NetworkScorerAppData NEW_SCORER = new NetworkScorerAppData( + "newPackageName", 1, "newScorerName", null /* configurationActivityClassName */, + "newScoringServiceClass"); + + @Mock private PackageManager mPackageManager; + @Mock private NetworkScorerAppManager mNetworkScorerAppManager; + @Mock private Context mContext; + @Mock private Resources mResources; + @Mock private INetworkScoreCache.Stub mNetworkScoreCache, mNetworkScoreCache2; + @Mock private IBinder mIBinder, mIBinder2; + @Captor private ArgumentCaptor<List<ScoredNetwork>> mScoredNetworkCaptor; + + private ContentResolver mContentResolver; + private NetworkScoreService mNetworkScoreService; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + when(mNetworkScoreCache.asBinder()).thenReturn(mIBinder); + when(mNetworkScoreCache2.asBinder()).thenReturn(mIBinder2); + mContentResolver = InstrumentationRegistry.getContext().getContentResolver(); + when(mContext.getContentResolver()).thenReturn(mContentResolver); + when(mContext.getResources()).thenReturn(mResources); + mNetworkScoreService = new NetworkScoreService(mContext, mNetworkScorerAppManager); + } + + @Test + public void testSystemReady_networkScorerProvisioned() throws Exception { + Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 1); + + mNetworkScoreService.systemReady(); + + verify(mNetworkScorerAppManager, never()).setActiveScorer(anyString()); + } + + @Test + public void testSystemReady_networkScorerNotProvisioned_defaultScorer() throws Exception { + Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 0); + + when(mResources.getString(R.string.config_defaultNetworkScorerPackageName)) + .thenReturn(NEW_SCORER.mPackageName); + + mNetworkScoreService.systemReady(); + + verify(mNetworkScorerAppManager).setActiveScorer(NEW_SCORER.mPackageName); + assertEquals(1, + Settings.Global.getInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED)); + + } + + @Test + public void testSystemReady_networkScorerNotProvisioned_noDefaultScorer() throws Exception { + Settings.Global.putInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED, 0); + + when(mResources.getString(R.string.config_defaultNetworkScorerPackageName)) + .thenReturn(null); + + mNetworkScoreService.systemReady(); + + verify(mNetworkScorerAppManager, never()).setActiveScorer(anyString()); + assertEquals(1, + Settings.Global.getInt(mContentResolver, Global.NETWORK_SCORING_PROVISIONED)); + } + + @Test + public void testSystemRunning() { + when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER); + + mNetworkScoreService.systemRunning(); + + verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent( + new ComponentName(NEW_SCORER.mPackageName, NEW_SCORER.mScoringServiceClassName))), + any(ServiceConnection.class), + eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE), + eq(UserHandle.SYSTEM)); + } + + @Test + public void testUpdateScores_notActiveScorer() { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); + + try { + mNetworkScoreService.updateScores(new ScoredNetwork[0]); + fail("SecurityException expected"); + } catch (SecurityException e) { + // expected + } + } + + @Test + public void testUpdateScores_oneRegisteredCache() throws RemoteException { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); + + mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); + + mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK}); + + verify(mNetworkScoreCache).updateScores(mScoredNetworkCaptor.capture()); + + assertEquals(1, mScoredNetworkCaptor.getValue().size()); + assertEquals(SCORED_NETWORK, mScoredNetworkCaptor.getValue().get(0)); + } + + @Test + public void testUpdateScores_twoRegisteredCaches() throws RemoteException { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); + + mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); + mNetworkScoreService.registerNetworkScoreCache( + NetworkKey.TYPE_WIFI, mNetworkScoreCache2); + + // updateScores should update both caches + mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK}); + + verify(mNetworkScoreCache).updateScores(anyListOf(ScoredNetwork.class)); + verify(mNetworkScoreCache2).updateScores(anyListOf(ScoredNetwork.class)); + + mNetworkScoreService.unregisterNetworkScoreCache( + NetworkKey.TYPE_WIFI, mNetworkScoreCache2); + + // updateScores should only update the first cache since the 2nd has been unregistered + mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK}); + + verify(mNetworkScoreCache, times(2)).updateScores(anyListOf(ScoredNetwork.class)); + + mNetworkScoreService.unregisterNetworkScoreCache( + NetworkKey.TYPE_WIFI, mNetworkScoreCache); + + // updateScores should not update any caches since they are both unregistered + mNetworkScoreService.updateScores(new ScoredNetwork[]{SCORED_NETWORK}); + + verifyNoMoreInteractions(mNetworkScoreCache, mNetworkScoreCache2); + } + + @Test + public void testClearScores_notActiveScorer_noBroadcastNetworkPermission() { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); + when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + .thenReturn(PackageManager.PERMISSION_DENIED); + try { + mNetworkScoreService.clearScores(); + fail("SecurityException expected"); + } catch (SecurityException e) { + // expected + } + } + + @Test + public void testClearScores_activeScorer_noBroadcastNetworkPermission() { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); + when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + .thenReturn(PackageManager.PERMISSION_DENIED); + + mNetworkScoreService.clearScores(); + } + + @Test + public void testClearScores_activeScorer() throws RemoteException { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); + + mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); + mNetworkScoreService.clearScores(); + + verify(mNetworkScoreCache).clearScores(); + } + + @Test + public void testClearScores_notActiveScorer_hasBroadcastNetworkPermission() + throws RemoteException { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); + when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + .thenReturn(PackageManager.PERMISSION_GRANTED); + + mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); + mNetworkScoreService.clearScores(); + + verify(mNetworkScoreCache).clearScores(); + } + + @Test + public void testSetActiveScorer_noScoreNetworksPermission() { + doThrow(new SecurityException()).when(mContext) + .enforceCallingOrSelfPermission(eq(permission.SCORE_NETWORKS), anyString()); + + try { + mNetworkScoreService.setActiveScorer(null); + fail("SecurityException expected"); + } catch (SecurityException e) { + // expected + } + } + + @Test + public void testSetActiveScorer_failure() throws RemoteException { + when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER); + when(mNetworkScorerAppManager.setActiveScorer(NEW_SCORER.mPackageName)).thenReturn(false); + mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); + + boolean success = mNetworkScoreService.setActiveScorer(NEW_SCORER.mPackageName); + + assertFalse(success); + verify(mNetworkScoreCache).clearScores(); + verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent( + new ComponentName(PREV_SCORER.mPackageName, PREV_SCORER.mScoringServiceClassName))), + any(ServiceConnection.class), + eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE), + eq(UserHandle.SYSTEM)); + } + + @Test + public void testSetActiveScorer_success() throws RemoteException { + when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, NEW_SCORER); + when(mNetworkScorerAppManager.setActiveScorer(NEW_SCORER.mPackageName)).thenReturn(true); + mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); + + boolean success = mNetworkScoreService.setActiveScorer(NEW_SCORER.mPackageName); + + assertTrue(success); + verify(mNetworkScoreCache).clearScores(); + verify(mContext).bindServiceAsUser(MockUtils.checkIntent(new Intent().setComponent( + new ComponentName(NEW_SCORER.mPackageName, NEW_SCORER.mScoringServiceClassName))), + any(ServiceConnection.class), + eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE), + eq(UserHandle.SYSTEM)); + verify(mContext, times(2)).sendBroadcastAsUser( + MockUtils.checkIntentAction(NetworkScoreManager.ACTION_SCORER_CHANGED), + eq(UserHandle.SYSTEM)); + } + + @Test + public void testDisableScoring_notActiveScorer_noBroadcastNetworkPermission() { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); + when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + .thenReturn(PackageManager.PERMISSION_DENIED); + + try { + mNetworkScoreService.disableScoring(); + fail("SecurityException expected"); + } catch (SecurityException e) { + // expected + } + + } + + @Test + public void testDisableScoring_activeScorer() throws RemoteException { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(true); + when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, null); + when(mNetworkScorerAppManager.setActiveScorer(null)).thenReturn(true); + mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); + + mNetworkScoreService.disableScoring(); + + verify(mNetworkScoreCache).clearScores(); + verify(mContext).sendBroadcastAsUser( + MockUtils.checkIntent(new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED) + .setPackage(PREV_SCORER.mPackageName)), + eq(UserHandle.SYSTEM)); + verify(mContext, never()).bindServiceAsUser(any(Intent.class), + any(ServiceConnection.class), anyInt(), any(UserHandle.class)); + } + + @Test + public void testDisableScoring_notActiveScorer_hasBroadcastNetworkPermission() + throws RemoteException { + when(mNetworkScorerAppManager.isCallerActiveScorer(anyInt())).thenReturn(false); + when(mContext.checkCallingOrSelfPermission(permission.BROADCAST_NETWORK_PRIVILEGED)) + .thenReturn(PackageManager.PERMISSION_GRANTED); + when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(PREV_SCORER, null); + when(mNetworkScorerAppManager.setActiveScorer(null)).thenReturn(true); + mNetworkScoreService.registerNetworkScoreCache(NetworkKey.TYPE_WIFI, mNetworkScoreCache); + + mNetworkScoreService.disableScoring(); + + verify(mNetworkScoreCache).clearScores(); + verify(mContext).sendBroadcastAsUser( + MockUtils.checkIntent(new Intent(NetworkScoreManager.ACTION_SCORER_CHANGED) + .setPackage(PREV_SCORER.mPackageName)), + eq(UserHandle.SYSTEM)); + verify(mContext, never()).bindServiceAsUser(any(Intent.class), + any(ServiceConnection.class), anyInt(), any(UserHandle.class)); + } + + @Test + public void testRegisterNetworkScoreCache_noBroadcastNetworkPermission() { + doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( + eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString()); + + try { + mNetworkScoreService.registerNetworkScoreCache( + NetworkKey.TYPE_WIFI, mNetworkScoreCache); + fail("SecurityException expected"); + } catch (SecurityException e) { + // expected + } + } + + @Test + public void testUnregisterNetworkScoreCache_noBroadcastNetworkPermission() { + doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( + eq(permission.BROADCAST_NETWORK_PRIVILEGED), anyString()); + + try { + mNetworkScoreService.unregisterNetworkScoreCache( + NetworkKey.TYPE_WIFI, mNetworkScoreCache); + fail("SecurityException expected"); + } catch (SecurityException e) { + // expected + } + } + + @Test + public void testDump_noDumpPermission() { + doThrow(new SecurityException()).when(mContext).enforceCallingOrSelfPermission( + eq(permission.DUMP), anyString()); + + try { + mNetworkScoreService.dump( + new FileDescriptor(), new PrintWriter(new StringWriter()), new String[0]); + fail("SecurityException expected"); + } catch (SecurityException e) { + // expected + } + } + + @Test + public void testDump_doesNotCrash() { + when(mNetworkScorerAppManager.getActiveScorer()).thenReturn(NEW_SCORER); + StringWriter stringWriter = new StringWriter(); + + mNetworkScoreService.dump( + new FileDescriptor(), new PrintWriter(stringWriter), new String[0]); + + assertFalse(stringWriter.toString().isEmpty()); + } +} diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java index 58db192f117a..3806da669297 100644 --- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java +++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java @@ -82,6 +82,21 @@ public class MockUtils { return Mockito.argThat(m); } + public static Intent checkIntent(final Intent intent) { + final Matcher<Intent> m = new BaseMatcher<Intent>() { + @Override + public boolean matches(Object item) { + if (item == null) return false; + return intent.filterEquals((Intent) item); + } + @Override + public void describeTo(Description description) { + description.appendText(intent.toString()); + } + }; + return Mockito.argThat(m); + } + public static Bundle checkUserRestrictions(String... keys) { final Bundle expected = DpmTestUtils.newRestrictions(Preconditions.checkNotNull(keys)); final Matcher<Bundle> m = new BaseMatcher<Bundle>() { diff --git a/test-runner/Android.mk b/test-runner/Android.mk index 68bde35d4ec5..a317994c41ba 100644 --- a/test-runner/Android.mk +++ b/test-runner/Android.mk @@ -20,7 +20,7 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(call all-java-files-under, src) -LOCAL_JAVA_LIBRARIES := core-oj core-libart core-junit framework +LOCAL_JAVA_LIBRARIES := core-oj core-libart junit framework LOCAL_STATIC_JAVA_LIBRARIES := junit-runner LOCAL_MODULE:= android.test.runner diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java index 69e9fcdbd1e6..43e624667644 100644 --- a/wifi/java/android/net/wifi/WifiConfiguration.java +++ b/wifi/java/android/net/wifi/WifiConfiguration.java @@ -746,50 +746,6 @@ public class WifiConfiguration implements Parcelable { @SystemApi public int numAssociation; - /** - * @hide - * Number of time user disabled WiFi while associated to this configuration with Low RSSI. - */ - public int numUserTriggeredWifiDisableLowRSSI; - - /** - * @hide - * Number of time user disabled WiFi while associated to this configuration with Bad RSSI. - */ - public int numUserTriggeredWifiDisableBadRSSI; - - /** - * @hide - * Number of time user disabled WiFi while associated to this configuration - * and RSSI was not HIGH. - */ - public int numUserTriggeredWifiDisableNotHighRSSI; - - /** - * @hide - * Number of ticks associated to this configuration with Low RSSI. - */ - public int numTicksAtLowRSSI; - - /** - * @hide - * Number of ticks associated to this configuration with Bad RSSI. - */ - public int numTicksAtBadRSSI; - - /** - * @hide - * Number of ticks associated to this configuration - * and RSSI was not HIGH. - */ - public int numTicksAtNotHighRSSI; - /** - * @hide - * Number of time user (WifiManager) triggered association to this configuration. - * TODO: count this only for Wifi Settings uuid, so as to not count 3rd party apps - */ - public int numUserTriggeredJoinAttempts; - /** @hide * Boost given to RSSI on a home network for the purpose of calculating the score * This adds stickiness to home networks, as defined by: @@ -1630,16 +1586,6 @@ public class WifiConfiguration implements Parcelable { sbuf.append('\n'); } } - sbuf.append("triggeredLow: ").append(this.numUserTriggeredWifiDisableLowRSSI); - sbuf.append(" triggeredBad: ").append(this.numUserTriggeredWifiDisableBadRSSI); - sbuf.append(" triggeredNotHigh: ").append(this.numUserTriggeredWifiDisableNotHighRSSI); - sbuf.append('\n'); - sbuf.append("ticksLow: ").append(this.numTicksAtLowRSSI); - sbuf.append(" ticksBad: ").append(this.numTicksAtBadRSSI); - sbuf.append(" ticksNotHigh: ").append(this.numTicksAtNotHighRSSI); - sbuf.append('\n'); - sbuf.append("triggeredJoin: ").append(this.numUserTriggeredJoinAttempts); - sbuf.append('\n'); return sbuf.toString(); } @@ -1946,13 +1892,6 @@ public class WifiConfiguration implements Parcelable { numScorerOverride = source.numScorerOverride; numScorerOverrideAndSwitchedNetwork = source.numScorerOverrideAndSwitchedNetwork; numAssociation = source.numAssociation; - numUserTriggeredWifiDisableLowRSSI = source.numUserTriggeredWifiDisableLowRSSI; - numUserTriggeredWifiDisableBadRSSI = source.numUserTriggeredWifiDisableBadRSSI; - numUserTriggeredWifiDisableNotHighRSSI = source.numUserTriggeredWifiDisableNotHighRSSI; - numTicksAtLowRSSI = source.numTicksAtLowRSSI; - numTicksAtBadRSSI = source.numTicksAtBadRSSI; - numTicksAtNotHighRSSI = source.numTicksAtNotHighRSSI; - numUserTriggeredJoinAttempts = source.numUserTriggeredJoinAttempts; userApproved = source.userApproved; numNoInternetAccessReports = source.numNoInternetAccessReports; noInternetAccessExpected = source.noInternetAccessExpected; @@ -2018,13 +1957,6 @@ public class WifiConfiguration implements Parcelable { dest.writeInt(numScorerOverride); dest.writeInt(numScorerOverrideAndSwitchedNetwork); dest.writeInt(numAssociation); - dest.writeInt(numUserTriggeredWifiDisableLowRSSI); - dest.writeInt(numUserTriggeredWifiDisableBadRSSI); - dest.writeInt(numUserTriggeredWifiDisableNotHighRSSI); - dest.writeInt(numTicksAtLowRSSI); - dest.writeInt(numTicksAtBadRSSI); - dest.writeInt(numTicksAtNotHighRSSI); - dest.writeInt(numUserTriggeredJoinAttempts); dest.writeInt(userApproved); dest.writeInt(numNoInternetAccessReports); dest.writeInt(noInternetAccessExpected ? 1 : 0); @@ -2090,13 +2022,6 @@ public class WifiConfiguration implements Parcelable { config.numScorerOverride = in.readInt(); config.numScorerOverrideAndSwitchedNetwork = in.readInt(); config.numAssociation = in.readInt(); - config.numUserTriggeredWifiDisableLowRSSI = in.readInt(); - config.numUserTriggeredWifiDisableBadRSSI = in.readInt(); - config.numUserTriggeredWifiDisableNotHighRSSI = in.readInt(); - config.numTicksAtLowRSSI = in.readInt(); - config.numTicksAtBadRSSI = in.readInt(); - config.numTicksAtNotHighRSSI = in.readInt(); - config.numUserTriggeredJoinAttempts = in.readInt(); config.userApproved = in.readInt(); config.numNoInternetAccessReports = in.readInt(); config.noInternetAccessExpected = in.readInt() != 0; diff --git a/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java new file mode 100644 index 000000000000..5f9497474a77 --- /dev/null +++ b/wifi/tests/src/android/net/wifi/WifiConfigurationTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.net.wifi; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import android.os.Parcel; + +import org.junit.Before; +import org.junit.Test; + +/** + * Unit tests for {@link android.net.wifi.WifiConfiguration}. + */ +public class WifiConfigurationTest { + + @Before + public void setUp() { + } + + /** + * Check that parcel marshalling/unmarshalling works + * + * Create and populate a WifiConfiguration. + * Marshall and unmashall it, and expect to recover a copy of the original. + * Marshall the resulting object, and expect the bytes to match the + * first marshall result. + */ + @Test + public void testWifiConfigurationParcel() { + String cookie = "C O.o |<IE"; + WifiConfiguration config = new WifiConfiguration(); + config.setPasspointManagementObjectTree(cookie); + Parcel parcelW = Parcel.obtain(); + config.writeToParcel(parcelW, 0); + byte[] bytes = parcelW.marshall(); + parcelW.recycle(); + + Parcel parcelR = Parcel.obtain(); + parcelR.unmarshall(bytes, 0, bytes.length); + parcelR.setDataPosition(0); + WifiConfiguration reconfig = WifiConfiguration.CREATOR.createFromParcel(parcelR); + + // lacking a useful config.equals, check one field near the end. + assertEquals(cookie, reconfig.getMoTree()); + + Parcel parcelWW = Parcel.obtain(); + reconfig.writeToParcel(parcelWW, 0); + byte[] rebytes = parcelWW.marshall(); + parcelWW.recycle(); + + assertArrayEquals(bytes, rebytes); + } +} |