Add update_engine unittests to the native tests.
am: 381ef84902

Change-Id: I0017920562881c09bcb50600045d4706250fe85d
diff --git a/libraries/aupt-lib/src/android/support/test/aupt/AuptTestCase.java b/libraries/aupt-lib/src/android/support/test/aupt/AuptTestCase.java
index 5ec427c..7755fc7 100644
--- a/libraries/aupt-lib/src/android/support/test/aupt/AuptTestCase.java
+++ b/libraries/aupt-lib/src/android/support/test/aupt/AuptTestCase.java
@@ -71,6 +71,7 @@
     private UiWatchers mWatchers;
     private IProcessStatusTracker mProcessStatusTracker;
     private DataCollector mDataCollector;
+    private List<String> mPaths;
 
     // We want to periodically collect dumpheap output if the process grows to large to proactivelly
     // help with catching memory leaks, but don't want to do it too often so it does not disturb the
@@ -805,6 +806,14 @@
         mDataCollector = collector;
     }
 
+    public void setDexedJarPaths(List<String> paths) {
+        mPaths = paths;
+    }
+
+    public List<String> getDexedJarPaths() {
+        return mPaths;
+    }
+
     public String getPackageVersion(String packageName) throws NameNotFoundException {
         if (null == packageName || packageName.isEmpty()) {
               throw new RuntimeException("Package name can't be null or empty");
diff --git a/libraries/aupt-lib/src/android/support/test/aupt/AuptTestRunner.java b/libraries/aupt-lib/src/android/support/test/aupt/AuptTestRunner.java
index 643e681..a689a58 100644
--- a/libraries/aupt-lib/src/android/support/test/aupt/AuptTestRunner.java
+++ b/libraries/aupt-lib/src/android/support/test/aupt/AuptTestRunner.java
@@ -88,6 +88,7 @@
 
     private boolean mTrackJank;
     private GraphicsStatsMonitor mGraphicsStatsMonitor;
+    private List<String> mJars;
 
     /**
      * {@inheritDoc}
@@ -164,7 +165,8 @@
     private void loadDexJars(String jars) {
         // scan provided jar paths, translate relative to absolute paths, and check for existence
         String[] jarsArray = jars.split(":");
-        StringBuilder jarFiles = new StringBuilder();
+        StringBuilder classLoaderPath = new StringBuilder();
+        mJars = new ArrayList<String>();
         for (int i = 0; i < jarsArray.length; i++) {
             String jar = jarsArray[i];
             if (!jar.startsWith("/")) {
@@ -176,9 +178,10 @@
                         + jar);
             }
             if (i != 0) {
-                jarFiles.append(File.pathSeparator);
+                classLoaderPath.append(File.pathSeparator);
             }
-            jarFiles.append(jarFile.getAbsolutePath());
+            classLoaderPath.append(jarFile.getAbsolutePath());
+            mJars.add(jarFile.getAbsolutePath());
         }
         // now load them
         File optDir = new File(getContext().getCacheDir(), DEX_OPT_PATH);
@@ -186,7 +189,7 @@
             throw new RuntimeException(
                     "Failed to create dex optimize directory: " + optDir.getAbsolutePath());
         }
-        mLoader = new BaseDexClassLoader(jarFiles.toString(), optDir, null,
+        mLoader = new BaseDexClassLoader(classLoaderPath.toString(), optDir, null,
                 super.getTargetContext().getClassLoader());
 
     }
@@ -220,7 +223,7 @@
     private void writeProgressMessage(String msg) {
         writeMessage("progress.txt", msg);
     }
-    
+
     private void writeGraphicsMessage(String msg) {
         writeMessage("graphics.txt", msg);
     }
@@ -440,6 +443,7 @@
                 ((AuptTestCase)test).setProcessStatusTracker(mProcessTracker);
                 ((AuptTestCase)test).setMemHealthRecords(mMemHealthRecords);
                 ((AuptTestCase)test).setDataCollector(mDataCollector);
+                ((AuptTestCase)test).setDexedJarPaths(mJars);
             }
         }
 
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractAngryBirdsHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractAngryBirdsHelper.java
new file mode 100644
index 0000000..dc1f037
--- /dev/null
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractAngryBirdsHelper.java
@@ -0,0 +1,48 @@
+/*
+ * 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.platform.test.helpers;
+
+import android.app.Instrumentation;
+
+public abstract class AbstractAngryBirdsHelper extends AbstractStandardAppHelper {
+
+    public AbstractAngryBirdsHelper(Instrumentation instr) {
+        super(instr);
+    }
+
+    /**
+     * Setup expectation: Angry Birds open and on main menu
+     *
+     * This method will set up game demo by going to level selection menu
+     */
+    public abstract void setUpDemo();
+
+    /**
+     * Setup expectation: Angry Birds open and on level selection menu
+     *
+     * This method plays a game demo for demoDurationInMinutes minutes
+     * @param demoDurationInMinutes: game demo duration in minutes
+     */
+    public abstract void playDemo(int demoDurationInMinutes);
+
+    /**
+     * Setup expectation: Angry Birds open and on level selection menu
+     *
+     * This method goes back to the main menu
+     */
+    public abstract void tearDownDemo();
+}
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractChromeHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractChromeHelper.java
index 050a1c9..7589d22 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractChromeHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractChromeHelper.java
@@ -61,4 +61,12 @@
      * is open on the original tab.
      */
     public abstract void unmergeTabs();
+
+    /**
+     * Setup expectations: Chrome is open on a page.
+     *
+     * This method will reload the page by clicking the refresh button, and block until the page
+     * is reopened.
+     */
+    public abstract void reloadPage();
 }
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleCameraHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleCameraHelper.java
index aa890c0..7b8e7a4 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleCameraHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleCameraHelper.java
@@ -20,6 +20,26 @@
 import android.support.test.uiautomator.Direction;
 
 public abstract class AbstractGoogleCameraHelper extends AbstractStandardAppHelper {
+    public static final int HDR_MODE_AUTO = -1;
+    public static final int HDR_MODE_OFF  =  0;
+    public static final int HDR_MODE_ON   =  1;
+
+    public static final int VIDEO_SD_480     = -2;
+    public static final int VIDEO_HD_720     = -1;
+    public static final int VIDEO_HD_1080    =  0;
+    public static final int VIDEO_4K_MODE_ON =  1;
+
+    public static final int VIDEO_30FPS = 0;
+    public static final int VIDEO_60FPS = 1;
+
+    public static final int HFR_MODE_OFF     = 0;
+    public static final int HFR_MODE_120_FPS = 1;
+    public static final int HFR_MODE_240_FPS = 2;
+
+    public static final int FLASH_AUTO = -1;
+    public static final int FLASH_OFF = 0;
+    public static final int FLASH_ON = 1;
+    public static final int NUM_FLASH_MODES = 3;
 
     public AbstractGoogleCameraHelper(Instrumentation instr) {
         super(instr);
@@ -158,6 +178,17 @@
     public abstract void setFrameRate(int mode);
 
     /**
+     * Setup expectation: GoogleCamera is open and idle in camera or video mode.
+     *
+     * This method will set flash to one of the following:
+     * - on   (mode == FLASH_ON)
+     * - auto (mode == FLASH_AUTO)
+     * - off  (mode == FLASH_OFF)
+     * @param mode the integer value of the mode denoted above.
+     */
+    public abstract void setFlashMode(int mode);
+
+    /**
      * Setup expectation: in Camera mode with the capture button present.
      *
      * This method will block until the capture button is enabled for pressing.
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleFitHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleFitHelper.java
index 2ee1a58..df2e9a7 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleFitHelper.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractGoogleFitHelper.java
@@ -16,6 +16,8 @@
 
 package android.platform.test.helpers;
 
+import java.io.IOException;
+
 import android.app.Instrumentation;
 import android.support.test.uiautomator.Direction;
 
@@ -65,15 +67,16 @@
      * @param steps value of Steps
      * @param distance value of Distance in mile
      */
-    public abstract void addActivity(String activity, int duration,
-                                     int calories, int steps, int distance);
+    public abstract void addActivity(String activity, int duration, int calories,
+                                     int steps, int distance);
     /**
      * Setup expectations: Google Fit is open and idle on the home page or timeline page.
      *
      * This method will select an activity type and start an activity session
      * @param activity case-insensitive activity types, like: running, biking, walking
      */
-    public abstract void startActivity(String activity);
+    public abstract void startActivity(String activity) throws IOException;
+
     /**
      * Setup expectations: An activity session is started.
      *
@@ -94,4 +97,12 @@
      * This method will terminate and save the current activity and end on the activity summary page
      */
     public abstract void saveActivity();
+
+    /**
+     * Setup expectations: An activity session is started.
+     *
+     * This method will stop the current activity and end on the activity page.
+     */
+    public abstract void stopActivity() throws IOException;
+
 }
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractSlackerHelper.java b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractSlackerHelper.java
new file mode 100644
index 0000000..caceb0a
--- /dev/null
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/AbstractSlackerHelper.java
@@ -0,0 +1,45 @@
+/*
+ * 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.platform.test.helpers;
+
+import android.app.Instrumentation;
+
+public abstract class AbstractSlackerHelper extends AbstractStandardAppHelper {
+
+    public AbstractSlackerHelper(Instrumentation instr) {
+        super(instr);
+    }
+
+    /**
+     * Setup expectation: Slacker is on page with playable radio channels
+     *
+     * This method starts playing one of the playable radio channels.
+     * If app is already on channel page, this function starts playing
+     * the radio on the current page. If it cannot start streaming a radio
+     * channel, it throws an exception.
+     */
+    public abstract void startAnyChannel();
+
+    /**
+     * Setup expectation: Slacker is on channel page
+     *
+     * This method pauses the audio streaming and returns to main page.
+     * If app is already on main page, this function does nothing.  If it
+     * cannot stop streamming channel, it throws an exception.
+     */
+    public abstract void stopChannel();
+}
diff --git a/libraries/base-app-helpers/src/android/platform/test/helpers/HelperManager.java b/libraries/base-app-helpers/src/android/platform/test/helpers/HelperManager.java
index 3ac9246..533b0b2 100644
--- a/libraries/base-app-helpers/src/android/platform/test/helpers/HelperManager.java
+++ b/libraries/base-app-helpers/src/android/platform/test/helpers/HelperManager.java
@@ -30,6 +30,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
@@ -44,10 +45,9 @@
  * <ol>
  * <li> Static inclusion - if all the code is included in the final APK, the Context can be used to
  * generate a HelperManager and to instantiate implementations.
- * <li> Dexed file inclusion - if this and the helper implementations are bundled into a dexed
- * file, such as a dexed JAR, that gets added after compilation, e.g. how the automated user
- * profile test suites are built, the path can be used to generate a HelperManager and to
- * instantiate implementations.
+ * <li> Dexed file inclusion - if this manager and the helper implementations are bundled into dex
+ * files and loaded from a single class loader, then the files can be used to generate a
+ * HelperManager and to instantiate implementations.
  * </ol>
  * <p>
  * Including and using this strategy will prune the explicit dependency tree for the App Helper
@@ -76,33 +76,36 @@
                         String.format("Cannot pass in null instrumentation."));
             }
             // Instantiation
-            sInstance = new HelperManager(context.getPackageCodePath(), instr);
+            List<String> paths = Arrays.asList(context.getPackageCodePath());
+            sInstance = new HelperManager(paths, instr);
         }
         return sInstance;
     }
 
     /**
-     * Returns an instance of the HelperManager that searches the supplied location for classes to
+     * Returns an instance of the HelperManager that searches the supplied locations for classes to
      * instantiate to helper implementations.
      *
-     * @param path the dexed file where the classes are included
+     * @param paths the dex files where the classes are included
      * @param instr the active instrumentation
      * @throws IllegalArgumentException if the path is not a valid file
      * @return a new instance of the HelperManager class
      */
-    public static HelperManager getInstance(String path, Instrumentation instr) {
+    public static HelperManager getInstance(List<String> paths, Instrumentation instr) {
         if (sInstance == null) {
             // Input checks
-            if (!(new File(path)).exists()) {
-                throw new IllegalArgumentException(
-                        String.format("No file found at path: %s.", path));
+            for (String path : paths) {
+                if (!(new File(path)).exists()) {
+                    throw new IllegalArgumentException(
+                            String.format("No file found at path: %s.", path));
+                }
             }
             if (instr == null) {
                 throw new NullPointerException(
                         String.format("Cannot pass in null instrumentation."));
             }
             // Instantiation
-            sInstance = new HelperManager(path, instr);
+            sInstance = new HelperManager(paths, instr);
         }
         return sInstance;
     }
@@ -110,12 +113,15 @@
     private Instrumentation mInstrumentation;
     private List<String> mClasses;
 
-    private HelperManager(String path, Instrumentation instr) {
+    private HelperManager(List<String> paths, Instrumentation instr) {
         mInstrumentation = instr;
         // Collect all of the available classes
+        mClasses = new ArrayList<String>();
         try {
-            DexFile dex = new DexFile(path);
-            mClasses = Collections.list(dex.entries());
+            for (String path : paths) {
+                DexFile dex = new DexFile(path);
+                mClasses.addAll(Collections.list(dex.entries()));
+            }
         } catch (IOException e) {
             throw new RuntimeException("Failed to retrieve the dex file.");
         }
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/LauncherStrategyFactory.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/LauncherStrategyFactory.java
index ce6bef4..cab96cd 100644
--- a/libraries/launcher-helper/src/android/support/test/launcherhelper/LauncherStrategyFactory.java
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/LauncherStrategyFactory.java
@@ -43,7 +43,9 @@
         registerLauncherStrategy(GoogleExperienceLauncherStrategy.class);
         registerLauncherStrategy(Launcher3Strategy.class);
         registerLauncherStrategy(NexusLauncherStrategy.class);
+        registerLauncherStrategy(PixelCLauncherStrategy.class);
         registerLauncherStrategy(LeanbackLauncherStrategy.class);
+        registerLauncherStrategy(WearLauncherStrategy.class);
     }
 
     /**
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/PixelCLauncherStrategy.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/PixelCLauncherStrategy.java
new file mode 100644
index 0000000..93b44ff
--- /dev/null
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/PixelCLauncherStrategy.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2017 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.support.test.launcherhelper;
+
+/**
+ * Implementation of {@link ILauncherStrategy} to support Pixel C launcher
+ */
+public class PixelCLauncherStrategy extends NexusLauncherStrategy {
+
+    private static final String LAUNCHER_PKG = "com.google.android.apps.pixelclauncher";
+
+    @Override
+    public String getSupportedLauncherPackage() {
+        return LAUNCHER_PKG;
+    }
+}
diff --git a/libraries/launcher-helper/src/android/support/test/launcherhelper/WearLauncherStrategy.java b/libraries/launcher-helper/src/android/support/test/launcherhelper/WearLauncherStrategy.java
new file mode 100644
index 0000000..7f326ab
--- /dev/null
+++ b/libraries/launcher-helper/src/android/support/test/launcherhelper/WearLauncherStrategy.java
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2017 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.support.test.launcherhelper;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+import android.os.SystemClock;
+import android.support.test.uiautomator.By;
+import android.support.test.uiautomator.BySelector;
+import android.support.test.uiautomator.Direction;
+import android.support.test.uiautomator.UiDevice;
+import android.support.test.uiautomator.UiObject2;
+import android.support.test.uiautomator.Until;
+import android.widget.TextView;
+import android.util.Log;
+
+import junit.framework.Assert;
+
+public class WearLauncherStrategy implements ILauncherStrategy {
+
+    private static final String LAUNCHER_PKG = "com.google.android.wearable.app";
+    private static final String LOG_TAG = WearLauncherStrategy.class.getSimpleName();
+    protected UiDevice mDevice;
+    protected Context mContext;
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getSupportedLauncherPackage() {
+        return LAUNCHER_PKG;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setUiDevice(UiDevice uiDevice) {
+        mDevice = uiDevice;
+    }
+
+    /**
+     * Shows the home screen of launcher
+     */
+    @Override
+    public void open() {
+        if (!mDevice.hasObject(getHotSeatSelector())) {
+            mDevice.pressBack();
+            if (!mDevice.wait(Until.hasObject(getHotSeatSelector()), 5000)) {
+                // HACK: dump hierarchy to logcat
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                try {
+                    mDevice.dumpWindowHierarchy(baos);
+                    baos.flush();
+                    baos.close();
+                    String[] lines = baos.toString().split("\\r?\\n");
+                    for (String line : lines) {
+                        Log.d(LOG_TAG, line.trim());
+                    }
+                } catch (IOException ioe) {
+                    Log.e(LOG_TAG, "error dumping XML to logcat", ioe);
+                }
+                Assert.fail("Failed to open launcher");
+            }
+            mDevice.waitForIdle();
+        }
+    }
+
+    /**
+     * Opens the all apps drawer of launcher
+     * @param reset if the all apps drawer should be reset to the beginning
+     * @return {@link UiObject2} representation of the all apps drawer
+     */
+    @Override
+    public UiObject2 openAllApps(boolean reset) {
+        if (!mDevice.hasObject(getAllAppsSelector())) {
+            mDevice.pressBack();
+        }
+        UiObject2 allAppsContainer = mDevice.wait(Until.findObject(getAllAppsSelector()), 2000);
+        if (reset) {
+            CommonLauncherHelper.getInstance(mDevice).scrollBackToBeginning(
+                    allAppsContainer, Direction.reverse(getAllAppsScrollDirection()));
+        }
+        return allAppsContainer;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public BySelector getHotSeatSelector() {
+         return By.res(getSupportedLauncherPackage(), "watchface_overlay");
+    }
+
+
+    /**
+     * Returns a {@link BySelector} describing the all apps drawer
+     * @return
+     */
+    @Override
+    public BySelector getAllAppsSelector() {
+        return By.res(getSupportedLauncherPackage(), "launcher_view");
+    }
+
+    /**
+     * Retrieves the all apps drawer forward scroll direction as implemented by the launcher
+     * @return
+     */
+    @Override
+    public Direction getAllAppsScrollDirection() {
+        return Direction.DOWN;
+    }
+
+    @Override
+    public BySelector getAllAppsButtonSelector() {
+        throw new UnsupportedOperationException(
+                "The 'All Apps' button is not available on Android Wear Launcher.");
+    }
+
+    @Override
+    public UiObject2 openAllWidgets(boolean reset) {
+        throw new UnsupportedOperationException(
+                "The 'All Widgets' button is not available on Android Wear Launcher.");
+    }
+
+    @Override
+    public BySelector getAllWidgetsSelector() {
+        throw new UnsupportedOperationException(
+                "The 'All Widgets' button is not available on Android Wear Launcher.");
+    }
+
+    @Override
+    public Direction getAllWidgetsScrollDirection() {
+        throw new UnsupportedOperationException(
+                "The 'All Widgets' button is not available on Android Wear Launcher.");
+    }
+
+    @Override
+    public BySelector getWorkspaceSelector() {
+        throw new UnsupportedOperationException(
+                "The 'Work space' is not available on Android Wear Launcher.");
+    }
+
+    @Override
+    public Direction getWorkspaceScrollDirection() {
+        throw new UnsupportedOperationException(
+                "The 'Work Space' is not available on Android Wear Launcher.");
+    }
+
+    /**
+     * Launch the named application
+     * @param appName the name of the application to launch as shown in launcher
+     * @param packageName the expected package name to verify that the application has been launched
+     *                    into foreground. If <code>null</code> is provided, no verification is
+     *                    performed.
+     * @return <code>true</code> if application is verified to be in foreground after launch, or the
+     *   verification is skipped; <code>false</code> otherwise.
+     */
+    @Override
+    public long launch(String appName, String packageName) {
+        BySelector app = By.res(
+                getSupportedLauncherPackage(), "title").clazz(TextView.class).text(appName);
+        return CommonLauncherHelper.getInstance(mDevice).launchApp(this, app, packageName);
+    }
+}
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/CardsJankTest.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/CardsJankTest.java
index 14507d3..5282f29 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/CardsJankTest.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/CardsJankTest.java
@@ -82,6 +82,20 @@
         super.afterTest(metrics);
     }
 
+    // Measure jank when dismissing on an expanded card
+    @JankTest(beforeLoop = "openSwipeExpandedCard", afterTest = "goBackHome",
+            expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_DISMISS_EXPANDED_CARDS_TEST)
+    @GfxMonitor(processName = "com.google.android.wearable.app")
+    public void testSwipeExpandedCard() {
+        mHelper.swipeRight();
+    }
+
+    // Preparing the expanded card
+    public void openSwipeExpandedCard() throws Exception {
+        openSwipeCard();
+        mHelper.clickScreenCenter();
+    }
+
     /*
      * (non-Javadoc)
      * @see android.test.InstrumentationTestCase#tearDown()
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/QuickSettingsJankTest.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/QuickSettingsJankTest.java
index ed9c069..fa9e89f 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/QuickSettingsJankTest.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/QuickSettingsJankTest.java
@@ -40,7 +40,7 @@
     private SysAppTestHelper mHelper;
 
     private static final String WEARABLE_APP_PACKAGE = "com.google.android.wearable.app";
-    private static final String QUICK_SETTINGS_LAUNCHED_INDICATOR = "settings_icon";
+    private static final String QUICK_SETTINGS_LAUNCHED_INDICATOR = "Quick settings";
 
     /*
      * (non-Javadoc)
@@ -55,9 +55,10 @@
     }
 
     private void isQuickSettingShadeLaunched() throws TimeoutException {
-        SystemClock.sleep(SysAppTestHelper.SHORT_TIMEOUT + SysAppTestHelper.SHORT_TIMEOUT); //Wait until date & battery info transitions to page indicator
+        //Wait until date & battery info transitions to page indicator
+        SystemClock.sleep(SysAppTestHelper.SHORT_TIMEOUT + SysAppTestHelper.SHORT_TIMEOUT);
         UiObject2 quickSettingsShade = mDevice.wait(
-                Until.findObject(By.res(WEARABLE_APP_PACKAGE, QUICK_SETTINGS_LAUNCHED_INDICATOR)),
+                Until.findObject(By.desc(QUICK_SETTINGS_LAUNCHED_INDICATOR)),
                 SysAppTestHelper.SHORT_TIMEOUT);
         Assert.assertNotNull("Quick settings shade not launched", quickSettingsShade);
 
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SettingsFlingJankTest.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SettingsFlingJankTest.java
index 1da3683..97f574f 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SettingsFlingJankTest.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SettingsFlingJankTest.java
@@ -21,12 +21,12 @@
 import android.support.test.jank.GfxMonitor;
 import android.support.test.jank.JankTest;
 import android.support.test.jank.JankTestBase;
+import android.support.test.jank.WindowAnimationFrameStatsMonitor;
 import android.support.test.uiautomator.By;
 import android.support.test.uiautomator.Direction;
 import android.support.test.uiautomator.UiDevice;
 import android.support.test.uiautomator.UiObject2;
 import android.support.test.uiautomator.Until;
-
 import java.util.concurrent.TimeoutException;
 
 /**
@@ -34,15 +34,13 @@
  */
 public class SettingsFlingJankTest extends JankTestBase {
 
-    private UiDevice mDevice;
-    private SysAppTestHelper mHelper;
-
     // Settings app resources
     private static final String CLOCK_SETTINGS_PACKAGE =
-        "com.google.android.apps.wearable.settings";
-
+            "com.google.android.apps.wearable.settings";
     private static final String CLOCK_SETTINGS_ACTIVITY =
-        "com.google.android.clockwork.settings.MainSettingsActivity";
+            "com.google.android.clockwork.settings.MainSettingsActivity";
+    private UiDevice mDevice;
+    private SysAppTestHelper mHelper;
 
     /*
      * (non-Javadoc)
@@ -64,20 +62,25 @@
 
     /**
      * Test the jank by flinging in settings screen.
-     * @throws TimeoutException
-     *
      */
     @JankTest(beforeTest = "openSettingsApp", afterTest = "goBackHome",
-        expectedFrames = SysAppTestHelper.EXPECTED_FRAMES)
+            expectedFrames = SysAppTestHelper.EXPECTED_FRAMES)
     @GfxMonitor(processName = CLOCK_SETTINGS_PACKAGE)
     public void testSettingsApp() throws TimeoutException {
-          UiObject2 listViewContents = mDevice.wait(Until.findObject(
-              By.res("android", "list")),
-              SysAppTestHelper.SHORT_TIMEOUT);
-          for (int i = 0; i < 3; i++) {
-              listViewContents.fling(Direction.DOWN, SysAppTestHelper.FLING_SPEED);
-              listViewContents.fling(Direction.UP, SysAppTestHelper.FLING_SPEED);
-         }
+        UiObject2 listViewContents = mDevice.wait(Until.findObject(
+                By.res("android", "list")),
+                SysAppTestHelper.SHORT_TIMEOUT);
+        for (int i = 0; i < 3; i++) {
+            listViewContents.fling(Direction.DOWN, SysAppTestHelper.FLING_SPEED);
+            listViewContents.fling(Direction.UP, SysAppTestHelper.FLING_SPEED);
+        }
+    }
+
+    @JankTest(beforeLoop = "openSettingsApp", afterTest = "goBackHome",
+            expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_SWIPERIGHT_TO_DISMISS_TEST)
+    @WindowAnimationFrameStatsMonitor
+    public void testSwipeRightToDismissApp() {
+        mHelper.swipeRight();
     }
 
     // Ensuring that we head back to the first screen before launching the app again
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SysAppTestHelper.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SysAppTestHelper.java
index 8e6ba1d..e78204e 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SysAppTestHelper.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/SysAppTestHelper.java
@@ -37,7 +37,10 @@
 public class SysAppTestHelper {
 
     public static final int EXPECTED_FRAMES_CARDS_TEST = 20;
+    public static final int EXPECTED_FRAMES_DISMISS_EXPANDED_CARDS_TEST = 15;
     public static final int EXPECTED_FRAMES_WATCHFACE_PICKER_TEST = 20;
+    public static final int EXPECTED_FRAMES_SWIPERIGHT_TO_DISMISS_TEST = 20;
+    public static final int EXPECTED_FRAMES_WATCHFACE_PICKER_TEST_ADD_FAVORITE = 5;
     public static final int EXPECTED_FRAMES = 100;
     public static final int LONG_TIMEOUT = 5000;
     public static final int SHORT_TIMEOUT = 500;
@@ -47,10 +50,6 @@
     private static final String RELOAD_NOTIFICATION_CARD_INTENT = "com.google.android.wearable."
             + "support.wearnotificationgenerator.SHOW_NOTIFICATION";
     private static final String HOME_INDICATOR = "charging_icon";
-    private static final String LAUNCHER_VIEW_NAME = "launcher_view";
-    private static final String CARD_VIEW_NAME = "activity_view";
-    private static final String QUICKSETTING_VIEW_NAME = "settings_icon";
-    private static final String WATCHFACE_PREVIEW_NAME = "preview_image";
 
     // Demo card selectors
     private static final UiSelector CARD_SELECTOR = new UiSelector()
@@ -147,6 +146,11 @@
         SystemClock.sleep(SHORT_TIMEOUT);
     }
 
+    public void clickScreenCenter() {
+        mDevice.click(mDevice.getDisplayWidth() / 2, mDevice.getDisplayHeight() / 2);
+        SystemClock.sleep(SHORT_TIMEOUT);
+    }
+
     // Helper method to go back to home screen
     public void goBackHome() {
         int count = 0;
@@ -159,23 +163,6 @@
             count++;
         } while (count < 5);
 
-        // TODO (yuanlang@) Delete the following hacky codes after charging icon issue fixed
-        // Make sure we're not in the launcher
-        if (waitForSysAppUiObject2(LAUNCHER_VIEW_NAME) != null) {
-            mDevice.pressBack();
-        }
-        // Make sure we're not in cards view
-        if (waitForSysAppUiObject2(CARD_VIEW_NAME) != null) {
-            mDevice.pressBack();
-        }
-        // Make sure we're not in the quick settings
-        if (waitForSysAppUiObject2(QUICKSETTING_VIEW_NAME) != null) {
-            mDevice.pressBack();
-        }
-        // Make sure we're not in watch face picker
-        if (waitForSysAppUiObject2(WATCHFACE_PREVIEW_NAME) != null) {
-            mDevice.pressBack();
-        }
         SystemClock.sleep(LONG_TIMEOUT);
     }
 
diff --git a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/WatchFacePickerJankTest.java b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/WatchFacePickerJankTest.java
index 7ca40bc..4fd04f8 100644
--- a/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/WatchFacePickerJankTest.java
+++ b/tests/jank/sysapp_wear/src/com/android/wearable/sysapp/janktests/WatchFacePickerJankTest.java
@@ -69,9 +69,8 @@
      * Test the jank by adding watch face to favorites.
      */
     @JankTest(beforeLoop = "startFromWatchFacePickerFull",
-            afterLoop = "resetToWatchFacePickerFull",
             afterTest = "removeAllButOneWatchFace",
-            expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_WATCHFACE_PICKER_TEST)
+            expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_WATCHFACE_PICKER_TEST_ADD_FAVORITE)
     @GfxMonitor(processName = WEARABLE_APP_PACKAGE)
     public void testSelectWatchFaceFromFullList() {
         selectWatchFaceFromFullList(0);
@@ -91,7 +90,7 @@
     /**
      * Test the jank on flinging watch face picker.
      */
-    @JankTest(beforeLoop = "startWithFourWatchFaces", afterLoop = "resetToWatchFacePicker",
+    @JankTest(beforeTest = "startWithFourWatchFaces", beforeLoop = "resetToWatchFacePicker",
             afterTest = "removeAllButOneWatchFace",
             expectedFrames = SysAppTestHelper.EXPECTED_FRAMES_WATCHFACE_PICKER_TEST)
     @GfxMonitor(processName = WEARABLE_APP_PACKAGE)
@@ -192,8 +191,14 @@
     }
 
     private void openPicker() {
-        mHelper.swipeLeft();
-        Assert.assertNotNull(mHelper.waitForSysAppUiObject2(WATCHFACE_PREVIEW_NAME));
+        // Try 5 times in case WFP is not ready
+        for (int i = 0; i < 5; i ++) {
+            mHelper.swipeLeft();
+            if (mHelper.waitForSysAppUiObject2(WATCHFACE_PREVIEW_NAME) != null) {
+                return;
+            }
+        }
+        Assert.fail("Still cannot open WFP after several attempts");
     }
 
     private void openPickerAllList() {
@@ -225,7 +230,10 @@
         List<UiObject2> watchFaces = watchFacePickerAllList.getChildren();
         Assert.assertNotNull(watchFaces);
         int localIndex = index % 4;
-        if (watchFaces.size() <= localIndex) return;
+        if (watchFaces.size() <= localIndex) {
+            mDevice.pressBack();
+            return;
+        }
 
         Log.v(TAG, "Tapping the " + localIndex + " watchface on screen ...");
         watchFaces.get(localIndex).click();
@@ -244,7 +252,9 @@
         Assert.assertNotNull(watchFacePicker);
         List<UiObject2> watchFaces = watchFacePicker.getChildren();
         Assert.assertNotNull(watchFaces);
-        if (isOnlyOneWatchFaceInFavorites()) return;
+        if (isOnlyOneWatchFaceInFavorites()) {
+            return;
+        }
 
         Log.v(TAG, "Removing first watch face from favorites ...");
         watchFaces.get(0).swipe(Direction.DOWN, 1.0f);
diff --git a/utils/wifistrengthscanner/Android.mk b/utils/wifistrengthscanner/Android.mk
new file mode 100644
index 0000000..d35afd4
--- /dev/null
+++ b/utils/wifistrengthscanner/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_PACKAGE_NAME := WifiStrengthScannerUtil
+LOCAL_STATIC_JAVA_LIBRARIES := ub-uiautomator
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SDK_VERSION := 23
+
+include $(BUILD_PACKAGE)
diff --git a/utils/wifistrengthscanner/AndroidManifest.xml b/utils/wifistrengthscanner/AndroidManifest.xml
new file mode 100644
index 0000000..ddce7a2
--- /dev/null
+++ b/utils/wifistrengthscanner/AndroidManifest.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (c) 2016 Google Inc.
+ *
+ * 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.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.test.util.wifistrengthscanner">
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
+    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
+    <uses-sdk android:minSdkVersion="23"
+              android:targetSdkVersion="23" />
+    <application>
+        <uses-library android:name="android.test.runner" />
+    </application>
+
+    <instrumentation android:name=".WifiStrengthScannerInstrumentation"
+        android:targetPackage="com.android.test.util.wifistrengthscanner"
+        android:label="Dismiss Dialog Util">
+    </instrumentation>
+</manifest>
diff --git a/utils/wifistrengthscanner/src/com/android/test/util/wifistrengthscanner/WifiStrengthScannerInstrumentation.java b/utils/wifistrengthscanner/src/com/android/test/util/wifistrengthscanner/WifiStrengthScannerInstrumentation.java
new file mode 100644
index 0000000..39c49c1
--- /dev/null
+++ b/utils/wifistrengthscanner/src/com/android/test/util/wifistrengthscanner/WifiStrengthScannerInstrumentation.java
@@ -0,0 +1,195 @@
+/*
+ * 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 com.android.test.util.wifistrengthscanner;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.wifi.ScanResult;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public class WifiStrengthScannerInstrumentation extends Instrumentation {
+    private static final String TAG = WifiStrengthScannerInstrumentation.class.getCanonicalName();
+    private final static String SD_CARD_PATH =
+            Environment.getExternalStorageDirectory().getAbsolutePath() + "/";
+    private final int NUMBER_OF_WIFI_LEVELS = 101;
+    private final int INVALID_RSSI = -127;
+    private Bundle mArguments;
+    private CountDownLatch mLatch;
+    private boolean scanReceived;
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        super.onCreate(arguments);
+        mArguments = arguments;
+        start();
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        try {
+            mLatch = new CountDownLatch(1);
+            getContext().registerReceiver(new WifiScanReceiver(),
+                    new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
+            WifiManager wifiManager =
+                    (WifiManager) getContext().getSystemService(Context.WIFI_SERVICE);
+            scanReceived = false;
+            wifiManager.startScan();
+            mLatch.await(10000, TimeUnit.MILLISECONDS);
+
+            if (!scanReceived) {
+                sendFailureStatus("no_scan_received");
+                finish(Activity.RESULT_CANCELED, new Bundle());
+                return;
+            }
+
+            WifiInfo wifiInfo = wifiManager.getConnectionInfo();
+            Bundle bundle = new Bundle();
+            bundle.putString("suplicant_state", wifiInfo.getSupplicantState().name());
+
+            String bssid = wifiInfo.getBSSID();
+            bundle.putString("bssid", bssid);
+            // zero counts as a level, so the max level is one less that the number of levels.
+            bundle.putInt("wifi_max_level", NUMBER_OF_WIFI_LEVELS - 1);
+
+            bundle.putInt("wifi_info_wifi_level",
+                    WifiManager.calculateSignalLevel(wifiInfo.getRssi(), NUMBER_OF_WIFI_LEVELS));
+            bundle.putInt("wifi_info_rssi", wifiInfo.getRssi());
+            bundle.putInt("wifi_info_frequency", wifiInfo.getFrequency());
+
+            ScanResult result = getScanResult(wifiManager, bssid);
+            if (result != null) {
+                bundle.putInt("scan_result_wifi_level", wifiManager.calculateSignalLevel(result
+                        .level, NUMBER_OF_WIFI_LEVELS));
+                bundle.putInt("scan_result_rssi", result.level);
+                bundle.putInt("scan_result_frequency", result.frequency);
+            }
+
+            int dumpsysRssi = getRssiFromDumpsys(bssid);
+            bundle.putInt("dumpsys_rssi", dumpsysRssi);
+            bundle.putInt("dumpsys_wifi_level",
+                    WifiManager.calculateSignalLevel(dumpsysRssi, NUMBER_OF_WIFI_LEVELS));
+            sendStatus(Activity.RESULT_OK, bundle);
+            finish(Activity.RESULT_OK, new Bundle());
+        } catch (IOException e) {
+            Log.e(TAG, Log.getStackTraceString(e));
+            sendFailureStatus("io_exception");
+            finish(Activity.RESULT_CANCELED, new Bundle());
+        } catch (InterruptedException e) {
+            Log.e(TAG, Log.getStackTraceString(e));
+            sendFailureStatus("interrupted_exception");
+            finish(Activity.RESULT_CANCELED, new Bundle());
+        }
+    }
+
+    private ScanResult getScanResult(WifiManager wifiManager, String bssid) {
+        List<ScanResult> scanResults = wifiManager.getScanResults();
+        for (ScanResult scanResult : scanResults) {
+            if (scanResult.BSSID.equals(bssid)) {
+                return scanResult;
+            }
+        }
+
+        return null;
+    }
+
+    private void sendFailureStatus(String update) {
+        Bundle result = new Bundle();
+        result.putString("wifi_strength_scanner_failure", update);
+        sendStatus(Activity.RESULT_CANCELED, result);
+    }
+
+    private Integer getRssiFromDumpsys(String bssid) throws IOException, InterruptedException {
+        List<String> dumpsysLines = getDumpsysWifiLastScanResults();
+
+        for (int i = 2; i < dumpsysLines.size(); i++) {
+            String line = dumpsysLines.get(i);
+            if (line != null && line.contains(bssid)) {
+                String[] tokens = line.trim().split("\\s\\s+");
+                return Integer.parseInt(tokens[2]);
+            }
+        }
+
+        return INVALID_RSSI;
+    }
+
+    private List<String> getDumpsysWifiLastScanResults() throws IOException, InterruptedException {
+        String dumpsysWifi = executeCommand("dumpsys wifi");
+        String[] lines = dumpsysWifi.split("\n");
+        List<String> scanResults = new ArrayList<>();
+
+        boolean scansStarted = false;
+        for (String line : lines) {
+            if (line.startsWith("Latest scan results:")) {
+                scansStarted = true;
+            }
+
+            if (scansStarted) {
+                if ("".equals(line.trim())) {
+                    break;
+                }
+
+                scanResults.add(line);
+            }
+        }
+
+        return scanResults;
+    }
+
+    private String executeCommand(String cmd) throws IOException, InterruptedException {
+        StringBuilder result = new StringBuilder();
+        try {
+            ParcelFileDescriptor pfd = getUiAutomation().executeShellCommand(cmd);
+            byte[] buf = new byte[1024];
+            int bytesRead;
+            FileInputStream fis = new ParcelFileDescriptor.AutoCloseInputStream(pfd);
+            while ((bytesRead = fis.read(buf)) != -1) {
+                result.append(new String(buf, 0, bytesRead));
+            }
+            fis.close();
+        } catch (IOException e) {
+            throw new IOException(String.format("Fails to execute command: %s ", cmd), e);
+        }
+
+        return result.toString();
+    }
+
+    private class WifiScanReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.d(TAG, "scan results received.");
+            scanReceived = true;
+            mLatch.countDown();
+        }
+    }
+}